00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_MESH_MRM_SKINNED_H
00027 #define NL_MESH_MRM_SKINNED_H
00028
00029 #include "nel/misc/types_nl.h"
00030 #include "nel/3d/shape.h"
00031 #include "nel/3d/driver.h"
00032 #include "nel/misc/aabbox.h"
00033 #include "nel/misc/uv.h"
00034 #include "nel/3d/vertex_buffer.h"
00035 #include "nel/3d/material.h"
00036 #include "nel/3d/index_buffer.h"
00037 #include "nel/3d/animated_material.h"
00038 #include "nel/3d/mesh_base.h"
00039 #include "nel/3d/mesh.h"
00040 #include "nel/3d/mrm_mesh.h"
00041 #include "nel/3d/mrm_parameters.h"
00042 #include "nel/3d/bone.h"
00043 #include "nel/3d/mesh_geom.h"
00044 #include "nel/3d/mrm_level_detail.h"
00045 #include "nel/3d/shadow_skin.h"
00046 #include <set>
00047 #include <vector>
00048
00049
00050 namespace NL3D
00051 {
00052
00053
00054 using NLMISC::CVector;
00055 using NLMISC::CPlane;
00056 using NLMISC::CMatrix;
00057 class CMRMBuilder;
00058
00059 class CMatrix3x4;
00060 class CRawVertexNormalSkinned1;
00061 class CRawVertexNormalSkinned2;
00062 class CRawVertexNormalSkinned3;
00063 class CRawVertexNormalSkinned4;
00064 class CRawSkinnedNormalCache;
00065 class CMeshMRMSkinnedInstance;
00066 class CSkinSpecularRdrPass;
00067
00068 #define NL3D_MESH_MRM_SKINNED_WEIGHT_FACTOR (255.f)
00069 #define NL3D_MESH_MRM_SKINNED_UV_FACTOR (8192.f)
00070 #define NL3D_MESH_MRM_SKINNED_NORMAL_FACTOR (32767.f)
00071 #define NL3D_MESH_MRM_SKINNED_DEFAULT_POS_SCALE (8.f/32767.f)
00072 #define NL3D_MESH_MRM_SKINNED_MAX_MATRIX 4
00073 #define NL3D_MESH_MRM_SKINNED_VERTEX_FORMAT (CVertexBuffer::PositionFlag|CVertexBuffer::NormalFlag|CVertexBuffer::TexCoord0Flag|CVertexBuffer::PaletteSkinFlag)
00074
00075
00089 class CMeshMRMSkinnedGeom : public IMeshGeom
00090 {
00091 public:
00093 CMeshMRMSkinnedGeom();
00094 ~CMeshMRMSkinnedGeom();
00095
00100 void build(CMesh::CMeshBuild &m, uint numMaxMaterial, const CMRMParameters ¶ms= CMRMParameters());
00101
00103 void applyMaterialRemap(const std::vector<sint> &remap);
00104
00105
00112 void changeMRMDistanceSetup(float distanceFinest, float distanceMiddle, float distanceCoarsest);
00113
00114
00116
00117
00119 virtual void initInstance(CMeshBaseInstance *mbi);
00120
00122 virtual bool clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix) ;
00123
00125 virtual void render(IDriver *drv, CTransformShape *trans, float polygonCount, uint32 rdrFlags, float globalAlpha);
00126
00128 virtual void renderSkin(CTransformShape *trans, float alphaMRM);
00129
00131 virtual float getNumTriangles (float distance);
00132
00134 virtual void serial(NLMISC::IStream &f);
00135 NLMISC_DECLARE_CLASS(CMeshMRMSkinnedGeom);
00136
00138 void profileSceneRender(CRenderTrav *rdrTrav, CTransformShape *trans, float polygonCount, uint32 rdrFlags);
00139
00140
00141
00142
00144
00145
00147 const NLMISC::CAABBoxExt& getBoundingBox() const
00148 {
00149 return _BBox;
00150 }
00151
00153 void getVertexBuffer(CVertexBuffer &output) const;
00154
00156 void getSkinWeights (std::vector<CMesh::CSkinWeight> &skinWeights) const;
00157
00158
00160 const std::vector<std::string> &getBonesName() const {return _BonesName;}
00161
00164 uint getNbLod() const { return _Lods.size() ; }
00165
00166
00170 uint getNbRdrPass(uint lodId) const { return _Lods[lodId].RdrPass.size() ; }
00171
00172
00177 void getRdrPassPrimitiveBlock(uint lodId, uint renderingPassIndex, CIndexBuffer &block) const
00178 {
00179 _Lods[lodId].getRdrPassPrimitiveBlock(renderingPassIndex, block);
00180 }
00181
00182
00187 uint32 getRdrPassMaterial(uint lodId, uint renderingPassIndex) const
00188 {
00189 return _Lods[lodId].RdrPass[renderingPassIndex].MaterialId ;
00190 }
00191
00192
00194 const std::vector<CMRMWedgeGeom> &getGeomorphs(uint lodId) const
00195 {
00196 return _Lods[lodId].Geomorphs;
00197 }
00198
00199
00200
00201
00203
00204
00206 void computeBonesId (CSkeletonModel *skeleton);
00207
00209 void updateSkeletonUsage(CSkeletonModel *sm, bool increment);
00210
00212 const std::vector<sint32> &getSkinBoneUsage() const {return _BonesId;}
00213
00215 const std::vector<NLMISC::CBSphere> &getSkinBoneSphere() const {return _BonesSphere;}
00216
00218 bool getSkinBoneBBox(CSkeletonModel *skeleton, NLMISC::CAABBox &bbox, uint boneId) const;
00219
00220
00221
00222
00224
00225
00229 virtual bool supportMeshBlockRendering () const;
00230
00231 virtual bool sortPerMaterial() const { return false; }
00232 virtual uint getNumRdrPassesForMesh() const { return 0; }
00233 virtual uint getNumRdrPassesForInstance(CMeshBaseInstance * ) const { return 0; }
00234 virtual void beginMesh(CMeshGeomRenderContext &) {}
00235 virtual void activeInstance(CMeshGeomRenderContext &, CMeshBaseInstance * , float , void * ) {}
00236 virtual void renderPass(CMeshGeomRenderContext &, CMeshBaseInstance * , float , uint ) {}
00237 virtual void endMesh(CMeshGeomRenderContext &) {}
00238
00239
00240
00241
00243 const CMRMLevelDetail &getLevelDetail() const {return _LevelDetail;}
00244
00245
00247
00248 bool supportSkinGrouping() const;
00249 sint renderSkinGroupGeom(CMeshMRMSkinnedInstance *mi, float alphaMRM, uint remainingVertices, uint8 *vbDest);
00250 void renderSkinGroupPrimitives(CMeshMRMSkinnedInstance *mi, uint baseVertex, std::vector<CSkinSpecularRdrPass> &specularRdrPasses, uint skinIndex);
00251 void renderSkinGroupSpecularRdrPass(CMeshMRMSkinnedInstance *mi, uint rdrPassId);
00252
00253
00254
00255 virtual bool hasMeshVertexProgram() const {return false;}
00256
00258
00260 void setShadowMesh(const std::vector<CShadowVertex> &shadowVertices, const std::vector<uint32> &triangles);
00261
00263 uint getNumShadowSkinVertices() const;
00264
00266 bool supportShadowSkinGrouping() const {return _SupportShadowSkinGrouping;}
00267 sint renderShadowSkinGeom(CMeshMRMSkinnedInstance *mi, uint remainingVertices, uint8 *vbDest);
00268 void renderShadowSkinPrimitives(CMeshMRMSkinnedInstance *mi, CMaterial &castMat, IDriver *drv, uint baseVertex);
00269
00273 bool supportIntersectSkin() const {return supportShadowSkinGrouping();}
00274 bool intersectSkin(CMeshMRMSkinnedInstance *mi, const CMatrix &toRaySpace, float &dist2D, float &distZ, bool computeDist2D);
00275
00276
00277
00278
00279 private:
00280 friend class CMRMBuilder;
00281
00283
00284
00286 class CRdrPass
00287 {
00288 public:
00289
00290 uint32 MaterialId;
00291
00292 std::vector<uint16> PBlock;
00293
00294
00295 void serial(NLMISC::IStream &f)
00296 {
00297 (void)f.serialVersion(0);
00298
00299 f.serial(MaterialId);
00300 f.serialCont(PBlock);
00301 }
00302
00303
00304 uint getNumTriangle () const
00305 {
00306 return PBlock.size()/3;
00307 }
00308 };
00309
00310
00312 struct CVertexBlock
00313 {
00314
00315 uint32 VertexStart;
00316
00317 uint32 NVertices;
00318
00319 void serial(NLMISC::IStream &f)
00320 {
00321 f.serial(VertexStart, NVertices);
00322 }
00323 };
00324
00325
00326
00328 class CLod
00329 {
00330 public:
00332 uint32 NWedges;
00334 std::vector<CMRMWedgeGeom> Geomorphs;
00336 std::vector<CRdrPass> RdrPass;
00337
00341 std::vector<uint32> InfluencedVertices[NL3D_MESH_SKINNING_MAX_MATRIX];
00343 std::vector<uint32> MatrixInfluences;
00344
00345
00346
00347 CLod()
00348 {
00349 }
00350
00351
00352 void serial(NLMISC::IStream &f);
00353
00354
00355 void optimizeTriangleOrder();
00356
00357
00358 void getRdrPassPrimitiveBlock (uint renderPass, CIndexBuffer &block) const;
00359
00360
00361 void buildPrimitiveBlock(uint renderPass, const CIndexBuffer &block);
00362 };
00363
00364 friend class CLod;
00365
00369 struct CMeshBuildMRM
00370 {
00371
00372 bool Skinned;
00373
00374
00375 std::vector<CMesh::CSkinWeight> SkinWeights;
00376
00377
00378 CVertexBuffer VBuffer;
00379
00380
00381 std::vector<CLod> Lods;
00382
00383
00384 std::vector<CBlendShape> BlendShapes;
00385
00387
00389 float DistanceFinest;
00391 float DistanceMiddle;
00393 float DistanceCoarsest;
00394
00395
00396 };
00398
00399
00400
00401 public:
00402
00404 class CPackedVertexBuffer
00405 {
00406 public:
00408 struct CPackedVertex
00409 {
00410 sint16 X, Y, Z;
00411 sint16 Nx, Ny, Nz;
00412 sint16 U, V;
00413 uint8 Matrices[NL3D_MESH_MRM_SKINNED_MAX_MATRIX];
00414 uint8 Weights[NL3D_MESH_MRM_SKINNED_MAX_MATRIX];
00415
00416
00417 inline void getPos (CVector &dest, float factor) const
00418 {
00419 dest.x = (float)X * factor;
00420 dest.y = (float)Y * factor;
00421 dest.z = (float)Z * factor;
00422 }
00423 inline void getNormal (CVector &dest) const
00424 {
00425 dest.x = (float)Nx * (1.f/NL3D_MESH_MRM_SKINNED_NORMAL_FACTOR);
00426 dest.y = (float)Ny * (1.f/NL3D_MESH_MRM_SKINNED_NORMAL_FACTOR);
00427 dest.z = (float)Nz * (1.f/NL3D_MESH_MRM_SKINNED_NORMAL_FACTOR);
00428 }
00429 inline void getU (float &_u) const
00430 {
00431 _u = (float)U * (1.f/NL3D_MESH_MRM_SKINNED_UV_FACTOR);
00432 }
00433 inline void getV (float &_v) const
00434 {
00435 _v = (float)V * (1.f/NL3D_MESH_MRM_SKINNED_UV_FACTOR);
00436 }
00437 inline void getWeight (float &dest, uint index) const
00438 {
00439 dest = (float)Weights[index] * (1.f/NL3D_MESH_MRM_SKINNED_WEIGHT_FACTOR);
00440 }
00441
00442
00443 void setNormal (const CVector &pos);
00444 void setUV (float _u, float _v);
00445 void setWeight (uint weightId, float weight);
00446 void setPos (const CVector &pos, float scaleFactor);
00447
00448
00449 void serial(NLMISC::IStream &f);
00450 };
00451
00452
00453 void build (const CVertexBuffer &buffer, const std::vector<CMesh::CSkinWeight> &skinWeight);
00454
00455
00456 void clear ()
00457 {
00458 _PackedBuffer.clear();
00459 }
00460
00461
00462 void contReset()
00463 {
00464 NLMISC::contReset (_PackedBuffer);
00465 }
00466
00467
00468 const CPackedVertex *getPackedVertices() const
00469 {
00470 if (_PackedBuffer.empty())
00471 return NULL;
00472 else
00473 return &(_PackedBuffer[0]);
00474 }
00475
00476
00477 CPackedVertex *getPackedVertices()
00478 {
00479 if (_PackedBuffer.empty())
00480 return NULL;
00481 else
00482 return &(_PackedBuffer[0]);
00483 }
00484
00485
00486 uint getNumVertices() const
00487 {
00488 return _PackedBuffer.size();
00489 }
00490
00491
00492 inline void getPos (CVector &dest, const CPackedVertex &src) const
00493 {
00494 src.getPos (dest, _DecompactScale);
00495 }
00496
00497
00498 void serial(NLMISC::IStream &f);
00499
00500 private:
00502 float _DecompactScale;
00503
00504
00505 std::vector<CPackedVertex> _PackedBuffer;
00506 };
00507
00508 private:
00509
00510
00511 CPackedVertexBuffer _VBufferFinal;
00512
00514 bool _BoneIdComputed;
00516 bool _BoneIdExtended;
00517
00519 uint8 _LastLodComputed;
00520
00522 std::vector<std::string> _BonesName;
00524 std::vector<sint32> _BonesId;
00526 std::vector<sint32> _BonesIdExt;
00528 std::vector<NLMISC::CBSphere> _BonesSphere;
00529
00531 std::vector<CLod> _Lods;
00533 NLMISC::CAABBoxExt _BBox;
00534
00535
00537
00538 CMRMLevelDetail _LevelDetail;
00539
00540
00541
00543
00544
00546 bool _PreciseClipping;
00547
00548
00549
00551
00552 CShadowSkin _ShadowSkin;
00553 bool _SupportShadowSkinGrouping;
00554
00555
00556 private:
00557
00559 sint chooseLod(float alphaMRM, float &alphaLod);
00560
00562 void applyGeomorph(std::vector<CMRMWedgeGeom> &geoms, float alphaLod);
00563
00565 void applyGeomorphWithVBHardPtr(std::vector<CMRMWedgeGeom> &geoms, float alphaLod);
00566
00568 void applyGeomorphPosNormalUV0Int(std::vector<CMRMWedgeGeom> &geoms, uint8 *vertexPtr, uint8 *vertexDestPtr, sint32 vertexSize, sint a, sint a1);
00569
00571 void applyGeomorphPosNormalUV0(std::vector<CMRMWedgeGeom> &geoms, uint8 *vertexPtr, uint8 *vertexDestPtr, sint32 vertexSize, float a, float a1);
00572
00576 void applyRawSkinWithNormal(CLod &lod, CRawSkinnedNormalCache &rawSkinLod, const CSkeletonModel *skeleton, uint8 *vbHard, float alphaLod);
00577
00578
00579 void compileRunTime();
00580
00581
00582 void updateShiftedTriangleCache(CMeshMRMSkinnedInstance *mi, sint curLodId, uint baseVertex);
00583
00584 private:
00585
00587
00588
00590 uint _MeshDataId;
00591
00593 void updateRawSkinNormal(bool enabled, CMeshMRMSkinnedInstance *mi, sint curLodId);
00595 void dirtMeshDataId();
00596
00597
00598 void applyArrayRawSkinNormal1(CRawVertexNormalSkinned1 *src, uint8 *destVertexPtr,
00599 CMatrix3x4 *boneMat3x4, uint nInf);
00600 void applyArrayRawSkinNormal2(CRawVertexNormalSkinned2 *src, uint8 *destVertexPtr,
00601 CMatrix3x4 *boneMat3x4, uint nInf);
00602 void applyArrayRawSkinNormal3(CRawVertexNormalSkinned3 *src, uint8 *destVertexPtr,
00603 CMatrix3x4 *boneMat3x4, uint nInf);
00604 void applyArrayRawSkinNormal4(CRawVertexNormalSkinned4 *src, uint8 *destVertexPtr,
00605 CMatrix3x4 *boneMat3x4, uint nInf);
00606
00607
00608 public:
00609 static uint NumCacheVertexNormal1;
00610 static uint NumCacheVertexNormal2;
00611 static uint NumCacheVertexNormal3;
00612 static uint NumCacheVertexNormal4;
00613
00614
00615 };
00616
00617
00618
00619
00634 class CMeshMRMSkinned : public CMeshBase
00635 {
00636 public:
00638 CMeshMRMSkinned();
00639
00643 static bool isCompatible(const CMesh::CMeshBuild &m);
00644
00650 void build ( CMeshBase::CMeshBaseBuild &mBase, CMesh::CMeshBuild &m,
00651 const CMRMParameters ¶ms= CMRMParameters() );
00652
00658 void build (CMeshBase::CMeshBaseBuild &m, const CMeshMRMSkinnedGeom &mgeom);
00659
00664 void optimizeMaterialUsage(std::vector<sint> &remap);
00665
00666
00668 void computeBonesId (CSkeletonModel *skeleton);
00669
00671 void updateSkeletonUsage(CSkeletonModel *sm, bool increment);
00672
00679 void changeMRMDistanceSetup(float distanceFinest, float distanceMiddle, float distanceCoarsest);
00680
00682
00683
00685 virtual CTransformShape *createInstance(CScene &scene);
00686
00688 virtual bool clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix) ;
00689
00691 virtual void render(IDriver *drv, CTransformShape *trans, bool passOpaque);
00692
00694 virtual float getNumTriangles (float distance);
00695
00697 virtual void serial(NLMISC::IStream &f);
00698 NLMISC_DECLARE_CLASS(CMeshMRMSkinned);
00699
00701 virtual void getAABBox(NLMISC::CAABBox &bbox) const {bbox= getBoundingBox().getAABBox();}
00702
00704 virtual void profileSceneRender(CRenderTrav *rdrTrav, CTransformShape *trans, bool opaquePass);
00705
00706
00707
00708
00710
00711
00713 const NLMISC::CAABBoxExt& getBoundingBox() const
00714 {
00715 return _MeshMRMGeom.getBoundingBox();
00716 }
00717
00719 void getVertexBuffer(CVertexBuffer &output) const { _MeshMRMGeom.getVertexBuffer(output); }
00720
00721
00724 uint getNbLod() const { return _MeshMRMGeom.getNbLod() ; }
00725
00726
00730 uint getNbRdrPass(uint lodId) const { return _MeshMRMGeom.getNbRdrPass(lodId) ; }
00731
00732
00737 void getRdrPassPrimitiveBlock(uint lodId, uint renderingPassIndex, CIndexBuffer &block) const
00738 {
00739 _MeshMRMGeom.getRdrPassPrimitiveBlock(lodId, renderingPassIndex, block);
00740 }
00741
00742
00747 uint32 getRdrPassMaterial(uint lodId, uint renderingPassIndex) const
00748 {
00749 return _MeshMRMGeom.getRdrPassMaterial(lodId, renderingPassIndex) ;
00750 }
00751
00753 const CMeshMRMSkinnedGeom& getMeshGeom () const;
00754
00755
00756
00757
00759
00760 virtual IMeshGeom *supportMeshBlockRendering (CTransformShape *trans, float &polygonCount ) const;
00761
00762
00763
00764
00765 private:
00766
00767 CMeshMRMSkinnedGeom _MeshMRMGeom;
00768
00769
00770 };
00771
00772
00773 }
00774
00775
00776 #endif // NL_MESH_MRM_SKINNED_H
00777
00778