From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/ps__mesh_8cpp-source.html | 2144 ++++++++++++++++++++++++++++ 1 file changed, 2144 insertions(+) create mode 100644 docs/doxygen/nel/ps__mesh_8cpp-source.html (limited to 'docs/doxygen/nel/ps__mesh_8cpp-source.html') diff --git a/docs/doxygen/nel/ps__mesh_8cpp-source.html b/docs/doxygen/nel/ps__mesh_8cpp-source.html new file mode 100644 index 00000000..705a5db9 --- /dev/null +++ b/docs/doxygen/nel/ps__mesh_8cpp-source.html @@ -0,0 +1,2144 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

ps_mesh.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000, 2001 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "std3d.h"
+00027 
+00028 #include "3d/ps_mesh.h"
+00029 #include "3d/ps_macro.h"
+00030 #include "3d/shape.h"
+00031 #include "3d/mesh.h"
+00032 #include "3d/transform_shape.h"
+00033 #include "3d/shape_bank.h"
+00034 #include "3d/texture_mem.h"
+00035 #include "3d/scene.h"
+00036 #include "3d/ps_located.h"
+00037 #include "3d/particle_system.h"
+00038 #include "3d/particle_system_shape.h"
+00039 #include "3d/ps_iterator.h"
+00040 #include "nel/misc/stream.h"
+00041 #include "nel/misc/path.h"
+00042 
+00043 #include <memory>
+00044 
+00045 
+00046 
+00047 
+00048 
+00049 namespace NL3D 
+00050 {
+00051 
+00053 // static members //
+00055 
+00056 
+00057 
+00058 
+00059 CPSConstraintMesh::CMeshDisplayShare            CPSConstraintMesh::_MeshDisplayShare(16);       
+00060 CVertexBuffer                                                           CPSConstraintMesh::_PreRotatedMeshVB;                     // mesh has no normals
+00061 CVertexBuffer                                                           CPSConstraintMesh::_PreRotatedMeshVBWithNormal;  // mesh has normals
+00062 
+00063 
+00064 
+00065 // this produce a random unit vector
+00066 static CVector MakeRandomUnitVect(void) 
+00067 {
+00068         CVector v((float) ((rand() % 20000) - 10000)
+00069                           ,(float) ((rand() % 20000) - 10000)
+00070                           ,(float) ((rand() % 20000) - 10000)
+00071                           );
+00072         v.normalize();
+00073         return v;
+00074 }
+00075 
+00076 
+00078 // CPSMesh implementation //
+00080 
+00081 
+00082 //====================================================================================
+00083 
+00084 
+00085 
+00086 
+00087 const std::string DummyShapeName("dummy mesh shape");
+00088 
+00092 static CMesh *CreateDummyShape(void)
+00093 {
+00094         CMesh::CMeshBuild mb;
+00095         CMeshBase::CMeshBaseBuild mbb;
+00096 
+00097         mb.VertexFlags = CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag;
+00098         mb.Vertices.push_back(CVector(-.5f, -.5f, -.5f));
+00099         mb.Vertices.push_back(CVector(.5f, -.5f, -.5f));
+00100         mb.Vertices.push_back(CVector(.5f, -.5f, .5f));
+00101         mb.Vertices.push_back(CVector(-.5f, -.5f, .5f));
+00102 
+00103         mb.Vertices.push_back(CVector(-.5f, .5f, -.5f));
+00104         mb.Vertices.push_back(CVector(.5f, .5f, -.5f));
+00105         mb.Vertices.push_back(CVector(.5f, .5f, .5f));
+00106         mb.Vertices.push_back(CVector(-.5f, .5f, .5f));
+00107 
+00108         // index for each face
+00109         uint32 tab[] = { 4, 1, 0,
+00110                                          4, 5, 1,
+00111                                          5, 2, 1,
+00112                                          5, 6, 2,
+00113                                          6, 3, 2,
+00114                                          6, 7, 3,
+00115                                          7, 0, 3,
+00116                                          7, 4, 0,
+00117                                          7, 5, 4,
+00118                                          7, 6, 5,
+00119                                          2, 0, 1,
+00120                                          2, 3, 0
+00121                                         };
+00122 
+00123         for (uint k = 0; k < 6; ++k)
+00124         {
+00125                 CMesh::CFace f;
+00126                 f.Corner[0].Vertex = tab[6 * k];
+00127                 f.Corner[0].Uvws[0] = NLMISC::CUVW(0, 0, 0);
+00128 
+00129                 f.Corner[1].Vertex = tab[6 * k + 1];
+00130                 f.Corner[1].Uvws[0] = NLMISC::CUVW(1, 1, 0);
+00131 
+00132                 f.Corner[2].Vertex = tab[6 * k + 2];
+00133                 f.Corner[2].Uvws[0] = NLMISC::CUVW(0, 1, 0);
+00134 
+00135                 f.MaterialId = 0;
+00136 
+00137                 mb.Faces.push_back(f);
+00138 
+00139                 f.Corner[0].Vertex = tab[6 * k + 3];
+00140                 f.Corner[0].Uvws[0] = NLMISC::CUVW(0, 0, 0);
+00141 
+00142                 f.Corner[1].Vertex = tab[6 * k + 4];
+00143                 f.Corner[1].Uvws[0] = NLMISC::CUVW(1, 0, 0);
+00144 
+00145                 f.Corner[2].Vertex = tab[6 * k + 5];
+00146                 f.Corner[2].Uvws[0] = NLMISC::CUVW(1, 1, 0);
+00147 
+00148                 f.MaterialId = 0;
+00149                 mb.Faces.push_back(f);          
+00150         }
+00151 
+00152         CMaterial mat;
+00153         CTextureMem *tex = new CTextureMem;
+00154         tex->makeDummy();
+00155         mat.setTexture(0, tex);
+00156         mat.setLighting(false);
+00157         mat.setColor(CRGBA::White);
+00158         mbb.Materials.push_back(mat);
+00159         CMesh *m = new CMesh;
+00160         m->build(mbb, mb);
+00161         return m;
+00162 } 
+00163 
+00164 
+00165 //====================================================================================
+00166 void CPSMesh::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+00167 {       
+00168         (void)f.serialVersion(3);       
+00169         CPSParticle::serial(f);
+00170         CPSSizedParticle::serialSizeScheme(f);
+00171         CPSRotated3DPlaneParticle::serialPlaneBasisScheme(f);
+00172         CPSRotated2DParticle::serialAngle2DScheme(f);
+00173         f.serial(_Shape);
+00174         if (f.isReading())
+00175         {
+00176                 invalidate();
+00177         }
+00178 }
+00179 
+00180 
+00181 //====================================================================================
+00182 uint32 CPSMesh::getMaxNumFaces(void) const
+00183 {
+00185         return 0;
+00186 }
+00187 
+00188 //====================================================================================
+00189 bool CPSMesh::hasTransparentFaces(void)
+00190 {
+00192         return false;
+00193 }
+00194 
+00195 //====================================================================================
+00196 bool CPSMesh::hasOpaqueFaces(void)
+00197 {
+00199         return false;
+00200 }
+00201 
+00202 //====================================================================================
+00203 void CPSMesh::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+00204 {
+00205         newPlaneBasisElement(emitterLocated, emitterIndex);
+00206         newAngle2DElement(emitterLocated, emitterIndex);
+00207         newSizeElement(emitterLocated, emitterIndex);
+00208 
+00209         nlassert(_Owner);
+00210         nlassert(_Owner->getOwner());
+00211 
+00212         CScene *scene = _Owner->getScene();
+00213         nlassert(scene); // the setScene method of the particle system should have been called
+00214         //CTransformShape *instance = _Shape->createInstance(*scene);
+00215 
+00216         CTransformShape *instance = scene->createInstance(_Shape);
+00217 
+00218         if (!instance)
+00219         {
+00220                 
+00221                 // mesh not found ...
+00222                 IShape *is = CreateDummyShape();
+00223                 scene->getShapeBank()->add(DummyShapeName, is);
+00224                 instance = scene->createInstance(DummyShapeName);
+00225                 nlassert(instance);
+00226         }
+00227 
+00228 
+00229         instance->setTransformMode(CTransform::DirectMatrix);
+00230 
+00231         instance->hide(); // the object hasn't the right matrix yet so we hide it. It'll be shown once it is computed
+00232         nlassert(instance);
+00233 
+00234         _Instances.insert(instance);
+00235 }
+00236 
+00237 //====================================================================================  
+00238 void CPSMesh::deleteElement(uint32 index)
+00239 {       
+00240         deleteSizeElement(index);
+00241         deleteAngle2DElement(index);
+00242         deletePlaneBasisElement(index);
+00243 
+00244         // check wether CTransformShape have been instanciated
+00245         if (_Invalidated) return;
+00246 
+00247         nlassert(_Owner);
+00248         nlassert(_Owner->getOwner());
+00249 
+00250         CScene *scene = _Owner->getScene();
+00251         nlassert(scene); // the setScene method of the particle system should have been called
+00252 
+00253         scene->deleteInstance(_Instances[index]);
+00254         _Instances.remove(index);
+00255 }
+00256 
+00257 //====================================================================================
+00258 void CPSMesh::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
+00259 {
+00260                 if (pass == PSSolidRender)                      
+00261                 {
+00262                         updatePos();
+00263                 }
+00264                 else 
+00265                 if (pass == PSToolRender) // edition mode only
+00266                 {                       
+00267                         showTool();
+00268                 }
+00269 
+00270 }
+00271 
+00272 //====================================================================================
+00273 void CPSMesh::updatePos()
+00274 {
+00275         const uint MeshBufSize = 512;
+00276         PARTICLES_CHECK_MEM;
+00277         nlassert(_Owner);
+00278         const uint32 size = _Owner->getSize();
+00279         if (!size) return;
+00280 
+00281 
+00282         _Owner->incrementNbDrawnParticles(size); // for benchmark purpose       
+00283 
+00284 
+00285         if (_Invalidated)
+00286         {
+00287                 // need to rebuild all the transform shapes
+00288                 nlassert(_Owner);
+00289                 nlassert(_Owner->getOwner());
+00290 
+00291                 CScene *scene = _Owner->getScene();
+00292                 nlassert(scene); // the setScene method of the particle system should have been called
+00293         
+00294 
+00295                 resize(_Owner->getMaxSize());
+00296 
+00297                 for (uint k = 0; k < size; ++k)
+00298                 {
+00299                         CTransformShape *instance = scene->createInstance(_Shape);
+00300                         instance->setTransformMode(CTransform::DirectMatrix);
+00301                         instance->hide();
+00302                         _Instances.insert(instance);
+00303                 }
+00304 
+00305                 _Invalidated = false;
+00306         }
+00307         
+00308         float sizes[MeshBufSize];
+00309         float angles[MeshBufSize];
+00310         static CPlaneBasis planeBasis[MeshBufSize];
+00311 
+00312         uint32 leftToDo = size, toProcess;
+00313 
+00314 
+00315         float *ptCurrSize;
+00316         const uint  ptCurrSizeIncrement = _SizeScheme ? 1 : 0;
+00317 
+00318         float *ptCurrAngle;
+00319         const uint  ptCurrAngleIncrement = _Angle2DScheme ? 1 : 0;
+00320 
+00321         CPlaneBasis *ptBasis;
+00322         const uint  ptCurrPlaneBasisIncrement = _PlaneBasisScheme ? 1 : 0;
+00323 
+00324         TPSAttribVector::const_iterator posIt = _Owner->getPos().begin(), endPosIt;
+00325 
+00326 
+00327         TInstanceCont::iterator instanceIt = _Instances.begin();
+00328 
+00329         do
+00330         {
+00331                 toProcess = leftToDo < MeshBufSize ? leftToDo : MeshBufSize;
+00332 
+00333                 if (_SizeScheme)
+00334                 {
+00335                         ptCurrSize  = (float *) (_SizeScheme->make(_Owner, size - leftToDo, &sizes[0], sizeof(float), toProcess, true));                        
+00336                 }
+00337                 else
+00338                 {
+00339                         ptCurrSize =& _ParticleSize;
+00340                 }
+00341 
+00342                 if (_Angle2DScheme)
+00343                 {
+00344                         ptCurrAngle  = (float *) (_Angle2DScheme->make(_Owner, size - leftToDo, &angles[0], sizeof(float), toProcess, true));                   
+00345                 }
+00346                 else
+00347                 {
+00348                         ptCurrAngle =& _Angle2D;
+00349                 }
+00350 
+00351 
+00352                 if (_PlaneBasisScheme)
+00353                 {
+00354                         ptBasis  = (CPlaneBasis *) (_PlaneBasisScheme->make(_Owner, size - leftToDo, &planeBasis[0], sizeof(CPlaneBasis), toProcess, true));                    
+00355                 }
+00356                 else
+00357                 {
+00358                         ptBasis = &_PlaneBasis;
+00359                 }
+00360 
+00361                 endPosIt = posIt + toProcess;           
+00362                 CMatrix mat, tmat;              
+00363 
+00364                 // the matrix used to get in the right basis
+00365                 const CMatrix &transfo = _Owner->isInSystemBasis() ? /*_Owner->getOwner()->*/getSysMat() : CMatrix::Identity;
+00366                 do
+00367                 {
+00368                         (*instanceIt)->show();
+00369 
+00370                         tmat.identity();
+00371                         mat.identity();
+00372 
+00373                         tmat.translate(*posIt);
+00374 
+00375                         
+00376 
+00377                         mat.setRot( ptBasis->X * CPSUtil::getCos((sint32) *ptCurrAngle) + ptBasis->Y * CPSUtil::getSin((sint32) *ptCurrAngle)
+00378                                                 , ptBasis->X * CPSUtil::getCos((sint32) *ptCurrAngle + 64) + ptBasis->Y * CPSUtil::getSin((sint32) *ptCurrAngle + 64)
+00379                                                 , ptBasis->X ^ ptBasis->Y
+00380                                           );
+00381 
+00382                         mat.scale(*ptCurrSize);                 
+00383                         
+00384                         (*instanceIt)->setMatrix(transfo * tmat * mat);                 
+00385 
+00386                         ++instanceIt;
+00387                         ++posIt;
+00388                         ptCurrSize += ptCurrSizeIncrement;
+00389                         ptCurrAngle += ptCurrAngleIncrement;
+00390                         ptBasis += ptCurrPlaneBasisIncrement;
+00391                 }
+00392                 while (posIt != endPosIt);
+00393                 leftToDo -= toProcess;
+00394         }
+00395         while (leftToDo);
+00396 
+00397         PARTICLES_CHECK_MEM;
+00398 }
+00399 
+00400 //====================================================================================
+00401 void CPSMesh::resize(uint32 size)
+00402 {
+00403         nlassert(size < (1 << 16));
+00404         resizeSize(size);
+00405         resizeAngle2D(size);
+00406         resizePlaneBasis(size);
+00407         _Instances.resize(size);
+00408 }
+00409 
+00410 
+00411 //====================================================================================
+00412 CPSMesh::~CPSMesh()
+00413 {       
+00414         if (_Owner && _Owner->getOwner())
+00415         {       
+00416                 CScene *scene = _Owner->getScene();
+00417                 nlassert(scene); // the setScene method of the particle system should have been called
+00418 
+00419                 for (TInstanceCont::iterator it = _Instances.begin(); it != _Instances.end(); ++it)
+00420                 {
+00421                         scene->deleteInstance(*it);
+00422                 }
+00423         }
+00424 }
+00425 
+00427 // CPSConstraintMesh implementation //
+00429 
+00431 static uint getMeshNumTri(const CMesh &m)
+00432 {       
+00433         uint numFaces = 0;
+00434         for (uint k = 0; k < m.getNbMatrixBlock(); ++k)
+00435         {
+00436                 for (uint l = 0; l  < m.getNbRdrPass(k); ++l)
+00437                 {
+00438                         const CPrimitiveBlock pb = m.getRdrPassPrimitiveBlock(k, l);
+00439                         numFaces += (pb.getNumLine() << 1) + pb.getNumTri() + (pb.getNumQuad() << 1);
+00440 
+00441                 }
+00442         }
+00443         return numFaces;
+00444 }
+00445 
+00446 
+00447 //====================================================================================
+00449 static void CheckForOpaqueAndTransparentFacesInMesh(const CMesh &m, bool &hasTransparentFaces, bool &hasOpaqueFaces)
+00450 {
+00451         hasTransparentFaces = false;
+00452         hasOpaqueFaces = false;
+00453         
+00454         for (uint k = 0; k < m.getNbRdrPass(0); ++k)
+00455         {
+00456                 const CMaterial &currMat = m.getMaterial(m.getRdrPassMaterial(0, k));
+00457                 if (!currMat.getZWrite())
+00458                 {
+00459                         hasTransparentFaces = true;
+00460                 }
+00461                 else // z-buffer write or no blending -> the face is opaque
+00462                 {
+00463                         hasOpaqueFaces = true;
+00464                 }
+00465         }        
+00466 }
+00467 
+00468 
+00469 
+00475 class CPSConstraintMeshHelper
+00476 {
+00477 public:
+00478         template <class T>      
+00479         static void drawMeshs(T posIt, CPSConstraintMesh &m, uint size, uint32 srcStep, bool opaque)
+00480         {
+00481                 CMesh                             &mesh = * NLMISC::safe_cast<CMesh *>((IShape *) m._Shapes[0]);        
+00482                 const CVertexBuffer   &modelVb = mesh.getVertexBuffer();
+00483 
+00484                 // size for model vertices
+00485                 const uint inVSize        = modelVb.getVertexSize(); // vertex size                             
+00486 
+00487                 // driver setup
+00488                 IDriver *driver = m.getDriver();
+00489                 m.setupDriverModelMatrix();     
+00490 
+00491                 // buffer to compute sizes
+00492                 float                   sizes[ConstraintMeshBufSize];
+00493                 
+00494                 float *ptCurrSize;
+00495                 uint ptCurrSizeIncrement = m._SizeScheme ? 1 : 0;
+00496 
+00497                 T endPosIt;
+00498                 uint leftToDo = size, toProcess;                        
+00499                 
+00501                 CPSConstraintMesh::CMeshDisplay  &md= m._MeshDisplayShare.getMeshDisplay(m._Shapes[0], modelVb.getVertexFormat() 
+00502                                                                                                                                 | (m._ColorScheme ? CVertexBuffer::PrimaryColorFlag : 0));
+00503 
+00504                 m.setupRenderPasses((float) m._Owner->getOwner()->getSystemDate() - m._GlobalAnimDate, md.RdrPasses, opaque);
+00505 
+00506                 CVertexBuffer &outVb = md.VB;
+00507                 const uint outVSize = outVb.getVertexSize();
+00508                 
+00509                 driver->activeVertexBuffer(outVb);      
+00510 
+00511                 // we don't have precomputed mesh there ... so each mesh must be transformed, which is the worst case   
+00512                 CPlaneBasis planeBasis[ConstraintMeshBufSize];
+00513                 CPlaneBasis *ptBasis;
+00514                 uint ptBasisIncrement = m._PlaneBasisScheme ? 1 : 0;
+00515 
+00516                 const uint nbVerticesInSource   = modelVb.getNumVertices();
+00517 
+00518                 sint inNormalOff=0;
+00519                 sint outNormalOff=0;
+00520                 if (modelVb.getVertexFormat() & CVertexBuffer::NormalFlag)
+00521                 {       
+00522                         inNormalOff  =  modelVb.getNormalOff();
+00523                         outNormalOff =  outVb.getNormalOff();   
+00524                 }
+00525                 
+00526                 do
+00527                 {
+00528                         uint8 *outVertex = (uint8 *) outVb.getVertexCoordPointer();             
+00529 
+00530                         toProcess = std::min(leftToDo, ConstraintMeshBufSize);
+00531 
+00532                         if (m._SizeScheme)
+00533                         {
+00534                                 ptCurrSize  = (float *) (m._SizeScheme->make(m._Owner, size -leftToDo, &sizes[0], sizeof(float), toProcess, true, srcStep));                            
+00535                         }
+00536                         else
+00537                         {
+00538                                 ptCurrSize = &m._ParticleSize;
+00539                         }
+00540 
+00541                         if (m._PlaneBasisScheme)
+00542                         {
+00543                                 ptBasis = (CPlaneBasis *) (m._PlaneBasisScheme->make(m._Owner, size -leftToDo, &planeBasis[0], sizeof(CPlaneBasis), toProcess, true, srcStep));
+00544                         }
+00545                         else
+00546                         {
+00547                                 ptBasis = &m._PlaneBasis;
+00548                         }
+00549                         
+00550 
+00551                         endPosIt = posIt + toProcess;
+00552                         // transfo matrix & scaled transfo matrix;
+00553                         CMatrix  M, sM;
+00554 
+00555                 
+00556                         if (m._Shapes.size() == 1)
+00557                         {
+00559                                 do
+00560                                 {
+00561 
+00562                                         uint8 *inVertex = (uint8 *) modelVb.getVertexCoordPointer();
+00563                                         uint k = nbVerticesInSource;
+00564 
+00565                                         // do we need a normal ?
+00566                                         if (modelVb.getVertexFormat() & CVertexBuffer::NormalFlag)
+00567                                         {
+00568                                                 M.identity();
+00569                                                 M.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
+00570                                                 sM = M;
+00571                                                 sM.scale(*ptCurrSize);
+00572 
+00573                                                 // offset of normals in the prerotated mesh                             
+00574                                                 do
+00575                                                 {
+00576                                                         CHECK_VERTEX_BUFFER(modelVb, inVertex); 
+00577                                                         CHECK_VERTEX_BUFFER(outVb,        outVertex);   
+00578                                                         CHECK_VERTEX_BUFFER(modelVb, inVertex + inNormalOff);   
+00579                                                         CHECK_VERTEX_BUFFER(outVb,        outVertex + outNormalOff);    
+00580 
+00581                                                         // translate and resize the vertex (relatively to the mesh origin)
+00582                                                         *(CVector *) outVertex = *posIt + sM * *(CVector *) inVertex;                                                                           
+00583                                                         // copy the normal
+00584                                                         *(CVector *) (outVertex + outNormalOff) = M * *(CVector *) (inVertex + inNormalOff);
+00585                                                         
+00586 
+00587                                                         inVertex  += inVSize;
+00588                                                         outVertex += outVSize;
+00589                                                 }
+00590                                                 while (--k);
+00591                                         }
+00592                                         else
+00593                                         {
+00594                                                 // no normal to transform
+00595                                                 sM.identity();
+00596                                                 sM.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
+00597                                                 sM.scale(*ptCurrSize);
+00598 
+00599                                                 do
+00600                                                 {
+00601                                                         CHECK_VERTEX_BUFFER(modelVb, inVertex);
+00602                                                         CHECK_VERTEX_BUFFER(outVb, outVertex);
+00603 
+00604                                                         // translate and resize the vertex (relatively to the mesh origin)
+00605                                                         *(CVector *) outVertex = *posIt + sM * *(CVector *) inVertex;                           
+00606 
+00607                                                         inVertex  += inVSize;
+00608                                                         outVertex += outVSize;
+00609                                                 }
+00610                                                 while (--k);
+00611                                         }
+00612 
+00613                                         
+00614                                         ++posIt;
+00615                                         ptCurrSize += ptCurrSizeIncrement;
+00616                                         ptBasis += ptBasisIncrement;
+00617                                 }
+00618                                 while (posIt != endPosIt);
+00619                         }
+00620                         else
+00621                         {
+00622                                 // morphed case
+00623                                 
+00624                                 // first, compute the morph value for each mesh
+00625                                 float   morphValues[ConstraintMeshBufSize];
+00626                                 float   *currMorphValue;
+00627                                 uint    morphValueIncr;
+00628 
+00629                                 if (m._MorphScheme) // variable case
+00630                                 {
+00631                                         currMorphValue = (float *) m._MorphScheme->make(m._Owner, size - leftToDo, &morphValues[0], sizeof(float), toProcess, true, srcStep);
+00632                                         morphValueIncr  = 1;
+00633                                 }
+00634                                 else 
+00635                                 {
+00636                                         currMorphValue = &m._MorphValue;
+00637                                         morphValueIncr  = 0;
+00638                                 }
+00639 
+00640                                 do
+00641                                 {
+00642                                         const uint numShapes = m._Shapes.size();
+00643                                         const uint8 *m0, *m1;
+00644                                         float lambda;
+00645                                         float opLambda;
+00646                                         const CVertexBuffer *inVB0, *inVB1;
+00647                                         if (*currMorphValue >= numShapes - 1)
+00648                                         {
+00649                                                 lambda = 0.f;
+00650                                                 opLambda = 1.f;
+00651                                                 inVB0 = inVB1 = &NLMISC::safe_cast<CMesh *>((IShape *) m._Shapes[numShapes - 1])->getVertexBuffer();
+00652                                         }
+00653                                         else if (*currMorphValue <= 0)
+00654                                         {
+00655                                                 lambda = 0.f;
+00656                                                 opLambda = 1.f;
+00657                                                 inVB0 = inVB1 = &NLMISC::safe_cast<CMesh *>((IShape *) m._Shapes[0])->getVertexBuffer();
+00658                                         }
+00659                                         else
+00660                                         {
+00661                                                 uint iMeshIndex = (uint) *currMorphValue;
+00662                                                 lambda = *currMorphValue - iMeshIndex;
+00663                                                 opLambda = 1.f - lambda;
+00664                                                 inVB0 = &NLMISC::safe_cast<CMesh *>((IShape *) m._Shapes[iMeshIndex])->getVertexBuffer();
+00665                                                 inVB1 = &NLMISC::safe_cast<CMesh *>((IShape *) m._Shapes[iMeshIndex + 1])->getVertexBuffer();
+00666                                         }
+00667 
+00668                                         m0 = (uint8 *) inVB0->getVertexCoordPointer();
+00669                                         m1 = (uint8 *) inVB1->getVertexCoordPointer();
+00670 
+00671                                                         
+00672                                         uint k = nbVerticesInSource;
+00673                                         // do we need a normal ?
+00674                                         if (modelVb.getVertexFormat() & CVertexBuffer::NormalFlag)
+00675                                         {
+00676                                                 M.identity();
+00677                                                 M.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
+00678                                                 sM = M;
+00679                                                 sM.scale(*ptCurrSize);
+00680 
+00681                                                 // offset of normals in the prerotated mesh                             
+00682                                                 do
+00683                                                 {
+00684                                                         CHECK_VERTEX_BUFFER((*inVB0),     m0);                                                  
+00685                                                         CHECK_VERTEX_BUFFER((*inVB1),     m1);  
+00686                                                         CHECK_VERTEX_BUFFER((*inVB0),     m0 + inNormalOff);                    
+00687                                                         CHECK_VERTEX_BUFFER((*inVB1),     m1 + inNormalOff);
+00688                                                         CHECK_VERTEX_BUFFER(outVb,        outVertex);                                                   
+00689                                                         CHECK_VERTEX_BUFFER(outVb,        outVertex + outNormalOff);    
+00690 
+00691                                                         // morph, and transform the vertex
+00692                                                         *(CVector *) outVertex = *posIt + sM * (opLambda * *(CVector *) m0 + lambda * *(CVector *) m1);
+00693                                                         // morph, and transform the normal
+00694                                                         *(CVector *) (outVertex + outNormalOff) = M * (opLambda * *(CVector *) (m0 + inNormalOff)
+00695                                                                                                                                                   + lambda * *(CVector *) (m1 + inNormalOff)).normed();
+00696                                                         
+00697 
+00698                                                         m0  += inVSize;
+00699                                                         m1  += inVSize;
+00700                                                         outVertex += outVSize;
+00701                                                 }
+00702                                                 while (--k);
+00703                                         }
+00704                                         else
+00705                                         {
+00706                                                 // no normal to transform
+00707                                                 sM.identity();
+00708                                                 sM.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
+00709                                                 sM.scale(*ptCurrSize);
+00710 
+00711                                                 do
+00712                                                 {                       
+00713                                                         CHECK_VERTEX_BUFFER((*inVB0),     m0);                                                  
+00714                                                         CHECK_VERTEX_BUFFER((*inVB1),     m1);          
+00715                                                         CHECK_VERTEX_BUFFER(outVb, outVertex);
+00716                                                         // morph, and transform the vertex
+00717                                                         *(CVector *) outVertex = *posIt + sM * (opLambda * *(CVector *) m0 + opLambda * *(CVector *) m1);
+00718 
+00719                                                         m0  += inVSize;
+00720                                                         m1  += inVSize;
+00721                                                         outVertex += outVSize;
+00722                                                 }
+00723                                                 while (--k);
+00724                                         }
+00725 
+00726                                         
+00727                                         ++posIt;
+00728                                         ptCurrSize += ptCurrSizeIncrement;
+00729                                         ptBasis += ptBasisIncrement;
+00730                                         currMorphValue += morphValueIncr;
+00731                                 }
+00732                                 while (posIt != endPosIt);
+00733                         }               
+00734 
+00735                         // compute colors if needed
+00736                         if (m._ColorScheme)
+00737                         {
+00738                                 m.computeColors(outVb, modelVb, size - leftToDo, toProcess, srcStep);
+00739                         }
+00740                         
+00741                         // render meshs
+00742                         m.doRenderPasses(driver, toProcess, md.RdrPasses, opaque);
+00743                         leftToDo -= toProcess;
+00744 
+00745                 }
+00746                 while (leftToDo);
+00747         }
+00748 
+00749 
+00750         template <class T, class U>     
+00751         static void drawPrerotatedMeshs(T posIt,
+00752                                                                     U indexIt,
+00753                                                                         CPSConstraintMesh &m,
+00754                                                                         uint size,
+00755                                                                         uint32 srcStep,
+00756                                                                         bool opaque,
+00757                                                                         TAnimationTime ellapsedTime)
+00758         {
+00759                 // get the vb from the original mesh
+00760                 CMesh                             &mesh = * NLMISC::safe_cast<CMesh *>((IShape *) m._Shapes[0]);        
+00761                 const CVertexBuffer   &modelVb = mesh.getVertexBuffer();
+00762 
+00764                 CVertexBuffer &prerotVb  = m.makePrerotatedVb(modelVb, ellapsedTime);   
+00765 
+00766                 // driver setup
+00767                 IDriver *driver = m.getDriver();
+00768                 m.setupDriverModelMatrix();     
+00769 
+00770                 // renderPasses setup
+00771                 nlassert(m._Owner)      
+00772 
+00773                 // storage for sizes of meshs
+00774                 float sizes[ConstraintMeshBufSize];
+00775                 
+00776                 // point the size for the current mesh
+00777                 float *ptCurrSize;
+00778                 uint ptCurrSizeIncrement = m._SizeScheme ? 1 : 0;
+00779 
+00780                 T endPosIt;
+00781                 uint leftToDo = size, toProcess;
+00782                 const uint nbVerticesInSource = modelVb.getNumVertices();
+00783                 
+00784 
+00785 
+00786                 // size of a complete prerotated model
+00787                 const uint prerotatedModelSize = prerotVb.getVertexSize() * modelVb.getNumVertices();
+00788 
+00790                 CPSConstraintMesh::CMeshDisplay  &md    = m._MeshDisplayShare.getMeshDisplay(m._Shapes[0], modelVb.getVertexFormat() 
+00791                                                                                                                                 | (m._ColorScheme ? CVertexBuffer::PrimaryColorFlag : 0));
+00792 
+00793 
+00794                 m.setupRenderPasses((float) m._Owner->getOwner()->getSystemDate() - m._GlobalAnimDate, md.RdrPasses, opaque);
+00795 
+00796                 CVertexBuffer &outVb = md.VB;
+00797 
+00798                 driver->activeVertexBuffer(outVb);
+00799 
+00800 
+00801                 // size of vertices in prerotated model
+00802                 const uint inVSize = prerotVb.getVertexSize();
+00803 
+00804                 // size ofr vertices in dest vb
+00805                 const uint outVSize = outVb.getVertexSize();
+00806 
+00807                 // offset of normals in vertices of the prerotated model, and source model              
+00808                 uint normalOff=0;
+00809                 uint pNormalOff=0;
+00810                 if (prerotVb.getVertexFormat() & CVertexBuffer::NormalFlag) 
+00811                 {
+00812                         normalOff  =  outVb.getNormalOff();
+00813                         pNormalOff =  prerotVb.getNormalOff();                  
+00814                 }
+00815                                         
+00816                 do
+00817                 {                       
+00818                         toProcess = std::min(leftToDo, ConstraintMeshBufSize);
+00819 
+00820                         if (m._SizeScheme)
+00821                         {
+00822                                 // compute size
+00823                                 ptCurrSize = (float *) (m._SizeScheme->make(m._Owner, size - leftToDo, &sizes[0], sizeof(float), toProcess, true, srcStep));                            
+00824                         }
+00825                         else
+00826                         {
+00827                                 // pointer on constant size
+00828                                 ptCurrSize = &m._ParticleSize;
+00829                         }
+00830 
+00831                         endPosIt = posIt + toProcess;
+00832                         uint8 *outVertex  = (uint8 *) outVb.getVertexCoordPointer();
+00834                         do
+00835                         {
+00836                                 uint8 *inVertex = (uint8 *) prerotVb.getVertexCoordPointer() + prerotatedModelSize * *indexIt; // prerotated vertex                     
+00837                                 uint k = nbVerticesInSource;
+00838                                 
+00839                                 if (prerotVb.getVertexFormat() & CVertexBuffer::NormalFlag) // has it a normal ?
+00840                                 {
+00841                                         do
+00842                                         {
+00843                                                 CHECK_VERTEX_BUFFER(outVb, outVertex);
+00844                                                 CHECK_VERTEX_BUFFER(prerotVb, inVertex);
+00845                                                 CHECK_VERTEX_BUFFER(outVb, outVertex + normalOff);
+00846                                                 CHECK_VERTEX_BUFFER(prerotVb, inVertex + pNormalOff);
+00847 
+00848 
+00849                                                 // translate and resize the vertex (relatively to the mesh origin)
+00850                                                 *(CVector *)  outVertex                                          = *posIt + *ptCurrSize * *(CVector *) inVertex;
+00851                                                 // copy the normal
+00852                                                 *(CVector *)  (outVertex + normalOff ) = *(CVector *) (inVertex + pNormalOff);
+00853                                                 inVertex  += inVSize;
+00854                                                 outVertex += outVSize;
+00855                                         }
+00856                                         while (--k);
+00857                                 }
+00858                                 else
+00859                                 {
+00860                                         do
+00861                                         {                                       
+00862                                                 // translate and resize the vertex (relatively to the mesh origin)
+00863                                                 CHECK_VERTEX_BUFFER(outVb, outVertex);
+00864                                                 CHECK_VERTEX_BUFFER(prerotVb, inVertex);
+00865                                                 *(CVector *)  outVertex = *posIt + *ptCurrSize * *(CVector *) inVertex;                                                                                                 
+00866                                                 inVertex  += inVSize;
+00867                                                 outVertex += outVSize;
+00868                                         }
+00869                                         while (--k);
+00870                                 }
+00871                                 
+00872                                 ++indexIt;
+00873                                 ++posIt;
+00874                                 ptCurrSize += ptCurrSizeIncrement;
+00875                         }
+00876                         while (posIt != endPosIt);
+00877 
+00878                         // compute colors if needed
+00879                         if (m._ColorScheme)
+00880                         {
+00881                                 m.computeColors(outVb, modelVb, size - leftToDo, toProcess, srcStep);
+00882                         }
+00883                                         
+00884 
+00886                         m.doRenderPasses(driver, toProcess, md.RdrPasses, opaque);
+00887                         leftToDo -= toProcess;
+00888 
+00889                 }
+00890                 while (leftToDo);
+00891                 PARTICLES_CHECK_MEM
+00892         }
+00893 };
+00894 
+00895 CPSConstraintMesh::CPSConstraintMesh() : _NumFaces(0),
+00896                                                                                  _ModelBank(NULL),
+00897                                                                                  _ModulatedStages(0),
+00898                                                                                  _Touched(1),
+00899                                                                                  _VertexColorLightingForced(false),
+00900                                                                                  _GlobalAnimationEnabled(0),
+00901                                                                                  _ReinitGlobalAnimTimeOnNewElement(0),
+00902                                                                                  _MorphValue(0),
+00903                                                                                  _MorphScheme(NULL)
+00904 {               
+00905         _Name = std::string("ConstraintMesh");
+00906 }
+00907 
+00908 //====================================================================================
+00909 uint32 CPSConstraintMesh::getMaxNumFaces(void) const
+00910 {
+00911 //      nlassert(_ModelVb);
+00912         return _NumFaces * _Owner->getMaxSize();
+00913         
+00914 }
+00915 
+00916 
+00917 //====================================================================================
+00918 bool CPSConstraintMesh::hasTransparentFaces(void)
+00919 {
+00920         if (!_Touched) return _HasTransparentFaces != 0;
+00922         update();
+00923         return _HasTransparentFaces != 0;
+00924 }
+00925 
+00926 //====================================================================================
+00927 bool CPSConstraintMesh::hasOpaqueFaces(void)
+00928 {
+00929         if (!_Touched) return _HasOpaqueFaces != 0;     
+00930         update();
+00931         return _HasOpaqueFaces != 0;
+00932 }
+00933 
+00934 //====================================================================================
+00935 void CPSConstraintMesh::setShape(const std::string &meshFileName)
+00936 {       
+00937         _MeshShapeFileName.resize(1);   
+00938         _MeshShapeFileName[0] = meshFileName;
+00939         _Touched = 1;
+00940 }
+00941 
+00942 
+00943 //===========================================================================
+00944 std::string                     CPSConstraintMesh::getShape(void) const
+00945 {
+00946         nlassert(_MeshShapeFileName.size() == 1);
+00947         return _MeshShapeFileName[0];
+00948 }
+00949 
+00950 //====================================================================================
+00951 void            CPSConstraintMesh::setShapes(const std::string *shapesNames, uint numShapes)
+00952 {
+00953         _MeshShapeFileName.resize(numShapes);
+00954         std::copy(shapesNames, shapesNames + numShapes, _MeshShapeFileName.begin());
+00955         _Touched = 1;
+00956 }
+00957 
+00958 //====================================================================================
+00959 uint        CPSConstraintMesh::getNumShapes() const
+00960 {
+00961         return _MeshShapeFileName.size();
+00962 }
+00963 
+00964 //====================================================================================
+00965 void    CPSConstraintMesh::getShapesNames(std::string *shapesNames) const
+00966 {
+00967         std::copy(_MeshShapeFileName.begin(), _MeshShapeFileName.end(), shapesNames);
+00968 }
+00969 
+00970 
+00971 
+00972 //====================================================================================
+00973 void            CPSConstraintMesh::setShape(uint index, const std::string &shapeName)
+00974 {
+00975         nlassert(index < _MeshShapeFileName.size());
+00976         _MeshShapeFileName[index] = shapeName;
+00977         _Touched = 1;
+00978 }
+00979 
+00980         
+00981 //====================================================================================
+00982 const std::string          &CPSConstraintMesh::getShape(uint index) const
+00983 {
+00984         nlassert(index < _MeshShapeFileName.size());
+00985         return _MeshShapeFileName[index];
+00986 }
+00987 
+00988 
+00989 
+00990 //====================================================================================
+00991 void    CPSConstraintMesh::setMorphValue(float value)
+00992 {
+00993         delete _MorphScheme;
+00994         _MorphScheme = NULL;
+00995         _MorphValue = value;
+00996 }
+00997 
+00998 
+00999 //====================================================================================
+01000 float   CPSConstraintMesh::getMorphValue() const
+01001 {
+01002         return _MorphValue;
+01003 }
+01004 
+01005 //====================================================================================
+01006 void    CPSConstraintMesh::setMorphScheme(CPSAttribMaker<float> *scheme)
+01007 {
+01008         delete _MorphScheme;
+01009         _MorphScheme = scheme;
+01010         if (_MorphScheme->hasMemory()) _MorphScheme->resize(_Owner->getMaxSize(), _Owner->getSize());
+01011 }
+01012 
+01013 //====================================================================================
+01014 CPSAttribMaker<float>           *CPSConstraintMesh::getMorphScheme()
+01015 {
+01016         return _MorphScheme;
+01017 }
+01018 
+01019 //====================================================================================
+01020 const CPSAttribMaker<float>     *CPSConstraintMesh::getMorphScheme() const
+01021 {
+01022         return _MorphScheme;
+01023 }
+01024 
+01025 
+01026 //====================================================================================
+01027 static IShape *GetDummyShapeFromBank(CShapeBank &sb)
+01028 {       
+01029         static const std::string dummyMeshName("dummy constraint mesh shape");
+01030         if (sb.isPresent(dummyMeshName) == CShapeBank::Present)
+01031         {                               
+01032                 return sb.addRef(dummyMeshName);
+01033         }
+01034         else
+01035         {
+01036                 // no dummy shape created -> add one to the bank
+01037                 IShape *is = CreateDummyShape();
+01038                 sb.add(std::string("dummy constraint mesh shape"), is);
+01039                 return is;
+01040         }
+01041 }
+01042 
+01043 //====================================================================================
+01044 bool CPSConstraintMesh::update(void)
+01045 {               
+01046         bool ok = true;
+01047         if (!_Touched) return ok;
+01048 
+01049         clean();
+01050         
+01051         nlassert(_Owner->getScene());
+01052 
+01053         CScene *scene = _Owner->getScene();
+01054         CShapeBank *sb = scene->getShapeBank();
+01055         IShape *is;
+01056 
+01057 
+01058         uint32 vFormat=0;
+01059         uint   numVerts=0;      
+01060 
+01061         if (_MeshShapeFileName.size() == 0)
+01062         {
+01063                 _MeshShapeFileName.resize(1);
+01064                 _MeshShapeFileName[0] = DummyShapeName;         
+01065         }
+01066         
+01067 
+01068         _Shapes.resize(_MeshShapeFileName.size());      
+01069         for (uint k = 0; k < _MeshShapeFileName.size(); ++k)
+01070         {
+01071                 if (sb->isPresent(_MeshShapeFileName[k]) == CShapeBank::Present)
+01072                 {
+01073                         _Shapes[k] = sb->addRef(_MeshShapeFileName[k]);
+01074 
+01076                         const CMesh &m  = * NLMISC::safe_cast<CMesh *>((IShape *) _Shapes[k]); // only mesh shape's can be used with this class!
+01077                         if (k == 0)
+01078                         {                       
+01079                                 vFormat = m.getVertexBuffer().getVertexFormat();
+01080                                 numVerts =  m.getVertexBuffer().getNumVertices();
+01081                         }
+01082                         else
+01083                         {
+01084                                 if (vFormat != m.getVertexBuffer().getVertexFormat()
+01085                                         || numVerts != m.getVertexBuffer().getNumVertices())
+01086                                 {
+01087                                         ok = false;
+01088                                 }
+01089                         }
+01090                 }
+01091                 else
+01092                 {
+01093                         try
+01094                         {
+01095                                 sb->load(_MeshShapeFileName[k]);
+01096                         }       
+01097                         catch (NLMISC::EPathNotFound &)
+01098                         {
+01099                                 nlwarning("mesh not found : %s; used as a constraint mesh particle", _MeshShapeFileName[k].c_str());
+01100                                 // shape not found, so not present in the shape bank -> we create a dummy shape
+01101                         }
+01102 
+01103                         if (sb->isPresent(_MeshShapeFileName[k]) != CShapeBank::Present)
+01104                         {                                       
+01105                                 ok = false;
+01106                         }
+01107                         else
+01108                         {
+01109                                 is = sb->addRef(_MeshShapeFileName[k]);
+01110                                 if (!dynamic_cast<CMesh *>(is)) // is it a mesh
+01111                                 {
+01112                                         nlwarning("Tried to bind a shape that is not a mesh to a mesh particle : %s", _MeshShapeFileName[k].c_str());
+01113                                         sb->release(is);                                        
+01114                                         ok = false;
+01115                                 }
+01116                                 else
+01117                                 {
+01118                                         const CMesh &m  = * NLMISC::safe_cast<CMesh *>(is);
+01120                                         if (m.getVertexBuffer().getNumVertices() > ConstraintMeshMaxNumVerts)
+01121                                         {
+01122                                                 nlwarning("Tried to bind a mesh that has more than %d vertices to a particle mesh: %s", (int) ConstraintMeshMaxNumVerts, _MeshShapeFileName[k].c_str());
+01123                                                 sb->release(is);                                                
+01124                                                 ok = false;
+01125                                         }
+01126                                         else
+01127                                         {
+01128                                                 _Shapes[k] = is;
+01130                                                 const CMesh &m  = * NLMISC::safe_cast<CMesh *>((IShape *) _Shapes[k]); // only mesh shape's can be used with this class!
+01131                                                 if (k == 0)
+01132                                                 {                       
+01133                                                         vFormat = m.getVertexBuffer().getVertexFormat();
+01134                                                         numVerts =  m.getVertexBuffer().getNumVertices();
+01135                                                 }
+01136                                                 else
+01137                                                 {
+01138                                                         if (vFormat != m.getVertexBuffer().getVertexFormat()
+01139                                                                 || numVerts != m.getVertexBuffer().getNumVertices())
+01140                                                         {
+01141                                                                 ok = false;
+01142                                                         }
+01143                                                 }
+01144                                         }
+01145                                 }
+01146                         }
+01147                 }
+01148                 
+01149                 if (!ok)
+01150                 {
+01151                         releaseShapes();
+01152                         _Shapes.resize(1);
+01153                         _Shapes[0] = GetDummyShapeFromBank(*sb);
+01154                         break;
+01155                 }
+01156         }
+01157 
+01158 
+01159         const CMesh &m  = * NLMISC::safe_cast<CMesh *>((IShape *) _Shapes[0]); // only mesh shape's can be used with this class!
+01160 
+01162         _NumFaces = getMeshNumTri(m);
+01163         notifyOwnerMaxNumFacesChanged();
+01164         
+01166         bool hasTransparentFaces, hasOpaqueFaces;
+01167         CheckForOpaqueAndTransparentFacesInMesh(m, hasTransparentFaces, hasOpaqueFaces);
+01168         _HasTransparentFaces = hasTransparentFaces;     
+01169         _HasOpaqueFaces = hasOpaqueFaces;
+01170         _ModelBank = sb;        
+01171         _GlobalAnimDate = _Owner->getOwner()->getSystemDate();
+01172         _Touched = 0;
+01173         nlassert(_Shapes.size() > 0);
+01174 
+01175         #ifdef NL_DEBUG
+01176                 for (uint j = 0; j < _Shapes.size(); ++j)
+01177                 {
+01178                         nlassert(dynamic_cast<CMesh *>((IShape *) _Shapes[j]));
+01179                 }
+01180         #endif
+01181 
+01182         return ok;
+01183         
+01184 }
+01185 
+01186 
+01187 
+01188 //====================================================================================
+01189 void CPSConstraintMesh::hintRotateTheSame(uint32 nbConfiguration,
+01190                                                                                   float minAngularVelocity,
+01191                                                                                   float maxAngularVelocity
+01192                                                                                 )
+01193 {
+01194         nlassert(nbConfiguration <= ConstraintMeshMaxNumPrerotatedModels);
+01195 
+01196         // TODO : avoid code duplication with CPSFace ...
+01197         _MinAngularVelocity = minAngularVelocity;
+01198         _MaxAngularVelocity = maxAngularVelocity;
+01199 
+01200 
+01201 
+01202         _PrecompBasis.resize(nbConfiguration);
+01203 
+01204         if (nbConfiguration)
+01205         {
+01206                 // each precomp basis is created randomly;
+01207                 for (uint k = 0; k < nbConfiguration; ++k)
+01208                 {
+01209                          CVector v = MakeRandomUnitVect();
+01210                         _PrecompBasis[k].Basis = CPlaneBasis(v);
+01211                         _PrecompBasis[k].Axis = MakeRandomUnitVect();
+01212                         _PrecompBasis[k].AngularVelocity = minAngularVelocity 
+01213                                                                                            + (rand() % 20000) / 20000.f * (maxAngularVelocity - minAngularVelocity);
+01214 
+01215                 }       
+01216 
+01217                 // we need to do this because nbConfs may have changed
+01218                 fillIndexesInPrecompBasis();
+01219         }       
+01220 }
+01221 
+01222 
+01223 //====================================================================================
+01224 void CPSConstraintMesh::fillIndexesInPrecompBasis(void)
+01225 {
+01226         // TODO : avoid code duplication with CPSFace ...
+01227         const uint32 nbConf = _PrecompBasis.size();
+01228         if (_Owner)
+01229         {
+01230                 _IndexInPrecompBasis.resize( _Owner->getMaxSize() );
+01231         }       
+01232         for (std::vector<uint32>::iterator it = _IndexInPrecompBasis.begin(); it != _IndexInPrecompBasis.end(); ++it)
+01233         {
+01234                 *it = rand() % nbConf;
+01235         }
+01236 }
+01237 
+01238 //====================================================================================  
+01240 void CPSConstraintMesh::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01241 {
+01242 
+01243         sint ver = f.serialVersion(4);
+01244         if (f.isReading())
+01245         {
+01246                 clean();
+01247         }
+01248 
+01249         CPSParticle::serial(f);
+01250         CPSSizedParticle::serialSizeScheme(f);
+01251         CPSRotated3DPlaneParticle::serialPlaneBasisScheme(f);
+01252 
+01253         // prerotations ...
+01254 
+01255         if (f.isReading())
+01256         {
+01257                 uint32 nbConfigurations;
+01258                 f.serial(nbConfigurations);
+01259                 if (nbConfigurations)
+01260                 {
+01261                         f.serial(_MinAngularVelocity, _MaxAngularVelocity);             
+01262                 }
+01263                 hintRotateTheSame(nbConfigurations, _MinAngularVelocity, _MaxAngularVelocity);  
+01264         }
+01265         else    
+01266         {                               
+01267                 uint32 nbConfigurations = _PrecompBasis.size();
+01268                 f.serial(nbConfigurations);
+01269                 if (nbConfigurations)
+01270                 {
+01271                         f.serial(_MinAngularVelocity, _MaxAngularVelocity);             
+01272                 }
+01273         }
+01274 
+01275         // saves the model file name, or an empty string if nothing has been set        
+01276         static std::string emptyStr;
+01277 
+01278         if (ver < 4) // early version : no morphing support
+01279         {
+01280                 if (!f.isReading())
+01281                 {
+01282                         if (_MeshShapeFileName.size() > 0)
+01283                         {
+01284                                 f.serial(_MeshShapeFileName[0]);                        
+01285                         }
+01286                         else
+01287                         {
+01288                                 f.serial(emptyStr); 
+01289                         }
+01290                 }
+01291                 else
+01292                 {       
+01293                         _MeshShapeFileName.resize(1);                           
+01294                         f.serial(_MeshShapeFileName[0]);
+01295                         _Touched = true;                        
+01296                 }
+01297         }
+01298 
+01299         if (ver > 1)
+01300         {
+01301                 CPSColoredParticle::serialColorScheme(f);
+01302                 f.serial(_ModulatedStages);
+01303                 if (f.isReading())
+01304                 {
+01305                         bool vcEnabled;
+01306                         f.serial(vcEnabled);
+01307                         _VertexColorLightingForced = vcEnabled;
+01308                 }
+01309                 else
+01310                 {
+01311                         bool vcEnabled = (_VertexColorLightingForced != 0);
+01312                         f.serial(vcEnabled);
+01313                 }                                               
+01314         }
+01315 
+01316         if (ver > 2) // texture animation
+01317         {
+01318                 if (f.isReading())
+01319                 {
+01320                         bool gaEnabled;
+01321                         f.serial(gaEnabled);
+01322                         _GlobalAnimationEnabled = gaEnabled;
+01323                         if (gaEnabled)
+01324                         {
+01325                                 PGlobalTexAnims newPtr(new CGlobalTexAnims); // create new
+01326                                 std::swap(_GlobalTexAnims, newPtr);                      // replace old
+01327                                 f.serial(*_GlobalTexAnims);
+01328                         }
+01329 
+01330                         bool rgt;
+01331                         f.serial(rgt);
+01332                         _ReinitGlobalAnimTimeOnNewElement = rgt;
+01333                 }
+01334                 else
+01335                 {
+01336                         bool gaEnabled = (_GlobalAnimationEnabled != 0);
+01337                         f.serial(gaEnabled);
+01338                         if (gaEnabled)
+01339                         {
+01340                                 f.serial(*_GlobalTexAnims);
+01341                         }
+01342 
+01343                         bool rgt = _ReinitGlobalAnimTimeOnNewElement != 0;
+01344                         f.serial(rgt);                  
+01345                 }
+01346         }
+01347 
+01348         if (ver > 3) // mesh morphing
+01349         {
+01350                 f.serialCont(_MeshShapeFileName);
+01351                 bool useScheme;
+01352                 if (f.isReading())
+01353                 {               
+01354                         delete _MorphScheme;
+01355                 }
+01356                 else
+01357                 {
+01358                         useScheme = _MorphScheme != NULL;
+01359                 }
+01360                 f.serial(useScheme);
+01361                 if (useScheme)
+01362                 {                               
+01363                         f.serialPolyPtr(_MorphScheme);
+01364                 }
+01365                 else
+01366                 {
+01367                         f.serial(_MorphValue);
+01368                 }               
+01369         }
+01370 }
+01371 
+01372 //====================================================================================
+01373 CPSConstraintMesh::~CPSConstraintMesh() 
+01374 {
+01375         clean();
+01376         delete _MorphScheme;
+01377 }
+01378 
+01379 
+01380 
+01381 //====================================================================================
+01382 void CPSConstraintMesh::releaseShapes()
+01383 {
+01384         for (TShapeVect::iterator it = _Shapes.begin(); it != _Shapes.end(); ++it)
+01385         {
+01386                 if (*it)
+01387                 {
+01388                         _ModelBank->release(*it);
+01389                 }
+01390         }
+01391         _Shapes.clear();
+01392 }
+01393 
+01394 //====================================================================================
+01395 void CPSConstraintMesh::clean(void)
+01396 {       
+01397         if (_ModelBank)
+01398         {       
+01399                 releaseShapes();                
+01400         }
+01401 }
+01402 
+01403 
+01404 //====================================================================================
+01405 CVertexBuffer &CPSConstraintMesh::makePrerotatedVb(const CVertexBuffer &inVb, TAnimationTime ellapsedTime)
+01406 {
+01407         // get a VB that has positions and eventually normals
+01408         CVertexBuffer &prerotatedVb = inVb.getVertexFormat() & CVertexBuffer::NormalFlag ? _PreRotatedMeshVBWithNormal : _PreRotatedMeshVB;
+01409 
+01410         // size of vertices for source VB
+01411         const uint vSize = inVb.getVertexSize();
+01412 
+01413         // size for vertices in prerotated model
+01414         const uint vpSize = prerotatedVb.getVertexSize();
+01415         
+01416 
+01417         // offset of normals in vertices of the prerotated model, and source model              
+01418         uint normalOff=0;
+01419         uint pNormalOff=0;
+01420         if (prerotatedVb.getVertexFormat() & CVertexBuffer::NormalFlag) 
+01421         {
+01422                 normalOff  =  inVb.getNormalOff();
+01423                 pNormalOff =  prerotatedVb.getNormalOff();                      
+01424         }
+01425 
+01426         const uint nbVerticesInSource   = inVb.getNumVertices();
+01427                 
+01428 
+01429         // rotate basis
+01430         // and compute the set of prerotated meshs that will then duplicated (with scale and translation) to create the Vb of what must be drawn
+01431         uint8 *outVertex = (uint8 *) prerotatedVb.getVertexCoordPointer();
+01432         for (std::vector< CPlaneBasisPair >::iterator it = _PrecompBasis.begin(); it != _PrecompBasis.end(); ++it)
+01433         {
+01434                 // not optimized at all, but this will apply to very few elements anyway...
+01435                 CMatrix mat;
+01436                 mat.rotate(CQuat(it->Axis, ellapsedTime * it->AngularVelocity));
+01437                 CVector n = mat * it->Basis.getNormal();
+01438                 it->Basis = CPlaneBasis(n);
+01439         
+01440                 mat.identity();
+01441                 mat.setRot(it->Basis.X, it->Basis.Y, it->Basis.X ^ it->Basis.Y);
+01442 
+01443                 uint8 *inVertex = (uint8 *) inVb.getVertexCoordPointer();
+01444 
+01445                 uint k = nbVerticesInSource;
+01446 
+01447                 // check wether we need to rotate normals as well...
+01448                 if (inVb.getVertexFormat() & CVertexBuffer::NormalFlag)
+01449                 {
+01450                 
+01451                         do
+01452                         {
+01453                                 CHECK_VERTEX_BUFFER(inVb, inVertex);
+01454                                 CHECK_VERTEX_BUFFER(inVb, inVertex + normalOff);
+01455                                 CHECK_VERTEX_BUFFER(prerotatedVb, outVertex);
+01456                                 CHECK_VERTEX_BUFFER(prerotatedVb, outVertex + pNormalOff);
+01457 
+01458                                 * (CVector *) outVertex =  mat.mulVector(* (CVector *) inVertex);
+01459                                 * (CVector *) (outVertex + normalOff) =  mat.mulVector(* (CVector *) (inVertex + pNormalOff) );
+01460                                 outVertex += vpSize;
+01461                                 inVertex  += vSize;
+01462                                 
+01463                         }
+01464                         while (--k);            
+01465                 }
+01466                 else
+01467                 {
+01468                         // no normal included
+01469                         do
+01470                         {       
+01471                                 
+01472                                 CHECK_VERTEX_BUFFER(prerotatedVb, outVertex);   
+01473                                 CHECK_VERTEX_BUFFER(inVb, inVertex);                                    
+01474 
+01475                                 * (CVector *) outVertex =  mat.mulVector(* (CVector *) inVertex);
+01476                                 outVertex += vpSize;
+01477                                 inVertex += vSize;
+01478                         }
+01479                         while (--k);    
+01480 
+01481                 }
+01482         }
+01483         return prerotatedVb;
+01484 }
+01485 
+01486 
+01487 //====================================================================================
+01488 void CPSConstraintMesh::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
+01489 {
+01490                 if (
+01491                         (pass == PSBlendRender && hasTransparentFaces())
+01492                         || (pass == PSSolidRender && hasOpaqueFaces())
+01493                         )
+01494                 {
+01495                         draw(pass == PSSolidRender, ellapsedTime);
+01496                 }
+01497                 else 
+01498                 if (pass == PSToolRender) // edition mode only
+01499                 {                       
+01500                         showTool();
+01501                 }
+01502 }
+01503 
+01504 //====================================================================================
+01505 void CPSConstraintMesh::draw(bool opaque, TAnimationTime ellapsedTime)
+01506 {
+01507         PARTICLES_CHECK_MEM;
+01508         nlassert(_Owner);       
+01509         
+01510         update(); // update mesh datas if needed
+01511         uint32 step;
+01512         uint   numToProcess;
+01513         computeSrcStep(step, numToProcess);     
+01514         if (!numToProcess) return;
+01515         _Owner->incrementNbDrawnParticles(numToProcess); // for benchmark purpose       
+01516 
+01517         
+01518         if (_PrecompBasis.size() == 0) 
+01519         {
+01520                 if (step == (1 << 16))
+01521                 {
+01522                         CPSConstraintMeshHelper::drawMeshs(_Owner->getPos().begin(),                                       
+01523                                                                                           *this,
+01524                                                                       numToProcess,
+01525                                                                                           step,
+01526                                                                                           opaque
+01527                                                                                          );
+01528                 }
+01529                 else
+01530                 {       
+01531                         CPSConstraintMeshHelper::drawMeshs(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
+01532                                                                                           *this,
+01533                                                                       numToProcess,
+01534                                                                                           step,
+01535                                                                                           opaque
+01536                                                                                          );             
+01537                 }
+01538         }
+01539         else
+01540         {
+01541                 if (step == (1 << 16))
+01542                 {
+01543                         CPSConstraintMeshHelper::drawPrerotatedMeshs(_Owner->getPos().begin(),
+01544                                                                                                              _IndexInPrecompBasis.begin(),
+01545                                                                                                                  *this,
+01546                                                                                                                  numToProcess,
+01547                                                                                                                  step,
+01548                                                                                                                  opaque,
+01549                                                                                                                  ellapsedTime
+01550                                                                                                             );
+01551                 }
+01552                 else
+01553                 {       
+01554                         typedef CAdvance1616Iterator<std::vector<uint32>::const_iterator, uint32> TIndexIterator;
+01555                         CPSConstraintMeshHelper::drawPrerotatedMeshs(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
+01556                                                                                                                  TIndexIterator(_IndexInPrecompBasis.begin(), 0, step),
+01557                                                                                                                  *this,
+01558                                                                                                                  numToProcess,
+01559                                                                                                                  step,
+01560                                                                                                                  opaque,
+01561                                                                                                                  ellapsedTime
+01562                                                                                                             );          
+01563                 }
+01564         }
+01565         
+01566                 
+01567 }
+01568 
+01569 //====================================================================================
+01570 // Private func used to force modulation on a material and to store the preious state
+01571 static inline void ForceMaterialModulation(CMaterial &destMat, CMaterial &srcMat, uint8 modulatedStages)
+01572 {
+01573         for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
+01574         {               
+01575                 if (modulatedStages & (1 << k))
+01576                 {
+01577                         destMat.texEnvArg0RGB(k, CMaterial::Previous, CMaterial::SrcColor);
+01578                         destMat.texEnvArg0Alpha(k, CMaterial::Previous, CMaterial::SrcAlpha);
+01579                         destMat.texEnvArg1RGB(k, CMaterial::Constant, CMaterial::SrcColor);
+01580                         destMat.texEnvArg1Alpha(k, CMaterial::Constant, CMaterial::SrcAlpha);
+01581                         destMat.texEnvOpRGB(k, CMaterial::Modulate);
+01582                         destMat.texEnvOpAlpha(k, CMaterial::Modulate);                  
+01583                 }
+01584                 else // restore from source material
+01585                 {
+01586                         destMat.setTexEnvMode(k, srcMat.getTexEnvMode(k));
+01587                 }
+01588         }       
+01589 }
+01590 
+01591 
+01592 //====================================================================================
+01593 void    CPSConstraintMesh::setupRenderPasses(float date, TRdrPassSet &rdrPasses, bool opaque)
+01594 {
+01595         // render meshs : we process each rendering pass
+01596         for (TRdrPassSet::iterator rdrPassIt = rdrPasses.begin() 
+01597                 ; rdrPassIt != rdrPasses.end(); ++rdrPassIt)
+01598         {
+01599 
+01600                 CMaterial &Mat = rdrPassIt->Mat;
+01601                 CMaterial &SourceMat = rdrPassIt->SourceMat;
+01602 
+01603 
+01605                 if ((opaque && Mat.getZWrite()) || (!opaque && ! Mat.getZWrite()))
+01606                 {               
+01607 
+01608         
+01609                         // has to setup material constant color ?
+01610                         // global color not supported for mesh
+01611                 /*      CParticleSystem &ps = *(_Owner->getOwner());
+01612                         if (!_ColorScheme) 
+01613                         {                                                               
+01614                                 NLMISC::CRGBA col;
+01615                                 col.modulateFromColor(SourceMat.getColor(), _Color);
+01616                                 if (ps.getColorAttenuationScheme() == NULL)
+01617                                 {
+01618                                         col.modulateFromColor(col, ps.getGlobalColor());
+01619                                 }
+01620                                 Mat.setColor(col);                              
+01621                         }
+01622                         else
+01623                         {                               
+01624                                 Mat.setColor(ps.getGlobalColor());
+01625                         }*/
+01626 
+01628                         ForceMaterialModulation(Mat, SourceMat, _ModulatedStages);
+01629 
+01631                         bool forceVertexcolorLighting = _VertexColorLightingForced != 0 ? true : SourceMat.getLightedVertexColor();
+01632                         if (forceVertexcolorLighting != Mat.getLightedVertexColor()) // avoid to touch mat if not needed
+01633                         {
+01634                                 Mat.setLightedVertexColor(forceVertexcolorLighting);
+01635                         }
+01636 
+01638                         if (_GlobalAnimationEnabled != 0)
+01639                         {
+01640                                 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
+01641                                 {
+01642                                         if (Mat.getTexture(k) != NULL)
+01643                                         {
+01644                                                 Mat.enableUserTexMat(k, true);
+01645                                                 CMatrix mat;
+01646                                                 _GlobalTexAnims->Anims[k].buildMatrix(date, mat);
+01647                                                 Mat.setUserTexMat(k ,mat);
+01648                                         }
+01649                                 }
+01650                         }               
+01651                 }                       
+01652         }
+01653 
+01654 }
+01655 
+01656 //====================================================================================
+01657 void    CPSConstraintMesh::doRenderPasses(IDriver *driver, uint numObj, TRdrPassSet &rdrPasses, bool opaque)
+01658 {               
+01659         // render meshs : we process each rendering pass
+01660         for (TRdrPassSet::iterator rdrPassIt = rdrPasses.begin() 
+01661                 ; rdrPassIt != rdrPasses.end(); ++rdrPassIt)
+01662         {       
+01663                 CMaterial &Mat = rdrPassIt->Mat;
+01664                 if ((opaque && Mat.getZWrite()) || (!opaque && ! Mat.getZWrite()))
+01665                 {
+01667                         rdrPassIt->Pb.setNumTri(rdrPassIt->Pb.capacityTri()   * numObj / ConstraintMeshBufSize);
+01668                         rdrPassIt->Pb.setNumQuad(rdrPassIt->Pb.capacityQuad() * numObj / ConstraintMeshBufSize);
+01669                         rdrPassIt->Pb.setNumLine(rdrPassIt->Pb.capacityLine() * numObj / ConstraintMeshBufSize);
+01670 
+01672                         driver->render(rdrPassIt->Pb, rdrPassIt->Mat);
+01673                 }
+01674         }
+01675 
+01676 }
+01677 
+01678 
+01679 //====================================================================================
+01680 void    CPSConstraintMesh::computeColors(CVertexBuffer &outVB, const CVertexBuffer &inVB, uint startIndex, uint toProcess, uint32 srcStep)
+01681 {       
+01682         nlassert(_ColorScheme);
+01683         // there are 2 case : 1 - the source mesh has colors, which are modulated with the current color
+01684         //                                        2 - the source mesh has no colors : colors are directly copied into the dest vb
+01685 
+01686         if (inVB.getVertexFormat() & CVertexBuffer::PrimaryColorFlag) // case 1
+01687         {
+01688                 // TODO: optimisation : avoid to duplicate colors...
+01689                 _ColorScheme->makeN(_Owner, startIndex, outVB.getColorPointer(), outVB.getVertexSize(), toProcess, inVB.getNumVertices(), srcStep);
+01690                 // modulate from the source mesh
+01691                 uint8 *vDest  = (uint8 *) outVB.getColorPointer();
+01692                 uint8 *vSrc   = (uint8 *) inVB.getColorPointer();
+01693                 const uint vSize = outVB.getVertexSize();
+01694                 const uint numVerts = inVB.getNumVertices();
+01695                 uint  meshSize = vSize * numVerts;              
+01696                 for (uint k = 0; k < toProcess; ++k)
+01697                 {
+01698                         NLMISC::CRGBA::modulateColors((CRGBA *) vDest, (CRGBA *) vSrc, (CRGBA *) vDest, numVerts, vSize, vSize);
+01699                         vDest += meshSize;
+01700                 }
+01701         }
+01702         else // case 2
+01703         {
+01704                 _ColorScheme->makeN(_Owner, startIndex, outVB.getColorPointer(), outVB.getVertexSize(), toProcess, inVB.getNumVertices(), srcStep);
+01705         }
+01706 }
+01707 
+01708 
+01709 //====================================================================================
+01710 void CPSConstraintMesh::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+01711 {
+01712         newSizeElement(emitterLocated, emitterIndex);
+01713         newPlaneBasisElement(emitterLocated, emitterIndex);
+01714         // TODO : avoid code cuplication with CPSFace ...
+01715         const uint32 nbConf = _PrecompBasis.size();
+01716         if (nbConf) // do we use precomputed basis ?
+01717         {
+01718                 _IndexInPrecompBasis[_Owner->getNewElementIndex()] = rand() % nbConf;
+01719         }
+01720         newColorElement(emitterLocated, emitterIndex);
+01721         if (_GlobalAnimationEnabled && _ReinitGlobalAnimTimeOnNewElement)
+01722         {               
+01723                 _GlobalAnimDate = _Owner->getOwner()->getSystemDate();
+01724         }
+01725         if (_MorphScheme && _MorphScheme->hasMemory()) _MorphScheme->newElement(emitterLocated, emitterIndex);
+01726 }
+01727         
+01728 //====================================================================================  
+01729 void CPSConstraintMesh::deleteElement(uint32 index)
+01730 {
+01731         deleteSizeElement(index);
+01732         deletePlaneBasisElement(index);
+01733         // TODO : avoid code cuplication with CPSFace ...
+01734         if (_PrecompBasis.size()) // do we use precomputed basis ?
+01735         {
+01736                 // replace ourself by the last element...
+01737                 _IndexInPrecompBasis[index] = _IndexInPrecompBasis[_Owner->getSize() - 1];
+01738         }
+01739         deleteColorElement(index);
+01740         if (_MorphScheme && _MorphScheme->hasMemory()) _MorphScheme->deleteElement(index);
+01741 }
+01742         
+01743 //====================================================================================
+01744 void CPSConstraintMesh::resize(uint32 size)
+01745 {
+01746         nlassert(size < (1 << 16));
+01747         resizeSize(size);
+01748         resizePlaneBasis(size);
+01749         // TODO : avoid code cuplication with CPSFace ...
+01750         if (_PrecompBasis.size()) // do we use precomputed basis ?
+01751         {
+01752                 _IndexInPrecompBasis.resize(size);
+01753         }
+01754         resizeColor(size);
+01755         if (_MorphScheme && _MorphScheme->hasMemory()) _MorphScheme->resize(size, _Owner->getSize());
+01756 }       
+01757 
+01758 //====================================================================================
+01759 void CPSConstraintMesh::updateMatAndVbForColor(void)
+01760 {
+01761         // nothing to do for us...
+01762 }
+01763 
+01764 //====================================================================================
+01765 void    CPSConstraintMesh::forceStageModulationByColor(uint stage, bool force)
+01766 {
+01767         nlassert(stage < IDRV_MAT_MAXTEXTURES);
+01768         if (force)
+01769         {
+01770                 _ModulatedStages |= 1 << stage;
+01771         }
+01772         else
+01773         {
+01774                 _ModulatedStages &= ~(1 << stage);
+01775         }
+01776 }
+01777 
+01778 //====================================================================================
+01779 bool    CPSConstraintMesh::isStageModulationForced(uint stage) const
+01780 {
+01781         nlassert(stage < IDRV_MAT_MAXTEXTURES);
+01782         return (_ModulatedStages & (1 << stage)) != 0;
+01783 }
+01784 
+01785 //====================================================================================
+01786 
+01792 static void DuplicatePrimitiveBlock(const CPrimitiveBlock &srcBlock, CPrimitiveBlock &destBlock, uint nbReplicate, uint vertOffset)
+01793 {
+01794         PARTICLES_CHECK_MEM;
+01795 
+01796         // this must be update each time a new primitive is added
+01797         
+01798         // loop counters, and index of the current primitive in the dest pb
+01799         uint k, l, index;
+01800 
+01801         // the current vertex offset.
+01802         uint currVertOffset;
+01803 
+01804 
+01805         // duplicate triangles
+01806         uint numTri = srcBlock.getNumTri();
+01807         destBlock.reserveTri(numTri * nbReplicate);
+01808         
+01809         index = 0;
+01810         currVertOffset = 0;
+01811 
+01812         const uint32 *triPtr = srcBlock.getTriPointer();
+01813         const uint32 *currTriPtr; // current Tri
+01814         for (k = 0; k < nbReplicate; ++k)
+01815         {
+01816                 currTriPtr = triPtr;
+01817                 for (l = 0; l < numTri; ++l)
+01818                 {
+01819                         destBlock.setTri(index, currTriPtr[0] + currVertOffset, currTriPtr[1] + currVertOffset, currTriPtr[2] + currVertOffset);
+01820                         currTriPtr += 3;
+01821                         ++ index;
+01822                 }
+01823                 currVertOffset += vertOffset;
+01824         }
+01825 
+01826 
+01827         // duplicate quads
+01828         uint numQuad = srcBlock.getNumQuad();
+01829         destBlock.reserveQuad(numQuad * nbReplicate);
+01830         
+01831         index = 0;
+01832         currVertOffset = 0;
+01833 
+01834         const uint32 *QuadPtr = srcBlock.getQuadPointer();
+01835         const uint32 *currQuadPtr; // current Quad
+01836         for (k = 0; k < nbReplicate; ++k)
+01837         {
+01838                 currQuadPtr = QuadPtr;
+01839                 for (l = 0; l < numQuad; ++l)
+01840                 {
+01841                         destBlock.setQuad(index, currQuadPtr[0] + currVertOffset, currQuadPtr[1] + currVertOffset, currQuadPtr[2] + currVertOffset, currQuadPtr[3] + currVertOffset);
+01842                         currQuadPtr += 4;
+01843                         ++ index;
+01844                 }
+01845                 currVertOffset += vertOffset;
+01846         }
+01847 
+01848         // duplicate lines
+01849         uint numLine = srcBlock.getNumLine();
+01850         destBlock.reserveLine(numLine * nbReplicate);
+01851         
+01852         index = 0;
+01853         currVertOffset = 0;
+01854 
+01855         const uint32 *LinePtr = srcBlock.getLinePointer();
+01856         const uint32 *currLinePtr; // current Line
+01857         for (k = 0; k < nbReplicate; ++k)
+01858         {
+01859                 currLinePtr = LinePtr;
+01860                 for (l = 0; l < numLine; ++l)
+01861                 {
+01862                         destBlock.setLine(index, currLinePtr[0] + currVertOffset, currLinePtr[1] + currVertOffset);
+01863                         currLinePtr += 4;
+01864                         ++ index;
+01865                 }
+01866                 currVertOffset += vertOffset;
+01867         }       
+01868 
+01869 
+01870         // TODO quad / strips duplication : (unimplemented in primitive blocks for now)
+01871 
+01872         PARTICLES_CHECK_MEM;
+01873 }
+01874 
+01875 //====================================================================================
+01876 void CPSConstraintMesh::initPrerotVB()
+01877 {
+01878         // position, no normals
+01879         _PreRotatedMeshVB.setVertexFormat(CVertexBuffer::PositionFlag);
+01880         _PreRotatedMeshVB.setNumVertices(ConstraintMeshMaxNumPrerotatedModels * ConstraintMeshMaxNumVerts);
+01881 
+01882         // position & normals
+01883         _PreRotatedMeshVBWithNormal.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::NormalFlag);
+01884         _PreRotatedMeshVBWithNormal.setNumVertices(ConstraintMeshMaxNumPrerotatedModels * ConstraintMeshMaxNumVerts);
+01885 }
+01886 
+01887 //====================================================================================
+01888 CPSConstraintMesh::CMeshDisplay &CPSConstraintMesh::CMeshDisplayShare::getMeshDisplay(IShape *shape, uint32 format)
+01889 {
+01890         CKey key;
+01891         key.Shape = shape;
+01892         key.Format = format;
+01893         if (MDMap.count(key)) // already exists ?
+01894         {
+01895                 nlassert(MDMap[key]);
+01896                 return *MDMap[key];
+01897         }
+01898         else
+01899         {
+01900                 if (MDQueue.size() == _MaxNumMD) // is there room left?
+01901                 {
+01902                         // no, destroy the least recent entry
+01903                         nlassert(MDMap.count(MDQueue.front())); // make sure it is also in the map
+01904                         MDMap.erase(MDQueue.front());
+01905                         MDQueue.pop();
+01906                 }
+01907                 std::auto_ptr<CMeshDisplay> MD(new CMeshDisplay);
+01908         
+01909                 // setup rdr passes & primitive blocks
+01910                 buildRdrPassSet(MD->RdrPasses, shape);
+01911                 
+01912                 // setup vb
+01913                 buildVB(format, MD->VB, shape);
+01914                 
+01915                 MDQueue.push(key);
+01916                 MDMap[key] = MD.get();
+01917                 return *(MD.release());
+01918         }
+01919 }
+01920 
+01921 
+01922 //====================================================================================
+01923 CPSConstraintMesh::CMeshDisplayShare::~CMeshDisplayShare()
+01924 {
+01925         for (TMDMap::iterator it = MDMap.begin(); it != MDMap.end(); ++it)
+01926         {
+01927                 delete it->second;
+01928         }
+01929 }
+01930 
+01931 //====================================================================================
+01932 void CPSConstraintMesh::CMeshDisplayShare::buildRdrPassSet(TRdrPassSet &dest, const IShape *shape)
+01933 {       
+01934         const CMesh &m = *NLMISC::safe_cast<const CMesh *>(shape);
+01935         // we don't support skinning for mesh particles, so there must be only one matrix block 
+01936         nlassert(m.getNbMatrixBlock() == 1);  // SKINNING UNSUPPORTED
+01937         
+01938         dest.resize(m.getNbRdrPass(0));
+01939         const CVertexBuffer &srcVb = m.getVertexBuffer();
+01940         
+01941         for (uint k = 0; k < m.getNbRdrPass(0); ++k)
+01942         {
+01943                 dest[k].Mat = m.getMaterial(m.getRdrPassMaterial(0, k));
+01944                 dest[k].SourceMat = dest[k].Mat;
+01945                 DuplicatePrimitiveBlock(m.getRdrPassPrimitiveBlock(0, k), dest[k].Pb, ConstraintMeshBufSize, srcVb.getNumVertices() );          
+01946         }       
+01947 }
+01948 
+01949 //====================================================================================
+01950 void CPSConstraintMesh::CMeshDisplayShare::buildVB(uint32 destFormat, CVertexBuffer &dest, const IShape *shape)
+01951 {
+01953         nlassert(shape);
+01954         const CMesh &m = *NLMISC::safe_cast<const CMesh *>(shape);
+01955         const CVertexBuffer &meshVb = m.getVertexBuffer();
+01956         nlassert(destFormat == meshVb.getVertexFormat() || destFormat == (meshVb.getVertexFormat() | (uint32) CVertexBuffer::PrimaryColorFlag) );
+01957         dest.setVertexFormat(destFormat);
+01958         dest.setNumVertices(ConstraintMeshBufSize * meshVb.getNumVertices());
+01959 
+01960         uint8 *outPtr = (uint8 *) dest.getVertexCoordPointer();
+01961         uint8 *inPtr = (uint8 *)  meshVb.getVertexCoordPointer();
+01962         uint  meshSize  = dest.getVertexSize() * meshVb.getNumVertices();
+01963 
+01964         if (destFormat == meshVb.getVertexFormat()) // no color added
+01965         {               
+01966                 for (uint k = 0; k < ConstraintMeshBufSize; ++k)
+01967                 {
+01968                         ::memcpy((void *) (outPtr + k * meshSize), (void *) inPtr, meshSize);                   
+01969                 }
+01970         }
+01971         else // color added, but not available in src 
+01972         {
+01973                 sint colorOff = dest.getColorOff();
+01974                 uint inVSize    = meshVb.getVertexSize();
+01975                 uint outVSize   = dest.getVertexSize();         
+01976                 for (uint k = 0; k < ConstraintMeshBufSize; ++k)
+01977                 {
+01978                         for (uint v = 0; v < meshVb.getNumVertices(); ++v)
+01979                         {
+01980                                 // copy until color
+01981                                 ::memcpy((void *) (outPtr + k * meshSize + v * outVSize), (void *) (inPtr + v * inVSize), colorOff);
+01982                                 // copy datas after color
+01983                                 ::memcpy((void *) (outPtr + k * meshSize + v * outVSize + colorOff + sizeof(uint8[4])), (void *) (inPtr + v * inVSize + colorOff), inVSize - colorOff);
+01984                         }
+01985                 }
+01986         }
+01987 }
+01988 
+01989 //=====================================================================================
+01990 CPSConstraintMesh::CMeshDisplayShare::CKey::~CKey()
+01991 {
+01992 }
+01993 
+01994 //===================================================================================== 
+01995 CPSConstraintMesh::CGlobalTexAnim::CGlobalTexAnim() : TransSpeed(NLMISC::CVector2f::Null),
+01996                                                          TransAccel(NLMISC::CVector2f::Null),
+01997                                                          ScaleStart(1 ,1),
+01998                                                          ScaleSpeed(NLMISC::CVector2f::Null),
+01999                                                          ScaleAccel(NLMISC::CVector2f::Null),
+02000                                                          WRotSpeed(0),
+02001                                                          WRotAccel(0)
+02002 {
+02003 }
+02004 
+02005 //=====================================================================================
+02006 void    CPSConstraintMesh::CGlobalTexAnim::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+02007 {
+02008         f.serialVersion(0);
+02009         f.serial(TransSpeed, TransAccel, ScaleStart, ScaleSpeed, ScaleAccel);
+02010         f.serial(WRotSpeed, WRotAccel);
+02011 }
+02012 
+02013 //=====================================================================================
+02014 void CPSConstraintMesh::CGlobalTexAnim::buildMatrix(float &date, NLMISC::CMatrix &dest)
+02015 {
+02016         float fDate = (float) date;
+02017         float halfDateSquared   = 0.5f * fDate * fDate;
+02018         NLMISC::CVector2f pos   = fDate * TransSpeed + halfDateSquared * fDate * TransAccel;
+02019         NLMISC::CVector2f scale = ScaleStart + fDate * ScaleSpeed + halfDateSquared * fDate * ScaleAccel;
+02020         float rot = fDate * WRotSpeed + halfDateSquared * WRotAccel;
+02021         
+02022                         
+02023         float fCos, fSin;
+02024         if (rot != 0.f)
+02025         {
+02026                 fCos = ::cosf(- rot);
+02027                 fSin = ::sinf(- rot);
+02028         }
+02029         else
+02030         {
+02031                 fCos = 1.f;
+02032                 fSin = 0.f;
+02033         }
+02034 
+02035         NLMISC::CVector I(fCos, fSin, 0);
+02036         NLMISC::CVector J(-fSin, fCos, 0);                              
+02037         dest.setRot(scale.x * I, scale.y * J, NLMISC::CVector::K);      
+02038         NLMISC::CVector center(-0.5f, -0.5f, 0.f);
+02039         NLMISC::CVector t(pos.x, pos.y, 0);
+02040         dest.setPos(t + dest.mulVector(center) - center);       
+02041 }
+02042 
+02043 //=====================================================================================
+02044 void    CPSConstraintMesh::setGlobalTexAnim(uint stage, const CGlobalTexAnim &properties)
+02045 {
+02046         nlassert(_GlobalAnimationEnabled != 0);
+02047         nlassert(stage < IDRV_MAT_MAXTEXTURES);
+02048         nlassert(_GlobalTexAnims.get());
+02049         _GlobalTexAnims->Anims[stage] = properties;
+02050 }
+02051 
+02052 //=====================================================================================
+02053 const CPSConstraintMesh::CGlobalTexAnim &CPSConstraintMesh::getGlobalTexAnim(uint stage) const
+02054 {
+02055         nlassert(_GlobalAnimationEnabled != 0);
+02056         nlassert(stage < IDRV_MAT_MAXTEXTURES);
+02057         nlassert(_GlobalTexAnims.get());
+02058         return _GlobalTexAnims->Anims[stage];
+02059 }
+02060 
+02061 
+02062 //=====================================================================================
+02063 CPSConstraintMesh::TTexAnimType CPSConstraintMesh::getTexAnimType() const
+02064 {
+02065         return (TTexAnimType) (_GlobalAnimationEnabled != 0 ? GlobalAnim : NoAnim);     
+02066 }
+02067 
+02068 //=====================================================================================
+02069 void  CPSConstraintMesh::setTexAnimType(TTexAnimType type)
+02070 {
+02071         nlassert(type < Last);
+02072         if (type == getTexAnimType()) return; // does the type of animation change ?
+02073         switch (type)
+02074         {
+02075                 case NoAnim:
+02076                         _GlobalTexAnims.reset();
+02077                         restoreMaterials();
+02078                         _GlobalAnimationEnabled = 0;
+02079                 break;
+02080                 case GlobalAnim:
+02081                 {
+02082                         PGlobalTexAnims newPtr(new CGlobalTexAnims);
+02083                         std::swap(_GlobalTexAnims, newPtr);                     
+02084                         _GlobalAnimationEnabled = 1;
+02085                 }
+02086                 break;
+02087                 default: break;
+02088         }
+02089 }
+02090 
+02091 //=====================================================================================
+02092 void    CPSConstraintMesh::CGlobalTexAnims::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+02093 {
+02094         f.serialVersion(0);
+02095         for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
+02096         {
+02097                 f.serial(Anims[k]);
+02098         }
+02099 }
+02100 
+02101 //=====================================================================================
+02102 void CPSConstraintMesh::restoreMaterials()
+02103 {
+02104         update();
+02105         CMesh                             &mesh = * NLMISC::safe_cast<CMesh *>((IShape *) _Shapes[0]);
+02106         const CVertexBuffer   &modelVb = mesh.getVertexBuffer();
+02107         CMeshDisplay  &md= _MeshDisplayShare.getMeshDisplay(_Shapes[0], modelVb.getVertexFormat() 
+02108                                                                                                                         | (_ColorScheme ? CVertexBuffer::PrimaryColorFlag : 0));
+02109 
+02110         TRdrPassSet rdrPasses = md.RdrPasses;
+02111                 // render meshs : we process each rendering pass
+02112         for (TRdrPassSet::iterator rdrPassIt = rdrPasses.begin() 
+02113                 ; rdrPassIt != rdrPasses.end(); ++rdrPassIt)
+02114         {       
+02115                 rdrPassIt->Mat = rdrPassIt->SourceMat;          
+02116         }
+02117 }
+02118 
+02119 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1