00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/3d/ps_mesh.h"
00027 #include "nel/3d/ps_macro.h"
00028 #include "nel/3d/shape.h"
00029 #include "nel/3d/mesh.h"
00030 #include "nel/3d/transform_shape.h"
00031 #include "nel/3d/shape_bank.h"
00032 #include "nel/3d/texture_mem.h"
00033 #include "nel/3d/scene.h"
00034 #include "nel/3d/ps_located.h"
00035 #include "nel/3d/particle_system.h"
00036 #include "nel/3d/particle_system_shape.h"
00037 #include "nel/3d/particle_system_model.h"
00038 #include "nel/3d/ps_iterator.h"
00039 #include "nel/misc/stream.h"
00040 #include "nel/misc/path.h"
00041
00042 #include <memory>
00043 #include <functional>
00044
00045
00046
00047
00048 namespace NL3D
00049 {
00050
00052
00054
00055
00056
00057
00058 CPSConstraintMesh::CMeshDisplayShare CPSConstraintMesh::_MeshDisplayShare(16);
00059 CVertexBuffer CPSConstraintMesh::_PreRotatedMeshVB;
00060 CVertexBuffer CPSConstraintMesh::_PreRotatedMeshVBWithNormal;
00061 CPSConstraintMesh::TMeshName2RamVB CPSConstraintMesh::_MeshRamVBs;
00062
00063
00064
00065
00066 static CVector MakeRandomUnitVect(void)
00067 {
00068 NL_PS_FUNC(MakeRandomUnitVect)
00069 CVector v((float) ((rand() % 20000) - 10000)
00070 ,(float) ((rand() % 20000) - 10000)
00071 ,(float) ((rand() % 20000) - 10000)
00072 );
00073 v.normalize();
00074 return v;
00075 }
00076
00077
00079
00081
00082
00083
00084
00085
00086
00087
00088 const std::string DummyShapeName("dummy mesh shape");
00089
00093 static CMesh *CreateDummyMesh(void)
00094 {
00095 NL_PS_FUNC(CreateDummyMesh)
00096 CMesh::CMeshBuild mb;
00097 CMeshBase::CMeshBaseBuild mbb;
00098
00099 mb.VertexFlags = CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag;
00100 mb.Vertices.push_back(CVector(-.5f, -.5f, -.5f));
00101 mb.Vertices.push_back(CVector(.5f, -.5f, -.5f));
00102 mb.Vertices.push_back(CVector(.5f, -.5f, .5f));
00103 mb.Vertices.push_back(CVector(-.5f, -.5f, .5f));
00104
00105 mb.Vertices.push_back(CVector(-.5f, .5f, -.5f));
00106 mb.Vertices.push_back(CVector(.5f, .5f, -.5f));
00107 mb.Vertices.push_back(CVector(.5f, .5f, .5f));
00108 mb.Vertices.push_back(CVector(-.5f, .5f, .5f));
00109
00110
00111 uint32 tab[] = { 4, 1, 0,
00112 4, 5, 1,
00113 5, 2, 1,
00114 5, 6, 2,
00115 6, 3, 2,
00116 6, 7, 3,
00117 7, 0, 3,
00118 7, 4, 0,
00119 7, 5, 4,
00120 7, 6, 5,
00121 2, 0, 1,
00122 2, 3, 0
00123 };
00124
00125 for (uint k = 0; k < 6; ++k)
00126 {
00127 CMesh::CFace f;
00128 f.Corner[0].Vertex = tab[6 * k];
00129 f.Corner[0].Uvws[0] = NLMISC::CUVW(0, 0, 0);
00130
00131 f.Corner[1].Vertex = tab[6 * k + 1];
00132 f.Corner[1].Uvws[0] = NLMISC::CUVW(1, 1, 0);
00133
00134 f.Corner[2].Vertex = tab[6 * k + 2];
00135 f.Corner[2].Uvws[0] = NLMISC::CUVW(0, 1, 0);
00136
00137 f.MaterialId = 0;
00138
00139 mb.Faces.push_back(f);
00140
00141 f.Corner[0].Vertex = tab[6 * k + 3];
00142 f.Corner[0].Uvws[0] = NLMISC::CUVW(0, 0, 0);
00143
00144 f.Corner[1].Vertex = tab[6 * k + 4];
00145 f.Corner[1].Uvws[0] = NLMISC::CUVW(1, 0, 0);
00146
00147 f.Corner[2].Vertex = tab[6 * k + 5];
00148 f.Corner[2].Uvws[0] = NLMISC::CUVW(1, 1, 0);
00149
00150 f.MaterialId = 0;
00151 mb.Faces.push_back(f);
00152 }
00153
00154 CMaterial mat;
00155 CTextureMem *tex = new CTextureMem;
00156 tex->makeDummy();
00157 mat.setTexture(0, tex);
00158 mat.setLighting(false);
00159 mat.setColor(CRGBA::White);
00160 mbb.Materials.push_back(mat);
00161 CMesh *m = new CMesh;
00162 m->build(mbb, mb);
00163 return m;
00164 }
00165
00166
00167
00168 void CPSMesh::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00169 {
00170 NL_PS_FUNC(CPSMesh_IStream )
00171 (void)f.serialVersion(3);
00172 CPSParticle::serial(f);
00173 CPSSizedParticle::serialSizeScheme(f);
00174 CPSRotated3DPlaneParticle::serialPlaneBasisScheme(f);
00175 CPSRotated2DParticle::serialAngle2DScheme(f);
00176 f.serial(_Shape);
00177 if (f.isReading())
00178 {
00179
00180 uint maxSize = 0;
00181 if (_Owner)
00182 {
00183 maxSize = _Owner->getMaxSize();
00184 _Instances.resize(maxSize);
00185 }
00186 for(uint k = 0; k < maxSize; ++k)
00187 {
00188 _Instances.insert(NULL);
00189 }
00190 }
00191 }
00192
00193
00194 void CPSMesh::setShape(const std::string &shape)
00195 {
00196 NL_PS_FUNC(CPSMesh_setShape)
00197 if (shape == _Shape) return;
00198 _Shape = shape;
00199 removeAllInstancesFromScene();
00200 }
00201
00202
00203 uint32 CPSMesh::getNumWantedTris() const
00204 {
00205 NL_PS_FUNC(CPSMesh_getNumWantedTris)
00207 return 0;
00208 }
00209
00210
00211 bool CPSMesh::hasTransparentFaces(void)
00212 {
00213 NL_PS_FUNC(CPSMesh_hasTransparentFaces)
00215 return false;
00216 }
00217
00218
00219 bool CPSMesh::hasOpaqueFaces(void)
00220 {
00221 NL_PS_FUNC(CPSMesh_hasOpaqueFaces)
00223 return false;
00224 }
00225
00226
00227 bool CPSMesh::hasLightableFaces()
00228 {
00229 NL_PS_FUNC(CPSMesh_hasLightableFaces)
00231 return false;
00232 }
00233
00234
00235 void CPSMesh::releaseAllRef()
00236 {
00237 NL_PS_FUNC(CPSMesh_releaseAllRef)
00238 CPSParticle::releaseAllRef();
00239 nlassert(_Owner && _Owner->getScene());
00240 removeAllInstancesFromScene();
00241 }
00242
00243
00244 void CPSMesh::removeAllInstancesFromScene()
00245 {
00246 NL_PS_FUNC(CPSMesh_removeAllInstancesFromScene)
00247 for(uint k = 0; k < _Instances.getSize(); ++k)
00248 {
00249 if (_Instances[k])
00250 {
00251 if (_Owner) _Owner->getScene()->deleteInstance(_Instances[k]);
00252 _Instances[k] = NULL;
00253 }
00254 }
00255 }
00256
00257
00258 CTransformShape *CPSMesh::createInstance()
00259 {
00260 NL_PS_FUNC(CPSMesh_createInstance)
00261 CScene *scene = _Owner->getScene();
00262 nlassert(scene);
00263 CTransformShape *instance = scene->createInstance(_Shape);
00264 if (!instance)
00265 {
00266
00267 IShape *is = CreateDummyMesh();
00268 scene->getShapeBank()->add(DummyShapeName, is);
00269 instance = scene->createInstance(DummyShapeName);
00270 nlassert(instance);
00271 }
00272 instance->setTransformMode(CTransform::DirectMatrix);
00273 instance->hide();
00274 return instance;
00275 }
00276
00277
00278 void CPSMesh::newElement(const CPSEmitterInfo &info)
00279 {
00280 NL_PS_FUNC(CPSMesh_newElement)
00281 newPlaneBasisElement(info);
00282 newAngle2DElement(info);
00283 newSizeElement(info);
00284 nlassert(_Owner);
00285 nlassert(_Owner->getOwner());
00286 CTransformShape *instance = createInstance();
00287 nlassert(instance);
00288 _Instances.insert(instance);
00289 }
00290
00291
00292 void CPSMesh::deleteElement(uint32 index)
00293 {
00294 NL_PS_FUNC(CPSMesh_deleteElement)
00295 deleteSizeElement(index);
00296 deleteAngle2DElement(index);
00297 deletePlaneBasisElement(index);
00298
00299
00300 nlassert(_Owner);
00301 nlassert(_Owner->getOwner());
00302 CScene *scene = _Owner->getScene();
00303 nlassert(scene);
00304 if (_Instances[index])
00305 {
00306 scene->deleteInstance(_Instances[index]);
00307 }
00308 _Instances.remove(index);
00309 }
00310
00311
00312 void CPSMesh::step(TPSProcessPass pass)
00313 {
00314 NL_PS_FUNC(CPSMesh_step)
00315 if (pass == PSMotion)
00316 {
00317 updatePos();
00318 }
00319 else
00320 if (pass == PSToolRender)
00321 {
00322 showTool();
00323 }
00324 }
00325
00326
00327 void CPSMesh::updatePos()
00328 {
00329 NL_PS_FUNC(CPSMesh_updatePos)
00330 const uint MeshBufSize = 512;
00331 PARTICLES_CHECK_MEM;
00332 nlassert(_Owner);
00333 const uint32 size = _Owner->getSize();
00334 if (!size) return;
00335
00336
00337 _Owner->incrementNbDrawnParticles(size);
00338
00339
00340 if (!_Instances[0])
00341 {
00342 for (uint k = 0; k < size; ++k)
00343 {
00344 nlassert(!_Instances[k]);
00345 _Instances[k] = createInstance();
00346 }
00347 }
00348
00349 float sizes[MeshBufSize];
00350 float angles[MeshBufSize];
00351 static CPlaneBasis planeBasis[MeshBufSize];
00352
00353 uint32 leftToDo = size, toProcess;
00354
00355
00356 float *ptCurrSize;
00357 const uint ptCurrSizeIncrement = _SizeScheme ? 1 : 0;
00358
00359 float *ptCurrAngle;
00360 const uint ptCurrAngleIncrement = _Angle2DScheme ? 1 : 0;
00361
00362 CPlaneBasis *ptBasis;
00363 const uint ptCurrPlaneBasisIncrement = _PlaneBasisScheme ? 1 : 0;
00364
00365 TPSAttribVector::const_iterator posIt = _Owner->getPos().begin(), endPosIt;
00366
00367
00368 TInstanceCont::iterator instanceIt = _Instances.begin();
00369
00370 do
00371 {
00372 toProcess = leftToDo < MeshBufSize ? leftToDo : MeshBufSize;
00373
00374 if (_SizeScheme)
00375 {
00376 ptCurrSize = (float *) (_SizeScheme->make(_Owner, size - leftToDo, &sizes[0], sizeof(float), toProcess, true));
00377 }
00378 else
00379 {
00380 ptCurrSize =& _ParticleSize;
00381 }
00382
00383 if (_Angle2DScheme)
00384 {
00385 ptCurrAngle = (float *) (_Angle2DScheme->make(_Owner, size - leftToDo, &angles[0], sizeof(float), toProcess, true));
00386 }
00387 else
00388 {
00389 ptCurrAngle =& _Angle2D;
00390 }
00391
00392
00393 if (_PlaneBasisScheme)
00394 {
00395 ptBasis = (CPlaneBasis *) (_PlaneBasisScheme->make(_Owner, size - leftToDo, &planeBasis[0], sizeof(CPlaneBasis), toProcess, true));
00396 }
00397 else
00398 {
00399 ptBasis = &_PlaneBasis;
00400 }
00401
00402 endPosIt = posIt + toProcess;
00403 CMatrix mat, tmat;
00404
00405
00406 const CMatrix &transfo = getLocalToWorldMatrix();
00407 do
00408 {
00409
00410 tmat.identity();
00411 mat.identity();
00412
00413 tmat.translate(*posIt);
00414
00415
00416
00417 mat.setRot( ptBasis->X * CPSUtil::getCos((sint32) *ptCurrAngle) + ptBasis->Y * CPSUtil::getSin((sint32) *ptCurrAngle)
00418 , ptBasis->X * CPSUtil::getCos((sint32) *ptCurrAngle + 64) + ptBasis->Y * CPSUtil::getSin((sint32) *ptCurrAngle + 64)
00419 , ptBasis->X ^ ptBasis->Y
00420 );
00421
00422 mat.scale(*ptCurrSize);
00423
00424 (*instanceIt)->setMatrix(transfo * tmat * mat);
00425 if (CParticleSystem::OwnerModel)
00426 {
00427
00428 if (CParticleSystem::OwnerModel->isHrcVisible())
00429 {
00430 (*instanceIt)->show();
00431 }
00432 else
00433 {
00434 (*instanceIt)->hide();
00435 }
00436 (*instanceIt)->setClusterSystem(CParticleSystem::OwnerModel->getClusterSystem());
00437 }
00438
00439 ++instanceIt;
00440 ++posIt;
00441 ptCurrSize += ptCurrSizeIncrement;
00442 ptCurrAngle += ptCurrAngleIncrement;
00443 ptBasis += ptCurrPlaneBasisIncrement;
00444 }
00445 while (posIt != endPosIt);
00446 leftToDo -= toProcess;
00447 }
00448 while (leftToDo);
00449
00450 PARTICLES_CHECK_MEM;
00451 }
00452
00453
00454 void CPSMesh::resize(uint32 size)
00455 {
00456 NL_PS_FUNC(CPSMesh_resize)
00457 nlassert(size < (1 << 16));
00458 resizeSize(size);
00459 resizeAngle2D(size);
00460 resizePlaneBasis(size);
00461 if (size < _Instances.getSize())
00462 {
00463 for(uint k = size; k < _Instances.getSize(); ++k)
00464 {
00465 if (_Owner) _Owner->getScene()->deleteInstance(_Instances[k]);
00466 }
00467 }
00468 _Instances.resize(size);
00469 }
00470
00471
00472
00473 CPSMesh::~CPSMesh()
00474 {
00475 NL_PS_FUNC(CPSMesh_CPSMeshDtor)
00476 if (_Owner && _Owner->getOwner())
00477 {
00478 removeAllInstancesFromScene();
00479 }
00480 else
00481 {
00482 #ifdef NL_DEBUG
00483 for (TInstanceCont::iterator it = _Instances.begin(); it != _Instances.end(); ++it)
00484 {
00485 nlassert(*it == NULL);
00486 }
00487 #endif
00488 }
00489 }
00490
00492
00494
00496 static uint getMeshNumTri(const CMesh &m)
00497 {
00498 NL_PS_FUNC(getMeshNumTri)
00499 uint numFaces = 0;
00500 for (uint k = 0; k < m.getNbMatrixBlock(); ++k)
00501 {
00502 for (uint l = 0; l < m.getNbRdrPass(k); ++l)
00503 {
00504 const CIndexBuffer pb = m.getRdrPassPrimitiveBlock(k, l);
00505 numFaces += pb.getNumIndexes()/3;
00506
00507 }
00508 }
00509 return numFaces;
00510 }
00511
00512
00513
00515 static void CheckForOpaqueAndTransparentFacesInMesh(const CMesh &m, bool &hasTransparentFaces, bool &hasOpaqueFaces)
00516 {
00517 NL_PS_FUNC(CheckForOpaqueAndTransparentFacesInMesh)
00518 hasTransparentFaces = false;
00519 hasOpaqueFaces = false;
00520
00521 for (uint k = 0; k < m.getNbRdrPass(0); ++k)
00522 {
00523 const CMaterial &currMat = m.getMaterial(m.getRdrPassMaterial(0, k));
00524 if (!currMat.getZWrite())
00525 {
00526 hasTransparentFaces = true;
00527 }
00528 else
00529 {
00530 hasOpaqueFaces = true;
00531 }
00532 }
00533 }
00534
00535
00537 static bool CheckForLightableFacesInMesh(const CMesh &m)
00538 {
00539 NL_PS_FUNC(CheckForLightableFacesInMesh)
00540 for (uint k = 0; k < m.getNbRdrPass(0); ++k)
00541 {
00542 const CMaterial &currMat = m.getMaterial(m.getRdrPassMaterial(0, k));
00543 if (currMat.isLighted()) return true;
00544 }
00545 return false;
00546 }
00547
00548
00554 class CPSConstraintMeshHelper
00555 {
00556 public:
00557 template <class T>
00558 static void drawMeshs(T posIt, CPSConstraintMesh &m, uint size, uint32 srcStep, bool opaque)
00559 {
00560 NL_PS_FUNC(CPSConstraintMeshHelper_drawMeshs)
00561 const CVertexBuffer &modelVb = m.getMeshVB(0);
00562
00563
00564
00565 const uint inVSize = modelVb.getVertexSize();
00566
00567
00568 IDriver *driver = m.getDriver();
00569 m.setupDriverModelMatrix();
00570
00571
00572 float sizes[ConstraintMeshBufSize];
00573
00574 float *ptCurrSize;
00575 uint ptCurrSizeIncrement = m._SizeScheme ? 1 : 0;
00576
00577 T endPosIt;
00578 uint leftToDo = size, toProcess;
00579
00581 CPSConstraintMesh::CMeshDisplay &md= m._MeshDisplayShare.getMeshDisplay(m._Meshes[0], modelVb, modelVb.getVertexFormat()
00582 | (m._ColorScheme ? CVertexBuffer::PrimaryColorFlag : 0));
00583
00584 m.setupRenderPasses((float) m._Owner->getOwner()->getSystemDate() - m._GlobalAnimDate, md.RdrPasses, opaque);
00585
00586 CVertexBuffer &outVb = md.VB;
00587 const uint outVSize = outVb.getVertexSize();
00588
00589
00590
00591
00592 CPlaneBasis planeBasis[ConstraintMeshBufSize];
00593 CPlaneBasis *ptBasis;
00594 uint ptBasisIncrement = m._PlaneBasisScheme ? 1 : 0;
00595
00596 const uint nbVerticesInSource = modelVb.getNumVertices();
00597
00598 sint inNormalOff=0;
00599 sint outNormalOff=0;
00600 if (modelVb.getVertexFormat() & CVertexBuffer::NormalFlag)
00601 {
00602 inNormalOff = modelVb.getNormalOff();
00603 outNormalOff = outVb.getNormalOff();
00604 }
00605 if (m._ColorScheme)
00606 {
00607 CVertexBuffer::TVertexColorType vtc = driver->getVertexColorFormat();
00608 m._ColorScheme->setColorType(vtc);
00609 if (modelVb.getVertexFormat() & CVertexBuffer::PrimaryColorFlag)
00610 {
00611 const_cast<CVertexBuffer &>(modelVb).setVertexColorFormat(vtc);
00612 }
00613 }
00614 CVertexBufferRead vbaRead;
00615 modelVb.lock (vbaRead);
00616 do
00617 {
00618 toProcess = std::min(leftToDo, ConstraintMeshBufSize);
00619 outVb.setNumVertices(toProcess * nbVerticesInSource);
00620 {
00621 CVertexBufferReadWrite vba;
00622 outVb.lock(vba);
00623 uint8 *outVertex = (uint8 *) vba.getVertexCoordPointer();
00624 if (m._SizeScheme)
00625 {
00626 ptCurrSize = (float *) (m._SizeScheme->make(m._Owner, size -leftToDo, &sizes[0], sizeof(float), toProcess, true, srcStep));
00627 }
00628 else
00629 {
00630 ptCurrSize = &m._ParticleSize;
00631 }
00632
00633 if (m._PlaneBasisScheme)
00634 {
00635 ptBasis = (CPlaneBasis *) (m._PlaneBasisScheme->make(m._Owner, size -leftToDo, &planeBasis[0], sizeof(CPlaneBasis), toProcess, true, srcStep));
00636 }
00637 else
00638 {
00639 ptBasis = &m._PlaneBasis;
00640 }
00641
00642
00643 endPosIt = posIt + toProcess;
00644
00645 CMatrix M, sM;
00646
00647
00648 if (m._Meshes.size() == 1)
00649 {
00651 do
00652 {
00653 const uint8 *inVertex = (const uint8 *) vbaRead.getVertexCoordPointer();
00654 uint k = nbVerticesInSource;
00655
00656
00657 if (modelVb.getVertexFormat() & CVertexBuffer::NormalFlag)
00658 {
00659 M.identity();
00660 M.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
00661 sM = M;
00662 sM.scale(*ptCurrSize);
00663
00664
00665 do
00666 {
00667 CHECK_VERTEX_BUFFER(modelVb, inVertex);
00668 CHECK_VERTEX_BUFFER(outVb, outVertex);
00669 CHECK_VERTEX_BUFFER(modelVb, inVertex + inNormalOff);
00670 CHECK_VERTEX_BUFFER(outVb, outVertex + outNormalOff);
00671
00672
00673 *(CVector *) outVertex = *posIt + sM * *(CVector *) inVertex;
00674
00675 *(CVector *) (outVertex + outNormalOff) = M * *(CVector *) (inVertex + inNormalOff);
00676
00677
00678 inVertex += inVSize;
00679 outVertex += outVSize;
00680 }
00681 while (--k);
00682 }
00683 else
00684 {
00685
00686 sM.identity();
00687 sM.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
00688 sM.scale(*ptCurrSize);
00689
00690 do
00691 {
00692 CHECK_VERTEX_BUFFER(modelVb, inVertex);
00693 CHECK_VERTEX_BUFFER(outVb, outVertex);
00694
00695
00696 *(CVector *) outVertex = *posIt + sM * *(CVector *) inVertex;
00697
00698 inVertex += inVSize;
00699 outVertex += outVSize;
00700 }
00701 while (--k);
00702 }
00703
00704
00705 ++posIt;
00706 ptCurrSize += ptCurrSizeIncrement;
00707 ptBasis += ptBasisIncrement;
00708 }
00709 while (posIt != endPosIt);
00710 }
00711 else
00712 {
00713
00714
00715
00716 float morphValues[ConstraintMeshBufSize];
00717 float *currMorphValue;
00718 uint morphValueIncr;
00719
00720 if (m._MorphScheme)
00721 {
00722 currMorphValue = (float *) m._MorphScheme->make(m._Owner, size - leftToDo, &morphValues[0], sizeof(float), toProcess, true, srcStep);
00723 morphValueIncr = 1;
00724 }
00725 else
00726 {
00727 currMorphValue = &m._MorphValue;
00728 morphValueIncr = 0;
00729 }
00730
00731 do
00732 {
00733 const uint numShapes = m._Meshes.size();
00734 const uint8 *m0, *m1;
00735 float lambda;
00736 float opLambda;
00737 const CVertexBuffer *inVB0, *inVB1;
00738 if (*currMorphValue >= numShapes - 1)
00739 {
00740 lambda = 0.f;
00741 opLambda = 1.f;
00742 inVB0 = inVB1 = &(m.getMeshVB(numShapes - 1));
00743 }
00744 else if (*currMorphValue <= 0)
00745 {
00746 lambda = 0.f;
00747 opLambda = 1.f;
00748 inVB0 = inVB1 = &(m.getMeshVB(0));
00749 }
00750 else
00751 {
00752 uint iMeshIndex = (uint) *currMorphValue;
00753 lambda = *currMorphValue - iMeshIndex;
00754 opLambda = 1.f - lambda;
00755 inVB0 = &(m.getMeshVB(iMeshIndex));
00756 inVB1 = &(m.getMeshVB(iMeshIndex + 1));
00757 }
00758 CVertexBufferRead vba0;
00759 inVB0->lock (vba0);
00760 CVertexBufferRead vba1;
00761 inVB1->lock (vba1);
00762
00763 m0 = (uint8 *) vba0.getVertexCoordPointer();
00764 m1 = (uint8 *) vba1.getVertexCoordPointer();
00765
00766
00767 uint k = nbVerticesInSource;
00768
00769 if (modelVb.getVertexFormat() & CVertexBuffer::NormalFlag)
00770 {
00771 M.identity();
00772 M.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
00773 sM = M;
00774 sM.scale(*ptCurrSize);
00775
00776
00777 do
00778 {
00779 CHECK_VERTEX_BUFFER((*inVB0), m0);
00780 CHECK_VERTEX_BUFFER((*inVB1), m1);
00781 CHECK_VERTEX_BUFFER((*inVB0), m0 + inNormalOff);
00782 CHECK_VERTEX_BUFFER((*inVB1), m1 + inNormalOff);
00783 CHECK_VERTEX_BUFFER(outVb, outVertex);
00784 CHECK_VERTEX_BUFFER(outVb, outVertex + outNormalOff);
00785
00786
00787 *(CVector *) outVertex = *posIt + sM * (opLambda * *(CVector *) m0 + lambda * *(CVector *) m1);
00788
00789 *(CVector *) (outVertex + outNormalOff) = M * (opLambda * *(CVector *) (m0 + inNormalOff)
00790 + lambda * *(CVector *) (m1 + inNormalOff)).normed();
00791
00792
00793 m0 += inVSize;
00794 m1 += inVSize;
00795 outVertex += outVSize;
00796 }
00797 while (--k);
00798 }
00799 else
00800 {
00801
00802 sM.identity();
00803 sM.setRot(ptBasis->X, ptBasis->Y, ptBasis->X ^ ptBasis->Y);
00804 sM.scale(*ptCurrSize);
00805
00806 do
00807 {
00808 CHECK_VERTEX_BUFFER((*inVB0), m0);
00809 CHECK_VERTEX_BUFFER((*inVB1), m1);
00810 CHECK_VERTEX_BUFFER(outVb, outVertex);
00811
00812 *(CVector *) outVertex = *posIt + sM * (opLambda * *(CVector *) m0 + opLambda * *(CVector *) m1);
00813
00814 m0 += inVSize;
00815 m1 += inVSize;
00816 outVertex += outVSize;
00817 }
00818 while (--k);
00819 }
00820
00821
00822 ++posIt;
00823 ptCurrSize += ptCurrSizeIncrement;
00824 ptBasis += ptBasisIncrement;
00825 currMorphValue += morphValueIncr;
00826 }
00827 while (posIt != endPosIt);
00828 }
00829
00830
00831 if (m._ColorScheme)
00832 {
00833 m.computeColors(outVb, modelVb, size - leftToDo, toProcess, srcStep, *driver, vba, vbaRead);
00834 }
00835 }
00836
00837
00838 driver->activeVertexBuffer(outVb);
00839 m.doRenderPasses(driver, toProcess, md.RdrPasses, opaque);
00840 leftToDo -= toProcess;
00841
00842 }
00843 while (leftToDo);
00844 }
00845
00846
00847 template <class T, class U>
00848 static void drawPrerotatedMeshs(T posIt,
00849 U indexIt,
00850 CPSConstraintMesh &m,
00851 uint size,
00852 uint32 srcStep,
00853 bool opaque)
00854 {
00855
00856 const CVertexBuffer &modelVb = m.getMeshVB(0);
00857
00859 CVertexBuffer &prerotVb = m.makePrerotatedVb(modelVb);
00860
00861
00862 IDriver *driver = m.getDriver();
00863 m.setupDriverModelMatrix();
00864
00865
00866 nlassert(m._Owner);
00867
00868
00869 float sizes[ConstraintMeshBufSize];
00870
00871
00872 float *ptCurrSize;
00873 uint ptCurrSizeIncrement = m._SizeScheme ? 1 : 0;
00874
00875 T endPosIt;
00876 uint leftToDo = size, toProcess;
00877 const uint nbVerticesInSource = modelVb.getNumVertices();
00878
00879
00880
00881
00882 const uint prerotatedModelSize = prerotVb.getVertexSize() * modelVb.getNumVertices();
00883
00885 CPSConstraintMesh::CMeshDisplay &md = m._MeshDisplayShare.getMeshDisplay(m._Meshes[0], modelVb, modelVb.getVertexFormat()
00886 | (m._ColorScheme ? CVertexBuffer::PrimaryColorFlag : 0));
00887
00888
00889 m.setupRenderPasses((float) m._Owner->getOwner()->getSystemDate() - m._GlobalAnimDate, md.RdrPasses, opaque);
00890
00891 CVertexBuffer &outVb = md.VB;
00892
00893
00894
00895
00896 const uint inVSize = prerotVb.getVertexSize();
00897
00898
00899 const uint outVSize = outVb.getVertexSize();
00900
00901
00902 uint normalOff=0;
00903 uint pNormalOff=0;
00904 if (prerotVb.getVertexFormat() & CVertexBuffer::NormalFlag)
00905 {
00906 normalOff = outVb.getNormalOff();
00907 pNormalOff = prerotVb.getNormalOff();
00908 }
00909
00910 if (m._ColorScheme)
00911 {
00912 CVertexBuffer::TVertexColorType vtc = driver->getVertexColorFormat();
00913 m._ColorScheme->setColorType(vtc);
00914 if (modelVb.getVertexFormat() & CVertexBuffer::PrimaryColorFlag)
00915 {
00916 const_cast<CVertexBuffer &>(modelVb).setVertexColorFormat(vtc);
00917 }
00918 }
00919
00920 CVertexBufferRead PrerotVba;
00921 prerotVb.lock(PrerotVba);
00922 do
00923 {
00924 toProcess = std::min(leftToDo, ConstraintMeshBufSize);
00925 outVb.setNumVertices(toProcess * nbVerticesInSource);
00926 {
00927 CVertexBufferReadWrite vba;
00928 outVb.lock(vba);
00929
00930
00931 if (m._SizeScheme)
00932 {
00933
00934 ptCurrSize = (float *) (m._SizeScheme->make(m._Owner, size - leftToDo, &sizes[0], sizeof(float), toProcess, true, srcStep));
00935 }
00936 else
00937 {
00938
00939 ptCurrSize = &m._ParticleSize;
00940 }
00941
00942 endPosIt = posIt + toProcess;
00943 uint8 *outVertex = (uint8 *) vba.getVertexCoordPointer();
00945 do
00946 {
00947 uint8 *inVertex = (uint8 *) PrerotVba.getVertexCoordPointer() + prerotatedModelSize * *indexIt;
00948 uint k = nbVerticesInSource;
00949
00950 if (prerotVb.getVertexFormat() & CVertexBuffer::NormalFlag)
00951 {
00952 do
00953 {
00954 CHECK_VERTEX_BUFFER(outVb, outVertex);
00955 CHECK_VERTEX_BUFFER(prerotVb, inVertex);
00956 CHECK_VERTEX_BUFFER(outVb, outVertex + normalOff);
00957 CHECK_VERTEX_BUFFER(prerotVb, inVertex + pNormalOff);
00958
00959
00960
00961 *(CVector *) outVertex = *posIt + *ptCurrSize * *(CVector *) inVertex;
00962
00963 *(CVector *) (outVertex + normalOff ) = *(CVector *) (inVertex + pNormalOff);
00964 inVertex += inVSize;
00965 outVertex += outVSize;
00966 }
00967 while (--k);
00968 }
00969 else
00970 {
00971 do
00972 {
00973
00974 CHECK_VERTEX_BUFFER(outVb, outVertex);
00975 CHECK_VERTEX_BUFFER(prerotVb, inVertex);
00976 *(CVector *) outVertex = *posIt + *ptCurrSize * *(CVector *) inVertex;
00977 inVertex += inVSize;
00978 outVertex += outVSize;
00979 }
00980 while (--k);
00981 }
00982
00983 ++indexIt;
00984 ++posIt;
00985 ptCurrSize += ptCurrSizeIncrement;
00986 }
00987 while (posIt != endPosIt);
00988
00989
00990 if (m._ColorScheme)
00991 {
00992 m.computeColors(outVb, modelVb, size - leftToDo, toProcess, srcStep, *driver, vba, PrerotVba);
00993 }
00994 }
00995
00997 driver->activeVertexBuffer(outVb);
00998 m.doRenderPasses(driver, toProcess, md.RdrPasses, opaque);
00999 leftToDo -= toProcess;
01000
01001 }
01002 while (leftToDo);
01003 PARTICLES_CHECK_MEM
01004 }
01005 };
01006
01007 CPSConstraintMesh::CPSConstraintMesh() : _NumFaces(0),
01008 _ModelBank(NULL),
01009 _ModulatedStages(0),
01010 _Touched(1),
01011 _HasOpaqueFaces(0),
01012 _VertexColorLightingForced(false),
01013 _GlobalAnimationEnabled(0),
01014 _ReinitGlobalAnimTimeOnNewElement(0),
01015 _HasLightableFaces(0),
01016 _ValidBuild(0),
01017 _MorphValue(0),
01018 _MorphScheme(NULL)
01019 {
01020 NL_PS_FUNC(CPSConstraintMesh_CPSConstraintMesh)
01021 if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("ConstraintMesh");
01022 }
01023
01024
01025 uint32 CPSConstraintMesh::getNumWantedTris() const
01026 {
01027 NL_PS_FUNC(CPSConstraintMesh_getNumWantedTris)
01028
01029
01030 return _NumFaces * _Owner->getSize();
01031 }
01032
01033
01034
01035 bool CPSConstraintMesh::hasTransparentFaces(void)
01036 {
01037 NL_PS_FUNC(CPSConstraintMesh_hasTransparentFaces)
01038 if (!_Touched) return _HasTransparentFaces != 0;
01040 update();
01041 return _HasTransparentFaces != 0;
01042 }
01043
01044
01045 bool CPSConstraintMesh::hasOpaqueFaces(void)
01046 {
01047 NL_PS_FUNC(CPSConstraintMesh_hasOpaqueFaces)
01048 if (!_Touched) return _HasOpaqueFaces != 0;
01049 update();
01050 return _HasOpaqueFaces != 0;
01051 }
01052
01053
01054 bool CPSConstraintMesh::hasLightableFaces()
01055 {
01056 NL_PS_FUNC(CPSConstraintMesh_hasLightableFaces)
01057 if (!_Touched) return _HasLightableFaces != 0;
01058 update();
01059 return _HasLightableFaces != 0;
01060 }
01061
01062
01063
01064 void CPSConstraintMesh::setShape(const std::string &meshFileName)
01065 {
01066 NL_PS_FUNC(CPSConstraintMesh_setShape)
01067 _MeshShapeFileName.resize(1);
01068 _MeshShapeFileName[0] = meshFileName;
01069 _Touched = 1;
01070 _ValidBuild = 0;
01071 }
01072
01073
01074
01075 std::string CPSConstraintMesh::getShape(void) const
01076 {
01077 NL_PS_FUNC(CPSConstraintMesh_getShape)
01078 if (_Touched)
01079 {
01080 const_cast<CPSConstraintMesh *>(this)->update();
01081 }
01082 nlassert(_MeshShapeFileName.size() == 1);
01083 return _MeshShapeFileName[0];
01084 }
01085
01086
01087 bool CPSConstraintMesh::isValidBuild() const
01088 {
01089 NL_PS_FUNC(CPSConstraintMesh_isValidBuild)
01090 if (_Touched)
01091 {
01092 const_cast<CPSConstraintMesh *>(this)->update();
01093 }
01094 return _ValidBuild != 0;
01095 }
01096
01097
01098 void CPSConstraintMesh::setShapes(const std::string *shapesNames, uint numShapes)
01099 {
01100 NL_PS_FUNC(CPSConstraintMesh_setShapes)
01101 _MeshShapeFileName.resize(numShapes);
01102 std::copy(shapesNames, shapesNames + numShapes, _MeshShapeFileName.begin());
01103 _Touched = 1;
01104 _ValidBuild = 0;
01105 }
01106
01107
01108 uint CPSConstraintMesh::getNumShapes() const
01109 {
01110 NL_PS_FUNC(CPSConstraintMesh_getNumShapes)
01111 if (_Touched)
01112 {
01113 const_cast<CPSConstraintMesh *>(this)->update();
01114 }
01115 return _MeshShapeFileName.size();
01116 }
01117
01118
01119 void CPSConstraintMesh::getShapesNames(std::string *shapesNames) const
01120 {
01121 NL_PS_FUNC(CPSConstraintMesh_getShapesNames)
01122 if (_Touched)
01123 {
01124 const_cast<CPSConstraintMesh *>(this)->update();
01125 }
01126 std::copy(_MeshShapeFileName.begin(), _MeshShapeFileName.end(), shapesNames);
01127 }
01128
01129
01130
01131
01132 void CPSConstraintMesh::setShape(uint index, const std::string &shapeName)
01133 {
01134 NL_PS_FUNC(CPSConstraintMesh_setShape)
01135 nlassert(index < _MeshShapeFileName.size());
01136 _MeshShapeFileName[index] = shapeName;
01137 _Touched = 1;
01138 _ValidBuild = 0;
01139 }
01140
01141
01142
01143 const std::string &CPSConstraintMesh::getShape(uint index) const
01144 {
01145 NL_PS_FUNC(CPSConstraintMesh_getShape)
01146 if (_Touched)
01147 {
01148 const_cast<CPSConstraintMesh *>(this)->update();
01149 }
01150 nlassert(index < _MeshShapeFileName.size());
01151 return _MeshShapeFileName[index];
01152 }
01153
01154
01155
01156
01157 void CPSConstraintMesh::setMorphValue(float value)
01158 {
01159 NL_PS_FUNC(CPSConstraintMesh_setMorphValue)
01160 delete _MorphScheme;
01161 _MorphScheme = NULL;
01162 _MorphValue = value;
01163 }
01164
01165
01166
01167 float CPSConstraintMesh::getMorphValue() const
01168 {
01169 NL_PS_FUNC(CPSConstraintMesh_getMorphValue)
01170 return _MorphValue;
01171 }
01172
01173
01174 void CPSConstraintMesh::setMorphScheme(CPSAttribMaker<float> *scheme)
01175 {
01176 NL_PS_FUNC(CPSConstraintMesh_setMorphScheme)
01177 delete _MorphScheme;
01178 _MorphScheme = scheme;
01179 if (_MorphScheme->hasMemory()) _MorphScheme->resize(_Owner->getMaxSize(), _Owner->getSize());
01180 }
01181
01182
01183 CPSAttribMaker<float> *CPSConstraintMesh::getMorphScheme()
01184 {
01185 NL_PS_FUNC(CPSConstraintMesh_getMorphScheme)
01186 return _MorphScheme;
01187 }
01188
01189
01190 const CPSAttribMaker<float> *CPSConstraintMesh::getMorphScheme() const
01191 {
01192 NL_PS_FUNC(CPSConstraintMesh_getMorphScheme)
01193 return _MorphScheme;
01194 }
01195
01196
01197
01198 static CMesh *GetDummyMeshFromBank(CShapeBank &sb)
01199 {
01200 NL_PS_FUNC(GetDummyMeshFromBank)
01201 static const std::string dummyMeshName("dummy constraint mesh shape");
01202 if (sb.getPresentState(dummyMeshName) == CShapeBank::Present)
01203 {
01204 return NLMISC::safe_cast<CMesh *>(sb.addRef(dummyMeshName));
01205 }
01206 else
01207 {
01208
01209 CMesh *m = CreateDummyMesh();
01210 sb.add(std::string("dummy constraint mesh shape"), m);
01211 return m;
01212 }
01213 }
01214
01215
01216 void CPSConstraintMesh::getShapeNumVerts(std::vector<sint> &numVerts)
01217 {
01218 NL_PS_FUNC(CPSConstraintMesh_getShapeNumVerts)
01219 _Touched = 1;
01220 update(&numVerts);
01221 }
01222
01223
01224 bool CPSConstraintMesh::update(std::vector<sint> *numVertsVect )
01225 {
01226 NL_PS_FUNC(CPSConstraintMesh_update)
01227 bool ok = true;
01228 if (!_Touched) return ok;
01229
01230 clean();
01231
01232 nlassert(_Owner->getScene());
01233
01234 CScene *scene = _Owner->getScene();
01235 _ModelBank = scene->getShapeBank();
01236 IShape *is = 0;
01237
01238
01239 uint32 vFormat = 0;
01240 uint numVerts = 0;
01241 uint8 uvRouting[CVertexBuffer::MaxStage];
01242
01243 if (_MeshShapeFileName.size() == 0)
01244 {
01245 _MeshShapeFileName.resize(1);
01246 _MeshShapeFileName[0] = DummyShapeName;
01247 }
01248
01249
01250 _Meshes.resize(_MeshShapeFileName.size());
01251 _MeshVertexBuffers.resize(_MeshShapeFileName.size());
01252 std::fill(_MeshVertexBuffers.begin(), _MeshVertexBuffers.end(), (CVertexBuffer *) NULL);
01253 if (numVertsVect) numVertsVect->resize(_MeshShapeFileName.size());
01254 for (uint k = 0; k < _MeshShapeFileName.size(); ++k)
01255 {
01256 if (_ModelBank->getPresentState(_MeshShapeFileName[k]) == CShapeBank::Present)
01257 {
01258 CMesh *mesh = dynamic_cast<CMesh *>( _ModelBank->addRef(_MeshShapeFileName[k]));
01259 if (!mesh)
01260 {
01261 nlwarning("Tried to bind a shape that is not a mesh to a mesh particle : %s", _MeshShapeFileName[k].c_str());
01262 _ModelBank->release(is);
01263 ok = false;
01264 if (numVertsVect) (*numVertsVect)[k] = ShapeFileIsNotAMesh;
01265 }
01266 else
01267 {
01268 _Meshes[k] = mesh;
01270 if (k == 0)
01271 {
01272 vFormat = mesh->getVertexBuffer().getVertexFormat();
01273 numVerts = mesh->getVertexBuffer().getNumVertices();
01274 std::copy(mesh->getVertexBuffer().getUVRouting(), mesh->getVertexBuffer().getUVRouting() + CVertexBuffer::MaxStage, uvRouting);
01275 if (numVertsVect) (*numVertsVect)[k] = (sint) numVerts;
01276 }
01277 else
01278 {
01279 if (vFormat != mesh->getVertexBuffer().getVertexFormat())
01280 {
01281 nlwarning("Vertex format differs between meshs");
01282 ok = false;
01283 }
01284 if (numVerts != mesh->getVertexBuffer().getNumVertices())
01285 {
01286 nlwarning("Num vertices differs between meshs");
01287 ok = false;
01288 }
01289 if (!std::equal(mesh->getVertexBuffer().getUVRouting(), mesh->getVertexBuffer().getUVRouting() + CVertexBuffer::MaxStage, uvRouting))
01290 {
01291 nlwarning("UV routing differs between meshs");
01292 ok = false;
01293 }
01294 if (numVertsVect) (*numVertsVect)[k] = (sint) mesh->getVertexBuffer().getNumVertices();
01295 }
01296 }
01297 }
01298 else
01299 {
01300 try
01301 {
01302 _ModelBank->load(_MeshShapeFileName[k]);
01303 }
01304 catch (NLMISC::EPathNotFound &)
01305 {
01306 nlwarning("mesh not found : %s; used as a constraint mesh particle", _MeshShapeFileName[k].c_str());
01307
01308 }
01309
01310 if (_ModelBank->getPresentState(_MeshShapeFileName[k]) != CShapeBank::Present)
01311 {
01312 ok = false;
01313 if (numVertsVect) (*numVertsVect)[k] = ShapeFileNotLoaded;
01314 }
01315 else
01316 {
01317 is = _ModelBank->addRef(_MeshShapeFileName[k]);
01318 if (!dynamic_cast<CMesh *>(is))
01319 {
01320 nlwarning("Tried to bind a shape that is not a mesh to a mesh particle : %s", _MeshShapeFileName[k].c_str());
01321 _ModelBank->release(is);
01322 ok = false;
01323 if (numVertsVect) (*numVertsVect)[k] = ShapeFileIsNotAMesh;
01324 }
01325 else
01326 {
01327 CMesh &m = * NLMISC::safe_cast<CMesh *>(is);
01329 if (m.getVertexBuffer().getNumVertices() > ConstraintMeshMaxNumVerts)
01330 {
01331 nlwarning("Tried to bind a mesh that has more than %d vertices to a particle mesh: %s", (int) ConstraintMeshMaxNumVerts, _MeshShapeFileName[k].c_str());
01332 _ModelBank->release(is);
01333 ok = false;
01334 if (numVertsVect) (*numVertsVect)[k] = ShapeHasTooMuchVertices;
01335 }
01336 else
01337 {
01338 _Meshes[k] = &m;
01339 if (k == 0)
01340 {
01341 vFormat = m.getVertexBuffer().getVertexFormat();
01342 numVerts = m.getVertexBuffer().getNumVertices();
01343 std::copy(m.getVertexBuffer().getUVRouting(), m.getVertexBuffer().getUVRouting() + CVertexBuffer::MaxStage, uvRouting);
01344 if (numVertsVect) (*numVertsVect)[k] = numVerts;
01345 }
01346 else
01347 {
01348 uint32 otherVFormat = m.getVertexBuffer().getVertexFormat();
01349 uint otherNumVerts = m.getVertexBuffer().getNumVertices();
01350 if (otherVFormat != vFormat ||
01351 otherNumVerts != numVerts ||
01352 !(std::equal(m.getVertexBuffer().getUVRouting(), m.getVertexBuffer().getUVRouting() + CVertexBuffer::MaxStage, uvRouting)))
01353 {
01354 ok = false;
01355 }
01356 if (numVertsVect) (*numVertsVect)[k] = otherNumVerts;
01357 }
01358 }
01359 }
01360 }
01361 }
01362
01363 if (!ok && !numVertsVect) break;
01364 }
01365
01366 if (!ok)
01367 {
01368 releaseShapes();
01369 _Meshes.resize(1);
01370 _MeshVertexBuffers.resize(1);
01371 _Meshes[0] = GetDummyMeshFromBank(*_ModelBank);
01372 _MeshVertexBuffers[0] = &_Meshes[0]->getVertexBuffer();
01373 }
01374
01375 const CMesh &m = *_Meshes[0];
01376
01378 _NumFaces = getMeshNumTri(m);
01379
01380
01381
01382
01383
01384
01385
01387 bool hasTransparentFaces, hasOpaqueFaces;
01388 CheckForOpaqueAndTransparentFacesInMesh(m, hasTransparentFaces, hasOpaqueFaces);
01389 _HasTransparentFaces = hasTransparentFaces;
01390 _HasOpaqueFaces = hasOpaqueFaces;
01391 _HasLightableFaces = CheckForLightableFacesInMesh(m);
01392 _GlobalAnimDate = _Owner->getOwner()->getSystemDate();
01393 _Touched = 0;
01394 _ValidBuild = ok ? 1 : 0;
01395 nlassert(_Meshes.size() > 0);
01396
01397 return ok;
01398
01399 }
01400
01401
01402
01403
01404 void CPSConstraintMesh::hintRotateTheSame(uint32 nbConfiguration,
01405 float minAngularVelocity,
01406 float maxAngularVelocity
01407 )
01408 {
01409 NL_PS_FUNC(CPSConstraintMesh_hintRotateTheSame)
01410 nlassert(nbConfiguration <= ConstraintMeshMaxNumPrerotatedModels);
01411
01412
01413 _MinAngularVelocity = minAngularVelocity;
01414 _MaxAngularVelocity = maxAngularVelocity;
01415
01416
01417
01418 _PrecompBasis.resize(nbConfiguration);
01419
01420 if (nbConfiguration)
01421 {
01422
01423 for (uint k = 0; k < nbConfiguration; ++k)
01424 {
01425 CVector v = MakeRandomUnitVect();
01426 _PrecompBasis[k].Basis = CPlaneBasis(v);
01427 _PrecompBasis[k].Axis = MakeRandomUnitVect();
01428 _PrecompBasis[k].AngularVelocity = minAngularVelocity
01429 + (rand() % 20000) / 20000.f * (maxAngularVelocity - minAngularVelocity);
01430
01431 }
01432
01433
01434 fillIndexesInPrecompBasis();
01435 }
01436 }
01437
01438
01439
01440 void CPSConstraintMesh::fillIndexesInPrecompBasis(void)
01441 {
01442 NL_PS_FUNC(CPSConstraintMesh_fillIndexesInPrecompBasis)
01443
01444 const uint32 nbConf = _PrecompBasis.size();
01445 if (_Owner)
01446 {
01447 _IndexInPrecompBasis.resize( _Owner->getMaxSize() );
01448 }
01449 for (CPSVector<uint32>::V::iterator it = _IndexInPrecompBasis.begin(); it != _IndexInPrecompBasis.end(); ++it)
01450 {
01451 *it = rand() % nbConf;
01452 }
01453 }
01454
01455
01457 void CPSConstraintMesh::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
01458 {
01459 NL_PS_FUNC(CPSConstraintMesh_IStream )
01460
01461 sint ver = f.serialVersion(4);
01462 if (f.isReading())
01463 {
01464 clean();
01465 }
01466
01467 CPSParticle::serial(f);
01468 CPSSizedParticle::serialSizeScheme(f);
01469 CPSRotated3DPlaneParticle::serialPlaneBasisScheme(f);
01470
01471
01472
01473 if (f.isReading())
01474 {
01475 uint32 nbConfigurations;
01476 f.serial(nbConfigurations);
01477 if (nbConfigurations)
01478 {
01479 f.serial(_MinAngularVelocity, _MaxAngularVelocity);
01480 }
01481 hintRotateTheSame(nbConfigurations, _MinAngularVelocity, _MaxAngularVelocity);
01482 }
01483 else
01484 {
01485 uint32 nbConfigurations = _PrecompBasis.size();
01486 f.serial(nbConfigurations);
01487 if (nbConfigurations)
01488 {
01489 f.serial(_MinAngularVelocity, _MaxAngularVelocity);
01490 }
01491 }
01492
01493
01494 static std::string emptyStr;
01495
01496 if (ver < 4)
01497 {
01498 if (!f.isReading())
01499 {
01500 if (_MeshShapeFileName.size() > 0)
01501 {
01502 f.serial(_MeshShapeFileName[0]);
01503 }
01504 else
01505 {
01506 f.serial(emptyStr);
01507 }
01508 }
01509 else
01510 {
01511 _MeshShapeFileName.resize(1);
01512 f.serial(_MeshShapeFileName[0]);
01513 _Touched = true;
01514 _ValidBuild = 0;
01515 }
01516 }
01517
01518 if (ver > 1)
01519 {
01520 CPSColoredParticle::serialColorScheme(f);
01521 f.serial(_ModulatedStages);
01522 if (f.isReading())
01523 {
01524 bool vcEnabled;
01525 f.serial(vcEnabled);
01526 _VertexColorLightingForced = vcEnabled;
01527 }
01528 else
01529 {
01530 bool vcEnabled = (_VertexColorLightingForced != 0);
01531 f.serial(vcEnabled);
01532 }
01533 }
01534
01535 if (ver > 2)
01536 {
01537 if (f.isReading())
01538 {
01539 bool gaEnabled;
01540 f.serial(gaEnabled);
01541 _GlobalAnimationEnabled = gaEnabled;
01542 if (gaEnabled)
01543 {
01544 PGlobalTexAnims newPtr(new CGlobalTexAnims);
01545
01546 _GlobalTexAnims = newPtr;
01547 f.serial(*_GlobalTexAnims);
01548 }
01549
01550 bool rgt;
01551 f.serial(rgt);
01552 _ReinitGlobalAnimTimeOnNewElement = rgt;
01553 }
01554 else
01555 {
01556 bool gaEnabled = (_GlobalAnimationEnabled != 0);
01557 f.serial(gaEnabled);
01558 if (gaEnabled)
01559 {
01560 f.serial(*_GlobalTexAnims);
01561 }
01562
01563 bool rgt = _ReinitGlobalAnimTimeOnNewElement != 0;
01564 f.serial(rgt);
01565 }
01566 }
01567
01568 if (ver > 3)
01569 {
01570 if (!f.isReading())
01571 {
01572
01573 TMeshNameVect meshNamesWithoutPath = _MeshShapeFileName;
01574 std::transform(meshNamesWithoutPath.begin(), meshNamesWithoutPath.end(), meshNamesWithoutPath.begin(), std::ptr_fun(NLMISC::CFile::getFilename));
01575 f.serialCont(meshNamesWithoutPath);
01576 }
01577 else
01578 {
01579 f.serialCont(_MeshShapeFileName);
01580 }
01581 bool useScheme;
01582 if (f.isReading())
01583 {
01584 delete _MorphScheme;
01585 }
01586 else
01587 {
01588 useScheme = _MorphScheme != NULL;
01589 }
01590 f.serial(useScheme);
01591 if (useScheme)
01592 {
01593 f.serialPolyPtr(_MorphScheme);
01594 }
01595 else
01596 {
01597 f.serial(_MorphValue);
01598 }
01599 }
01600 }
01601
01602
01603 CPSConstraintMesh::~CPSConstraintMesh()
01604 {
01605 NL_PS_FUNC(CPSConstraintMesh_CPSConstraintMeshDtor)
01606 clean();
01607 delete _MorphScheme;
01608 }
01609
01610
01611
01612
01613 void CPSConstraintMesh::releaseShapes()
01614 {
01615 NL_PS_FUNC(CPSConstraintMesh_releaseShapes)
01616 for (TMeshVect::iterator it = _Meshes.begin(); it != _Meshes.end(); ++it)
01617 {
01618 if (*it)
01619 {
01620 if (_ModelBank) _ModelBank->release(*it);
01621 }
01622 }
01623 _Meshes.clear();
01624 _MeshVertexBuffers.clear();
01625 }
01626
01627
01628 void CPSConstraintMesh::clean(void)
01629 {
01630 NL_PS_FUNC(CPSConstraintMesh_clean)
01631 if (_ModelBank)
01632 {
01633 releaseShapes();
01634 }
01635 }
01636
01637
01638
01639 CVertexBuffer &CPSConstraintMesh::makePrerotatedVb(const CVertexBuffer &inVb)
01640 {
01641 NL_PS_FUNC(CPSConstraintMesh_makePrerotatedVb)
01642
01643 CVertexBuffer &prerotatedVb = inVb.getVertexFormat() & CVertexBuffer::NormalFlag ? _PreRotatedMeshVBWithNormal : _PreRotatedMeshVB;
01644 CVertexBufferReadWrite vba;
01645 prerotatedVb.lock (vba);
01646 CVertexBufferRead vbaIn;
01647 inVb.lock (vbaIn);
01648
01649
01650 const uint vSize = inVb.getVertexSize();
01651
01652
01653 const uint vpSize = prerotatedVb.getVertexSize();
01654
01655
01656
01657 uint normalOff=0;
01658 uint pNormalOff=0;
01659 if (prerotatedVb.getVertexFormat() & CVertexBuffer::NormalFlag)
01660 {
01661 normalOff = inVb.getNormalOff();
01662 pNormalOff = prerotatedVb.getNormalOff();
01663 }
01664
01665 const uint nbVerticesInSource = inVb.getNumVertices();
01666
01667
01668
01669
01670 uint8 *outVertex = (uint8 *) vba.getVertexCoordPointer();
01671 for (CPSVector<CPlaneBasisPair>::V::iterator it = _PrecompBasis.begin(); it != _PrecompBasis.end(); ++it)
01672 {
01673
01674 CMatrix mat;
01675 mat.rotate(CQuat(it->Axis, CParticleSystem::EllapsedTime * it->AngularVelocity));
01676 CVector n = mat * it->Basis.getNormal();
01677 it->Basis = CPlaneBasis(n);
01678
01679 mat.identity();
01680 mat.setRot(it->Basis.X, it->Basis.Y, it->Basis.X ^ it->Basis.Y);
01681
01682 uint8 *inVertex = (uint8 *) vbaIn.getVertexCoordPointer();
01683
01684 uint k = nbVerticesInSource;
01685
01686
01687 if (inVb.getVertexFormat() & CVertexBuffer::NormalFlag)
01688 {
01689
01690 do
01691 {
01692 CHECK_VERTEX_BUFFER(inVb, inVertex);
01693 CHECK_VERTEX_BUFFER(inVb, inVertex + normalOff);
01694 CHECK_VERTEX_BUFFER(prerotatedVb, outVertex);
01695 CHECK_VERTEX_BUFFER(prerotatedVb, outVertex + pNormalOff);
01696
01697 * (CVector *) outVertex = mat.mulVector(* (CVector *) inVertex);
01698 * (CVector *) (outVertex + normalOff) = mat.mulVector(* (CVector *) (inVertex + pNormalOff) );
01699 outVertex += vpSize;
01700 inVertex += vSize;
01701
01702 }
01703 while (--k);
01704 }
01705 else
01706 {
01707
01708 do
01709 {
01710
01711 CHECK_VERTEX_BUFFER(prerotatedVb, outVertex);
01712 CHECK_VERTEX_BUFFER(inVb, inVertex);
01713
01714 * (CVector *) outVertex = mat.mulVector(* (CVector *) inVertex);
01715 outVertex += vpSize;
01716 inVertex += vSize;
01717 }
01718 while (--k);
01719
01720 }
01721 }
01722 return prerotatedVb;
01723 }
01724
01725
01726
01727 void CPSConstraintMesh::step(TPSProcessPass pass)
01728 {
01729 NL_PS_FUNC(CPSConstraintMesh_step)
01730 if (
01731 (pass == PSBlendRender && hasTransparentFaces())
01732 || (pass == PSSolidRender && hasOpaqueFaces())
01733 )
01734 {
01735 draw(pass == PSSolidRender);
01736 }
01737 else
01738 if (pass == PSToolRender)
01739 {
01740 showTool();
01741 }
01742 }
01743
01744
01745 void CPSConstraintMesh::draw(bool opaque)
01746 {
01747
01748 NL_PS_FUNC(CPSConstraintMesh_draw)
01749 PARTICLES_CHECK_MEM;
01750 nlassert(_Owner);
01751
01752 update();
01753 uint32 step;
01754 uint numToProcess;
01755 computeSrcStep(step, numToProcess);
01756 if (!numToProcess) return;
01757 _Owner->incrementNbDrawnParticles(numToProcess);
01758
01759
01760 if (_PrecompBasis.size() == 0)
01761 {
01762 if (step == (1 << 16))
01763 {
01764 CPSConstraintMeshHelper::drawMeshs(_Owner->getPos().begin(),
01765 *this,
01766 numToProcess,
01767 step,
01768 opaque
01769 );
01770 }
01771 else
01772 {
01773 CPSConstraintMeshHelper::drawMeshs(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
01774 *this,
01775 numToProcess,
01776 step,
01777 opaque
01778 );
01779 }
01780 }
01781 else
01782 {
01783 if (step == (1 << 16))
01784 {
01785 CPSConstraintMeshHelper::drawPrerotatedMeshs(_Owner->getPos().begin(),
01786 _IndexInPrecompBasis.begin(),
01787 *this,
01788 numToProcess,
01789 step,
01790 opaque
01791 );
01792 }
01793 else
01794 {
01795 typedef CAdvance1616Iterator<CPSVector<uint32>::V::const_iterator, uint32> TIndexIterator;
01796 CPSConstraintMeshHelper::drawPrerotatedMeshs(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
01797 TIndexIterator(_IndexInPrecompBasis.begin(), 0, step),
01798 *this,
01799 numToProcess,
01800 step,
01801 opaque
01802 );
01803 }
01804 }
01805
01806
01807 }
01808
01809
01810 void CPSConstraintMesh::setupMaterialColor(CMaterial &destMat, CMaterial &srcMat)
01811 {
01812 NL_PS_FUNC(CPSConstraintMesh_setupMaterialColor)
01813 if (destMat.getShader() != CMaterial::Normal) return;
01814 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
01815 {
01816 if (_ModulatedStages & (1 << k))
01817 {
01818 destMat.texEnvArg0RGB(k, CMaterial::Texture, CMaterial::SrcColor);
01819 destMat.texEnvArg0Alpha(k, CMaterial::Texture, CMaterial::SrcAlpha);
01820 destMat.texEnvArg1RGB(k, CMaterial::Diffuse, CMaterial::SrcColor);
01821 destMat.texEnvArg1Alpha(k, CMaterial::Diffuse, CMaterial::SrcAlpha);
01822 destMat.texEnvOpRGB(k, CMaterial::Modulate);
01823 destMat.texEnvOpAlpha(k, CMaterial::Modulate);
01824 }
01825 else
01826 {
01827 destMat.setTexEnvMode(k, srcMat.getTexEnvMode(k));
01828 }
01829 }
01830 if (_ColorScheme == NULL)
01831 {
01832 destMat.setColor(_Color);
01833 if (destMat.isLighted())
01834 {
01835 destMat.setDiffuse(_Color);
01836 }
01837 }
01838 }
01839
01840
01841
01842
01843
01844 void CPSConstraintMesh::setupRenderPasses(float date, TRdrPassSet &rdrPasses, bool opaque)
01845 {
01846 NL_PS_FUNC(CPSConstraintMesh_setupRenderPasses)
01847
01848 for (TRdrPassSet::iterator rdrPassIt = rdrPasses.begin();
01849 rdrPassIt != rdrPasses.end(); ++rdrPassIt)
01850 {
01851
01852 CMaterial &Mat = rdrPassIt->Mat;
01853 CMaterial &SourceMat = rdrPassIt->SourceMat;
01854
01855
01857 if ((opaque && Mat.getZWrite()) || (!opaque && ! Mat.getZWrite()))
01858 {
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01881 setupMaterialColor(Mat, SourceMat);
01882
01884 bool forceVertexcolorLighting;
01885 if (_ColorScheme != NULL)
01886 {
01887 forceVertexcolorLighting = _VertexColorLightingForced != 0 ? true : SourceMat.getLightedVertexColor();
01888 }
01889 else
01890 {
01891 forceVertexcolorLighting = false;
01892 }
01893 if (forceVertexcolorLighting != Mat.getLightedVertexColor())
01894 {
01895 Mat.setLightedVertexColor(forceVertexcolorLighting);
01896 }
01897
01899 if (_GlobalAnimationEnabled != 0)
01900 {
01901 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
01902 {
01903 if (Mat.getTexture(k) != NULL)
01904 {
01905 Mat.enableUserTexMat(k, true);
01906 CMatrix mat;
01907 _GlobalTexAnims->Anims[k].buildMatrix(date, mat);
01908 Mat.setUserTexMat(k ,mat);
01909 }
01910 }
01911 }
01912 }
01913 }
01914
01915 }
01916
01917
01918 void CPSConstraintMesh::doRenderPasses(IDriver *driver, uint numObj, TRdrPassSet &rdrPasses, bool opaque)
01919 {
01920 NL_PS_FUNC(CPSConstraintMesh_doRenderPasses)
01921
01922 for (TRdrPassSet::iterator rdrPassIt = rdrPasses.begin(); rdrPassIt != rdrPasses.end(); ++rdrPassIt)
01923 {
01924 CMaterial &Mat = rdrPassIt->Mat;
01925 if ((opaque && Mat.getZWrite()) || (!opaque && ! Mat.getZWrite()))
01926 {
01928 rdrPassIt->PbTri.setNumIndexes(((rdrPassIt->PbTri.capacity()/3) * numObj / ConstraintMeshBufSize) * 3);
01929 rdrPassIt->PbLine.setNumIndexes(((rdrPassIt->PbLine.capacity()/2) * numObj / ConstraintMeshBufSize) * 2);
01930
01932 driver->activeIndexBuffer (rdrPassIt->PbTri);
01933 driver->renderTriangles(rdrPassIt->Mat, 0, rdrPassIt->PbTri.getNumIndexes()/3);
01934 if (rdrPassIt->PbLine.getNumIndexes() != 0)
01935 {
01936 driver->activeIndexBuffer (rdrPassIt->PbLine);
01937 driver->renderLines(rdrPassIt->Mat, 0, rdrPassIt->PbLine.getNumIndexes()/2);
01938 }
01939 }
01940 }
01941
01942 }
01943
01944
01945
01946 void CPSConstraintMesh::computeColors(CVertexBuffer &outVB, const CVertexBuffer &inVB, uint startIndex, uint toProcess, uint32 srcStep, IDriver &drv,
01947 CVertexBufferReadWrite &vba,
01948 CVertexBufferRead &vbaIn
01949 )
01950 {
01951 NL_PS_FUNC(CPSConstraintMesh_computeColors)
01952 nlassert(_ColorScheme);
01953
01954
01955
01956 if (inVB.getVertexFormat() & CVertexBuffer::PrimaryColorFlag)
01957 {
01958
01959 _ColorScheme->makeN(_Owner, startIndex, vba.getColorPointer(), outVB.getVertexSize(), toProcess, inVB.getNumVertices(), srcStep);
01960
01961
01962 uint8 *vDest = (uint8 *) vba.getColorPointer();
01963 uint8 *vSrc = (uint8 *) vbaIn.getColorPointer();
01964 const uint vSize = outVB.getVertexSize();
01965 const uint numVerts = inVB.getNumVertices();
01966 uint meshSize = vSize * numVerts;
01967 for (uint k = 0; k < toProcess; ++k)
01968 {
01969 NLMISC::CRGBA::modulateColors((CRGBA *) vDest, (CRGBA *) vSrc, (CRGBA *) vDest, numVerts, vSize, vSize);
01970 vDest += meshSize;
01971 }
01972 }
01973 else
01974 {
01975 _ColorScheme->makeN(_Owner, startIndex, vba.getColorPointer(), outVB.getVertexSize(), toProcess, inVB.getNumVertices(), srcStep);
01976 }
01977 }
01978
01979
01980
01981 void CPSConstraintMesh::newElement(const CPSEmitterInfo &info)
01982 {
01983 NL_PS_FUNC(CPSConstraintMesh_newElement)
01984 newSizeElement(info);
01985 newPlaneBasisElement(info);
01986
01987 const uint32 nbConf = _PrecompBasis.size();
01988 if (nbConf)
01989 {
01990 _IndexInPrecompBasis[_Owner->getNewElementIndex()] = rand() % nbConf;
01991 }
01992 newColorElement(info);
01993 if (_GlobalAnimationEnabled && _ReinitGlobalAnimTimeOnNewElement)
01994 {
01995 _GlobalAnimDate = _Owner->getOwner()->getSystemDate();
01996 }
01997 if (_MorphScheme && _MorphScheme->hasMemory()) _MorphScheme->newElement(info);
01998 }
01999
02000
02001 void CPSConstraintMesh::deleteElement(uint32 index)
02002 {
02003 NL_PS_FUNC(CPSConstraintMesh_deleteElement)
02004 deleteSizeElement(index);
02005 deletePlaneBasisElement(index);
02006
02007 if (_PrecompBasis.size())
02008 {
02009
02010 _IndexInPrecompBasis[index] = _IndexInPrecompBasis[_Owner->getSize() - 1];
02011 }
02012 deleteColorElement(index);
02013 if (_MorphScheme && _MorphScheme->hasMemory()) _MorphScheme->deleteElement(index);
02014 }
02015
02016
02017 void CPSConstraintMesh::resize(uint32 size)
02018 {
02019 NL_PS_FUNC(CPSConstraintMesh_resize)
02020 nlassert(size < (1 << 16));
02021 resizeSize(size);
02022 resizePlaneBasis(size);
02023
02024 if (_PrecompBasis.size())
02025 {
02026 _IndexInPrecompBasis.resize(size);
02027 }
02028 resizeColor(size);
02029 if (_MorphScheme && _MorphScheme->hasMemory()) _MorphScheme->resize(size, _Owner->getSize());
02030 }
02031
02032
02033 void CPSConstraintMesh::updateMatAndVbForColor(void)
02034 {
02035 NL_PS_FUNC(CPSConstraintMesh_updateMatAndVbForColor)
02036
02037 }
02038
02039
02040 void CPSConstraintMesh::forceStageModulationByColor(uint stage, bool force)
02041 {
02042 NL_PS_FUNC(CPSConstraintMesh_forceStageModulationByColor)
02043 nlassert(stage < IDRV_MAT_MAXTEXTURES);
02044 if (force)
02045 {
02046 _ModulatedStages |= 1 << stage;
02047 }
02048 else
02049 {
02050 _ModulatedStages &= ~(1 << stage);
02051 }
02052 }
02053
02054
02055 bool CPSConstraintMesh::isStageModulationForced(uint stage) const
02056 {
02057 NL_PS_FUNC(CPSConstraintMesh_isStageModulationForced)
02058 nlassert(stage < IDRV_MAT_MAXTEXTURES);
02059 return (_ModulatedStages & (1 << stage)) != 0;
02060 }
02061
02062
02063
02069 static void DuplicatePrimitiveBlock(const CIndexBuffer &srcBlock, CIndexBuffer &destBlock, uint nbReplicate, uint vertOffset)
02070 {
02071 NL_PS_FUNC(DuplicatePrimitiveBlock)
02072 PARTICLES_CHECK_MEM;
02073
02074
02075
02076
02077 uint k, l, index;
02078
02079
02080 uint currVertOffset;
02081
02082
02083
02084 uint numTri = srcBlock.getNumIndexes()/3;
02085 destBlock.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
02086 destBlock.setNumIndexes(3 * numTri * nbReplicate);
02087
02088 index = 0;
02089 currVertOffset = 0;
02090
02091 CIndexBufferRead ibaRead;
02092 srcBlock.lock (ibaRead);
02093 CIndexBufferReadWrite ibaWrite;
02094 destBlock.lock (ibaWrite);
02095
02096
02097 nlassert(destBlock.getFormat() == CIndexBuffer::Indices16);
02098
02099
02100 if (ibaRead.getFormat() == CIndexBuffer::Indices16)
02101 {
02102 const TIndexType *triPtr = (TIndexType *) ibaRead.getPtr();
02103 const TIndexType *currTriPtr;
02104 for (k = 0; k < nbReplicate; ++k)
02105 {
02106 currTriPtr = triPtr;
02107 for (l = 0; l < numTri; ++l)
02108 {
02109 ibaWrite.setTri(3*index, currTriPtr[0] + currVertOffset, currTriPtr[1] + currVertOffset, currTriPtr[2] + currVertOffset);
02110 currTriPtr += 3;
02111 ++ index;
02112 }
02113 currVertOffset += vertOffset;
02114 }
02115 }
02116 else
02117 {
02118 const uint32 *triPtr = (uint32 *) ibaRead.getPtr();
02119 const uint32 *currTriPtr;
02120 for (k = 0; k < nbReplicate; ++k)
02121 {
02122 currTriPtr = triPtr;
02123 for (l = 0; l < numTri; ++l)
02124 {
02125 nlassert(currTriPtr[0] + currVertOffset <= 0xffff);
02126 nlassert(currTriPtr[1] + currVertOffset <= 0xffff);
02127 nlassert(currTriPtr[2] + currVertOffset <= 0xffff);
02128
02129 ibaWrite.setTri(3*index, (uint16) (currTriPtr[0] + currVertOffset), (uint16) (currTriPtr[1] + currVertOffset), (uint16) (currTriPtr[2] + currVertOffset));
02130 currTriPtr += 3;
02131 ++ index;
02132 }
02133 currVertOffset += vertOffset;
02134 }
02135 }
02136
02137
02138
02139
02140
02141 PARTICLES_CHECK_MEM;
02142 }
02143
02144
02145 void CPSConstraintMesh::initPrerotVB()
02146 {
02147 NL_PS_FUNC(CPSConstraintMesh_initPrerotVB)
02148
02149 _PreRotatedMeshVB.setVertexFormat(CVertexBuffer::PositionFlag);
02150 _PreRotatedMeshVB.setNumVertices(ConstraintMeshMaxNumPrerotatedModels * ConstraintMeshMaxNumVerts);
02151 _PreRotatedMeshVB.setName("CPSConstraintMesh::_PreRotatedMeshVB");
02152
02153
02154 _PreRotatedMeshVBWithNormal.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::NormalFlag);
02155 _PreRotatedMeshVBWithNormal.setNumVertices(ConstraintMeshMaxNumPrerotatedModels * ConstraintMeshMaxNumVerts);
02156 _PreRotatedMeshVB.setName("CPSConstraintMesh::_PreRotatedMeshVBWithNormal");
02157 }
02158
02159
02160 CPSConstraintMesh::CMeshDisplay &CPSConstraintMesh::CMeshDisplayShare::getMeshDisplay(CMesh *mesh, const CVertexBuffer &meshVB, uint32 format)
02161 {
02162 NL_PS_FUNC(CMeshDisplayShare_getMeshDisplay)
02163 nlassert(mesh);
02164
02165 for(std::list<CMDEntry>::iterator it = _Cache.begin(); it != _Cache.end(); ++it)
02166 {
02167 if (it->Format == format && it->Mesh == mesh)
02168 {
02169
02170 _Cache.splice(_Cache.begin(), _Cache, it);
02171 return it->MD;
02172 }
02173 }
02174 if (_NumMD == _MaxNumMD)
02175 {
02176 _Cache.pop_back();
02177 -- _NumMD;
02178 }
02179
02180 _Cache.push_front(CMDEntry());
02181 _Cache.front().Mesh = mesh;
02182 _Cache.front().Format = format;
02183 buildRdrPassSet(_Cache.front().MD.RdrPasses, *mesh);
02184 _Cache.front().MD.VB.setName("CPSConstraintMesh::CMeshDisplay");
02185 buildVB(_Cache.front().MD.VB, meshVB, format);
02186 ++ _NumMD;
02187
02188
02189 return _Cache.front().MD;
02190 }
02191
02192
02193 void CPSConstraintMesh::CMeshDisplayShare::buildRdrPassSet(TRdrPassSet &dest, const CMesh &m)
02194 {
02195 NL_PS_FUNC(CMeshDisplayShare_buildRdrPassSet)
02196
02197 nlassert(m.getNbMatrixBlock() == 1);
02198
02199 dest.resize(m.getNbRdrPass(0));
02200 const CVertexBuffer &srcVb = m.getVertexBuffer();
02201
02202 for (uint k = 0; k < m.getNbRdrPass(0); ++k)
02203 {
02204 dest[k].Mat = m.getMaterial(m.getRdrPassMaterial(0, k));
02205 dest[k].SourceMat = dest[k].Mat;
02206 DuplicatePrimitiveBlock(m.getRdrPassPrimitiveBlock(0, k), dest[k].PbTri, ConstraintMeshBufSize, srcVb.getNumVertices() );
02207 }
02208 }
02209
02210
02211
02212
02213 void CPSConstraintMesh::CMeshDisplayShare::buildVB(CVertexBuffer &dest, const CVertexBuffer &meshVb, uint32 destFormat)
02214 {
02215 NL_PS_FUNC(CMeshDisplayShare_buildVB)
02217 nlassert(destFormat == meshVb.getVertexFormat() || destFormat == (meshVb.getVertexFormat() | (uint32) CVertexBuffer::PrimaryColorFlag) );
02218 dest.setVertexFormat(destFormat);
02219 dest.setPreferredMemory(CVertexBuffer::AGPVolatile, true);
02220 dest.setNumVertices(ConstraintMeshBufSize * meshVb.getNumVertices());
02221 for(uint k = 0; k < CVertexBuffer::MaxStage; ++k)
02222 {
02223 dest.setUVRouting((uint8) k, meshVb.getUVRouting()[k]);
02224 }
02225
02226 CVertexBufferReadWrite vba;
02227 dest.lock (vba);
02228 CVertexBufferRead vbaIn;
02229 meshVb.lock (vbaIn);
02230
02231 uint8 *outPtr = (uint8 *) vba.getVertexCoordPointer();
02232 uint8 *inPtr = (uint8 *) vbaIn.getVertexCoordPointer();
02233 uint meshSize = dest.getVertexSize() * meshVb.getNumVertices();
02234
02235 if (destFormat == meshVb.getVertexFormat())
02236 {
02237 for (uint k = 0; k < ConstraintMeshBufSize; ++k)
02238 {
02239 ::memcpy((void *) (outPtr + k * meshSize), (void *) inPtr, meshSize);
02240 }
02241 }
02242 else
02243 {
02244 sint colorOff = dest.getColorOff();
02245 uint inVSize = meshVb.getVertexSize();
02246 uint outVSize = dest.getVertexSize();
02247 for (uint k = 0; k < ConstraintMeshBufSize; ++k)
02248 {
02249 for (uint v = 0; v < meshVb.getNumVertices(); ++v)
02250 {
02251
02252 ::memcpy((void *) (outPtr + k * meshSize + v * outVSize), (void *) (inPtr + v * inVSize), colorOff);
02253
02254 ::memcpy((void *) (outPtr + k * meshSize + v * outVSize + colorOff + sizeof(uint8[4])), (void *) (inPtr + v * inVSize + colorOff), inVSize - colorOff);
02255 }
02256 }
02257 }
02258 }
02259
02260
02261
02262 CPSConstraintMesh::CGlobalTexAnim::CGlobalTexAnim() : TransOffset(NLMISC::CVector2f::Null),
02263 TransSpeed(NLMISC::CVector2f::Null),
02264 TransAccel(NLMISC::CVector2f::Null),
02265 ScaleStart(1 ,1),
02266 ScaleSpeed(NLMISC::CVector2f::Null),
02267 ScaleAccel(NLMISC::CVector2f::Null),
02268 WRotSpeed(0),
02269 WRotAccel(0)
02270 {
02271 NL_PS_FUNC(CGlobalTexAnim_CGlobalTexAnim)
02272 }
02273
02274
02275 void CPSConstraintMesh::CGlobalTexAnim::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
02276 {
02277 NL_PS_FUNC(CGlobalTexAnim_IStream )
02278
02279 sint ver = f.serialVersion(1);
02280 if (ver >= 1)
02281 {
02282 f.serial(TransOffset);
02283 }
02284 f.serial(TransSpeed, TransAccel, ScaleStart, ScaleSpeed, ScaleAccel);
02285 f.serial(WRotSpeed, WRotAccel);
02286 }
02287
02288
02289 void CPSConstraintMesh::CGlobalTexAnim::buildMatrix(float date, NLMISC::CMatrix &dest)
02290 {
02291 NL_PS_FUNC(CGlobalTexAnim_buildMatrix)
02292 float fDate = (float) date;
02293 float halfDateSquared = 0.5f * fDate * fDate;
02294 NLMISC::CVector2f pos = fDate * TransSpeed + halfDateSquared * fDate * TransAccel + TransOffset;
02295 NLMISC::CVector2f scale = ScaleStart + fDate * ScaleSpeed + halfDateSquared * fDate * ScaleAccel;
02296 float rot = fDate * WRotSpeed + halfDateSquared * WRotAccel;
02297
02298
02299 float fCos, fSin;
02300 if (rot != 0.f)
02301 {
02302 fCos = ::cosf(- rot);
02303 fSin = ::sinf(- rot);
02304 }
02305 else
02306 {
02307 fCos = 1.f;
02308 fSin = 0.f;
02309 }
02310
02311 NLMISC::CVector I(fCos, fSin, 0);
02312 NLMISC::CVector J(-fSin, fCos, 0);
02313 dest.setRot(scale.x * I, scale.y * J, NLMISC::CVector::K);
02314 NLMISC::CVector center(-0.5f, -0.5f, 0.f);
02315 NLMISC::CVector t(pos.x, pos.y, 0);
02316 dest.setPos(t + dest.mulVector(center) - center);
02317 }
02318
02319
02320 void CPSConstraintMesh::setGlobalTexAnim(uint stage, const CGlobalTexAnim &properties)
02321 {
02322 NL_PS_FUNC(CPSConstraintMesh_setGlobalTexAnim)
02323 nlassert(_GlobalAnimationEnabled != 0);
02324 nlassert(stage < IDRV_MAT_MAXTEXTURES);
02325 nlassert(_GlobalTexAnims.get());
02326 _GlobalTexAnims->Anims[stage] = properties;
02327 }
02328
02329
02330 const CPSConstraintMesh::CGlobalTexAnim &CPSConstraintMesh::getGlobalTexAnim(uint stage) const
02331 {
02332 NL_PS_FUNC(CPSConstraintMesh_getGlobalTexAnim)
02333 nlassert(_GlobalAnimationEnabled != 0);
02334 nlassert(stage < IDRV_MAT_MAXTEXTURES);
02335 nlassert(_GlobalTexAnims.get());
02336 return _GlobalTexAnims->Anims[stage];
02337 }
02338
02339
02340
02341 CPSConstraintMesh::TTexAnimType CPSConstraintMesh::getTexAnimType() const
02342 {
02343 NL_PS_FUNC(CPSConstraintMesh_getTexAnimType)
02344 return (TTexAnimType) (_GlobalAnimationEnabled != 0 ? GlobalAnim : NoAnim);
02345 }
02346
02347
02348 void CPSConstraintMesh::setTexAnimType(TTexAnimType type)
02349 {
02350 NL_PS_FUNC(CPSConstraintMesh_setTexAnimType)
02351 nlassert(type < Last);
02352 if (type == getTexAnimType()) return;
02353 switch (type)
02354 {
02355 case NoAnim:
02356 _GlobalTexAnims.reset();
02357 restoreMaterials();
02358 _GlobalAnimationEnabled = 0;
02359 break;
02360 case GlobalAnim:
02361 {
02362 PGlobalTexAnims newPtr(new CGlobalTexAnims);
02363
02364 _GlobalTexAnims = newPtr;
02365 _GlobalAnimationEnabled = 1;
02366 }
02367 break;
02368 default: break;
02369 }
02370 }
02371
02372
02373 void CPSConstraintMesh::CGlobalTexAnims::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
02374 {
02375 NL_PS_FUNC(CGlobalTexAnims_IStream )
02376 f.serialVersion(0);
02377 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
02378 {
02379 f.serial(Anims[k]);
02380 }
02381 }
02382
02383
02384 void CPSConstraintMesh::restoreMaterials()
02385 {
02386 NL_PS_FUNC(CPSConstraintMesh_restoreMaterials)
02387 update();
02388 CMeshDisplay &md= _MeshDisplayShare.getMeshDisplay(_Meshes[0], getMeshVB(0), _Meshes[0]->getVertexBuffer().getVertexFormat() | (_ColorScheme ? CVertexBuffer::PrimaryColorFlag : 0));
02389 TRdrPassSet rdrPasses = md.RdrPasses;
02390
02391 for (TRdrPassSet::iterator rdrPassIt = rdrPasses.begin(); rdrPassIt != rdrPasses.end(); ++rdrPassIt)
02392 {
02393 rdrPassIt->Mat = rdrPassIt->SourceMat;
02394 }
02395 }
02396
02397
02398 const CVertexBuffer &CPSConstraintMesh::getMeshVB(uint index)
02399 {
02400 nlassert(!_Touched);
02401 nlassert(index < _Meshes.size());
02402 nlassert(_MeshVertexBuffers.size() == _Meshes.size());
02403 const CVertexBuffer *vb = _MeshVertexBuffers[index];
02404 if (!vb )
02405 {
02406 CMesh &mesh = * NLMISC::safe_cast<CMesh *>((IShape *) _Meshes[index]);
02407 vb = _MeshVertexBuffers[index] = &mesh.getVertexBuffer();
02408 }
02409 if (vb->getLocation() != CVertexBuffer::NotResident)
02410 {
02411 TMeshName2RamVB::iterator it = _MeshRamVBs.find(_MeshShapeFileName[index]);
02412 if (it == _MeshRamVBs.end())
02413 {
02414 CVertexBuffer &destVb = _MeshRamVBs[_MeshShapeFileName[index]];
02415 CMesh &mesh = * NLMISC::safe_cast<CMesh *>((IShape *) _Meshes[index]);
02416 mesh.getVertexBuffer().copyVertices(destVb);
02417 _MeshVertexBuffers[index] = vb = &destVb;
02418 }
02419 else
02420 {
02421 _MeshVertexBuffers[index] = vb = &it->second;
02422 }
02423 }
02424 nlassert(vb->getLocation() == CVertexBuffer::NotResident);
02425 return *vb;
02426 }
02427
02428
02429 void CPSMesh::onShow(bool shown)
02430 {
02431 for(uint k = 0; k < _Instances.getSize(); ++k)
02432 {
02433 if (_Instances[k])
02434 {
02435 if (shown)
02436 {
02437 _Instances[k]->show();
02438 }
02439 else
02440 {
02441 _Instances[k]->hide();
02442 }
02443 }
02444 }
02445 }
02446
02447 }