#include <mesh.h>
Inheritance diagram for NL3D::CMeshGeom:

Nevrax France
Definition at line 335 of file mesh.h.
Mesh Block Render Implementation | |
| enum | TMBRSupport { MBROk = 1, MBRSortPerMaterial = 2, MBRCurrentUseVP = 4 } |
| setuped at compileRunTime. More... | |
| uint8 | _SupportMBRFlags |
| setuped at compileRunTime. | |
Skinning | |
| enum | TSkinType { SkinPosOnly = 0, SkinWithNormal, SkinWithTgSpace } |
| void | applySkin (CSkeletonModel *skeleton) |
| void | bkupOriginalSkinVertices () |
| void | buildBoneUsageVer3 () |
| void | buildSkin (CMesh::CMeshBuild &m, std::vector< CFaceTmp > &tmpFaces) |
| void | computeSkinMatrixes (CSkeletonModel *skeleton, CMatrix3x4 *matrixes, CMatrixBlock *prevBlock, CMatrixBlock &curBlock) |
| void | computeSoftwarePointSkinning (CMatrix3x4 *matrixes, CVector *srcVector, CPaletteSkin *srcPal, float *srcWgt, CVector *dstVector) |
| void | computeSoftwareVectorSkinning (CMatrix3x4 *matrixes, CVector *srcVector, CPaletteSkin *srcPal, float *srcWgt, CVector *dstVector) |
| void | flagSkinVerticesForMatrixBlock (uint8 *skinFlags, CMatrixBlock &mb) |
| void | restoreOriginalSkinVertices () |
VBufferHard mgt. | |
| void | updateVertexBufferHard (IDriver *drv) |
| update the VertexBufferHard if NULL (ie not created or deleted by driver) or if VertexBufferDirty. | |
| CRefPtr< IDriver > | _Driver |
| This is the driver used to setup the vbuffer hard. error if a mesh has not the same driver in his life. | |
| CRefPtr< IVertexBufferHard > | _VertexBufferHard |
| The only one VBufferHard of the mesh. NULL by default. | |
| bool | _VertexBufferHardDirty |
| This tells if the VBuffer has changed since the last time or not. | |
Public Types | |
| enum | TRenderFlag { RenderOpaqueMaterial = 1, RenderTransparentMaterial = 2, RenderPassOpaque = 4, RenderGlobalAlpha = 8, RenderGADisableZWrite = 16 } |
| Render Flags, used in render. More... | |
Public Member Functions | |
| void | applyMaterialRemap (const std::vector< sint > &remap) |
| change materials Ids (called from CMesh::optimizeMaterialUsage()) | |
| void | build (CMesh::CMeshBuild &mbuild, uint numMaxMaterial) |
| Build a meshGeom. | |
| CMeshGeom () | |
| Constructor. | |
| virtual std::string | getClassName ()=0 |
| virtual bool | hasMeshVertexProgram () const |
| True if this mesh has a vertexProgram. | |
| void | renderSimpleWithMaterial (IDriver *drv, const CMatrix &worldMatrix, CMaterial &mat) |
| void | setBlendShapes (std::vector< CBlendShape > &bs) |
| virtual | ~CMeshGeom () |
Mesh Block Render Implementation | |
| virtual void | activeInstance (CMeshGeomRenderContext &rdrCtx, CMeshBaseInstance *inst, float polygonCount, void *vbDst) |
| virtual void | beginMesh (CMeshGeomRenderContext &rdrCtx) |
| virtual void | computeMeshVBHeap (void *dst, uint indexStart) |
| virtual void | endMesh (CMeshGeomRenderContext &rdrCtx) |
| virtual uint | getNumRdrPassesForInstance (CMeshBaseInstance *inst) const |
| virtual uint | getNumRdrPassesForMesh () const |
| virtual bool | getVBHeapInfo (uint &vertexFormat, uint &numVertices) |
| virtual void | renderPass (CMeshGeomRenderContext &rdrCtx, CMeshBaseInstance *inst, float polygonCount, uint rdrPass) |
| virtual bool | sortPerMaterial () const |
| virtual bool | supportMeshBlockRendering () const |
From IMeshGeom | |
| virtual bool | clip (const std::vector< CPlane > &pyramid, const CMatrix &worldMatrix) |
| clip this mesh | |
| virtual float | getNumTriangles (float distance) |
| clip this mesh | |
| virtual void | initInstance (CMeshBaseInstance *mbi) |
| Init instance info. | |
| NLMISC_DECLARE_CLASS (CMeshGeom) | |
| clip this mesh | |
| virtual void | profileSceneRender (CRenderTrav *rdrTrav, CTransformShape *trans, float polygonCount, uint32 rdrFlags) |
| clip this mesh | |
| virtual void | render (IDriver *drv, CTransformShape *trans, float polygonCount, uint32 rdrFlags, float globalAlpha) |
| render() this mesh in a driver. | |
| virtual void | renderSkin (CTransformShape *trans, float alphaMRM) |
| render() this mesh as a skin | |
| virtual void | serial (NLMISC::IStream &f) throw (NLMISC::EStream) |
| serial this mesh. | |
Skinning Behavior | |
| void | computeBonesId (CSkeletonModel *skeleton) |
| Compute skinning id. | |
| const std::vector< sint32 > & | getSkinBoneUsage () const |
| return array of bones used by the skin. computeBonesId must has been called before. | |
| bool | isSkinned () const |
| Return true if the mesh is skinned, else return false. | |
| void | updateSkeletonUsage (CSkeletonModel *sm, bool increment) |
| update Skeleton Usage. increment or decrement. computeBonesId must has been called before. | |
Geometry accessors | |
| const NLMISC::CAABBoxExt & | getBoundingBox () const |
| get the extended axis aligned bounding box of the mesh | |
| uint | getNbBlendShapes () const |
| get the number of BlendShapes | |
| uint | getNbMatrixBlock () const |
| get the number of matrix block | |
| uint | getNbRdrPass (uint matrixBlockIndex) const |
| uint32 | getRdrPassMaterial (uint matrixBlockIndex, uint renderingPassIndex) const |
| const CPrimitiveBlock & | getRdrPassPrimitiveBlock (uint matrixBlockIndex, uint renderingPassIndex) const |
| const CVertexBuffer & | getVertexBuffer () const |
| get the vertex buffer used by the mesh | |
Private Types | |
| typedef TBoneMap::iterator | ItBoneMap |
| typedef TCornerSet::iterator | ItCornerSet |
| typedef std::map< uint, CBoneTmp > | TBoneMap |
| typedef std::set< CCornerTmp *, CCornerPred > | TCornerSet |
Private Member Functions | |
| void | compileRunTime () |
| void | findVBId (TCornerSet &corners, const CCornerTmp *corn, sint ¤tVBIndex, const CVector &vert, const CMesh::CMeshBuild &mb) |
| void | optimizeTriangleOrder () |
Private Attributes | |
| NLMISC::CAABBoxExt | _BBox |
| For clipping. | |
| bool | _BoneIdComputed |
| This boolean is true if the bones id have been passed in the skeleton. | |
| bool | _BoneIdExtended |
| true if the _BonesIdExt have been computed (for bone Usage). | |
| std::vector< sint32 > | _BonesId |
| This array give the index in the skeleton of the local bones used. computed at first computeBoneId(). | |
| std::vector< sint32 > | _BonesIdExt |
| Same as _BonesId but with parent of bones added. (used for bone usage). | |
| std::vector< std::string > | _BonesName |
| This array give the name of the local bones used. | |
| std::vector< CMatrixBlock > | _MatrixBlocks |
| The matrix blocks. | |
| CMeshMorpher * | _MeshMorpher |
| NLMISC::CSmartPtr< IMeshVertexProgram > | _MeshVertexProgram |
| std::vector< CVector > | _OriginalSkinNormals |
| bool | _OriginalSkinRestored |
| This tells if the mesh VBuffer has coorect BindPos vertices. | |
| std::vector< CVector > | _OriginalSkinVertices |
| std::vector< CVector > | _OriginalTGSpace |
| bool | _PreciseClipping |
| Estimate if we must do a Precise clipping (ie with bboxes). | |
| bool | _Skinned |
| This tells if the mesh is correctly skinned. | |
| CVertexBuffer | _VBuffer |
| VBuffer of the mesh (potentially modified by the mesh morpher and skinning). | |
| CVertexBuffer | _VBufferOri |
| The original VBuffer of the mesh used only if there are blend shapes. | |
|
|
Definition at line 606 of file mesh.h. Referenced by buildSkin(). |
|
|
Definition at line 730 of file mesh.h. Referenced by findVBId(). |
|
|
Just for build process. A map of Bone. Definition at line 605 of file mesh.h. Referenced by buildSkin(). |
|
|
Definition at line 729 of file mesh.h. Referenced by build(), and findVBId(). |
|
|
setuped at compileRunTime.
Definition at line 698 of file mesh.h.
00699 {
00700 MBROk= 1,
00701 MBRSortPerMaterial= 2,
00702 MBRCurrentUseVP= 4,
00703 };
|
|
|
Render Flags, used in render.
Definition at line 82 of file mesh_geom.h.
00083 {
00084 RenderOpaqueMaterial= 1, // set when the mesh geom must render opaque material
00085 RenderTransparentMaterial= 2, // set when the mesh geom must render transparent material
00086 RenderPassOpaque=4, // set when the current traversal rdrPass is the opaque pass
00087 RenderGlobalAlpha= 8, // set when the caller wants to draw material with global alpha
00088 RenderGADisableZWrite= 16, // only when globalAlpha is used. set if must disable ZWrite
00089 };
|
|
|
Definition at line 799 of file mesh.h. Referenced by applySkin().
00799 {SkinPosOnly=0, SkinWithNormal, SkinWithTgSpace};
|
|
|
Constructor.
Definition at line 123 of file mesh.cpp. References _BoneIdComputed, _BoneIdExtended, _MeshMorpher, _OriginalSkinRestored, _PreciseClipping, _Skinned, and _VertexBufferHardDirty.
00124 {
00125 _Skinned= false;
00126 _OriginalSkinRestored= true;
00127 _VertexBufferHardDirty= true;
00128 _MeshMorpher = new CMeshMorpher;
00129 _BoneIdComputed = false;
00130 _BoneIdExtended= false;
00131 _PreciseClipping= false;
00132 }
|
|
|
Definition at line 136 of file mesh.cpp. References _MeshMorpher, _VertexBufferHard, and nlassert.
00137 {
00138 // test (refptr) if the object still exist in memory.
00139 if(_VertexBufferHard!=NULL)
00140 {
00141 // A vbufferhard should still exist only if driver still exist.
00142 nlassert(_Driver!=NULL);
00143
00144 // delete it from driver.
00145 _Driver->deleteVertexBufferHard(_VertexBufferHard);
00146 _VertexBufferHard= NULL;
00147 }
00148 delete _MeshMorpher;
00149 }
|
|
||||||||||||||||||||
|
The framework call this method any time a change of instance occurs. Implements NL3D::IMeshGeom. Definition at line 2058 of file mesh.cpp. References _MeshVertexProgram, _SupportMBRFlags, NL3D::CTransformShape::changeLightSetup(), NL3D::CMeshGeomRenderContext::Driver, NL3D::CTransform::getWorldMatrix(), NLMISC::CMatrix::inverted(), MBRCurrentUseVP, NL3D::CMeshGeomRenderContext::RenderTrav, NL3D::CMeshGeomRenderContext::Scene, and NL3D::IDriver::setupModelMatrix().
02059 {
02060 // setup instance matrix
02061 rdrCtx.Driver->setupModelMatrix(inst->getWorldMatrix());
02062
02063 // setupLighting.
02064 inst->changeLightSetup(rdrCtx.RenderTrav);
02065
02066 // MeshVertexProgram ?
02067 if( _SupportMBRFlags & MBRCurrentUseVP )
02068 {
02069 CMatrix invertedObjectMatrix;
02070 invertedObjectMatrix = inst->getWorldMatrix().inverted();
02071 _MeshVertexProgram->beginMBRInstance(rdrCtx.Driver, rdrCtx.Scene, inst, invertedObjectMatrix);
02072 }
02073 }
|
|
|
change materials Ids (called from CMesh::optimizeMaterialUsage())
Definition at line 458 of file mesh.cpp. References _MatrixBlocks, getNbMatrixBlock(), getNbRdrPass(), nlassert, uint, and uint32. Referenced by NL3D::CMesh::optimizeMaterialUsage().
00459 {
00460 for(uint mb=0;mb<getNbMatrixBlock();mb++)
00461 {
00462 for(uint rp=0;rp<getNbRdrPass(mb);rp++)
00463 {
00464 // remap
00465 uint32 &matId= _MatrixBlocks[mb].RdrPass[rp].MaterialId;
00466 nlassert(remap[matId]>=0);
00467 matId= remap[matId];
00468 }
00469 }
00470 }
|
|
|
Definition at line 1715 of file mesh.cpp. References _MatrixBlocks, _OriginalSkinNormals, _OriginalSkinRestored, _OriginalSkinVertices, _OriginalTGSpace, computeSkinMatrixes(), computeSoftwarePointSkinning(), computeSoftwareVectorSkinning(), flagSkinVerticesForMatrixBlock(), NL3D::CVertexBuffer::getNormalCoordPointer(), NL3D::CVertexBuffer::getNumTexCoordUsed(), NL3D::CVertexBuffer::getPaletteSkinPointer(), NL3D::CVertexBuffer::getTexCoordPointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexSize(), NL3D::CVertexBuffer::getWeightPointer(), NL3D::CPaletteSkin::MatrixId, NL3D_SOFTSKIN_VCOMPUTED, NL3D_SOFTSKIN_VMUSTCOMPUTE, NL3D_SOFTSKIN_VNEEDCOMPUTE, nlassert, size, SkinPosOnly, SkinWithNormal, SkinWithTgSpace, TSkinType, uint, and uint8. Referenced by renderSkin().
01716 {
01717 // init.
01718 //===================
01719 if(_OriginalSkinVertices.empty())
01720 return;
01721
01722 // Use correct skinning
01723 TSkinType skinType;
01724 if( _OriginalSkinNormals.empty() )
01725 skinType= SkinPosOnly;
01726 else if( _OriginalTGSpace.empty() )
01727 skinType= SkinWithNormal;
01728 else
01729 skinType= SkinWithTgSpace;
01730
01731 // Get VB src/dst info/ptrs.
01732 uint numVertices= _OriginalSkinVertices.size();
01733 uint dstStride= _VBuffer.getVertexSize();
01734 // Get dst TgSpace.
01735 uint tgSpaceStage = 0;
01736 if( skinType>= SkinWithTgSpace)
01737 {
01738 nlassert(_VBuffer.getNumTexCoordUsed() > 0);
01739 tgSpaceStage= _VBuffer.getNumTexCoordUsed() - 1;
01740 }
01741
01742 // Mark all vertices flag to not computed.
01743 static vector<uint8> skinFlags;
01744 skinFlags.resize(numVertices);
01745 // reset all flags
01746 memset(&skinFlags[0], NL3D_SOFTSKIN_VNEEDCOMPUTE, numVertices );
01747
01748
01749 // For all MatrixBlocks
01750 //===================
01751 for(uint mb= 0; mb<_MatrixBlocks.size();mb++)
01752 {
01753 // compute matrixes for this block.
01754 static CMatrix3x4 matrixes[IDriver::MaxModelMatrix];
01755 computeSkinMatrixes(skeleton, matrixes, mb==0?NULL:&_MatrixBlocks[mb-1], _MatrixBlocks[mb]);
01756
01757 // check what vertex to skin for this PB.
01758 flagSkinVerticesForMatrixBlock(&skinFlags[0], _MatrixBlocks[mb]);
01759
01760 // Get VB src/dst ptrs.
01761 uint8 *pFlag= &skinFlags[0];
01762 CVector *srcVector= &_OriginalSkinVertices[0];
01763 uint8 *srcPal= (uint8*)_VBuffer.getPaletteSkinPointer(0);
01764 uint8 *srcWgt= (uint8*)_VBuffer.getWeightPointer(0);
01765 uint8 *dstVector= (uint8*)_VBuffer.getVertexCoordPointer(0);
01766 // Normal.
01767 CVector *srcNormal= NULL;
01768 uint8 *dstNormal= NULL;
01769 if(skinType>=SkinWithNormal)
01770 {
01771 srcNormal= &_OriginalSkinNormals[0];
01772 dstNormal= (uint8*)_VBuffer.getNormalCoordPointer(0);
01773 }
01774 // TgSpace.
01775 CVector *srcTgSpace= NULL;
01776 uint8 *dstTgSpace= NULL;
01777 if(skinType>=SkinWithTgSpace)
01778 {
01779 srcTgSpace= &_OriginalTGSpace[0];
01780 dstTgSpace= (uint8*)_VBuffer.getTexCoordPointer(0, tgSpaceStage);
01781 }
01782
01783
01784 // For all vertices that need to be computed.
01785 uint size= numVertices;
01786 for(;size>0;size--)
01787 {
01788 // If we must compute this vertex.
01789 if(*pFlag==NL3D_SOFTSKIN_VMUSTCOMPUTE)
01790 {
01791 // Flag this vertex as computed.
01792 *pFlag=NL3D_SOFTSKIN_VCOMPUTED;
01793
01794 CPaletteSkin *psPal= (CPaletteSkin*)srcPal;
01795
01796 // checks indices.
01797 nlassert(psPal->MatrixId[0]<IDriver::MaxModelMatrix);
01798 nlassert(psPal->MatrixId[1]<IDriver::MaxModelMatrix);
01799 nlassert(psPal->MatrixId[2]<IDriver::MaxModelMatrix);
01800 nlassert(psPal->MatrixId[3]<IDriver::MaxModelMatrix);
01801
01802 // compute vertex part.
01803 computeSoftwarePointSkinning(matrixes, srcVector, psPal, (float*)srcWgt, (CVector*)dstVector);
01804
01805 // compute normal part.
01806 if(skinType>=SkinWithNormal)
01807 computeSoftwareVectorSkinning(matrixes, srcNormal, psPal, (float*)srcWgt, (CVector*)dstNormal);
01808
01809 // compute tg part.
01810 if(skinType>=SkinWithTgSpace)
01811 computeSoftwareVectorSkinning(matrixes, srcTgSpace, psPal, (float*)srcWgt, (CVector*)dstTgSpace);
01812 }
01813
01814 // inc flags.
01815 pFlag++;
01816 // inc src (all whatever skin type used...)
01817 srcVector++;
01818 srcNormal++;
01819 srcTgSpace++;
01820 // inc paletteSkin and dst (all whatever skin type used...)
01821 srcPal+= dstStride;
01822 srcWgt+= dstStride;
01823 dstVector+= dstStride;
01824 dstNormal+= dstStride;
01825 dstTgSpace+= dstStride;
01826 }
01827 }
01828
01829
01830 // dirt
01831 _OriginalSkinRestored= false;
01832 }
|
|
|
The framework call this method when he will render instances of this meshGeom soon. Implements NL3D::IMeshGeom. Definition at line 2021 of file mesh.cpp. References _MeshVertexProgram, _SupportMBRFlags, _VertexBufferHard, NL3D::IDriver::activeVertexBuffer(), NL3D::IDriver::activeVertexBufferHard(), NL3D::CMeshGeomRenderContext::Driver, MBRCurrentUseVP, nlassert, NL3D::CMeshGeomRenderContext::RenderThroughVBHeap, NL3D::CMeshGeomRenderContext::Scene, and updateVertexBufferHard().
02022 {
02023 if(rdrCtx.RenderThroughVBHeap)
02024 {
02025 // Don't setup VB in this case, since use the VBHeap setuped one.
02026 // NB: no VertexProgram test since VBHeap not possible with it...
02027 nlassert( (_SupportMBRFlags & MBRCurrentUseVP)==0 );
02028 }
02029 else
02030 {
02031 // update the VBufferHard (create/delete), to maybe render in AGP memory.
02032 updateVertexBufferHard ( rdrCtx.Driver );
02033
02034 // use MeshVertexProgram effect?
02035 if( _MeshVertexProgram != NULL && _MeshVertexProgram->isMBRVpOk(rdrCtx.Driver) )
02036 {
02037 // Ok will use it.
02038 _SupportMBRFlags|= MBRCurrentUseVP;
02039 // Before VB activation
02040 _MeshVertexProgram->beginMBRMesh(rdrCtx.Driver, rdrCtx.Scene );
02041 }
02042
02043
02044 // if VB Hard is here, use it.
02045 if(_VertexBufferHard != NULL)
02046 {
02047 // active VB Hard.
02048 rdrCtx.Driver->activeVertexBufferHard(_VertexBufferHard);
02049 }
02050 else
02051 {
02052 // active VB. SoftwareSkinning: reset flags for skinning.
02053 rdrCtx.Driver->activeVertexBuffer(_VBuffer);
02054 }
02055 }
02056 }
|
|
|
Definition at line 1615 of file mesh.cpp. References _MeshVertexProgram, _OriginalSkinNormals, _OriginalSkinVertices, _OriginalTGSpace, _Skinned, NL3D::CVertexBuffer::getNormalCoordPointer(), NL3D::CVertexBuffer::getNumTexCoordUsed(), NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getTexCoordPointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), nlassert, and uint. Referenced by compileRunTime().
01616 {
01617 nlassert(_Skinned);
01618
01619 // reset
01620 contReset(_OriginalSkinVertices);
01621 contReset(_OriginalSkinNormals);
01622 contReset(_OriginalTGSpace);
01623
01624 // get num of vertices
01625 uint numVertices= _VBuffer.getNumVertices();
01626
01627 // Copy VBuffer content into Original vertices normals.
01628 if(_VBuffer.getVertexFormat() & CVertexBuffer::PositionFlag)
01629 {
01630 // copy vertices from VBuffer. (NB: unusefull geomorphed vertices are still copied, but doesn't matter).
01631 _OriginalSkinVertices.resize(numVertices);
01632 for(uint i=0; i<numVertices;i++)
01633 {
01634 _OriginalSkinVertices[i]= *(CVector*)_VBuffer.getVertexCoordPointer(i);
01635 }
01636 }
01637 if(_VBuffer.getVertexFormat() & CVertexBuffer::NormalFlag)
01638 {
01639 // copy normals from VBuffer. (NB: unusefull geomorphed normals are still copied, but doesn't matter).
01640 _OriginalSkinNormals.resize(numVertices);
01641 for(uint i=0; i<numVertices;i++)
01642 {
01643 _OriginalSkinNormals[i]= *(CVector*)_VBuffer.getNormalCoordPointer(i);
01644 }
01645 }
01646
01647 // is there tangent space added ?
01648 if (_MeshVertexProgram && _MeshVertexProgram->needTangentSpace())
01649 {
01650 // yes, backup it
01651 nlassert(_VBuffer.getNumTexCoordUsed() > 0);
01652 uint tgSpaceStage = _VBuffer.getNumTexCoordUsed() - 1;
01653 _OriginalTGSpace.resize(numVertices);
01654 for(uint i=0; i<numVertices;i++)
01655 {
01656 _OriginalTGSpace[i]= *(CVector*)_VBuffer.getTexCoordPointer(i, tgSpaceStage);
01657 }
01658 }
01659 }
|
|
||||||||||||
|
Build a meshGeom. 0. First, make bbox. 1. If skinning, group by matrix Block the vertices. 2. Then, for all faces, resolve continuities, building VBuffer. 3. build the RdrPass material. 4. Then, for all faces, build the RdrPass PBlock. 5. Remove empty RdrPasses. 6. Misc. 7. Compact bones id and build bones name array. If all texture coordinates are of dimension 2, we can setup the flags as before. If this isn't the case, we must setup a custom format
Definition at line 172 of file mesh.cpp. References _BoneIdComputed, _BoneIdExtended, _BonesName, _MatrixBlocks, _MeshMorpher, _MeshVertexProgram, _Skinned, _VertexBufferHardDirty, NL3D::CVertexBuffer::addValueEx(), NL3D::CMesh::CMeshBuild::BlendShapes, NL3D::CMeshMorpher::BlendShapes, NL3D::CMesh::CMeshBuild::BonesNames, buildSkin(), NL3D::CVertexBuffer::clearValueEx(), compileRunTime(), NL3D::CMeshGeom::CFaceTmp::Corner, NL3D::CMesh::CMeshBuild::Faces, findVBId(), NL3D::CVertexBuffer::initEx(), NL3D::makeBBox(), NL3D::CMeshGeom::CFaceTmp::MaterialId, matrix, NL3D::CMeshGeom::CFaceTmp::MatrixBlockId, NL3D::CMeshGeom::CMatrixBlock::MatrixId, NL3D::CMesh::CMeshBuild::MeshVertexProgram, nlassert, NL3D::CMesh::CMeshBuild::NumCoords, NL3D::CMeshGeom::CMatrixBlock::NumMatrix, optimizeTriangleOrder(), NL3D::CVertexBuffer::reserve(), NLMISC::CAABBoxExt::setCenter(), NL3D::CVertexBuffer::setNumVertices(), NLMISC::CAABBoxExt::setSize(), NL3D::CVertexBuffer::setUVRouting(), NL3D::CVertexBuffer::setVertexFormat(), sint, NL3D::CMesh::CMeshBuild::SkinWeights, TCornerSet, uint, uint32, NL3D::CMesh::CMeshBuild::UVRouting, NL3D::CMeshGeom::CCornerTmp::VBId, NL3D::CMesh::CCorner::Vertex, NL3D::CMesh::CMeshBuild::VertexFlags, NL3D::CMesh::CMeshBuild::Vertices, and NL3D::CMesh::CMeshBuild::VertLink. Referenced by NL3D::CMesh::build().
00173 {
00174 sint i;
00175
00176 // Dirt the VBuffer.
00177 _VertexBufferHardDirty= true;
00178
00179 // Empty geometry?
00180 if(m.Vertices.size()==0 || m.Faces.size()==0)
00181 {
00182 _VBuffer.setNumVertices(0);
00183 _VBuffer.reserve(0);
00184 _MatrixBlocks.clear();
00185 _BBox.setCenter(CVector::Null);
00186 _BBox.setSize(CVector::Null);
00187 return;
00188 }
00189 nlassert(numMaxMaterial>0);
00190
00191 // Copy the UV routing table
00192 for (i=0; i<CVertexBuffer::MaxStage; i++)
00193 _VBuffer.setUVRouting (i, m.UVRouting[i]);
00194
00196 //======================
00197 _BBox= makeBBox(m.Vertices);
00198
00199
00201 //================================================
00202
00203 // First, copy Face array.
00204 vector<CFaceTmp> tmpFaces;
00205 tmpFaces.resize(m.Faces.size());
00206 for(i=0;i<(sint)tmpFaces.size();i++)
00207 tmpFaces[i]= m.Faces[i];
00208
00209 _Skinned= ((m.VertexFlags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag);
00210 // Skinning is OK only if SkinWeights are of same size as vertices.
00211 _Skinned= _Skinned && (m.Vertices.size()==m.SkinWeights.size());
00212
00213 // If skinning is KO, remove the Skin option.
00214 uint vbFlags= m.VertexFlags;
00215 if(!_Skinned)
00216 vbFlags&= ~CVertexBuffer::PaletteSkinFlag;
00217 // Force presence of vertex.
00218 vbFlags|= CVertexBuffer::PositionFlag;
00219
00220
00221 // If the mesh is not skinned, we have just 1 _MatrixBlocks.
00222 if(!_Skinned)
00223 {
00224 _MatrixBlocks.resize(1);
00225 // For each faces, assign it to the matrix block 0.
00226 for(i=0;i<(sint)tmpFaces.size();i++)
00227 tmpFaces[i].MatrixBlockId= 0;
00228 }
00229 // Else We must group/compute the matrixs blocks.
00230 else
00231 {
00232 // reset matrix blocks.
00233 _MatrixBlocks.clear();
00234 // build matrix blocks, and link faces to good matrix blocks.
00235 buildSkin(m, tmpFaces);
00236 }
00237
00238
00240 //================================================
00241 // Setup VB.
00242 _VBuffer.setNumVertices(0);
00243 _VBuffer.reserve(0);
00244
00245 bool useFormatExt = false;
00249 for (uint k = 0; k < CVertexBuffer::MaxStage; ++k)
00250 {
00251 if (
00252 (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
00253 && m.NumCoords[k] != 2)
00254 {
00255 useFormatExt = true;
00256 break;
00257 }
00258 }
00259
00260 if (!useFormatExt)
00261 {
00262 // setup standard format
00263 _VBuffer.setVertexFormat(vbFlags);
00264 }
00265 else // setup extended format
00266 {
00267 _VBuffer.clearValueEx();
00268 if (vbFlags & CVertexBuffer::PositionFlag) _VBuffer.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3);
00269 if (vbFlags & CVertexBuffer::NormalFlag) _VBuffer.addValueEx(CVertexBuffer::Normal, CVertexBuffer::Float3);
00270 if (vbFlags & CVertexBuffer::PrimaryColorFlag) _VBuffer.addValueEx(CVertexBuffer::PrimaryColor, CVertexBuffer::UChar4);
00271 if (vbFlags & CVertexBuffer::SecondaryColorFlag) _VBuffer.addValueEx(CVertexBuffer::SecondaryColor, CVertexBuffer::UChar4);
00272 if (vbFlags & CVertexBuffer::WeightFlag) _VBuffer.addValueEx(CVertexBuffer::Weight, CVertexBuffer::Float4);
00273 if (vbFlags & CVertexBuffer::PaletteSkinFlag) _VBuffer.addValueEx(CVertexBuffer::PaletteSkin, CVertexBuffer::UChar4);
00274 if (vbFlags & CVertexBuffer::FogFlag) _VBuffer.addValueEx(CVertexBuffer::Fog, CVertexBuffer::Float1);
00275
00276 for (uint k = 0; k < CVertexBuffer::MaxStage; ++k)
00277 {
00278 if (vbFlags & (CVertexBuffer::TexCoord0Flag << k))
00279 {
00280 switch(m.NumCoords[k])
00281 {
00282 case 2:
00283 _VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float2);
00284 break;
00285 case 3:
00286 _VBuffer.addValueEx((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + k), CVertexBuffer::Float3);
00287 break;
00288 default:
00289 nlassert(0);
00290 break;
00291 }
00292 }
00293 }
00294 _VBuffer.initEx();
00295 }
00296
00297 // Set local flags for corner comparison.
00298 CCornerTmp::Flags= vbFlags;
00299 // Setup locals.
00300 TCornerSet corners;
00301 const CFaceTmp *pFace= &(*tmpFaces.begin());
00302 uint32 nFaceMB = 0;
00303 sint N= tmpFaces.size();
00304 sint currentVBIndex=0;
00305
00306 m.VertLink.clear ();
00307
00308 // process each face, building up the VB.
00309 for(;N>0;N--, pFace++)
00310 {
00311 sint v0= pFace->Corner[0].Vertex;
00312 sint v1= pFace->Corner[1].Vertex;
00313 sint v2= pFace->Corner[2].Vertex;
00314 findVBId(corners, &pFace->Corner[0], currentVBIndex, m.Vertices[v0], m);
00315 findVBId(corners, &pFace->Corner[1], currentVBIndex, m.Vertices[v1], m);
00316 findVBId(corners, &pFace->Corner[2], currentVBIndex, m.Vertices[v2], m);
00317 CMesh::CVertLink vl1(nFaceMB, 0, pFace->Corner[0].VBId);
00318 CMesh::CVertLink vl2(nFaceMB, 1, pFace->Corner[1].VBId);
00319 CMesh::CVertLink vl3(nFaceMB, 2, pFace->Corner[2].VBId);
00320 m.VertLink.push_back(vl1);
00321 m.VertLink.push_back(vl2);
00322 m.VertLink.push_back(vl3);
00323 ++nFaceMB;
00324 }
00325
00326
00328 //================================
00329 uint mb;
00330
00331 // For each _MatrixBlocks, point on those materials.
00332 for(mb= 0;mb<_MatrixBlocks.size();mb++)
00333 {
00334 // Build RdrPass ids.
00335 _MatrixBlocks[mb].RdrPass.resize (numMaxMaterial);
00336
00338 for(i=0;i<(sint)_MatrixBlocks[mb].RdrPass.size(); i++)
00339 {
00340 _MatrixBlocks[mb].RdrPass[i].MaterialId= i;
00341 }
00342 }
00343
00344
00346 //===================================================
00347 pFace= &(*tmpFaces.begin());
00348 N= tmpFaces.size();
00349 for(;N>0;N--, pFace++)
00350 {
00351 sint mbId= pFace->MatrixBlockId;
00352 nlassert(mbId>=0 && mbId<(sint)_MatrixBlocks.size());
00353 // Insert the face in good MatrixBlock/RdrPass.
00354 _MatrixBlocks[mbId].RdrPass[pFace->MaterialId].PBlock.addTri(pFace->Corner[0].VBId, pFace->Corner[1].VBId, pFace->Corner[2].VBId);
00355 }
00356
00357
00359 //============================
00360 for(mb= 0;mb<_MatrixBlocks.size();mb++)
00361 {
00362 // NB: slow process (erase from a vector). Doens't matter since made at build.
00363 vector<CRdrPass>::iterator itPass;
00364 for( itPass=_MatrixBlocks[mb].RdrPass.begin(); itPass!=_MatrixBlocks[mb].RdrPass.end(); )
00365 {
00366 // If this pass is empty, remove it.
00367 if( itPass->PBlock.getNumTri()==0 )
00368 itPass= _MatrixBlocks[mb].RdrPass.erase(itPass);
00369 else
00370 itPass++;
00371 }
00372 }
00373
00375 //============================
00376 // BShapes
00377 this->_MeshMorpher->BlendShapes = m.BlendShapes;
00378
00379 // sort triangles for better cache use.
00380 optimizeTriangleOrder();
00381
00382 // SmartPtr Copy VertexProgram effect.
00383 this->_MeshVertexProgram= m.MeshVertexProgram;
00384
00386 //=================================================
00387
00388 // If skinned
00389 if(_Skinned)
00390 {
00391 // Reserve some space
00392 _BonesName.reserve (m.BonesNames.size ());
00393
00394 // Current local bone
00395 uint currentBone = 0;
00396
00397 // For each matrix block
00398 uint matrixBlock;
00399 for (matrixBlock=0; matrixBlock<_MatrixBlocks.size(); matrixBlock++)
00400 {
00401 // Ref on the matrix block
00402 CMatrixBlock &mb = _MatrixBlocks[matrixBlock];
00403
00404 // Remap the skeleton index in model index
00405 std::map<uint, uint> remap;
00406
00407 // For each matrix
00408 uint matrix;
00409 for (matrix=0; matrix<mb.NumMatrix; matrix++)
00410 {
00411 // Get bone id in the skeleton
00412 std::map<uint, uint>::iterator ite = remap.find (mb.MatrixId[matrix]);
00413
00414 // Not found
00415 if (ite == remap.end())
00416 {
00417 // Insert it
00418 remap.insert (std::map<uint, uint>::value_type (mb.MatrixId[matrix], currentBone));
00419
00420 // Check the matrix id
00421 nlassert (mb.MatrixId[matrix] < m.BonesNames.size());
00422
00423 // Set the bone name
00424 _BonesName.push_back (m.BonesNames[mb.MatrixId[matrix]]);
00425
00426 // Set the id in local
00427 mb.MatrixId[matrix] = currentBone++;
00428 }
00429 else
00430 {
00431 // Set the id in local
00432 mb.MatrixId[matrix] = ite->second;
00433 }
00434 }
00435 }
00436
00437 // Bone id in local
00438 _BoneIdComputed = false;
00439 _BoneIdExtended = false;
00440 }
00441
00442
00443 // End!!
00444 // Some runtime not serialized compilation
00445 compileRunTime();
00446 }
|
|
|
Definition at line 1549 of file mesh.cpp. References _BonesId, _MatrixBlocks, _Skinned, matrix, NL3D::CMeshGeom::CMatrixBlock::MatrixId, NL3D::CMeshGeom::CMatrixBlock::NumMatrix, uint, and uint32.
01550 {
01551 if(_Skinned)
01552 {
01553 // parse all matrixBlocks, couting MaxBoneId used.
01554 uint32 maxBoneId= 0;
01555 // For each matrix block
01556 uint matrixBlock;
01557 for (matrixBlock=0; matrixBlock<_MatrixBlocks.size(); matrixBlock++)
01558 {
01559 CMatrixBlock &mb = _MatrixBlocks[matrixBlock];
01560 // For each matrix
01561 for (uint matrix=0; matrix<mb.NumMatrix; matrix++)
01562 {
01563 maxBoneId= max(mb.MatrixId[matrix], maxBoneId);
01564 }
01565 }
01566
01567 // alloc an array of maxBoneId+1, reset to 0.
01568 std::vector<uint8> boneUsage;
01569 boneUsage.resize(maxBoneId+1, 0);
01570
01571 // reparse all matrixBlocks, counting usage for each bone.
01572 for (matrixBlock=0; matrixBlock<_MatrixBlocks.size(); matrixBlock++)
01573 {
01574 CMatrixBlock &mb = _MatrixBlocks[matrixBlock];
01575 // For each matrix
01576 for (uint matrix=0; matrix<mb.NumMatrix; matrix++)
01577 {
01578 // mark this bone as used.
01579 boneUsage[mb.MatrixId[matrix]]= 1;
01580 }
01581 }
01582
01583 // For each bone used
01584 _BonesId.clear();
01585 for(uint i=0; i<boneUsage.size();i++)
01586 {
01587 // if the bone is used by the mesh, add it to BoneId.
01588 if(boneUsage[i])
01589 _BonesId.push_back(i);
01590 }
01591 }
01592 }
|
|
||||||||||||
|
Definition at line 1105 of file mesh.cpp. References _MatrixBlocks, NL3D::CMeshGeom::CFaceTmp::Corner, NL3D::CMeshGeom::CMatrixBlock::getMatrixIdLocation(), NL3D::CMeshGeom::CBoneTmp::Inserted, ItBoneMap, NL3D::CMeshGeom::CFaceTmp::MatrixBlockId, NL3D::CPaletteSkin::MatrixId, NL3D::CMeshGeom::CMatrixBlock::MatrixId, NL3D::CMesh::CSkinWeight::MatrixId, NL3D::CMeshGeom::CBoneTmp::MatrixIdInMB, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NL3D::CMeshGeom::CMatrixBlock::NumMatrix, NL3D::CMeshGeom::CCornerTmp::Palette, NL3D::CMeshGeom::CBoneTmp::RefCount, NL3D::CMeshGeom::CMatrixBlockRemap::Remap, sint, NL3D::CMesh::CMeshBuild::SkinWeights, TBoneMap, uint, uint8, NL3D::CMesh::CCorner::Vertex, NL3D::CMeshGeom::CCornerTmp::Weights, and NL3D::CMesh::CSkinWeight::Weights. Referenced by build().
01106 {
01107 sint i,j,k;
01108 TBoneMap remainingBones;
01109 list<uint> remainingFaces;
01110
01111
01112 // 0. normalize SkinWeights: for all weights at 0, copy the matrixId from 0th matrix => no random/bad use of matrix.
01113 //================================
01114 for(i=0;i<(sint)m.SkinWeights.size();i++)
01115 {
01116 CMesh::CSkinWeight &sw= m.SkinWeights[i];
01117
01118 // 0th weight must not be 0.
01119 nlassert(sw.Weights[0]!=0);
01120
01121 // Begin at 1, tests all other weights.
01122 for(j=1;j<NL3D_MESH_SKINNING_MAX_MATRIX;j++)
01123 {
01124 // We don't use this entry??
01125 if(sw.Weights[j]==0)
01126 {
01127 // Setup MatrixId so that this vertex do no use more matrix than it really wants.
01128 sw.MatrixId[j]= sw.MatrixId[0];
01129 }
01130 }
01131 }
01132
01133
01134 // 1. build the list of used/remaining bones, in ascending order. (so we use the depth-first topolgy of hierarchy).
01135 //================================
01136 for(i=0;i<(sint)tmpFaces.size();i++)
01137 {
01138 CFaceTmp &face= tmpFaces[i];
01139
01140 for(j=0;j<3;j++)
01141 {
01142 CMesh::CSkinWeight &sw= m.SkinWeights[face.Corner[j].Vertex];
01143 for(k=0;k<NL3D_MESH_SKINNING_MAX_MATRIX;k++)
01144 {
01145 // insert (if not already here) the used bone in the set.
01146 // and insert his refcount. (NB: ctor() init it to 0 :) ).
01147 remainingBones[sw.MatrixId[k]].RefCount++;
01148 }
01149 }
01150 }
01151
01152
01153 // 2. Create the list of un-inserted faces.
01154 //================================
01155 for(i=0;i<(sint)tmpFaces.size();i++)
01156 {
01157 remainingFaces.push_back(i);
01158 }
01159
01160
01161
01162 // 3. Create as many Blocks as necessary.
01163 //================================
01164 // Which bones a face use (up to 12).
01165 vector<uint> boneUse;
01166 boneUse.reserve(NL3D_MESH_SKINNING_MAX_MATRIX*3);
01167
01168 // While still exist faces.
01169 while(!remainingFaces.empty())
01170 {
01171 // create a new matrix block.
01172 _MatrixBlocks.push_back(CMatrixBlock());
01173 CMatrixBlock &matrixBlock= _MatrixBlocks[_MatrixBlocks.size()-1];
01174 matrixBlock.NumMatrix=0;
01175
01176 // a. reset remainingBones as not inserted in the current matrixBlock.
01177 //============================
01178 ItBoneMap itBone;
01179 for(itBone= remainingBones.begin();itBone!=remainingBones.end();itBone++)
01180 {
01181 itBone->second.Inserted= false;
01182 }
01183
01184
01185 // b. while still exist bones, try to insert faces which use them in matrixBlock.
01186 //============================
01187 while(!remainingBones.empty())
01188 {
01189 // get the first bone from the map. (remind: depth-first order).
01190 uint currentBoneId= remainingBones.begin()->first;
01191
01192 // If no more faces in the remainingFace list use this bone, remove it, and continue.
01193 if(remainingBones.begin()->second.RefCount==0)
01194 {
01195 remainingBones.erase(remainingBones.begin());
01196 continue;
01197 }
01198
01199 // this is a marker, to know if a face insertion will occurs.
01200 bool faceAdded= false;
01201
01202 // traverse all faces, trying to insert them in current MatrixBlock processed.
01203 list<uint>::iterator itFace;
01204 for(itFace= remainingFaces.begin(); itFace!=remainingFaces.end();)
01205 {
01206 bool useCurrentBoneId;
01207 uint newBoneAdded;
01208
01209 // i/ Get info on current face.
01210 //-----------------------------
01211
01212 // build which bones this face use.
01213 tmpFaces[*itFace].buildBoneUse(boneUse, m.SkinWeights);
01214
01215 // test if this face use the currentBoneId.
01216 useCurrentBoneId= false;
01217 for(i=0;i<(sint)boneUse.size();i++)
01218 {
01219 // if this face use the currentBoneId
01220 if(boneUse[i]==currentBoneId)
01221 {
01222 useCurrentBoneId= true;
01223 break;
01224 }
01225 }
01226 // compute how many bones that are not in the current matrixblock this face use.
01227 newBoneAdded=0;
01228 for(i=0;i<(sint)boneUse.size();i++)
01229 {
01230 // if this bone is not inserted in the current matrix block, inform it.
01231 if(!remainingBones[boneUse[i]].Inserted)
01232 newBoneAdded++;
01233 }
01234
01235
01236 // ii/ insert/reject face.
01237 //------------------------
01238
01239 // If this face do not add any more bone, we can insert it into the current matrixblock.
01240 // If it use the currentBoneId, and do not explode max count, we allow insert it too in the current matrixblock.
01241 if( newBoneAdded==0 ||
01242 (useCurrentBoneId && newBoneAdded+matrixBlock.NumMatrix < IDriver::MaxModelMatrix) )
01243 {
01244 // Insert this face in the current matrix block
01245
01246 CFaceTmp &face= tmpFaces[*itFace];
01247
01248 // for all vertices of this face.
01249 for(j=0;j<3;j++)
01250 {
01251 CMesh::CSkinWeight &sw= m.SkinWeights[face.Corner[j].Vertex];
01252
01253 // for each corner weight (4)
01254 for(k=0;k<NL3D_MESH_SKINNING_MAX_MATRIX;k++)
01255 {
01256 // get the global boneId this corner weight use.
01257 uint boneId= sw.MatrixId[k];
01258 // get the CBoneTmp this corner weight use.
01259 CBoneTmp &bone= remainingBones[boneId];
01260
01261 // decRef the bone .
01262 bone.RefCount--;
01263
01264 // Is this bone already inserted in the MatrixBlock ?
01265 if( !bone.Inserted )
01266 {
01267 // No, insert it.
01268 bone.Inserted= true;
01269 // link it to the MatrixId in the current matrixBlock.
01270 bone.MatrixIdInMB= matrixBlock.NumMatrix;
01271
01272 // modify the matrixBlock
01273 matrixBlock.MatrixId[matrixBlock.NumMatrix]= boneId;
01274 // increment the number of matrix in the matrixBlock.
01275 matrixBlock.NumMatrix++;
01276 }
01277
01278 // Copy Weight info for this Corner.
01279 // Set what matrix in the current matrix block this corner use.
01280 face.Corner[j].Palette.MatrixId[k]= bone.MatrixIdInMB;
01281 // Set weight.
01282 face.Corner[j].Weights[k]= sw.Weights[k];
01283 }
01284 }
01285
01286 // to Which matrixblock this face is inserted.
01287 face.MatrixBlockId= _MatrixBlocks.size()-1;
01288
01289 // remove the face from remain face list.
01290 itFace= remainingFaces.erase(itFace);
01291
01292 // inform the algorithm that a face has been added.
01293 faceAdded= true;
01294 }
01295 else
01296 {
01297 // do not append this face to the current matrix block, skip to the next
01298 itFace++;
01299 }
01300 }
01301
01302 // If no faces have been added during this pass, we are blocked, and either the MatrixBlock may be full,
01303 // or there is no more face. So quit this block and process a new one.
01304 if(!faceAdded)
01305 break;
01306 }
01307
01308 }
01309 // NB: at the end of this loop, remainingBones may not be empty(), but all remainingBones should have RefCount==0.
01310
01311
01312
01313 // 4. Re-order matrix use in MatrixBlocks, for minimum matrix change between MatrixBlocks.
01314 //================================
01315 vector<CMatrixBlockRemap> blockRemaps;
01316 blockRemaps.resize(_MatrixBlocks.size());
01317
01318
01319 // For all MatrixBlocks > first, try to "mirror" bones from previous.
01320 for(i=1;i<(sint)_MatrixBlocks.size();i++)
01321 {
01322 CMatrixBlock &mBlock= _MatrixBlocks[i];
01323 CMatrixBlock &mPrevBlock= _MatrixBlocks[i-1];
01324 CMatrixBlockRemap &remap= blockRemaps[i];
01325
01326 // First bkup the bone ids in remap table.
01327 for(j=0;j<(sint)mBlock.NumMatrix;j++)
01328 {
01329 remap.Remap[j]= mBlock.MatrixId[j];
01330 }
01331
01332 // For all ids of this blocks, try to mirror them.
01333 for(j=0;j<(sint)mBlock.NumMatrix;j++)
01334 {
01335 // get the location of this bone in the prev bone.
01336 sint idLoc= mPrevBlock.getMatrixIdLocation(mBlock.MatrixId[j]);
01337 // If not found, or if bigger than current array, fails (cant be mirrored).
01338 // Or if already mirrored.
01339 if(idLoc==-1 || idLoc>=(sint)mBlock.NumMatrix || idLoc==j)
01340 {
01341 // next id.
01342 j++;
01343 }
01344 else
01345 {
01346 // puts me on my mirrored location. and swap with the current one at this mirrored location.
01347 swap(mBlock.MatrixId[j], mBlock.MatrixId[idLoc]);
01348 // mBlock.MatrixId[j] is now a candidate for mirror.
01349 }
01350 }
01351
01352 // Then build the Remap table, to re-order faces matrixId which use this matrix block.
01353 for(j=0;j<(sint)mBlock.NumMatrix;j++)
01354 {
01355 // get the boneid which was at this position j before.
01356 uint boneId= remap.Remap[j];
01357 // search his new position, and store the result in the remap table.
01358 remap.Remap[j]= mBlock.getMatrixIdLocation(boneId);
01359 }
01360
01361 // NB: this matrixBlock is re-ordered. next matrixBlock use this state.
01362 }
01363
01364
01365 // For all faces/corners/weights, remap MatrixIds.
01366 for(i=0;i<(sint)tmpFaces.size();i++)
01367 {
01368 CFaceTmp &face= tmpFaces[i];
01369 // do it but for matrixblock0.
01370 if(face.MatrixBlockId!=0)
01371 {
01372 CMatrixBlockRemap &remap= blockRemaps[face.MatrixBlockId];
01373 // For all corners.
01374 for(j=0;j<3;j++)
01375 {
01376 for(k=0;k<NL3D_MESH_SKINNING_MAX_MATRIX;k++)
01377 {
01378 uint oldId= face.Corner[j].Palette.MatrixId[k];
01379 face.Corner[j].Palette.MatrixId[k]= (uint8)remap.Remap[oldId];
01380 }
01381 }
01382 }
01383 }
01384
01385 }
|
|
||||||||||||
|
clip this mesh
Reimplemented from NL3D::IMeshGeom. Definition at line 482 of file mesh.cpp. References _PreciseClipping, NLMISC::CBSphere::applyTransform(), NLMISC::CBSphere::Center, NLMISC::CAABBoxExt::clipBack(), NLMISC::CAABBoxExt::getCenter(), NLMISC::CAABBoxExt::getRadius(), NLMISC::CPlane::normalize(), NLMISC::CBSphere::Radius, and sint. Referenced by NL3D::CMesh::clip().
00483 {
00484 // Speed Clip: clip just the sphere.
00485 CBSphere localSphere(_BBox.getCenter(), _BBox.getRadius());
00486 CBSphere worldSphere;
00487
00488 // transform the sphere in WorldMatrix (with nearly good scale info).
00489 localSphere.applyTransform(worldMatrix, worldSphere);
00490
00491 // if out of only plane, entirely out.
00492 for(sint i=0;i<(sint)pyramid.size();i++)
00493 {
00494 // We are sure that pyramid has normalized plane normals.
00495 // if SpherMax OUT return false.
00496 float d= pyramid[i]*worldSphere.Center;
00497 if(d>worldSphere.Radius)
00498 return false;
00499 }
00500
00501 // test if must do a precise clip, according to mesh size.
00502 if( _PreciseClipping )
00503 {
00504 CPlane localPlane;
00505
00506 // if out of only plane, entirely out.
00507 for(sint i=0;i<(sint)pyramid.size();i++)
00508 {
00509 // Transform the pyramid in Object space.
00510 localPlane= pyramid[i]*worldMatrix;
00511 // localPlane must be normalized, because worldMatrix mya have a scale.
00512 localPlane.normalize();
00513 // if the box is not partially inside the plane, quit
00514 if( !_BBox.clipBack(localPlane) )
00515 return false;
00516 }
00517 }
00518
00519 return true;
00520 }
|
|
|
Definition at line 1062 of file mesh.cpp. References _MatrixBlocks, _MeshMorpher, _MeshVertexProgram, _PreciseClipping, _Skinned, _SupportMBRFlags, bkupOriginalSkinVertices(), NL3D::CMeshMorpher::BlendShapes, NLMISC::CAABBoxExt::getRadius(), MBROk, MBRSortPerMaterial, and NL3D_MESH_PRECISE_CLIP_THRESHOLD. Referenced by build(), and setBlendShapes().
01063 {
01064 // if skinned, prepare skinning
01065 if(_Skinned)
01066 bkupOriginalSkinVertices();
01067
01068 // Do precise clipping for big object??
01069 _PreciseClipping= _BBox.getRadius() >= NL3D_MESH_PRECISE_CLIP_THRESHOLD;
01070
01071 // Support MeshBlockRendering only if not skinned/meshMorphed.
01072 bool supportMeshBlockRendering= !_Skinned && _MeshMorpher->BlendShapes.size()==0;
01073
01074 // true only if one matrix block, and at least one rdrPass.
01075 supportMeshBlockRendering= supportMeshBlockRendering && _MatrixBlocks.size()==1 && _MatrixBlocks[0].RdrPass.size()>0;
01076 if (supportMeshBlockRendering && _MeshVertexProgram)
01077 {
01078 supportMeshBlockRendering = supportMeshBlockRendering && _MeshVertexProgram->supportMeshBlockRendering();
01079 }
01080
01081 // TestYoyo
01082 //supportMeshBlockRendering= false;
01083
01084 // support MeshVertexProgram, but no material sorting...
01085 bool supportMBRPerMaterial= supportMeshBlockRendering && _MeshVertexProgram==NULL;
01086
01087
01088 // setup flags
01089 _SupportMBRFlags= 0;
01090 if(supportMeshBlockRendering)
01091 _SupportMBRFlags|= MBROk;
01092 if(supportMBRPerMaterial)
01093 _SupportMBRFlags|= MBRSortPerMaterial;
01094 }
|
|
|
Compute skinning id.
Definition at line 1456 of file mesh.cpp. References _BoneIdComputed, _BoneIdExtended, _BonesId, _BonesIdExt, _BonesName, _MatrixBlocks, NL3D::CSkeletonModel::Bones, NL3D::CSkeletonModel::flagBoneAndParents(), NL3D::CSkeletonModel::getBoneIdByName(), matrix, NL3D::CMeshGeom::CMatrixBlock::MatrixId, nlassert, nlwarning, NL3D::CMeshGeom::CMatrixBlock::NumMatrix, sint32, uint, and uint32. Referenced by NL3D::CMesh::computeBonesId().
01457 {
01458 // Already computed ?
01459 if (!_BoneIdComputed)
01460 {
01461 // Get a pointer on the skeleton
01462 nlassert (skeleton);
01463 if (skeleton)
01464 {
01465 // Resize boneId to the good size.
01466 _BonesId.resize(_BonesName.size());
01467
01468 // For each matrix block
01469 uint matrixBlock;
01470 for (matrixBlock=0; matrixBlock<_MatrixBlocks.size(); matrixBlock++)
01471 {
01472 // Ref on the matrix block
01473 CMatrixBlock &mb = _MatrixBlocks[matrixBlock];
01474
01475 // For each matrix
01476 uint matrix;
01477 for (matrix=0; matrix<mb.NumMatrix; matrix++)
01478 {
01479 // Get bone id in the skeleton
01480 nlassert (mb.MatrixId[matrix]<_BonesName.size());
01481 sint32 boneId = skeleton->getBoneIdByName (_BonesName[mb.MatrixId[matrix]]);
01482
01483 // Setup the _BoneId.
01484 _BonesId[mb.MatrixId[matrix]]= boneId;
01485
01486 // Bones found ?
01487 if (boneId != -1)
01488 {
01489 // Set the bone id
01490 mb.MatrixId[matrix] = (uint32)boneId;
01491 }
01492 else
01493 {
01494 // Put id 0
01495 mb.MatrixId[matrix] = 0;
01496
01497 // Error
01498 nlwarning ("Bone %s not found in the skeleton.", _BonesName[mb.MatrixId[matrix]].c_str());
01499 }
01500 }
01501 }
01502
01503 // Computed
01504 _BoneIdComputed = true;
01505 }
01506 }
01507
01508 // Already extended ?
01509 if (!_BoneIdExtended)
01510 {
01511 nlassert (skeleton);
01512 if (skeleton)
01513 {
01514 // the total bone Usage of the mesh.
01515 vector<bool> boneUsage;
01516 boneUsage.resize(skeleton->Bones.size(), false);
01517
01518 // for all Bones marked as valid.
01519 uint i;
01520 for(i=0; i<_BonesId.size(); i++)
01521 {
01522 // if not a valid boneId, skip it.
01523 if(_BonesId[i]<0)
01524 continue;
01525
01526 // mark him and his father in boneUsage.
01527 skeleton->flagBoneAndParents(_BonesId[i], boneUsage);
01528 }
01529
01530 // fill _BonesIdExt with bones of _BonesId and their parents.
01531 _BonesIdExt.clear();
01532 for(i=0; i<boneUsage.size();i++)
01533 {
01534 // if the bone is used by the mesh, add it to BoneIdExt.
01535 if(boneUsage[i])
01536 _BonesIdExt.push_back(i);
01537 }
01538
01539 }
01540
01541 // Extended
01542 _BoneIdExtended= true;
01543 }
01544
01545 }
|
|
||||||||||||
|
When the framework succes to allocate a VBHeap space, it call this method to fill this space and compute shifted Primitive block.
Reimplemented from NL3D::IMeshGeom. Definition at line 2133 of file mesh.cpp. References _MatrixBlocks, NL3D::CPrimitiveBlock::getLinePointer(), NL3D::CPrimitiveBlock::getNumLine(), NL3D::CPrimitiveBlock::getNumQuad(), NL3D::CPrimitiveBlock::getNumTri(), NL3D::CVertexBuffer::getNumVertices(), NL3D::CPrimitiveBlock::getQuadPointer(), NL3D::CPrimitiveBlock::getTriPointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexSize(), nlassert, NL3D::CMeshGeom::CMatrixBlock::RdrPass, NL3D::CPrimitiveBlock::setNumLine(), NL3D::CPrimitiveBlock::setNumQuad(), NL3D::CPrimitiveBlock::setNumTri(), uint, and uint32.
02134 {
02135 // Fill dst with Buffer content.
02136 memcpy(dst, _VBuffer.getVertexCoordPointer(), _VBuffer.getNumVertices()*_VBuffer.getVertexSize() );
02137
02138 // NB: only 1 MB is possible ...
02139 nlassert(_MatrixBlocks.size()==1);
02140 CMatrixBlock &mBlock= _MatrixBlocks[0];
02141 // For all rdrPass.
02142 for(uint i=0;i<mBlock.RdrPass.size();i++)
02143 {
02144 // shift the PB
02145 CPrimitiveBlock &srcPb= mBlock.RdrPass[i].PBlock;
02146 CPrimitiveBlock &dstPb= mBlock.RdrPass[i].VBHeapPBlock;
02147 uint j;
02148
02149 // Lines.
02150 dstPb.setNumLine(srcPb.getNumLine());
02151 uint32 *srcLinePtr= srcPb.getLinePointer();
02152 uint32 *dstLinePtr= dstPb.getLinePointer();
02153 for(j=0; j<dstPb.getNumLine()*2;j++)
02154 {
02155 dstLinePtr[j]= srcLinePtr[j]+indexStart;
02156 }
02157 // Tris.
02158 dstPb.setNumTri(srcPb.getNumTri());
02159 uint32 *srcTriPtr= srcPb.getTriPointer();
02160 uint32 *dstTriPtr= dstPb.getTriPointer();
02161 for(j=0; j<dstPb.getNumTri()*3;j++)
02162 {
02163 dstTriPtr[j]= srcTriPtr[j]+indexStart;
02164 }
02165 // Quads.
02166 dstPb.setNumQuad(srcPb.getNumQuad());
02167 uint32 *srcQuadPtr= srcPb.getQuadPointer();
02168 uint32 *dstQuadPtr= dstPb.getQuadPointer();
02169 for(j=0; j<dstPb.getNumQuad()*4;j++)
02170 {
02171 dstQuadPtr[j]= srcQuadPtr[j]+indexStart;
02172 }
02173 }
02174 }
|
|
||||||||||||||||||||
|
Definition at line 1914 of file mesh.cpp. References NL3D::CSkeletonModel::getActiveBoneSkinMatrix(), NL3D::CMeshGeom::CMatrixBlock::MatrixId, NL3D::CMeshGeom::CMatrixBlock::NumMatrix, NL3D::CMatrix3x4::set(), and uint. Referenced by applySkin().
01915 {
01916 // For all matrix of this mBlock.
01917 for(uint idMat=0;idMat<mBlock.NumMatrix;idMat++)
01918 {
01919 uint curBoneId= mBlock.MatrixId[idMat];
01920
01921 // If same matrix binded as previous block, no need to bind!!
01922 if(prevBlock && idMat<prevBlock->NumMatrix && prevBlock->MatrixId[idMat]== curBoneId)
01923 continue;
01924
01925 // Else, we must setup the matrix
01926 matrixes[idMat].set(skeleton->getActiveBoneSkinMatrix(curBoneId));
01927 }
01928 }
|
|
||||||||||||||||||||||||
|
Definition at line 1870 of file mesh.cpp. References NL3D::CPaletteSkin::MatrixId, NL3D::CMatrix3x4::mulAddPoint(), and NL3D::CMatrix3x4::mulSetPoint(). Referenced by applySkin().
01871 {
01872 CMatrix3x4 *pMat;
01873
01874 // \todo yoyo: TODO_OPTIMIZE: SSE verion...
01875
01876 // 0th matrix influence.
01877 pMat= matrixes + srcPal->MatrixId[0];
01878 pMat->mulSetPoint(*srcVec, srcWgt[0], *pDst);
01879 // 1th matrix influence.
01880 pMat= matrixes + srcPal->MatrixId[1];
01881 pMat->mulAddPoint(*srcVec, srcWgt[1], *pDst);
01882 // 2th matrix influence.
01883 pMat= matrixes + srcPal->MatrixId[2];
01884 pMat->mulAddPoint(*srcVec, srcWgt[2], *pDst);
01885 // 3th matrix influence.
01886 pMat= matrixes + srcPal->MatrixId[3];
01887 pMat->mulAddPoint(*srcVec, srcWgt[3], *pDst);
01888 }
|
|
||||||||||||||||||||||||
|
Definition at line 1892 of file mesh.cpp. References NL3D::CPaletteSkin::MatrixId, NL3D::CMatrix3x4::mulAddVector(), and NL3D::CMatrix3x4::mulSetVector(). Referenced by applySkin().
01893 {
01894 CMatrix3x4 *pMat;
01895
01896 // \todo yoyo: TODO_OPTIMIZE: SSE verion...
01897
01898 // 0th matrix influence.
01899 pMat= matrixes + srcPal->MatrixId[0];
01900 pMat->mulSetVector(*srcVec, srcWgt[0], *pDst);
01901 // 1th matrix influence.
01902 pMat= matrixes + srcPal->MatrixId[1];
01903 pMat->mulAddVector(*srcVec, srcWgt[1], *pDst);
01904 // 2th matrix influence.
01905 pMat= matrixes + srcPal->MatrixId[2];
01906 pMat->mulAddVector(*srcVec, srcWgt[2], *pDst);
01907 // 3th matrix influence.
01908 pMat= matrixes + srcPal->MatrixId[3];
01909 pMat->mulAddVector(*srcVec, srcWgt[3], *pDst);
01910 }
|
|
|
The framework call this method when it has done with this meshGeom Implements NL3D::IMeshGeom. Definition at line 2100 of file mesh.cpp. References _MeshVertexProgram, _SupportMBRFlags, NL3D::CMeshGeomRenderContext::Driver, and MBRCurrentUseVP.
02101 {
02102 // MeshVertexProgram ?
02103 if( _SupportMBRFlags & MBRCurrentUseVP )
02104 {
02105 // End Mesh
02106 _MeshVertexProgram->endMBRMesh( rdrCtx.Driver );
02107
02108 // and remove Current Flag.
02109 _SupportMBRFlags&= ~MBRCurrentUseVP;
02110 }
02111 }
|
|
||||||||||||||||||||||||
|
Definition at line 733 of file mesh.h. References ItCornerSet, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NL3D::CMesh::CMeshBuild::NumCoords, NL3D::CVertexBuffer::setColor(), NL3D::CVertexBuffer::setNormalCoord(), NL3D::CVertexBuffer::setNumVertices(), NL3D::CVertexBuffer::setPaletteSkin(), NL3D::CVertexBuffer::setSpecular(), NL3D::CVertexBuffer::setTexCoord(), NL3D::CVertexBuffer::setValueFloat3Ex(), NL3D::CVertexBuffer::setVertexCoord(), NL3D::CVertexBuffer::setWeight(), sint, and TCornerSet. Referenced by build().
00734 {
00735 ItCornerSet it= corners.find(const_cast<CCornerTmp *>(corn));
00736 if(it!=corners.end())
00737 corn->VBId= (*it)->VBId;
00738 else
00739 {
00740 // Add corner to the set to not insert same corner two times.
00741 corners.insert (const_cast<CCornerTmp *>(corn));
00742 sint i;
00743 corn->VBId= currentVBIndex++;
00744 // Fill the VBuffer.
00745 _VBuffer.setNumVertices(currentVBIndex);
00746 sint id= currentVBIndex-1;
00747 // XYZ.
00748 _VBuffer.setVertexCoord(id, vert);
00749 // Normal
00750 if(CCornerTmp::Flags & CVertexBuffer::NormalFlag)
00751 _VBuffer.setNormalCoord(id, corn->Normal);
00752 // Uvws.
00753 for(i=0;i<CVertexBuffer::MaxStage;i++)
00754 {
00755 if(CCornerTmp::Flags & (CVertexBuffer::TexCoord0Flag<<i))
00756 {
00757 switch(mb.NumCoords[i])
00758 {
00759 case 2:
00760 _VBuffer.setTexCoord(id, i, corn->Uvws[i].U, corn->Uvws[i].V);
00761 break;
00762 case 3:
00763 _VBuffer.setValueFloat3Ex((CVertexBuffer::TValue) (CVertexBuffer::TexCoord0 + i), id, corn->Uvws[i].U, corn->Uvws[i].V, corn->Uvws[i].W);
00764 break;
00765 default: // not supported
00766 nlassert(0);
00767 break;
00768 }
00769 }
00770 }
00771 // Color.
00772 if(CCornerTmp::Flags & CVertexBuffer::PrimaryColorFlag)
00773 _VBuffer.setColor(id, corn->Color);
00774 // Specular.
00775 if(CCornerTmp::Flags & CVertexBuffer::SecondaryColorFlag)
00776 _VBuffer.setSpecular(id, corn->Specular);
00777
00778 // setup palette skinning.
00779 if ((CCornerTmp::Flags & CVertexBuffer::PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag)
00780 {
00781 _VBuffer.setPaletteSkin(id, corn->Palette);
00782 for(i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
00783 _VBuffer.setWeight(id, i, corn->Weights[i]);
00784 }
00785 }
00786 }
|
|
||||||||||||
|
Definition at line 1836 of file mesh.cpp. References NL3D::CPrimitiveBlock::getLinePointer(), NL3D::CPrimitiveBlock::getNumLine(), NL3D::CPrimitiveBlock::getNumQuad(), NL3D::CPrimitiveBlock::getNumTri(), NL3D::CPrimitiveBlock::getQuadPointer(), NL3D::CPrimitiveBlock::getTriPointer(), NL3D_SOFTSKIN_VMUSTCOMPUTE, NL3D::CMeshGeom::CMatrixBlock::RdrPass, uint, uint32, and uint8. Referenced by applySkin().
01837 {
01838 for(uint i=0; i<mb.RdrPass.size(); i++)
01839 {
01840 CPrimitiveBlock &PB= mb.RdrPass[i].PBlock;
01841
01842 uint32 *pIndex;
01843 uint nIndex;
01844
01845 // This may be better to flags in 2 pass (first traverse primitives, then test vertices).
01846 // Better sol for BTB..., because number of tests are divided by 6 (for triangles).
01847
01848 // for all prims, indicate which vertex we must compute.
01849 // nothing if not already computed (ie 0), because 0&1==0.
01850 // Lines.
01851 pIndex= (uint32*)PB.getLinePointer();
01852 nIndex= PB.getNumLine()*2;
01853 for(;nIndex>0;nIndex--, pIndex++)
01854 skinFlags[*pIndex]&= NL3D_SOFTSKIN_VMUSTCOMPUTE;
01855 // Tris.
01856 pIndex= (uint32*)PB.getTriPointer();
01857 nIndex= PB.getNumTri()*3;
01858 for(;nIndex>0;nIndex--, pIndex++)
01859 skinFlags[*pIndex]&= NL3D_SOFTSKIN_VMUSTCOMPUTE;
01860 // Quads.
01861 pIndex= (uint32*)PB.getQuadPointer();
01862 nIndex= PB.getNumQuad()*4;
01863 for(;nIndex>0;nIndex--, pIndex++)
01864 skinFlags[*pIndex]&= NL3D_SOFTSKIN_VMUSTCOMPUTE;
01865 }
01866 }
|
|
|
get the extended axis aligned bounding box of the mesh
Implements NL3D::IMeshGeom. Definition at line 384 of file mesh.h. Referenced by NL3D::CMesh::getBoundingBox().
00385 {
00386 return _BBox;
00387 }
|
|
|
Implemented in NLAIAGENT::CNumericIndex, NLAIC::IPointerGestion, NLAIC::CIdentType, and CAutomataDesc. Referenced by NLMISC::CClassRegistry::checkObject(), and NL3D::GetTextureSize(). |
|
|
get the number of BlendShapes
Definition at line 419 of file mesh.h. References _MeshMorpher, NL3D::CMeshMorpher::BlendShapes, and uint.
00419 { if(_MeshMorpher) return _MeshMorpher->BlendShapes.size(); }
|
|
|
get the number of matrix block
Definition at line 393 of file mesh.h. References _MatrixBlocks, and uint. Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), applyMaterialRemap(), NL3D::CCoarseMeshBuild::buildBitmap(), NL3D::CMeshMultiLod::compileCoarseMeshes(), NL3D::UShape::getMeshTriangles(), NL3D::CMesh::getNbMatrixBlock(), and NL3D::CCoarseMeshBuild::remapCoordinates().
00393 { return _MatrixBlocks.size() ; }
|
|
|
get the number of rendering pass for a given matrix block
Definition at line 398 of file mesh.h. References _MatrixBlocks, and uint. Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), applyMaterialRemap(), NL3D::CCoarseMeshBuild::buildBitmap(), NL3D::CMeshMultiLod::compileCoarseMeshes(), NL3D::UShape::getMeshTriangles(), NL3D::CMesh::getNbRdrPass(), and NL3D::CCoarseMeshBuild::remapCoordinates().
00398 { return _MatrixBlocks[matrixBlockIndex].RdrPass.size() ; }
|
|
|
return the number of renderPasses for this instance. Called after activateInstance() Used only if sortPerMaterial()) is false Implements NL3D::IMeshGeom. Definition at line 2016 of file mesh.cpp. References _MatrixBlocks, and uint.
02017 {
02018 return _MatrixBlocks[0].RdrPass.size();
02019 }
|
|
|
return the number of renderPasses for this mesh. Used only if sortPerMaterial()) is true Implements NL3D::IMeshGeom. Definition at line 2011 of file mesh.cpp. References _MatrixBlocks, and uint.
02012 {
02013 return _MatrixBlocks[0].RdrPass.size();
02014 }
|
|
|
clip this mesh
Implements NL3D::IMeshGeom. Definition at line 1429 of file mesh.cpp. References _MatrixBlocks, NL3D::CPrimitiveBlock::getNumTriangles(), NL3D::CMeshGeom::CRdrPass::PBlock, NL3D::CMeshGeom::CMatrixBlock::RdrPass, uint, and uint32.
01430 {
01431 // Sum of triangles
01432 uint32 triCount=0;
01433
01434 // For each matrix block
01435 uint mbCount=_MatrixBlocks.size();
01436 for (uint mb=0; mb<mbCount; mb++)
01437 {
01438 CMatrixBlock &block=_MatrixBlocks[mb];
01439
01440 // Count of primitive block
01441 uint pCount=block.RdrPass.size();
01442 for (uint pb=0; pb<pCount; pb++)
01443 {
01444 // Ref on the primitive block
01445 CRdrPass &pass=block.RdrPass[pb];
01446
01447 // Sum tri
01448 triCount+=pass.PBlock.getNumTriangles ();
01449 }
01450 }
01451 return (float)triCount;
01452 }
|
|
||||||||||||
|
get the material ID associated with a rendering pass of a matrix block
Definition at line 413 of file mesh.h. References _MatrixBlocks, uint, and uint32. Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CCoarseMeshBuild::buildBitmap(), NL3D::CMesh::getRdrPassMaterial(), and NL3D::CCoarseMeshBuild::remapCoordinates().
00414 {
00415 return _MatrixBlocks[matrixBlockIndex].RdrPass[renderingPassIndex].MaterialId ;
00416 }
|
|
||||||||||||
|
get the primitive block associated with a rendering pass of a matrix block
Definition at line 404 of file mesh.h. References _MatrixBlocks, and uint. Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), NL3D::CMeshMultiLod::compileCoarseMeshes(), NL3D::UShape::getMeshTriangles(), NL3D::CMesh::getRdrPassPrimitiveBlock(), and NL3D::CCoarseMeshBuild::remapCoordinates().
00405 {
00406 return _MatrixBlocks[matrixBlockIndex].RdrPass[renderingPassIndex].PBlock ;
00407 }
|
|
|
return array of bones used by the skin. computeBonesId must has been called before.
Definition at line 440 of file mesh.h. References _BonesId. Referenced by NL3D::CMeshInstance::getSkinBoneUsage().
00440 {return _BonesId;}
|
|
||||||||||||
|
The framework call this method to know if the mesh can fit in VBHeap. if yes, deriver must return mesh vertexFormat and num of vertices. Reimplemented from NL3D::IMeshGeom. Definition at line 2114 of file mesh.cpp. References _MeshVertexProgram, _SupportMBRFlags, NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getVertexFormat(), and uint.
02115 {
02116 // CMeshGeom support VBHeap rendering, assuming supportMeshBlockRendering is true.
02117 if( _SupportMBRFlags )
02118 /* Yoyo: If VertexProgram, DON'T SUPPORT!! because VB need to be activated AFTER meshVP activation
02119 NB: still possible with complex code to do it (sort per VP type (with or not)...), but tests in Ryzom
02120 shows that VBHeap is not really important (not so much different shapes...)
02121 */
02122 if( _MeshVertexProgram==NULL )
02123 {
02124 vertexFormat= _VBuffer.getVertexFormat();
02125 numVertices= _VBuffer.getNumVertices();
02126 return true;
02127 }
02128
02129 return false;
02130 }
|
|
|
get the vertex buffer used by the mesh
Definition at line 390 of file mesh.h. Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), NL3D::UShape::getMeshTriangles(), NL3D::CMesh::getVertexBuffer(), NL3D::CMeshMultiLod::instanciateCoarseMeshSpace(), NL3D::CCoarseMeshBuild::remapCoordinates(), NL3D::CMeshMultiLod::renderCoarseMesh(), NL3D::CMeshMultiLodInstance::setPosCoarseMesh(), and NL3D::CMeshMultiLodInstance::setUVCoarseMesh().
00390 { return _VBuffer ; }
|
|
|
True if this mesh has a vertexProgram.
Reimplemented from NL3D::IMeshGeom. Definition at line 478 of file mesh.h. References _MeshVertexProgram. Referenced by NL3D::CMeshInstance::initRenderFilterType().
00478 {return _MeshVertexProgram!=NULL;}
|
|
|
Init instance info.
Implements NL3D::IMeshGeom. Definition at line 474 of file mesh.cpp. References _MeshVertexProgram. Referenced by NL3D::CMesh::createInstance().
00475 {
00476 // init the instance with _MeshVertexProgram infos
00477 if(_MeshVertexProgram)
00478 _MeshVertexProgram->initInstance(mbi);
00479 }
|
|
|
Return true if the meshGeom has to Fill some Vertices at activeInstance() time if VBHeap enabled at this time, then vbDst in activeInstance(,,,vbDst) will contains the vb to write to. Reimplemented in NL3D::CMeshMRMGeom. Definition at line 212 of file mesh_geom.h. Referenced by NL3D::CMeshBlockManager::render().
00212 {return false;}
|
|
|
Return true if the meshGeom has to Fill some Vertices at activeInstance() time if VBHeap enabled at this time, then vbDst in activeInstance(,,,vbDst) will contains the vb to write to. Definition at line 215 of file mesh_geom.h. References NL3D::IMeshGeom::_MeshVBHeapId. Referenced by NL3D::CMeshMRMGeom::profileSceneRender(), and profileSceneRender().
00215 {return _MeshVBHeapId!=0;}
|
|
|
Return true if the mesh is skinned, else return false.
Definition at line 428 of file mesh.h. References _Skinned. Referenced by NL3D::CMeshInstance::isSkinnable().
00429 {
00430 return _Skinned;
00431 }
|
|
|
clip this mesh
|
|
|
Definition at line 153 of file mesh.cpp. References _MatrixBlocks, NL3D::CStripifier::optimizeTriangles(), NL3D::CMeshGeom::CRdrPass::PBlock, and uint. Referenced by build().
00154 {
00155 CStripifier stripifier;
00156
00157 // for all rdrpass of all matrix blocks.
00158 for(uint mb= 0;mb<_MatrixBlocks.size();mb++)
00159 {
00160 for(uint rp=0; rp<_MatrixBlocks[mb].RdrPass.size(); rp++ )
00161 {
00162 // stripify list of triangles of this pass.
00163 CRdrPass &pass= _MatrixBlocks[mb].RdrPass[rp];
00164 stripifier.optimizeTriangles(pass.PBlock, pass.PBlock);
00165 }
00166 }
00167
00168 }
|
|
||||||||||||||||||||
|
clip this mesh
Implements NL3D::IMeshGeom. Definition at line 1932 of file mesh.cpp. References _MatrixBlocks, _VertexBufferHard, NL3D::CScene::BenchRes, NL3D::CPrimitiveBlock::getNumTri(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CScene::incrementProfileTriVBFormat(), NL3D::IMeshGeom::isMeshInVBHeap(), NL3D::CMeshGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, NL3D::UScene::CBenchResults::MeshProfileTriVBFormat, NL3D::UScene::CBenchResults::NumMeshRdrBlock, NL3D::UScene::CBenchResults::NumMeshRdrBlockWithVBHeap, NL3D::UScene::CBenchResults::NumMeshRdrNormal, NL3D::UScene::CBenchResults::NumMeshTriRdrBlock, NL3D::UScene::CBenchResults::NumMeshTriRdrBlockWithVBHeap, NL3D::UScene::CBenchResults::NumMeshTriRdrNormal, NL3D::UScene::CBenchResults::NumMeshVBufferHard, NL3D::UScene::CBenchResults::NumMeshVBufferStd, NL3D::CMeshGeom::CRdrPass::PBlock, NL3D::CMeshGeom::CMatrixBlock::RdrPass, NL3D::CTraversal::Scene, supportMeshBlockRendering(), uint, and uint32. Referenced by NL3D::CMesh::profileSceneRender().
01933 {
01934 // get the mesh instance.
01935 CMeshBaseInstance *mi= safe_cast<CMeshBaseInstance*>(trans);
01936
01937 // For all _MatrixBlocks
01938 uint triCount= 0;
01939 for(uint mb=0;mb<_MatrixBlocks.size();mb++)
01940 {
01941 CMatrixBlock &mBlock= _MatrixBlocks[mb];
01942
01943 // Profile all pass.
01944 for (uint i=0;i<mBlock.RdrPass.size();i++)
01945 {
01946 CRdrPass &rdrPass= mBlock.RdrPass[i];
01947 // Profile with the Materials of the MeshInstance.
01948 if ( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) ) ||
01949 ( (mi->Materials[rdrPass.MaterialId].getBlend() == true) && (rdrFlags & IMeshGeom::RenderTransparentMaterial) ) )
01950 {
01951 triCount+= rdrPass.PBlock.getNumTri();
01952 }
01953 }
01954 }
01955
01956 // Profile
01957 if(triCount)
01958 {
01959 // tri per VBFormat
01960 rdrTrav->Scene->incrementProfileTriVBFormat(rdrTrav->Scene->BenchRes.MeshProfileTriVBFormat,
01961 _VBuffer.getVertexFormat(), triCount);
01962
01963 // VBHard
01964 if(_VertexBufferHard)
01965 rdrTrav->Scene->BenchRes.NumMeshVBufferHard++;
01966 else
01967 rdrTrav->Scene->BenchRes.NumMeshVBufferStd++;
01968
01969 // rendered in BlockRendering, only if not transparent pass (known it if RenderTransparentMaterial is set)
01970 if(supportMeshBlockRendering() && (rdrFlags & IMeshGeom::RenderTransparentMaterial)==0 )
01971 {
01972 if(isMeshInVBHeap())
01973 {
01974 rdrTrav->Scene->BenchRes.NumMeshRdrBlockWithVBHeap++;
01975 rdrTrav->Scene->BenchRes.NumMeshTriRdrBlockWithVBHeap+= triCount;
01976 }
01977 else
01978 {
01979 rdrTrav->Scene->BenchRes.NumMeshRdrBlock++;
01980 rdrTrav->Scene->BenchRes.NumMeshTriRdrBlock+= triCount;
01981 }
01982 }
01983 else
01984 {
01985 rdrTrav->Scene->BenchRes.NumMeshRdrNormal++;
01986 rdrTrav->Scene->BenchRes.NumMeshTriRdrNormal+= triCount;
01987 }
01988 }
01989 }
|
|
||||||||||||||||||||||||
|
render() this mesh in a driver.
Implements NL3D::IMeshGeom. Definition at line 598 of file mesh.cpp. References _MatrixBlocks, _MeshMorpher, _MeshVertexProgram, _OriginalSkinNormals, _OriginalSkinRestored, _OriginalSkinVertices, _OriginalTGSpace, _Skinned, _VBufferOri, _VertexBufferHard, NL3D::IDriver::activeVertexBuffer(), NL3D::IDriver::activeVertexBufferHard(), NL3D::CMeshMorpher::BlendShapes, NL3D::CTravCameraScene::CamPos, NL3D::CMeshBaseInstance::getBlendShapeFactors(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), NL3D::CTransform::getSkeletonModel(), NL3D::CTransform::getWorldMatrix(), H_AUTO, NL3D::CMeshMorpher::init(), NL3D::CMeshMorpher::initSkinned(), NLMISC::CMatrix::inverted(), NL3D::CTransform::isSkinned(), NL3D::CMeshGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, nlassert, NLMISC::OptFastFloor(), NL3D::CMeshGeom::CRdrPass::PBlock, NL3D::CMeshBlender::prepareRenderForGlobalAlpha(), NL3D::CMeshGeom::CMatrixBlock::RdrPass, NL3D::IDriver::render(), restoreOriginalSkinVertices(), NL3D::CMeshBlender::restoreRender(), NL3D::IDriver::setupModelMatrix(), uint, uint32, uint8, NL3D::CMeshMorpher::update(), NL3D::CMeshMorpher::updateSkinned(), and updateVertexBufferHard(). Referenced by NL3D::CMesh::render().
00599 {
00600 nlassert(drv);
00601 // get the mesh instance.
00602 CMeshBaseInstance *mi= safe_cast<CMeshBaseInstance*>(trans);
00603 // get a ptr on scene
00604 CScene *ownerScene= mi->getOwnerScene();
00605 // get a ptr on renderTrav
00606 CRenderTrav *renderTrav= &ownerScene->getRenderTrav();
00607
00608 // update the VBufferHard (create/delete), to maybe render in AGP memory.
00609 updateVertexBufferHard (drv);
00610 /* currentVBHard is NULL if must disable it temporarily
00611 For now, never disable it, but switch of VBHard may be VERY EXPENSIVE if NV_vertex_array_range2 is not
00612 supported (old drivers).
00613 */
00614 IVertexBufferHard *currentVBHard= _VertexBufferHard;
00615
00616
00617 // get the skeleton model to which I am binded (else NULL).
00618 CSkeletonModel *skeleton;
00619 skeleton= mi->getSkeletonModel();
00620 // The mesh must not be skinned for render()
00621 nlassert(!(_Skinned && mi->isSkinned() && skeleton));
00622 bool bMorphApplied = _MeshMorpher->BlendShapes.size() > 0;
00623 bool useTangentSpace = _MeshVertexProgram && _MeshVertexProgram->needTangentSpace();
00624
00625
00626 // Profiling
00627 //===========
00628 H_AUTO( NL3D_MeshGeom_RenderNormal );
00629
00630
00631 // Morphing
00632 // ========
00633 if (bMorphApplied)
00634 {
00635 // If _Skinned (NB: the skin is not applied) and if lod.OriginalSkinRestored, then restoreOriginalSkinPart is
00636 // not called but mush morpher write changed vertices into VBHard so its ok. The unchanged vertices
00637 // are written in the preceding call to restoreOriginalSkinPart.
00638 if (_Skinned)
00639 {
00640 _MeshMorpher->initSkinned(&_VBufferOri,
00641 &_VBuffer,
00642 currentVBHard,
00643 useTangentSpace,
00644 &_OriginalSkinVertices,
00645 &_OriginalSkinNormals,
00646 useTangentSpace ? &_OriginalTGSpace : NULL,
00647 false );
00648 _MeshMorpher->updateSkinned (mi->getBlendShapeFactors());
00649 }
00650 else // Not even skinned so we have to do all the stuff
00651 {
00652 _MeshMorpher->init(&_VBufferOri,
00653 &_VBuffer,
00654 currentVBHard,
00655 useTangentSpace);
00656 _MeshMorpher->update (mi->getBlendShapeFactors());
00657 }
00658 }
00659
00660
00661 // Skinning
00662 // ========
00663
00664 // else setup instance matrix
00665 drv->setupModelMatrix(trans->getWorldMatrix());
00666
00667
00668 // since instance skin is invalid but mesh is skinned , we must copy vertices/normals from original vertices.
00669 if (_Skinned)
00670 {
00671 // do it for this Lod only, and if cache say it is necessary.
00672 if (!_OriginalSkinRestored)
00673 restoreOriginalSkinVertices();
00674 }
00675
00676
00677 // Setup meshVertexProgram
00678 //===========
00679
00680 // use MeshVertexProgram effect?
00681 bool useMeshVP= _MeshVertexProgram != NULL;
00682 if( useMeshVP )
00683 {
00684 CMatrix invertedObjectMatrix;
00685 invertedObjectMatrix = trans->getWorldMatrix().inverted();
00686 // really ok if success to begin VP
00687 useMeshVP= _MeshVertexProgram->begin(drv, ownerScene, mi, invertedObjectMatrix, renderTrav->CamPos);
00688 }
00689
00690
00691 // Render the mesh.
00692 //===========
00693 // active VB.
00694 if(currentVBHard != NULL)
00695 drv->activeVertexBufferHard(currentVBHard);
00696 else
00697 drv->activeVertexBuffer(_VBuffer);
00698
00699
00700 // Global alpha used ?
00701 uint32 globalAlphaUsed= rdrFlags & IMeshGeom::RenderGlobalAlpha;
00702 uint8 globalAlphaInt=(uint8)NLMISC::OptFastFloor(globalAlpha*255);
00703
00704
00705 // For all _MatrixBlocks
00706 for(uint mb=0;mb<_MatrixBlocks.size();mb++)
00707 {
00708 CMatrixBlock &mBlock= _MatrixBlocks[mb];
00709 if(mBlock.RdrPass.size()==0)
00710 continue;
00711
00712 // Global alpha ?
00713 if (globalAlphaUsed)
00714 {
00715 bool gaDisableZWrite= (rdrFlags & IMeshGeom::RenderGADisableZWrite)?true:false;
00716
00717 // Render all pass.
00718 for (uint i=0;i<mBlock.RdrPass.size();i++)
00719 {
00720 CRdrPass &rdrPass= mBlock.RdrPass[i];
00721 // Render with the Materials of the MeshInstance.
00722 if ( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) ) ||
00723 ( (mi->Materials[rdrPass.MaterialId].getBlend() == true) && (rdrFlags & IMeshGeom::RenderTransparentMaterial) ) )
00724 {
00725 // CMaterial Ref
00726 CMaterial &material=mi->Materials[rdrPass.MaterialId];
00727
00728 // Use a MeshBlender to modify material and driver.
00729 CMeshBlender blender;
00730 blender.prepareRenderForGlobalAlpha(material, drv, globalAlpha, globalAlphaInt, gaDisableZWrite);
00731
00732 // Setup VP material
00733 if (useMeshVP)
00734 {
00735 if(currentVBHard)
00736 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, currentVBHard);
00737 else
00738 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, &_VBuffer);
00739 }
00740
00741 // Render
00742 drv->render(rdrPass.PBlock, material);
00743
00744 // Resetup material/driver
00745 blender.restoreRender(material, drv, gaDisableZWrite);
00746 }
00747 }
00748 }
00749 else
00750 {
00751 // Render all pass.
00752 for(uint i=0;i<mBlock.RdrPass.size();i++)
00753 {
00754 CRdrPass &rdrPass= mBlock.RdrPass[i];
00755 // Render with the Materials of the MeshInstance.
00756 if( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) ) ||
00757 ( (mi->Materials[rdrPass.MaterialId].getBlend() == true) && (rdrFlags & IMeshGeom::RenderTransparentMaterial) ) )
00758 {
00759 // CMaterial Ref
00760 CMaterial &material=mi->Materials[rdrPass.MaterialId];
00761
00762 // Setup VP material
00763 if (useMeshVP)
00764 {
00765 if(currentVBHard)
00766 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, currentVBHard);
00767 else
00768 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, &_VBuffer);
00769 }
00770
00771 // render primitives
00772 drv->render(rdrPass.PBlock, material);
00773 }
00774 }
00775 }
00776 }
00777
00778 // End VertexProgram effect
00779 if(useMeshVP)
00780 {
00781 // Apply it.
00782 _MeshVertexProgram->end(drv);
00783 }
00784 }
|
|
||||||||||||||||||||
|
The framework call this method to render the current renderPass, with the current instance NB: if the material is blended, DON'T render it!! Implements NL3D::IMeshGeom. Definition at line 2075 of file mesh.cpp. References _MatrixBlocks, _SupportMBRFlags, NL3D::CRenderTrav::changeVPLightSetupMaterial(), NL3D::CMeshGeomRenderContext::Driver, NL3D::CMeshGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, MBRCurrentUseVP, NL3D::CMeshGeom::CRdrPass::PBlock, NL3D::CMeshGeom::CMatrixBlock::RdrPass, NL3D::IDriver::render(), NL3D::CMeshGeomRenderContext::RenderThroughVBHeap, NL3D::CMeshGeomRenderContext::RenderTrav, uint, and NL3D::CMeshGeom::CRdrPass::VBHeapPBlock.
02076 {
02077 CMatrixBlock &mBlock= _MatrixBlocks[0];
02078
02079 CRdrPass &rdrPass= mBlock.RdrPass[rdrPassId];
02080 // Render with the Materials of the MeshInstance, only if not blended.
02081 if( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) ) )
02082 {
02083 CMaterial &material= mi->Materials[rdrPass.MaterialId];
02084
02085 // MeshVertexProgram ?
02086 if( _SupportMBRFlags & MBRCurrentUseVP )
02087 {
02088 rdrCtx.RenderTrav->changeVPLightSetupMaterial(material, false);
02089 }
02090
02091 if(rdrCtx.RenderThroughVBHeap)
02092 // render shifted primitives
02093 rdrCtx.Driver->render(rdrPass.VBHeapPBlock, material);
02094 else
02095 // render primitives
02096 rdrCtx.Driver->render(rdrPass.PBlock, material);
02097 }
02098 }
|
|
||||||||||||||||
|
render the mesh geometry with a single material. Render is said "Simple" because no special features are used:
Definition at line 915 of file mesh.cpp. References _MatrixBlocks, NL3D::IDriver::activeVertexBuffer(), H_AUTO, nlassert, NL3D::CMeshGeom::CRdrPass::PBlock, NL3D::CMeshGeom::CMatrixBlock::RdrPass, NL3D::IDriver::render(), NL3D::IDriver::setupModelMatrix(), and uint. Referenced by NL3D::CMeshMultiLod::renderMeshGeom().
00916 {
00917 H_AUTO( NL3D_MeshGeom_RenderSimpleWithMaterial );
00918
00919 nlassert(drv);
00920
00921 // setup matrix
00922 drv->setupModelMatrix(worldMatrix);
00923
00924 // Active simple VB.
00925 drv->activeVertexBuffer(_VBuffer);
00926
00927 // For all _MatrixBlocks
00928 for(uint mb=0;mb<_MatrixBlocks.size();mb++)
00929 {
00930 CMatrixBlock &mBlock= _MatrixBlocks[mb];
00931 if(mBlock.RdrPass.size()==0)
00932 continue;
00933
00934 // Render all pass.
00935 for(uint i=0;i<mBlock.RdrPass.size();i++)
00936 {
00937 CRdrPass &rdrPass= mBlock.RdrPass[i];
00938
00939 // render primitives
00940 drv->render(rdrPass.PBlock, mat);
00941 }
00942 }
00943
00944 }
|
|
||||||||||||
|
render() this mesh as a skin
Implements NL3D::IMeshGeom. Definition at line 788 of file mesh.cpp. References _MatrixBlocks, _MeshMorpher, _MeshVertexProgram, _OriginalSkinNormals, _OriginalSkinVertices, _OriginalTGSpace, _Skinned, _VBufferOri, _VertexBufferHard, NL3D::IDriver::activeVertexBuffer(), NL3D::IDriver::activeVertexBufferHard(), applySkin(), NL3D::CMeshMorpher::BlendShapes, NL3D::CTravCameraScene::CamPos, NL3D::CMeshBaseInstance::getBlendShapeFactors(), NL3D::CRenderTrav::getDriver(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), NL3D::CTransform::getSkeletonModel(), NL3D::CTransform::getWorldMatrix(), H_AUTO, NL3D::CMeshMorpher::initSkinned(), NLMISC::CMatrix::inverted(), NL3D::CTransform::isSkinned(), NL3D::CMeshGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, nlassert, NL3D::CMeshGeom::CRdrPass::PBlock, NL3D::CMeshGeom::CMatrixBlock::RdrPass, NL3D::IDriver::render(), uint, NL3D::CMeshMorpher::updateSkinned(), and updateVertexBufferHard(). Referenced by NL3D::CMeshInstance::renderSkin().
00789 {
00790 // get the mesh instance.
00791 CMeshBaseInstance *mi= safe_cast<CMeshBaseInstance*>(trans);
00792 // get a ptr on scene
00793 CScene *ownerScene= mi->getOwnerScene();
00794 // get a ptr on renderTrav
00795 CRenderTrav *renderTrav= &ownerScene->getRenderTrav();
00796 // get a ptr on the driver
00797 IDriver *drv= renderTrav->getDriver();
00798 nlassert(drv);
00799
00800
00801 // update the VBufferHard (create/delete), to maybe render in AGP memory.
00802 updateVertexBufferHard (drv);
00803 /* currentVBHard is NULL if must disable it temporarily
00804 For now, never disable it, but switch of VBHard may be VERY EXPENSIVE if NV_vertex_array_range2 is not
00805 supported (old drivers).
00806 */
00807 IVertexBufferHard *currentVBHard= _VertexBufferHard;
00808
00809
00810 // get the skeleton model to which I am binded (else NULL).
00811 CSkeletonModel *skeleton;
00812 skeleton= mi->getSkeletonModel();
00813 // must be skinned for renderSkin()
00814 nlassert(_Skinned && mi->isSkinned() && skeleton);
00815 bool bMorphApplied = _MeshMorpher->BlendShapes.size() > 0;
00816 bool useTangentSpace = _MeshVertexProgram && _MeshVertexProgram->needTangentSpace();
00817
00818
00819 // Profiling
00820 //===========
00821 H_AUTO( NL3D_MeshGeom_RenderSkinned );
00822
00823
00824 // Morphing
00825 // ========
00826 if (bMorphApplied)
00827 {
00828 // Since Skinned we must update original skin vertices and normals because skinning use it
00829 _MeshMorpher->initSkinned(&_VBufferOri,
00830 &_VBuffer,
00831 currentVBHard,
00832 useTangentSpace,
00833 &_OriginalSkinVertices,
00834 &_OriginalSkinNormals,
00835 useTangentSpace ? &_OriginalTGSpace : NULL,
00836 true );
00837 _MeshMorpher->updateSkinned (mi->getBlendShapeFactors());
00838 }
00839
00840
00841 // Skinning
00842 // ========
00843
00844 // NB: the skeleton matrix has already been setuped by CSkeletonModel
00845 // NB: the normalize flag has already been setuped by CSkeletonModel
00846
00847
00848 // apply the skinning: _VBuffer is modified.
00849 applySkin(skeleton);
00850
00851
00852 // Setup meshVertexProgram
00853 //===========
00854
00855 // use MeshVertexProgram effect?
00856 bool useMeshVP= _MeshVertexProgram != NULL;
00857 if( useMeshVP )
00858 {
00859 CMatrix invertedObjectMatrix;
00860 invertedObjectMatrix = skeleton->getWorldMatrix().inverted();
00861 // really ok if success to begin VP
00862 useMeshVP= _MeshVertexProgram->begin(drv, ownerScene, mi, invertedObjectMatrix, renderTrav->CamPos);
00863 }
00864
00865
00866 // Render the mesh.
00867 //===========
00868 // active VB.
00869 if(currentVBHard != NULL)
00870 drv->activeVertexBufferHard(currentVBHard);
00871 else
00872 drv->activeVertexBuffer(_VBuffer);
00873
00874
00875 // For all _MatrixBlocks
00876 for(uint mb=0;mb<_MatrixBlocks.size();mb++)
00877 {
00878 CMatrixBlock &mBlock= _MatrixBlocks[mb];
00879 if(mBlock.RdrPass.size()==0)
00880 continue;
00881
00882 // Render all pass.
00883 for(uint i=0;i<mBlock.RdrPass.size();i++)
00884 {
00885 CRdrPass &rdrPass= mBlock.RdrPass[i];
00886
00887 // CMaterial Ref
00888 CMaterial &material=mi->Materials[rdrPass.MaterialId];
00889
00890 // Setup VP material
00891 if (useMeshVP)
00892 {
00893 if(currentVBHard)
00894 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, currentVBHard);
00895 else
00896 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, &_VBuffer);
00897 }
00898
00899 // render primitives
00900 drv->render(rdrPass.PBlock, material);
00901 }
00902 }
00903
00904 // End VertexProgram effect
00905 if(useMeshVP)
00906 {
00907 // Apply it.
00908 _MeshVertexProgram->end(drv);
00909 }
00910
00911 }
|
|
|
Definition at line 1663 of file mesh.cpp. References _MeshVertexProgram, _OriginalSkinNormals, _OriginalSkinRestored, _OriginalSkinVertices, _OriginalTGSpace, _Skinned, NL3D::CVertexBuffer::getNormalCoordPointer(), NL3D::CVertexBuffer::getNumTexCoordUsed(), NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getTexCoordPointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), nlassert, and uint. Referenced by render().
01664 {
01665 nlassert(_Skinned);
01666
01667 // get num of vertices
01668 uint numVertices= _VBuffer.getNumVertices();
01669
01670 // Copy VBuffer content into Original vertices normals.
01671 if(_VBuffer.getVertexFormat() & CVertexBuffer::PositionFlag)
01672 {
01673 // copy vertices from VBuffer. (NB: unusefull geomorphed vertices are still copied, but doesn't matter).
01674 for(uint i=0; i<numVertices;i++)
01675 {
01676 *(CVector*)_VBuffer.getVertexCoordPointer(i)= _OriginalSkinVertices[i];
01677 }
01678 }
01679 if(_VBuffer.getVertexFormat() & CVertexBuffer::NormalFlag)
01680 {
01681 // copy normals from VBuffer. (NB: unusefull geomorphed normals are still copied, but doesn't matter).
01682 for(uint i=0; i<numVertices;i++)
01683 {
01684 *(CVector*)_VBuffer.getNormalCoordPointer(i)= _OriginalSkinNormals[i];
01685 }
01686 }
01687 if (_MeshVertexProgram && _MeshVertexProgram->needTangentSpace())
01688 {
01689 uint numTexCoords = _VBuffer.getNumTexCoordUsed();
01690 nlassert(numTexCoords >= 2);
01691 nlassert(_OriginalTGSpace.size() == numVertices);
01692 // copy tangent space vectors
01693 for(uint i = 0; i < numVertices; ++i)
01694 {
01695 *(CVector*)_VBuffer.getTexCoordPointer(i, numTexCoords - 1)= _OriginalTGSpace[i];
01696 }
01697 }
01698
01699 // cleared
01700 _OriginalSkinRestored= true;
01701 }
|
|
|
serial this mesh.
Implements NLMISC::IStreamable. Definition at line 948 of file mesh.cpp. References nlassert, and sint.
00949 {
00950 /*
00951 Version 4:
00952 - BonesName.
00953 Version 3:
00954 - MeshVertexProgram.
00955 Version 2:
00956 - precompute of triangle order. (nothing more to load).
00957 Version 1:
00958 - added blend shapes
00959 Version 0:
00960 - separate serialisation CMesh / CMeshGeom.
00961 */
00962 sint ver = f.serialVersion (4);
00963
00964
00965 // must have good original Skinned Vertex before writing.
00966 if( !f.isReading() && _Skinned && !_OriginalSkinRestored )
00967 {
00968 restoreOriginalSkinVertices();
00969 }
00970
00971
00972 // Version 4+: Array of bone name
00973 if (ver >= 4)
00974 {
00975 f.serialCont (_BonesName);
00976 }
00977
00978 if (f.isReading())
00979 {
00980 // Version3-: Bones index are in skeleton model id list
00981 _BoneIdComputed = (ver < 4);
00982 // In all case, must recompute usage of parents.
00983 _BoneIdExtended= false;
00984 }
00985 else
00986 {
00987 // Warning, if you have skinned this shape, you can't write it anymore because skinning id have been changed!
00988 nlassert (_BoneIdComputed==false);
00989 }
00990
00991 // Version3+: MeshVertexProgram.
00992 if (ver >= 3)
00993 {
00994 IMeshVertexProgram *mvp= NULL;
00995 if(f.isReading())
00996 {
00997 f.serialPolyPtr(mvp);
00998 _MeshVertexProgram= mvp;
00999 }
01000 else
01001 {
01002 mvp= _MeshVertexProgram;
01003 f.serialPolyPtr(mvp);
01004 }
01005 }
01006 else if(f.isReading())
01007 {
01008 // release vp
01009 _MeshVertexProgram= NULL;
01010 }
01011
01012 // TestYoyo
01013 //_MeshVertexProgram= NULL;
01014
01015 // Version1+: _MeshMorpher.
01016 if (ver >= 1)
01017 f.serial (*_MeshMorpher);
01018
01019 // serial geometry.
01020 f.serial (_VBuffer);
01021 f.serialCont (_MatrixBlocks);
01022 f.serial (_BBox);
01023 f.serial (_Skinned);
01024
01025
01026 // If _VertexBuffer changed, flag the VertexBufferHard.
01027 if(f.isReading())
01028 {
01029 _VertexBufferHardDirty = true;
01030
01031 // if >= version 2, reorder of triangles is precomputed, else compute it now.
01032 if(ver < 2 )
01033 {
01034 optimizeTriangleOrder();
01035 }
01036 }
01037
01038 // Skinning: If Version < 4, _BonesName are not present, must compute _BonesId from localId
01039 // Else it is computed at first computeBonesId().
01040 if(ver < 4)
01041 buildBoneUsageVer3();
01042
01043 // TestYoyo
01044 //_MeshVertexProgram= NULL;
01045 /*{
01046 uint numTris= 0;
01047 for(uint i=0;i<_MatrixBlocks.size();i++)
01048 {
01049 for(uint j=0;j<_MatrixBlocks[i].RdrPass.size();j++)
01050 numTris+= _MatrixBlocks[i].RdrPass[j].PBlock.getNumTri();
01051 }
01052 nlinfo("YOYO: %d Vertices. %d Triangles.", _VBuffer.getNumVertices(), numTris);
01053 }*/
01054
01055 // Some runtime not serialized compilation
01056 if(f.isReading())
01057 compileRunTime();
01058 }
|
|
|
Definition at line 449 of file mesh.cpp. References _MeshMorpher, NL3D::CMeshMorpher::BlendShapes, and compileRunTime(). Referenced by NL3D::CMesh::setBlendShapes().
00450 {
00451 _MeshMorpher->BlendShapes = bs;
00452 // must update some RunTime parameters
00453 compileRunTime();
00454 }
|
|
|
true if the sort criterion must be by material. Else, sort per instance. Implements NL3D::IMeshGeom. Definition at line 2006 of file mesh.cpp. References _SupportMBRFlags, and MBRSortPerMaterial.
02007 {
02008 return (_SupportMBRFlags & MBRSortPerMaterial)!=0;
02009 }
|
|
|
true if this meshGeom support meshBlock rendering. return false if skinned/meshMorphed. Implements NL3D::IMeshGeom. Definition at line 2000 of file mesh.cpp. References _SupportMBRFlags. Referenced by profileSceneRender(), and NL3D::CMesh::supportMeshBlockRendering().
02001 {
02002 return _SupportMBRFlags!=0;
02003 }
|
|
||||||||||||
|
update Skeleton Usage. increment or decrement. computeBonesId must has been called before.
Definition at line 1596 of file mesh.cpp. References _BonesIdExt, NL3D::CSkeletonModel::Bones, NL3D::CSkeletonModel::decBoneUsage(), NL3D::CSkeletonModel::incBoneUsage(), nlerror, and uint. Referenced by NL3D::CMesh::updateSkeletonUsage().
01597 {
01598 // For all Bones used by this mesh.
01599 for(uint i=0; i<_BonesIdExt.size();i++)
01600 {
01601 uint boneId= _BonesIdExt[i];
01602 // Some explicit Error.
01603 if(boneId>=sm->Bones.size())
01604 nlerror(" Skin is incompatible with Skeleton: tries to use bone %d", boneId);
01605 // increment or decrement not Forced, because CMeshGeom use getActiveBoneSkinMatrix().
01606 if(increment)
01607 sm->incBoneUsage(boneId, CSkeletonModel::UsageNormal);
01608 else
01609 sm->decBoneUsage(boneId, CSkeletonModel::UsageNormal);
01610 }
01611 }
|
|
|
update the VertexBufferHard if NULL (ie not created or deleted by driver) or if VertexBufferDirty.
Definition at line 523 of file mesh.cpp. References _MeshMorpher, _Skinned, _VertexBufferHard, _VertexBufferHardDirty, NL3D::CMeshMorpher::BlendShapes, NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getUVRouting(), NL3D::CVertexBuffer::getValueTypePointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CVertexBuffer::getVertexSize(), nlassert, NL3D::IDriver::slowUnlockVertexBufferHard(), and NL3D::IDriver::supportVertexBufferHard(). Referenced by beginMesh(), render(), and renderSkin().
00524 {
00525 if(!drv->supportVertexBufferHard())
00526 return;
00527
00528
00529 /* If the mesh is skinned, still use normal CVertexBuffer.
00530 * \todo yoyo: optimize. not done now because CMesh Skinned are not so used in game,
00531 * and CMesh skinning is far not optimized (4 matrix mul all the time). Should use later the renderSkinGroupGeom()
00532 * scheme
00533 * Also, if the driver has slow VBhard unlock() (ie ATI gl extension), avoid use of them if MeshMorpher
00534 * is used.
00535 */
00536 bool avoidVBHard;
00537 avoidVBHard= _Skinned || ( _MeshMorpher && _MeshMorpher->BlendShapes.size()>0 && drv->slowUnlockVertexBufferHard() );
00538 if( _VertexBufferHardDirty && avoidVBHard )
00539 {
00540 // delete possible old VBHard.
00541 if(_VertexBufferHard!=NULL)
00542 {
00543 // VertexBufferHard lifetime < Driver lifetime.
00544 nlassert(_Driver!=NULL);
00545 _Driver->deleteVertexBufferHard(_VertexBufferHard);
00546 }
00547 return;
00548 }
00549
00550 // If the vbufferhard is not synced to the vbuffer.
00551 if(_VertexBufferHardDirty || _VertexBufferHard==NULL)
00552 {
00553 _VertexBufferHardDirty= false;
00554
00555 // delete possible old VBHard.
00556 if(_VertexBufferHard!=NULL)
00557 {
00558 // VertexBufferHard lifetime < Driver lifetime.
00559 nlassert(_Driver!=NULL);
00560 _Driver->deleteVertexBufferHard(_VertexBufferHard);
00561 }
00562
00563 // bkup drv in a refptr. (so we know if the vbuffer hard has to be deleted).
00564 _Driver= drv;
00565 // try to create new one, in AGP Ram
00566 _VertexBufferHard= _Driver->createVertexBufferHard(_VBuffer.getVertexFormat(), _VBuffer.getValueTypePointer (), _VBuffer.getNumVertices(), IDriver::VBHardAGP, _VBuffer.getUVRouting());
00567
00568 // If KO, use normal VertexBuffer.
00569 if(_VertexBufferHard==NULL)
00570 return;
00571 // else, setup and Fill it with VertexBuffer.
00572 else
00573 {
00574 // If the mesh is static: not skinned/no meshMorpher, then setup a static VBHard -> runs faster under NVidia
00575 if( !_Skinned && ( !_MeshMorpher || _MeshMorpher->BlendShapes.size()==0) )
00576 _VertexBufferHard->lockHintStatic(true);
00577
00578
00579 // Fill VB
00580 void *vertexPtr= _VertexBufferHard->lock();
00581
00582 nlassert(_VBuffer.getVertexFormat() == _VertexBufferHard->getVertexFormat());
00583 nlassert(_VBuffer.getNumVertices() == _VertexBufferHard->getNumVertices());
00584 nlassert(_VBuffer.getVertexSize() == _VertexBufferHard->getVertexSize());
00585
00586 // \todo yoyo: TODO_DX8 and DX8 ???
00587 // Because same internal format, just copy all block.
00588 memcpy(vertexPtr, _VBuffer.getVertexCoordPointer(), _VBuffer.getNumVertices() * _VBuffer.getVertexSize() );
00589
00590 _VertexBufferHard->unlock();
00591 }
00592
00593 }
00594 }
|
|
|
For clipping.
|
|
|
This boolean is true if the bones id have been passed in the skeleton.
Definition at line 669 of file mesh.h. Referenced by build(), CMeshGeom(), and computeBonesId(). |
|
|
true if the _BonesIdExt have been computed (for bone Usage).
Definition at line 671 of file mesh.h. Referenced by build(), CMeshGeom(), and computeBonesId(). |
|
|
This array give the index in the skeleton of the local bones used. computed at first computeBoneId().
Definition at line 676 of file mesh.h. Referenced by buildBoneUsageVer3(), computeBonesId(), and getSkinBoneUsage(). |
|
|
Same as _BonesId but with parent of bones added. (used for bone usage).
Definition at line 678 of file mesh.h. Referenced by computeBonesId(), and updateSkeletonUsage(). |
|
|
This array give the name of the local bones used.
Definition at line 674 of file mesh.h. Referenced by build(), and computeBonesId(). |
|
|
This is the driver used to setup the vbuffer hard. error if a mesh has not the same driver in his life.
|
|
|
The matrix blocks.
Definition at line 660 of file mesh.h. Referenced by applyMaterialRemap(), applySkin(), build(), buildBoneUsageVer3(), buildSkin(), compileRunTime(), computeBonesId(), computeMeshVBHeap(), getNbMatrixBlock(), getNbRdrPass(), getNumRdrPassesForInstance(), getNumRdrPassesForMesh(), getNumTriangles(), getRdrPassMaterial(), getRdrPassPrimitiveBlock(), optimizeTriangleOrder(), profileSceneRender(), render(), renderPass(), renderSimpleWithMaterial(), and renderSkin(). |
|
|
Definition at line 712 of file mesh.h. Referenced by build(), CMeshGeom(), compileRunTime(), getNbBlendShapes(), render(), renderSkin(), setBlendShapes(), updateVertexBufferHard(), and ~CMeshGeom(). |
|
|
Definition at line 716 of file mesh.h. Referenced by activeInstance(), beginMesh(), bkupOriginalSkinVertices(), build(), compileRunTime(), endMesh(), getVBHeapInfo(), hasMeshVertexProgram(), initInstance(), render(), renderSkin(), and restoreOriginalSkinVertices(). |
|
|
Definition at line 652 of file mesh.h. Referenced by applySkin(), bkupOriginalSkinVertices(), render(), renderSkin(), and restoreOriginalSkinVertices(). |
|
|
This tells if the mesh VBuffer has coorect BindPos vertices.
Definition at line 666 of file mesh.h. Referenced by applySkin(), CMeshGeom(), render(), and restoreOriginalSkinVertices(). |
|
|
Skinning: this is the list of vertices (mirror of VBuffer), at the bind Pos. Potentially modified by the mesh morpher Definition at line 651 of file mesh.h. Referenced by applySkin(), bkupOriginalSkinVertices(), render(), renderSkin(), and restoreOriginalSkinVertices(). |
|
|
Definition at line 653 of file mesh.h. Referenced by applySkin(), bkupOriginalSkinVertices(), render(), renderSkin(), and restoreOriginalSkinVertices(). |
|
|
Estimate if we must do a Precise clipping (ie with bboxes).
Definition at line 709 of file mesh.h. Referenced by clip(), CMeshGeom(), and compileRunTime(). |
|
|
This tells if the mesh is correctly skinned.
Definition at line 664 of file mesh.h. Referenced by bkupOriginalSkinVertices(), build(), buildBoneUsageVer3(), CMeshGeom(), compileRunTime(), isSkinned(), render(), renderSkin(), restoreOriginalSkinVertices(), and updateVertexBufferHard(). |
|
|
setuped at compileRunTime.
Definition at line 705 of file mesh.h. Referenced by activeInstance(), beginMesh(), compileRunTime(), endMesh(), getVBHeapInfo(), renderPass(), sortPerMaterial(), and supportMeshBlockRendering(). |
|
|
VBuffer of the mesh (potentially modified by the mesh morpher and skinning).
|
|
|
The original VBuffer of the mesh used only if there are blend shapes.
Definition at line 658 of file mesh.h. Referenced by render(), and renderSkin(). |
|
|
The only one VBufferHard of the mesh. NULL by default.
Definition at line 684 of file mesh.h. Referenced by beginMesh(), profileSceneRender(), render(), renderSkin(), updateVertexBufferHard(), and ~CMeshGeom(). |
|
|
This tells if the VBuffer has changed since the last time or not.
Definition at line 688 of file mesh.h. Referenced by build(), CMeshGeom(), and updateVertexBufferHard(). |
1.3.6