00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_MESH_H
00027 #define NL_MESH_H
00028
00029 #include "nel/misc/types_nl.h"
00030 #include "3d/shape.h"
00031 #include "3d/driver.h"
00032 #include "nel/misc/aabbox.h"
00033 #include "nel/misc/uv.h"
00034 #include "3d/vertex_buffer.h"
00035 #include "3d/vertex_buffer_hard.h"
00036 #include "3d/material.h"
00037 #include "3d/primitive_block.h"
00038 #include "3d/animated_material.h"
00039 #include "3d/mesh_base.h"
00040 #include "3d/mesh_geom.h"
00041 #include "3d/mesh_morpher.h"
00042 #include "3d/mesh_vertex_program.h"
00043 #include <set>
00044 #include <vector>
00045
00046
00047 namespace NL3D
00048 {
00049
00050
00051 using NLMISC::CVector;
00052 using NLMISC::CPlane;
00053 using NLMISC::CMatrix;
00054
00055
00056 class CMeshGeom;
00057 class CSkeletonModel;
00058 class CMatrix3x4;
00059
00060
00061
00062 #define NL3D_MESH_SKINNING_MAX_MATRIX 4
00063
00064
00065 #define NL3D_MESH_PRECISE_CLIP_THRESHOLD 5.0f
00066
00067
00068
00076 class CMesh : public CMeshBase
00077 {
00078 public:
00079
00081
00082
00084 struct CCorner
00085 {
00086 sint32 Vertex;
00087 CVector Normal;
00088 NLMISC::CUVW Uvws[CVertexBuffer::MaxStage];
00089 CRGBA Color;
00090 CRGBA Specular;
00091
00092
00093
00094 CCorner();
00095
00096 void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00097 };
00098
00100 struct CFace
00101 {
00102 CCorner Corner[3];
00103 sint32 MaterialId;
00104 sint32 SmoothGroup;
00105 void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00106 };
00107
00108
00112 struct CSkinWeight
00113 {
00115 uint32 MatrixId[NL3D_MESH_SKINNING_MAX_MATRIX];
00117 float Weights[NL3D_MESH_SKINNING_MAX_MATRIX];
00118
00120 CSkinWeight()
00121 {
00122 for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
00123 {
00124 MatrixId[i]=0;
00125 Weights[i]=0;
00126 }
00127 }
00128
00129 void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00130 };
00131
00132 struct CVertLink
00133 {
00134 uint32 nFace, nCorner;
00135 uint32 VertVB;
00136
00137 CVertLink (uint32 face, uint32 corner, uint32 iVB)
00138 {
00139 nFace = face;
00140 nCorner = corner;
00141 VertVB = iVB;
00142 }
00143 };
00144
00146 struct CMeshBuild
00147 {
00152 sint32 VertexFlags;
00153 uint8 NumCoords[CVertexBuffer::MaxStage];
00154
00155
00156 std::vector<CVector> Vertices;
00157
00158
00159 std::vector<CSkinWeight> SkinWeights;
00160
00161
00162 std::vector<std::string> BonesNames;
00163
00164
00165 std::vector<CFace> Faces;
00166
00167
00168 std::vector<CBlendShape> BlendShapes;
00169
00170
00171 std::vector<CVertLink> VertLink;
00172
00173
00174 NLMISC::CSmartPtr<IMeshVertexProgram> MeshVertexProgram;
00175
00176
00177 CMeshBuild();
00178
00179
00180
00181
00182 };
00184
00185
00186 public:
00188 CMesh();
00190 ~CMesh();
00191 CMesh(const CMesh &mesh);
00192 CMesh &operator=(const CMesh &mesh);
00193
00194
00196 void build(CMeshBase::CMeshBaseBuild &mbase, CMeshBuild &mbuild);
00197
00198
00200 void build(CMeshBase::CMeshBaseBuild &mbuild, CMeshGeom &meshGeom);
00201
00202 void setBlendShapes(std::vector<CBlendShape>&bs);
00203
00205 void computeBonesId (CSkeletonModel *skeleton);
00206
00208 void updateSkeletonUsage(CSkeletonModel *sm, bool increment);
00209
00211
00212
00214 virtual CTransformShape *createInstance(CScene &scene);
00215
00217 virtual bool clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix) ;
00218
00220 virtual void render(IDriver *drv, CTransformShape *trans, bool opaquePass);
00221
00223 virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00224 NLMISC_DECLARE_CLASS(CMesh);
00225
00227 virtual float getNumTriangles (float distance);
00228
00230 virtual void getAABBox(NLMISC::CAABBox &bbox) const {bbox= getBoundingBox().getAABBox();}
00231
00232
00233
00235
00236
00238 const NLMISC::CAABBoxExt& getBoundingBox() const;
00239
00241 const CVertexBuffer &getVertexBuffer() const;
00242
00244 uint getNbMatrixBlock() const;
00245
00249 uint getNbRdrPass(uint matrixBlockIndex) const;
00250
00255 const CPrimitiveBlock &getRdrPassPrimitiveBlock(uint matrixBlockIndex, uint renderingPassIndex) const;
00256
00261 uint32 getRdrPassMaterial(uint matrixBlockIndex, uint renderingPassIndex) const;
00262
00264 const CMeshGeom &getMeshGeom () const;
00265
00266
00267
00268
00270
00271 virtual IMeshGeom *supportMeshBlockRendering (CTransformShape *trans, float &polygonCount ) const;
00272
00273
00274 private:
00275
00276
00277 CMeshGeom *_MeshGeom;
00278 };
00279
00280
00281
00282
00283
00291 class CMeshGeom: public IMeshGeom
00292 {
00293 public:
00294
00296 CMeshGeom();
00297 virtual ~CMeshGeom();
00298
00300 void build(CMesh::CMeshBuild &mbuild, uint numMaxMaterial);
00301
00302 void setBlendShapes(std::vector<CBlendShape>&bs);
00303
00304
00306
00307
00309 virtual void initInstance(CMeshBaseInstance *mbi);
00310
00312 virtual bool clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix) ;
00313
00315 virtual void render(IDriver *drv, CTransformShape *trans, float polygonCount, uint32 rdrFlags, float globalAlpha);
00316
00318 virtual void renderSkin(CTransformShape *trans, float alphaMRM);
00319
00320
00321 virtual float getNumTriangles (float distance);
00322
00324 virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
00325 NLMISC_DECLARE_CLASS(CMeshGeom);
00326
00327
00328
00329
00331
00332
00334 const NLMISC::CAABBoxExt& getBoundingBox() const
00335 {
00336 return _BBox;
00337 }
00338
00340 const CVertexBuffer &getVertexBuffer() const { return _VBuffer ; }
00341
00343 uint getNbMatrixBlock() const { return _MatrixBlocks.size() ; }
00344
00348 uint getNbRdrPass(uint matrixBlockIndex) const { return _MatrixBlocks[matrixBlockIndex].RdrPass.size() ; }
00349
00354 const CPrimitiveBlock &getRdrPassPrimitiveBlock(uint matrixBlockIndex, uint renderingPassIndex) const
00355 {
00356 return _MatrixBlocks[matrixBlockIndex].RdrPass[renderingPassIndex].PBlock ;
00357 }
00358
00363 uint32 getRdrPassMaterial(uint matrixBlockIndex, uint renderingPassIndex) const
00364 {
00365 return _MatrixBlocks[matrixBlockIndex].RdrPass[renderingPassIndex].MaterialId ;
00366 }
00367
00368
00369
00370
00372
00373
00375 bool isSkinned () const
00376 {
00377 return _Skinned;
00378 }
00379
00381 void computeBonesId (CSkeletonModel *skeleton);
00382
00384 void updateSkeletonUsage(CSkeletonModel *sm, bool increment);
00385
00387 const std::vector<sint32> &getSkinBoneUsage() const {return _BonesId;}
00388
00389
00390
00391
00399 void renderSimpleWithMaterial(IDriver *drv, const CMatrix &worldMatrix, CMaterial &mat);
00400
00401
00402
00404
00405
00409 virtual bool supportMeshBlockRendering () const;
00410
00411 virtual bool sortPerMaterial() const;
00412 virtual uint getNumRdrPasses() const ;
00413 virtual void beginMesh(CMeshGeomRenderContext &rdrCtx) ;
00414 virtual void activeInstance(CMeshGeomRenderContext &rdrCtx, CMeshBaseInstance *inst, float polygonCount) ;
00415 virtual void renderPass(CMeshGeomRenderContext &rdrCtx, CMeshBaseInstance *inst, float polygonCount, uint rdrPass) ;
00416 virtual void endMesh(CMeshGeomRenderContext &rdrCtx) ;
00417
00418 virtual bool getVBHeapInfo(uint &vertexFormat, uint &numVertices);
00419 virtual void computeMeshVBHeap(void *dst, uint indexStart);
00420
00421
00422
00423
00424
00425 private:
00426
00428 class CRdrPass
00429 {
00430 public:
00431
00432 uint32 MaterialId;
00433
00434 CPrimitiveBlock PBlock;
00435
00436
00437 CPrimitiveBlock VBHeapPBlock;
00438
00439
00440
00441 void serial(NLMISC::IStream &f)
00442 {
00443 (void)f.serialVersion(0);
00444
00445 f.serial(MaterialId);
00446 f.serial(PBlock);
00447 }
00448 };
00449
00450
00452 class CMatrixBlock
00453 {
00454 public:
00456 uint32 MatrixId[IDriver::MaxModelMatrix];
00458 uint32 NumMatrix;
00460 std::vector<CRdrPass> RdrPass;
00461
00462 void serial(NLMISC::IStream &f)
00463 {
00464 (void)f.serialVersion(0);
00465
00466
00467 nlassert(IDriver::MaxModelMatrix == 16);
00468 for(uint i=0;i<IDriver::MaxModelMatrix;i++)
00469 f.serial(MatrixId[i]);
00470 f.serial(NumMatrix);
00471 f.serialCont(RdrPass);
00472 }
00473
00474
00476 sint getMatrixIdLocation(uint32 boneId) const;
00477 };
00478
00479
00480 private:
00486 struct CCornerTmp : public CMesh::CCorner
00487 {
00488 CPaletteSkin Palette;
00489 float Weights[NL3D_MESH_SKINNING_MAX_MATRIX];
00490
00491
00492 bool operator<(const CCornerTmp &c) const;
00493
00494 mutable sint VBId;
00495
00496 static sint Flags;
00497
00498
00499
00500 CCornerTmp()
00501 {
00502 VBId= 0;
00503 for(sint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
00504 {
00505 Palette.MatrixId[i]=0;
00506 Weights[i]=0;
00507 }
00508 }
00509
00510
00511 CCornerTmp &operator=(const CMesh::CCorner &o)
00512 {
00513 Vertex= o.Vertex;
00514 Normal= o.Normal;
00515 for(sint i=0;i<=CVertexBuffer::MaxStage;i++)
00516 {
00517 Uvws[i]= o.Uvws[i];
00518 }
00519 Color= o.Color;
00520 Specular= o.Specular;
00521
00522 return *this;
00523 }
00524
00525 };
00526
00527
00530 struct CBoneTmp
00531 {
00532
00533 uint RefCount;
00534
00535 bool Inserted;
00536
00537 uint MatrixIdInMB;
00538
00539 CBoneTmp()
00540 {
00541 RefCount= 0;
00542 Inserted=false;
00543 }
00544 };
00545
00546
00549 typedef std::map<uint, CBoneTmp> TBoneMap;
00550 typedef TBoneMap::iterator ItBoneMap;
00551
00552
00555 struct CFaceTmp
00556 {
00557 CCornerTmp Corner[3];
00558 uint MaterialId;
00559
00560 sint MatrixBlockId;
00561
00562 CFaceTmp()
00563 {
00564 MatrixBlockId= -1;
00565 }
00566 CFaceTmp &operator=(const CMesh::CFace& o)
00567 {
00568 Corner[0]= o.Corner[0];
00569 Corner[1]= o.Corner[1];
00570 Corner[2]= o.Corner[2];
00571 MaterialId= o.MaterialId;
00572
00573 return *this;
00574 }
00575
00576
00577 void buildBoneUse(std::vector<uint> &boneUse, std::vector<CMesh::CSkinWeight> &skinWeights);
00578
00579 };
00580
00581
00584 class CMatrixBlockRemap
00585 {
00586 public:
00587 uint32 Remap[IDriver::MaxModelMatrix];
00588 };
00589
00590
00591 private:
00595 std::vector<CVector> _OriginalSkinVertices;
00596 std::vector<CVector> _OriginalSkinNormals;
00597 std::vector<CVector> _OriginalTGSpace;
00598
00600 CVertexBuffer _VBuffer;
00602 CVertexBuffer _VBufferOri;
00604 std::vector<CMatrixBlock> _MatrixBlocks;
00606 NLMISC::CAABBoxExt _BBox;
00608 bool _Skinned;
00610 bool _OriginalSkinRestored;
00611
00613 bool _BoneIdComputed;
00615 bool _BoneIdExtended;
00616
00618 std::vector<std::string> _BonesName;
00620 std::vector<sint32> _BonesId;
00622 std::vector<sint32> _BonesIdExt;
00623
00624
00626
00628
00630
00632
00633
00635 void updateVertexBufferHard(IDriver *drv);
00636
00637
00638
00640
00642
00643
00644
00646 bool _PreciseClipping;
00647
00648
00649 CMeshMorpher *_MeshMorpher;
00650
00651
00652
00653 NLMISC::CSmartPtr<IMeshVertexProgram> _MeshVertexProgram;
00654
00655
00656 private:
00657
00658 class CCornerPred
00659 {
00660 public:
00661 bool operator()(const CCornerTmp *x, const CCornerTmp *y) const
00662 {
00663 return (*x<*y);
00664 }
00665 };
00666 typedef std::set<CCornerTmp*, CCornerPred> TCornerSet;
00667 typedef TCornerSet::iterator ItCornerSet;
00668
00669
00670 void findVBId(TCornerSet &corners, const CCornerTmp *corn, sint ¤tVBIndex, const CVector &vert, const CMesh::CMeshBuild &mb)
00671 {
00672 ItCornerSet it= corners.find(const_cast<CCornerTmp *>(corn));
00673 if(it!=corners.end())
00674 corn->VBId= (*it)->VBId;
00675 else
00676 {
00677
00678 corners.insert (const_cast<CCornerTmp *>(corn));
00679 sint i;
00680 corn->VBId= currentVBIndex++;
00681
00682 _VBuffer.setNumVertices(currentVBIndex);
00683 sint id= currentVBIndex-1;
00684
00685 _VBuffer.setVertexCoord(id, vert);
00686
00687 if(CCornerTmp::Flags & CVertexBuffer::NormalFlag)
00688 _VBuffer.setNormalCoord(id, corn->Normal);
00689
00690 for(i=0;i<CVertexBuffer::MaxStage;i++)
00691 {
00692 if(CCornerTmp::Flags & (CVertexBuffer::TexCoord0Flag<<i))
00693 {
00694 switch(mb.NumCoords[i])
00695 {
00696 case 2:
00697 _VBuffer.setTexCoord(id, i, corn->Uvws[i].U, corn->Uvws[i].V);
00698 break;
00699 case 3:
00700 _VBuffer.setValueFloat3Ex((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + i), id, corn->Uvws[i].U, corn->Uvws[i].V, corn->Uvws[i].W);
00701 break;
00702 default:
00703 nlassert(0);
00704 break;
00705 }
00706 }
00707 }
00708
00709 if(CCornerTmp::Flags & CVertexBuffer::PrimaryColorFlag)
00710 _VBuffer.setColor(id, corn->Color);
00711
00712 if(CCornerTmp::Flags & CVertexBuffer::SecondaryColorFlag)
00713 _VBuffer.setSpecular(id, corn->Specular);
00714
00715
00716 if ((CCornerTmp::Flags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag)
00717 {
00718 _VBuffer.setPaletteSkin(id, corn->Palette);
00719 for(i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
00720 _VBuffer.setWeight(id, i, corn->Weights[i]);
00721 }
00722 }
00723 }
00724
00725
00726
00727 void optimizeTriangleOrder();
00728
00729
00730 void compileRunTime();
00731
00732
00734
00735
00736 enum TSkinType {SkinPosOnly=0, SkinWithNormal, SkinWithTgSpace};
00737
00738
00739 void buildSkin(CMesh::CMeshBuild &m, std::vector<CFaceTmp> &tmpFaces);
00740
00741
00742 void buildBoneUsageVer3 ();
00743
00744
00745 void bkupOriginalSkinVertices();
00746
00747 void restoreOriginalSkinVertices();
00748
00749
00750 void applySkin(CSkeletonModel *skeleton);
00751
00752
00753 void flagSkinVerticesForMatrixBlock(uint8 *skinFlags, CMatrixBlock &mb);
00754 void computeSkinMatrixes(CSkeletonModel *skeleton, CMatrix3x4 *matrixes, CMatrixBlock *prevBlock, CMatrixBlock &curBlock);
00755 void computeSoftwarePointSkinning(CMatrix3x4 *matrixes, CVector *srcVector, CPaletteSkin *srcPal, float *srcWgt, CVector *dstVector);
00756 void computeSoftwareVectorSkinning(CMatrix3x4 *matrixes, CVector *srcVector, CPaletteSkin *srcPal, float *srcWgt, CVector *dstVector);
00757
00758
00759
00760 };
00761
00762
00763
00764
00765 }
00766
00767
00768 #endif // NL_MESH_H
00769
00770