From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/a02892.html | 8248 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 8248 insertions(+) create mode 100644 docs/doxygen/nel/a02892.html (limited to 'docs/doxygen/nel/a02892.html') diff --git a/docs/doxygen/nel/a02892.html b/docs/doxygen/nel/a02892.html new file mode 100644 index 00000000..a4816f08 --- /dev/null +++ b/docs/doxygen/nel/a02892.html @@ -0,0 +1,8248 @@ + + +NeL: NL3D::CMeshMRMGeom class Reference + + + +
+

NL3D::CMeshMRMGeom Class Reference

#include <mesh_mrm.h> +

+

Inheritance diagram for NL3D::CMeshMRMGeom: +

+ +NL3D::IMeshGeom +NLMISC::IStreamable +NLMISC::IClassable + +

Detailed Description

+An MRM mesh geometry, with no materials information.

+To build a CMeshMRMGeom, you should:

+

+NB: internally, build() use CMRMBuilder, a builder of MRM.

+

Author:
Lionel Berenguier

+Nevrax France

+
Date:
2001
+ +

+ +

+Definition at line 81 of file mesh_mrm.h. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

RawSkin optimisation.

uint NumCacheVertexNormal1 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin1)
uint NumCacheVertexNormal2 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin2)
uint NumCacheVertexNormal3 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin3)
uint NumCacheVertexNormal4 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin4)
uint NumCacheVertexShadow = NL_BlockByteL1 / sizeof(CMeshMRMGeom::CShadowVertex)
void applyArrayRawSkinNormal1 (CRawVertexNormalSkin1 *src, uint8 *destVertexPtr, CMatrix3x4 *boneMat3x4, uint nInf)
void applyArrayRawSkinNormal2 (CRawVertexNormalSkin2 *src, uint8 *destVertexPtr, CMatrix3x4 *boneMat3x4, uint nInf)
void applyArrayRawSkinNormal3 (CRawVertexNormalSkin3 *src, uint8 *destVertexPtr, CMatrix3x4 *boneMat3x4, uint nInf)
void applyArrayRawSkinNormal4 (CRawVertexNormalSkin4 *src, uint8 *destVertexPtr, CMatrix3x4 *boneMat3x4, uint nInf)
void dirtMeshDataId ()
 Increment the refCount, so instances RawSkins are no longer valid.

void updateRawSkinNormal (bool enabled, CMeshMRMInstance *mi, sint curLodId)
 compute RawSkin info in the MRMInstance according to current skin setup.

uint _MeshDataId
 Each time the mesh is loaded/built, this increment.


ShadowMap Skin rendering

void applyArrayShadowSkin (CShadowVertex *src, CVector *dst, CSkeletonModel *skeleton, uint numVerts)
std::vector< uint32_ShadowSkinTriangles
std::vector< CShadowVertex_ShadowSkinVertices
bool _SupportShadowSkinGrouping

Hard VB

void deleteVertexBufferHard ()
void fillAGPSkinPartWithVBHardPtr (CLod &lod, uint8 *vertexDst)
void updateVertexBufferHard (IDriver *drv, uint32 numVertices)
CRefPtr< IDriver_Driver
bool _PreciseClipping
 NB: HERE FOR PACKING ONLY. For clipping. Estimate if we must do a Precise clipping (ie with bboxes).

CRefPtr< IVertexBufferHard_VBHard
bool _VertexBufferHardDirty

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 &m, std::vector< CMesh::CMeshBuild * > &bsList, uint numMaxMaterial, const CMRMParameters &params=CMRMParameters())
void changeMRMDistanceSetup (float distanceFinest, float distanceMiddle, float distanceCoarsest)
 CMeshMRMGeom ()
 Constructor.

virtual std::string getClassName ()=0
const CMRMLevelDetailgetLevelDetail () const
 get the MRM level detail information

virtual bool hasMeshVertexProgram () const
 True if this mesh has a vertexProgram.

 ~CMeshMRMGeom ()
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 bool isActiveInstanceNeedVBFill () const
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 in a driver. true if visible.

virtual float getNumTriangles (float distance)
 get an approximation of the number of triangles this instance will render for a fixed distance.

virtual void initInstance (CMeshBaseInstance *mbi)
 Init instance info.

 NLMISC_DECLARE_CLASS (CMeshMRMGeom)
 clip this mesh in a driver. true if visible.

void profileSceneRender (CRenderTrav *rdrTrav, CTransformShape *trans, float polygonCount, uint32 rdrFlags)
 Scene profile.

virtual void render (IDriver *drv, CTransformShape *trans, float polygonCount, uint32 rdrFlags, float globalAlpha)
 render() this mesh in a driver, given an instance and his materials.

virtual void renderSkin (CTransformShape *trans, float alphaMRM)
 render() this mesh as a skin

virtual void serial (NLMISC::IStream &f) throw (NLMISC::EStream)
 serial this meshGeom.

Skinning Behavior
void computeBonesId (CSkeletonModel *skeleton)
 Compute skinning id.

const std::vector< NLMISC::CBSphere > & getSkinBoneSphere () const
 see CTransform::getSkinBoneSphere() doc for the meaning of this value. computeBonesId must has been called before.

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 std::vector< std::string > & getBonesName () const
 get the bone names of the meshMRM.

const NLMISC::CAABBoxExtgetBoundingBox () const
 get the extended axis aligned bounding box of the mesh

const std::vector< CMRMWedgeGeom > & getGeomorphs (uint lodId) const
 Advanced. get the geomorphs for a special lod.

uint getNbBlendShapes () const
 get the number of BlendShapes

uint getNbLod () const
uint getNbRdrPass (uint lodId) const
uint32 getRdrPassMaterial (uint lodId, uint renderingPassIndex) const
const CPrimitiveBlockgetRdrPassPrimitiveBlock (uint lodId, uint renderingPassIndex) const
const std::vector< CMesh::CSkinWeight > & getSkinWeights () const
 get the skinWeights used by the mrm mesh. NB: same size of the vertexBuffer. empty if !isSkinned()

const CVertexBuffergetVertexBuffer () const
 get the vertex buffer used by the mrm mesh. NB: this VB store all Vertices used by All LODs.

Lod management.
uint getNbLodLoaded () const
void loadFirstLod (NLMISC::IStream &f)
void loadNextLod (NLMISC::IStream &f)
void unloadNextLod (NLMISC::IStream &f)
ShadowMap Skin rendering
uint getNumShadowSkinVertices () const
 Get the num of shadow skin vertices.

sint renderShadowSkinGeom (CMeshMRMInstance *mi, uint remainingVertices, uint8 *vbDest)
 Get the num of shadow skin vertices.

void renderShadowSkinPrimitives (CMeshMRMInstance *mi, CMaterial &castMat, IDriver *drv, uint baseVertex)
 Get the num of shadow skin vertices.

void setShadowMesh (const std::vector< CShadowVertex > &shadowVertices, const std::vector< uint32 > &triangles)
 Setup the ShadowMesh.

bool supportShadowSkinGrouping () const
 Render the ShadowSkin (SkinGroup like).

Special SkinGrouping Rendering
sint renderSkinGroupGeom (CMeshMRMInstance *mi, float alphaMRM, uint remainingVertices, uint8 *vbDest)
void renderSkinGroupPrimitives (CMeshMRMInstance *mi, uint baseVertex, std::vector< CSkinSpecularRdrPass > &specularRdrPasses, uint skinIndex)
void renderSkinGroupSpecularRdrPass (CMeshMRMInstance *mi, uint rdrPassId)
bool supportSkinGrouping () const

Private Member Functions

void applyGeomorph (std::vector< CMRMWedgeGeom > &geoms, float alphaLod, IVertexBufferHard *currentVBHard)
 Apply the geomorph to the _VBuffer, or the VBhard, if exist/used.

void applyGeomorphPosNormalUV0 (std::vector< CMRMWedgeGeom > &geoms, uint8 *vertexPtr, uint8 *vertexDestPtr, sint32 vertexSize, float a, float a1)
 Faster, but common geomorph apply.

void applyGeomorphWithVBHardPtr (std::vector< CMRMWedgeGeom > &geoms, float alphaLod, uint8 *vertexDestPtr)
 Apply the geomorph to the VBhard ptr, if not NULL.

void applyRawSkinWithNormal (CLod &lod, CRawSkinNormalCache &rawSkinLod, const CSkeletonModel *skeleton, uint8 *vbHard, float alphaLod)
void applySkin (CLod &lod, const CSkeletonModel *skeleton)
 Skinning: Apply skinning to the _VBuffer (before geomorph).

void applySkinWithNormal (CLod &lod, const CSkeletonModel *skeleton)
void applySkinWithTangentSpace (CLod &lod, const CSkeletonModel *skeleton, uint tangentSpaceTexCoord)
void bkupOriginalSkinVertices ()
 Skinning: bkup Vertex/Normal into _OriginalSkin* from VBuffer.

void bkupOriginalSkinVerticesSubset (uint wedgeStart, uint wedgeEnd)
void buildBoneUsageVer2 ()
sint chooseLod (float alphaMRM, float &alphaLod)
 choose the lod according to the alphaMRM [0,1] given.

void compileRunTime ()
void load (NLMISC::IStream &f) throw (NLMISC::EStream)
 load this mesh.

sint loadHeader (NLMISC::IStream &f) throw (NLMISC::EStream)
 load the header of this mesh. return the version of the header.

void restoreOriginalSkinPart (CLod &lod, IVertexBufferHard *currentVBHard)
 Skinning: same as restoreOriginalSkinVertices(), but for one Lod only.

void restoreOriginalSkinVertices ()
 Skinning: restore Vertex/Normal from _OriginalSkin* to VBuffer.

void save (NLMISC::IStream &f) throw (NLMISC::EStream)
 save the entire mesh.

void serialLodVertexData (NLMISC::IStream &f, uint startWedge, uint endWedge)
 serial a subset of the vertices.

void updateShiftedTriangleCache (CMeshMRMInstance *mi, sint curLodId, uint baseVertex)

Private Attributes

NLMISC::CAABBoxExt _BBox
 For clipping. this is the BB of all vertices of all Lods.

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.

std::vector< NLMISC::CBSphere_BonesSphere
 see CTransform::getSkinBoneSphere() doc for the meaning of this value

uint8 _LastLodComputed
 Last lod rendered. used with renderSkinGroup*() only.

std::vector< CLodInfo_LodInfos
 Info for pre-loading Lods.

std::vector< CLod_Lods
 List of Lods.

CMeshMorpher _MeshMorpher
NLMISC::CSmartPtr< IMeshVertexProgram_MeshVertexProgram
uint _NbLodLoaded
std::vector< CVector_OriginalSkinNormals
std::vector< CVector_OriginalSkinVertices
 Skinning: this is the list of vertices (mirror of VBuffer), at the bind Pos.

std::vector< CVector_OriginalTGSpace
bool _Skinned
 Skinning: This tells if the mesh is correctly skinned (suuport skinning).

std::vector< CMesh::CSkinWeight_SkinWeights
 This is the array of SkinWeights, same size as the VB.

bool _SupportSkinGrouping
 if true, then maybe use faster render

CVertexBuffer _VBufferFinal
 The Final VBuffer.

CVertexBuffer _VBufferOriginal
 The Original VBuffer.

CMRMLevelDetail _LevelDetail
Mesh Block Render Implementation
bool _MBRBkupNormalize
 BeginMesh setup.

sint _MBRCurrentLodId
 global setup at activateInstance()

bool _SupportMeshBlockRendering
 setuped at compileRunTime.


Friends

class CMRMBuilder
Structures for building a MRM mesh.
class CLod
+


Member Enumeration Documentation

+

+ + + + +
+ + +
enum NL3D::IMeshGeom::TRenderFlag [inherited] +
+
+ + + + + +
+   + + +

+Render Flags, used in render. +

+

Enumeration values:
+ + + + + + +
RenderOpaqueMaterial  +
RenderTransparentMaterial  +
RenderPassOpaque  +
RenderGlobalAlpha  +
RenderGADisableZWrite  +
+
+ +

+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         };
+
+


Constructor & Destructor Documentation

+

+ + + + +
+ + + + + + + + + +
NL3D::CMeshMRMGeom::CMeshMRMGeom  ) 
+
+ + + + + +
+   + + +

+Constructor. +

+ +

+Definition at line 204 of file mesh_mrm.cpp. +

+References _MBRCurrentLodId, _MeshDataId, _NbLodLoaded, _SupportMeshBlockRendering, _SupportShadowSkinGrouping, and _SupportSkinGrouping. +

+

00205 {
+00206         _VertexBufferHardDirty= true;
+00207         _Skinned= false;
+00208         _NbLodLoaded= 0;
+00209         _BoneIdComputed = false;
+00210         _BoneIdExtended = false;
+00211         _PreciseClipping= false;
+00212         _SupportSkinGrouping= false;
+00213         _MeshDataId= 0;
+00214         _SupportMeshBlockRendering=  false;
+00215         _MBRCurrentLodId= 0;
+00216         _SupportShadowSkinGrouping= false;
+00217 }
+
+

+ + + + +
+ + + + + + + + + +
NL3D::CMeshMRMGeom::~CMeshMRMGeom  ) 
+
+ + + + + +
+   + + +

+ +

+Definition at line 221 of file mesh_mrm.cpp. +

+References deleteVertexBufferHard(). +

+

00222 {
+00223         deleteVertexBufferHard();
+00224 }
+
+


Member Function Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::activeInstance CMeshGeomRenderContext rdrCtx,
CMeshBaseInstance inst,
float  polygonCount,
void *  vbDst
[virtual]
+
+ + + + + +
+   + + +

+The framework call this method any time a change of instance occurs. +

+Implements NL3D::IMeshGeom. +

+Definition at line 2738 of file mesh_mrm.cpp. +

+References _LevelDetail, _Lods, _MBRCurrentLodId, applyGeomorph(), applyGeomorphWithVBHardPtr(), NL3D::CTransformShape::changeLightSetup(), chooseLod(), NL3D::CMeshGeomRenderContext::Driver, NL3D::CMRMLevelDetail::getLevelDetailFromPolyCount(), NL3D::CTransform::getWorldMatrix(), H_AUTO, NL3D::CMeshGeomRenderContext::RenderThroughVBHeap, NL3D::CMeshGeomRenderContext::RenderTrav, NL3D::IDriver::setupModelMatrix(), and uint8. +

+

02739 {
+02740         H_AUTO( NL3D_MeshMRMGeom_RenderNormal );
+02741 
+02742         if(_Lods.empty())
+02743                 return;
+02744 
+02745         // get the result of the Load Balancing.
+02746         float   alphaMRM= _LevelDetail.getLevelDetailFromPolyCount(polygonCount);
+02747 
+02748         // choose the lod.
+02749         float   alphaLod;
+02750         _MBRCurrentLodId= chooseLod(alphaMRM, alphaLod);
+02751 
+02752         // Geomorph the choosen Lod (if not the coarser mesh).
+02753         if(_MBRCurrentLodId>0)
+02754         {
+02755                 if(rdrCtx.RenderThroughVBHeap)
+02756                         applyGeomorphWithVBHardPtr(_Lods[_MBRCurrentLodId].Geomorphs, alphaLod, (uint8*)vbDst);
+02757                 else
+02758                         applyGeomorph(_Lods[_MBRCurrentLodId].Geomorphs, alphaLod, _VBHard);
+02759         }
+02760 
+02761         // set the instance worldmatrix.
+02762         rdrCtx.Driver->setupModelMatrix(inst->getWorldMatrix());
+02763 
+02764         // setupLighting.
+02765         inst->changeLightSetup(rdrCtx.RenderTrav);
+02766 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyArrayRawSkinNormal1 CRawVertexNormalSkin1 src,
uint8 destVertexPtr,
CMatrix3x4 boneMat3x4,
uint  nInf
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 895 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyArrayRawSkinNormal2 CRawVertexNormalSkin2 src,
uint8 destVertexPtr,
CMatrix3x4 boneMat3x4,
uint  nInf
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 1074 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyArrayRawSkinNormal3 CRawVertexNormalSkin3 src,
uint8 destVertexPtr,
CMatrix3x4 boneMat3x4,
uint  nInf
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 1377 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyArrayRawSkinNormal4 CRawVertexNormalSkin4 src,
uint8 destVertexPtr,
CMatrix3x4 boneMat3x4,
uint  nInf
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 1771 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyArrayShadowSkin CShadowVertex src,
CVector dst,
CSkeletonModel skeleton,
uint  numVerts
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 339 of file mesh_mrm_skin.cpp. +

+References _Lods, NL3D::computeBoneMatrixes3x4(), NL3D::CMeshMRMGeom::CLod::MatrixInfluences, min, NumCacheVertexShadow, src, and uint. +

+Referenced by renderShadowSkinGeom(). +

+

00340 {
+00341         // For all matrix this Mesh use. (the shadow geometry cannot use other Matrix than the mesh use).
+00342         // NB: take the best lod since the lower lods cannot use other Matrix than the higher one.
+00343         static  vector<CMatrix3x4>              boneMat3x4;
+00344         CLod    &lod= _Lods[_Lods.size()-1];
+00345         computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
+00346 
+00347         // Then do the skin
+00348         for(;numVerts>0;)
+00349         {
+00350                 // number of vertices to process for this block.
+00351                 uint    nBlockInf= min(NumCacheVertexShadow, numVerts);
+00352                 // next block.
+00353                 numVerts-= nBlockInf;
+00354 
+00355                 // cache the data in L1 cache.
+00356                 CFastMem::precache(src, nBlockInf * sizeof(CShadowVertex));
+00357 
+00358                 //  for all InfluencedVertices only.
+00359                 for(;nBlockInf>0;nBlockInf--, src++, dst++)
+00360                 {
+00361                         boneMat3x4[ src->MatrixId ].mulSetPoint( src->Vertex, *dst );
+00362                 }
+00363         }
+00364 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyGeomorph std::vector< CMRMWedgeGeom > &  geoms,
float  alphaLod,
IVertexBufferHard currentVBHard
[private]
+
+ + + + + +
+   + + +

+Apply the geomorph to the _VBuffer, or the VBhard, if exist/used. +

+ +

+Definition at line 477 of file mesh_mrm.cpp. +

+References _VBufferFinal, applyGeomorphWithVBHardPtr(), NL3D::IVertexBufferHard::getVertexSize(), NL3D::CVertexBuffer::getVertexSize(), NL3D::IVertexBufferHard::lock(), nlassert, uint8, and NL3D::IVertexBufferHard::unlock(). +

+Referenced by activeInstance(), render(), and renderSkin(). +

+

00478 {
+00479         if(currentVBHard!=NULL)
+00480         {
+00481                 // must write into it
+00482                 uint8   *vertexDestPtr= (uint8*)currentVBHard->lock();
+00483                 nlassert(_VBufferFinal.getVertexSize() == currentVBHard->getVertexSize());
+00484 
+00485                 // apply the geomorph
+00486                 applyGeomorphWithVBHardPtr(geoms, alphaLod, vertexDestPtr);
+00487 
+00488                 // unlock. ATI: copy only geomorphed vertices.
+00489                 currentVBHard->unlock(0, geoms.size());
+00490         }
+00491         else
+00492                 applyGeomorphWithVBHardPtr(geoms, alphaLod, NULL);
+00493 
+00494 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyGeomorphPosNormalUV0 std::vector< CMRMWedgeGeom > &  geoms,
uint8 vertexPtr,
uint8 vertexDestPtr,
sint32  vertexSize,
float  a,
float  a1
[private]
+
+ + + + + +
+   + + +

+Faster, but common geomorph apply. +

+ +

+Definition at line 817 of file mesh_mrm.cpp. +

+References NL3D::CMRMWedgeGeom::End, nlassert, sint32, NL3D::CMRMWedgeGeom::Start, uint, and uint8. +

+Referenced by applyGeomorphWithVBHardPtr(). +

+

00818 {
+00819         nlassert(vertexSize==32);
+00820 
+00821 
+00822         // For all geomorphs.
+00823         uint                    nGeoms= geoms.size();
+00824         CMRMWedgeGeom   *ptrGeom= &(geoms[0]);
+00825         uint8                   *destPtr= vertexDestPtr;
+00826         for(; nGeoms>0; nGeoms--, ptrGeom++, destPtr+= vertexSize )
+00827         {
+00828                 // Consider the Pos/Normal/UV as an array of 8 float to interpolate.
+00829                 float                   *start= (float*)(vertexPtr + (ptrGeom->Start<<5));
+00830                 float                   *end=   (float*)(vertexPtr + (ptrGeom->End<<5));
+00831                 float                   *dst=   (float*)(destPtr);
+00832 
+00833                 // unrolled
+00834                 dst[0]= start[0] * a + end[0]* a1;
+00835                 dst[1]= start[1] * a + end[1]* a1;
+00836                 dst[2]= start[2] * a + end[2]* a1;
+00837                 dst[3]= start[3] * a + end[3]* a1;
+00838                 dst[4]= start[4] * a + end[4]* a1;
+00839                 dst[5]= start[5] * a + end[5]* a1;
+00840                 dst[6]= start[6] * a + end[6]* a1;
+00841                 dst[7]= start[7] * a + end[7]* a1;
+00842         }
+00843 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyGeomorphWithVBHardPtr std::vector< CMRMWedgeGeom > &  geoms,
float  alphaLod,
uint8 vertexDestPtr
[private]
+
+ + + + + +
+   + + +

+Apply the geomorph to the VBhard ptr, if not NULL. +

+ +

+Definition at line 498 of file mesh_mrm.cpp. +

+References _VBufferFinal, applyGeomorphPosNormalUV0(), NLMISC::CRGBA::blendFromui(), NLMISC::clamp(), NL3D::CMRMWedgeGeom::End, NL3D::CVertexBuffer::getColorOff(), NL3D::CVertexBuffer::getNormalOff(), NL3D::CVertexBuffer::getSpecularOff(), NL3D::CVertexBuffer::getTexCoordOff(), NL3D::CVertexBuffer::getValueType(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CVertexBuffer::getVertexSize(), nlassert, sint32, NL3D::CMRMWedgeGeom::Start, uint, and uint8. +

+Referenced by activeInstance(), and applyGeomorph(). +

+

00499 {
+00500         // no geomorphs? quit.
+00501         if(geoms.size()==0)
+00502                 return;
+00503 
+00504         clamp(alphaLod, 0.f, 1.f);
+00505         float           a= alphaLod;
+00506         float           a1= 1 - alphaLod;
+00507 
+00508 
+00509         // info from VBuffer.
+00510         uint8           *vertexPtr= (uint8*)_VBufferFinal.getVertexCoordPointer();
+00511         uint            flags= _VBufferFinal.getVertexFormat();
+00512         sint32          vertexSize= _VBufferFinal.getVertexSize();
+00513         // because of the unrolled code for 4 first UV, must assert this.
+00514         nlassert(CVertexBuffer::MaxStage>=4);
+00515         // must have XYZ.
+00516         nlassert(flags & CVertexBuffer::PositionFlag);
+00517 
+00518 
+00519         // If VBuffer Hard disabled
+00520         if(vertexDestPtr==NULL)
+00521         {
+00522                 // write into vertexPtr.
+00523                 vertexDestPtr= vertexPtr;
+00524         }
+00525 
+00526 
+00527         // if it is a common format
+00528         if( flags== (CVertexBuffer::PositionFlag | CVertexBuffer::NormalFlag | CVertexBuffer::TexCoord0Flag) &&
+00529                 _VBufferFinal.getValueType(CVertexBuffer::TexCoord0) == CVertexBuffer::Float2 )
+00530         {
+00531                 // use a faster method
+00532                 applyGeomorphPosNormalUV0(geoms, vertexPtr, vertexDestPtr, vertexSize, a, a1);
+00533         }
+00534         else
+00535         {
+00536                 // for color interp
+00537                 uint            i;
+00538                 uint            ua= (uint)(a*256);
+00539                 clamp(ua, (uint)0, (uint)256);
+00540                 uint            ua1= 256 - ua;
+00541                 
+00542                 // if an offset is 0, it means that the component is not in the VBuffer.
+00543                 sint32          normalOff;
+00544                 sint32          colorOff;
+00545                 sint32          specularOff;
+00546                 sint32          uvOff[CVertexBuffer::MaxStage];
+00547                 bool            has3Coords[CVertexBuffer::MaxStage];
+00548 
+00549 
+00550                 // Compute offset of each component of the VB.
+00551                 if(flags & CVertexBuffer::NormalFlag)
+00552                         normalOff= _VBufferFinal.getNormalOff();
+00553                 else
+00554                         normalOff= 0;
+00555                 if(flags & CVertexBuffer::PrimaryColorFlag)
+00556                         colorOff= _VBufferFinal.getColorOff();
+00557                 else
+00558                         colorOff= 0;
+00559                 if(flags & CVertexBuffer::SecondaryColorFlag)
+00560                         specularOff= _VBufferFinal.getSpecularOff();
+00561                 else
+00562                         specularOff= 0;
+00563                         
+00564                 for(i= 0; i<CVertexBuffer::MaxStage;i++)
+00565                 {
+00566                         if(flags & (CVertexBuffer::TexCoord0Flag<<i))
+00567                         {
+00568                                 uvOff[i]= _VBufferFinal.getTexCoordOff(i);                      
+00569                                 has3Coords[i] = (_VBufferFinal.getValueType(i + CVertexBuffer::TexCoord0) == CVertexBuffer::Float3);
+00570                         }
+00571                         else
+00572                         {
+00573                                 uvOff[i]= 0;
+00574                         }
+00575                 }
+00576 
+00577 
+00578                 // For all geomorphs.
+00579                 uint                    nGeoms= geoms.size();
+00580                 CMRMWedgeGeom   *ptrGeom= &(geoms[0]);
+00581                 uint8                   *destPtr= vertexDestPtr;
+00582                 /* NB: optimisation: lot of "if" in this Loop, but because of BTB, they always cost nothing (prediction is good).
+00583                    NB: this also is why we unroll the 4 1st Uv. The other (if any), are done in the other loop.
+00584                    NB: optimisation for AGP write cominers: the order of write (vertex, normal, uvs...) is important for good
+00585                    use of AGP write combiners.
+00586                    We have 2 version : one that tests for 3 coordinates texture coords, and one that doesn't
+00587                 */
+00588 
+00589                 if (!has3Coords[0] && !has3Coords[1] && !has3Coords[2] && !has3Coords[3])
+00590                 {
+00591                         // there are no texture coordinate of dimension 3
+00592                         for(; nGeoms>0; nGeoms--, ptrGeom++, destPtr+= vertexSize )
+00593                         {
+00594                                 uint8                   *startPtr=      vertexPtr + ptrGeom->Start*vertexSize;
+00595                                 uint8                   *endPtr=        vertexPtr + ptrGeom->End*vertexSize;
+00596 
+00597                                 // Vertex.
+00598                                 {
+00599                                         CVector         *start= (CVector*)startPtr;
+00600                                         CVector         *end=   (CVector*)endPtr;
+00601                                         CVector         *dst=   (CVector*)destPtr;
+00602                                         *dst= *start * a + *end * a1;
+00603                                 }
+00604 
+00605                                 // Normal.
+00606                                 if(normalOff)
+00607                                 {
+00608                                         CVector         *start= (CVector*)(startPtr + normalOff);
+00609                                         CVector         *end=   (CVector*)(endPtr   + normalOff);
+00610                                         CVector         *dst=   (CVector*)(destPtr  + normalOff);
+00611                                         *dst= *start * a + *end * a1;
+00612                                 }
+00613 
+00614 
+00615                                 // Uvs.
+00616                                 // uv[0].
+00617                                 if(uvOff[0])
+00618                                 {                               
+00619                                         // Uv.
+00620                                         CUV                     *start= (CUV*)(startPtr + uvOff[0]);
+00621                                         CUV                     *end=   (CUV*)(endPtr   + uvOff[0]);
+00622                                         CUV                     *dst=   (CUV*)(destPtr  + uvOff[0]);
+00623                                         *dst= *start * a + *end * a1;                           
+00624                                 }
+00625                                 // uv[1].
+00626                                 if(uvOff[1])
+00627                                 {                               
+00628                                         // Uv.
+00629                                         CUV                     *start= (CUV*)(startPtr + uvOff[1]);
+00630                                         CUV                     *end=   (CUV*)(endPtr   + uvOff[1]);
+00631                                         CUV                     *dst=   (CUV*)(destPtr  + uvOff[1]);
+00632                                         *dst= *start * a + *end * a1;                           
+00633                                 }
+00634                                 // uv[2].
+00635                                 if(uvOff[2])
+00636                                 {                               
+00637                                         CUV                     *start= (CUV*)(startPtr + uvOff[2]);
+00638                                         CUV                     *end=   (CUV*)(endPtr   + uvOff[2]);
+00639                                         CUV                     *dst=   (CUV*)(destPtr  + uvOff[2]);
+00640                                         *dst= *start * a + *end * a1;                           
+00641                                 }
+00642                                 // uv[3].
+00643                                 if(uvOff[3])
+00644                                 {                               
+00645                                         // Uv.
+00646                                         CUV                     *start= (CUV*)(startPtr + uvOff[3]);
+00647                                         CUV                     *end=   (CUV*)(endPtr   + uvOff[3]);
+00648                                         CUV                     *dst=   (CUV*)(destPtr  + uvOff[3]);
+00649                                         *dst= *start * a + *end * a1;                           
+00650                                 }
+00651                         }
+00652                 }
+00653                 else // THERE ARE TEXTURE COORDINATES OF DIMENSION 3
+00654                 {
+00655                         for(; nGeoms>0; nGeoms--, ptrGeom++, destPtr+= vertexSize )
+00656                         {
+00657                                 uint8                   *startPtr=      vertexPtr + ptrGeom->Start*vertexSize;
+00658                                 uint8                   *endPtr=        vertexPtr + ptrGeom->End*vertexSize;
+00659 
+00660                                 // Vertex.
+00661                                 {
+00662                                         CVector         *start= (CVector*)startPtr;
+00663                                         CVector         *end=   (CVector*)endPtr;
+00664                                         CVector         *dst=   (CVector*)destPtr;
+00665                                         *dst= *start * a + *end * a1;
+00666                                 }
+00667 
+00668                                 // Normal.
+00669                                 if(normalOff)
+00670                                 {
+00671                                         CVector         *start= (CVector*)(startPtr + normalOff);
+00672                                         CVector         *end=   (CVector*)(endPtr   + normalOff);
+00673                                         CVector         *dst=   (CVector*)(destPtr  + normalOff);
+00674                                         *dst= *start * a + *end * a1;
+00675                                 }
+00676                                 // Uvs.
+00677                                 // uv[0].
+00678                                 if(uvOff[0])
+00679                                 {
+00680                                         if (!has3Coords[0])
+00681                                         {
+00682                                                 // Uv.
+00683                                                 CUV                     *start= (CUV*)(startPtr + uvOff[0]);
+00684                                                 CUV                     *end=   (CUV*)(endPtr   + uvOff[0]);
+00685                                                 CUV                     *dst=   (CUV*)(destPtr  + uvOff[0]);
+00686                                                 *dst= *start * a + *end * a1;
+00687                                         }
+00688                                         else
+00689                                         {
+00690                                                 // Uv.
+00691                                                 CUVW            *start= (CUVW*)(startPtr + uvOff[0]);
+00692                                                 CUVW            *end=   (CUVW*)(endPtr   + uvOff[0]);
+00693                                                 CUVW            *dst=   (CUVW*)(destPtr  + uvOff[0]);
+00694                                                 *dst= *start * a + *end * a1;
+00695                                         }
+00696                                 }
+00697                                 // uv[1].
+00698                                 if(uvOff[1])
+00699                                 {
+00700                                         if (!has3Coords[1])
+00701                                         {
+00702                                                 // Uv.
+00703                                                 CUV                     *start= (CUV*)(startPtr + uvOff[1]);
+00704                                                 CUV                     *end=   (CUV*)(endPtr   + uvOff[1]);
+00705                                                 CUV                     *dst=   (CUV*)(destPtr  + uvOff[1]);
+00706                                                 *dst= *start * a + *end * a1;
+00707                                         }
+00708                                         else
+00709                                         {
+00710                                                 // Uv.
+00711                                                 CUVW            *start= (CUVW*)(startPtr + uvOff[1]);
+00712                                                 CUVW            *end=   (CUVW*)(endPtr   + uvOff[1]);
+00713                                                 CUVW            *dst=   (CUVW*)(destPtr  + uvOff[1]);
+00714                                                 *dst= *start * a + *end * a1;
+00715                                         }
+00716                                 }
+00717                                 // uv[2].
+00718                                 if(uvOff[2])
+00719                                 {
+00720                                         if (!has3Coords[2])
+00721                                         {
+00722                                                 // Uv.
+00723                                                 CUV                     *start= (CUV*)(startPtr + uvOff[2]);
+00724                                                 CUV                     *end=   (CUV*)(endPtr   + uvOff[2]);
+00725                                                 CUV                     *dst=   (CUV*)(destPtr  + uvOff[2]);
+00726                                                 *dst= *start * a + *end * a1;
+00727                                         }
+00728                                         else
+00729                                         {
+00730                                                 // Uv.
+00731                                                 CUVW            *start= (CUVW*)(startPtr + uvOff[2]);
+00732                                                 CUVW            *end=   (CUVW*)(endPtr   + uvOff[2]);
+00733                                                 CUVW            *dst=   (CUVW*)(destPtr  + uvOff[2]);
+00734                                                 *dst= *start * a + *end * a1;
+00735                                         }
+00736                                 }
+00737                                 // uv[3].
+00738                                 if(uvOff[3])
+00739                                 {
+00740                                         if (!has3Coords[3])
+00741                                         {
+00742                                                 // Uv.
+00743                                                 CUV                     *start= (CUV*)(startPtr + uvOff[3]);
+00744                                                 CUV                     *end=   (CUV*)(endPtr   + uvOff[3]);
+00745                                                 CUV                     *dst=   (CUV*)(destPtr  + uvOff[3]);
+00746                                                 *dst= *start * a + *end * a1;
+00747                                         }
+00748                                         else
+00749                                         {
+00750                                                 // Uv.
+00751                                                 CUVW            *start= (CUVW*)(startPtr + uvOff[3]);
+00752                                                 CUVW            *end=   (CUVW*)(endPtr   + uvOff[3]);
+00753                                                 CUVW            *dst=   (CUVW*)(destPtr  + uvOff[3]);
+00754                                                 *dst= *start * a + *end * a1;
+00755                                         }
+00756                                 }
+00757                                 // color.
+00758                                 if(colorOff)
+00759                                 {
+00760                                         CRGBA           *start= (CRGBA*)(startPtr + colorOff);
+00761                                         CRGBA           *end=   (CRGBA*)(endPtr   + colorOff);
+00762                                         CRGBA           *dst=   (CRGBA*)(destPtr  + colorOff);
+00763                                         dst->blendFromui(*start, *end,  ua1);
+00764                                 }
+00765                                 // specular.
+00766                                 if(specularOff)
+00767                                 {
+00768                                         CRGBA           *start= (CRGBA*)(startPtr + specularOff);
+00769                                         CRGBA           *end=   (CRGBA*)(endPtr   + specularOff);
+00770                                         CRGBA           *dst=   (CRGBA*)(destPtr  + specularOff);
+00771                                         dst->blendFromui(*start, *end,  ua1);
+00772                                 }
+00773                         }
+00774                 }
+00775 
+00776 
+00777                 // Process extra UVs (maybe never, so don't bother optims :)).
+00778                 // For all stages after 4.
+00779                 for(i=4;i<CVertexBuffer::MaxStage;i++)
+00780                 {
+00781                         uint                    nGeoms= geoms.size();
+00782                         CMRMWedgeGeom   *ptrGeom= &(geoms[0]);
+00783                         uint8                   *destPtr= vertexDestPtr;
+00784 
+00785                         if(uvOff[i]==0)
+00786                                 continue;
+00787 
+00788                         // For all geomorphs.
+00789                         for(; nGeoms>0; nGeoms--, ptrGeom++, destPtr+= vertexSize )
+00790                         {
+00791                                 uint8                   *startPtr=      vertexPtr + ptrGeom->Start*vertexSize;
+00792                                 uint8                   *endPtr=        vertexPtr + ptrGeom->End*vertexSize;
+00793 
+00794                                 // uv[i].
+00795                                 // Uv.
+00796                                 if (!has3Coords[i])
+00797                                 {
+00798                                         CUV                     *start= (CUV*)(startPtr + uvOff[i]);
+00799                                         CUV                     *end=   (CUV*)(endPtr   + uvOff[i]);
+00800                                         CUV                     *dst=   (CUV*)(destPtr  + uvOff[i]);
+00801                                         *dst= *start * a + *end * a1;
+00802                                 }
+00803                                 else
+00804                                 {
+00805                                         CUVW            *start= (CUVW*)(startPtr + uvOff[i]);
+00806                                         CUVW            *end=   (CUVW*)(endPtr  + uvOff[i]);
+00807                                         CUVW            *dst=   (CUVW*)(destPtr + uvOff[i]);
+00808                                         *dst= *start * a + *end * a1;
+00809                                 }
+00810                         }
+00811                 }
+00812         }
+00813 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyMaterialRemap const std::vector< sint > &  remap  ) 
+
+ + + + + +
+   + + +

+change materials Ids (called from CMesh::optimizeMaterialUsage()) +

+ +

+Definition at line 462 of file mesh_mrm.cpp. +

+References _Lods, getNbLod(), getNbRdrPass(), nlassert, uint, and uint32. +

+Referenced by NL3D::CMeshMRM::optimizeMaterialUsage(). +

+

00463 {
+00464         for(uint lod=0;lod<getNbLod();lod++)
+00465         {
+00466                 for(uint rp=0;rp<getNbRdrPass(lod);rp++)
+00467                 {
+00468                         // remap
+00469                         uint32  &matId= _Lods[lod].RdrPass[rp].MaterialId;
+00470                         nlassert(remap[matId]>=0);
+00471                         matId= remap[matId];
+00472                 }
+00473         }
+00474 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applyRawSkinWithNormal CLod lod,
CRawSkinNormalCache rawSkinLod,
const CSkeletonModel skeleton,
uint8 vbHard,
float  alphaLod
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 1825 of file mesh_mrm_skin.cpp. +

+Referenced by renderSkinGroupGeom().

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applySkin CLod lod,
const CSkeletonModel skeleton
[private]
+
+ + + + + +
+   + + +

+Skinning: Apply skinning to the _VBuffer (before geomorph). +

+ +

+Definition at line 207 of file mesh_mrm_skin.cpp. +

+References _SkinWeights, _VBufferFinal, NL3D::computeBoneMatrixes3x4(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CVertexBuffer::getVertexSize(), index, NL3D::CMeshMRMGeom::CLod::InfluencedVertices, NL3D::CMesh::CSkinWeight::MatrixId, NL3D::CMeshMRMGeom::CLod::MatrixInfluences, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, sint32, uint, uint32, uint8, and NL3D::CMesh::CSkinWeight::Weights. +

+Referenced by renderSkin(). +

+

00208 {
+00209         nlassert(_Skinned);
+00210         if(_SkinWeights.size()==0)
+00211                 return;
+00212 
+00213         // get vertexPtr.
+00214         //===========================
+00215         uint8           *destVertexPtr= (uint8*)_VBufferFinal.getVertexCoordPointer();
+00216         uint            flags= _VBufferFinal.getVertexFormat();
+00217         sint32          vertexSize= _VBufferFinal.getVertexSize();
+00218         // must have XYZ.
+00219         nlassert(flags & CVertexBuffer::PositionFlag);
+00220 
+00221 
+00222         // compute src array.
+00223         CMesh::CSkinWeight      *srcSkinPtr;
+00224         CVector                         *srcVertexPtr;
+00225         srcSkinPtr= &_SkinWeights[0];
+00226         srcVertexPtr= &_OriginalSkinVertices[0];
+00227 
+00228 
+00229 
+00230         // Compute usefull Matrix for this lod.
+00231         //===========================
+00232         // Those arrays map the array of bones in skeleton.
+00233         static  vector<CMatrix3x4>                      boneMat3x4;
+00234         computeBoneMatrixes3x4(boneMat3x4, lod.MatrixInfluences, skeleton);
+00235 
+00236 
+00237         // apply skinning.
+00238         //===========================
+00239         // assert, code below is written especially for 4 per vertex.
+00240         nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
+00241         for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
+00242         {
+00243                 uint            nInf= lod.InfluencedVertices[i].size();
+00244                 if( nInf==0 )
+00245                         continue;
+00246                 uint32          *infPtr= &(lod.InfluencedVertices[i][0]);
+00247 
+00248                 // apply the skin to the vertices
+00249                 switch(i)
+00250                 {
+00251                 //=========
+00252                 case 0:
+00253                         // Special case for Vertices influenced by one matrix. Just copy result of mul.
+00254                         //  for all InfluencedVertices only.
+00255                         for(;nInf>0;nInf--, infPtr++)
+00256                         {
+00257                                 uint    index= *infPtr;
+00258                                 CMesh::CSkinWeight      *srcSkin= srcSkinPtr + index;
+00259                                 CVector                         *srcVertex= srcVertexPtr + index;
+00260                                 uint8                           *dstVertexVB= destVertexPtr + index * vertexSize;
+00261                                 CVector                         *dstVertex= (CVector*)(dstVertexVB);
+00262 
+00263 
+00264                                 // Vertex.
+00265                                 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, *dstVertex);
+00266                         }
+00267                         break;
+00268 
+00269                 //=========
+00270                 case 1:
+00271                         //  for all InfluencedVertices only.
+00272                         for(;nInf>0;nInf--, infPtr++)
+00273                         {
+00274                                 uint    index= *infPtr;
+00275                                 CMesh::CSkinWeight      *srcSkin= srcSkinPtr + index;
+00276                                 CVector                         *srcVertex= srcVertexPtr + index;
+00277                                 uint8                           *dstVertexVB= destVertexPtr + index * vertexSize;
+00278                                 CVector                         *dstVertex= (CVector*)(dstVertexVB);
+00279 
+00280 
+00281                                 // Vertex.
+00282                                 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
+00283                                 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
+00284                         }
+00285                         break;
+00286 
+00287                 //=========
+00288                 case 2:
+00289                         //  for all InfluencedVertices only.
+00290                         for(;nInf>0;nInf--, infPtr++)
+00291                         {
+00292                                 uint    index= *infPtr;
+00293                                 CMesh::CSkinWeight      *srcSkin= srcSkinPtr + index;
+00294                                 CVector                         *srcVertex= srcVertexPtr + index;
+00295                                 uint8                           *dstVertexVB= destVertexPtr + index * vertexSize;
+00296                                 CVector                         *dstVertex= (CVector*)(dstVertexVB);
+00297 
+00298 
+00299                                 // Vertex.
+00300                                 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
+00301                                 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
+00302                                 boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
+00303                         }
+00304                         break;
+00305 
+00306                 //=========
+00307                 case 3:
+00308                         //  for all InfluencedVertices only.
+00309                         for(;nInf>0;nInf--, infPtr++)
+00310                         {
+00311                                 uint    index= *infPtr;
+00312                                 CMesh::CSkinWeight      *srcSkin= srcSkinPtr + index;
+00313                                 CVector                         *srcVertex= srcVertexPtr + index;
+00314                                 uint8                           *dstVertexVB= destVertexPtr + index * vertexSize;
+00315                                 CVector                         *dstVertex= (CVector*)(dstVertexVB);
+00316 
+00317 
+00318                                 // Vertex.
+00319                                 boneMat3x4[ srcSkin->MatrixId[0] ].mulSetPoint( *srcVertex, srcSkin->Weights[0], *dstVertex);
+00320                                 boneMat3x4[ srcSkin->MatrixId[1] ].mulAddPoint( *srcVertex, srcSkin->Weights[1], *dstVertex);
+00321                                 boneMat3x4[ srcSkin->MatrixId[2] ].mulAddPoint( *srcVertex, srcSkin->Weights[2], *dstVertex);
+00322                                 boneMat3x4[ srcSkin->MatrixId[3] ].mulAddPoint( *srcVertex, srcSkin->Weights[3], *dstVertex);
+00323                         }
+00324                         break;
+00325 
+00326                 }
+00327         }
+00328 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applySkinWithNormal CLod lod,
const CSkeletonModel skeleton
[private]
+
+ + + + + +
+   + + +

+The same as apply skin, but with normal modified. Normal is not normalized. 4 versions from slower to faster. +

+Definition at line 741 of file mesh_mrm_skin.cpp. +

+Referenced by renderSkin().

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::applySkinWithTangentSpace CLod lod,
const CSkeletonModel skeleton,
uint  tangentSpaceTexCoord
[private]
+
+ + + + + +
+   + + +

+The same as apply skin with normal, but with a tangent space added (encoded in a texture coordinate). The tangent space is modified, but not normalized (must be done in a vertex program). 4 versions from slower to faster. +

+Definition at line 804 of file mesh_mrm_skin.cpp. +

+Referenced by renderSkin().

+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::beginMesh CMeshGeomRenderContext rdrCtx  )  [virtual]
+
+ + + + + +
+   + + +

+The framework call this method when he will render instances of this meshGeom soon. +

+Implements NL3D::IMeshGeom. +

+Definition at line 2705 of file mesh_mrm.cpp. +

+References _Lods, _MBRBkupNormalize, _VBufferFinal, NL3D::IDriver::activeVertexBuffer(), NL3D::IDriver::activeVertexBufferHard(), NL3D::CMeshGeomRenderContext::Driver, NL3D::IDriver::forceNormalize(), NL3D::CVertexBuffer::getNumVertices(), NL3D::IDriver::isForceNormalize(), NL3D::CMeshGeomRenderContext::RenderThroughVBHeap, and updateVertexBufferHard(). +

+

02706 {
+02707         if(_Lods.empty())
+02708                 return;
+02709 
+02710         IDriver *drv= rdrCtx.Driver;
+02711 
+02712         if(rdrCtx.RenderThroughVBHeap)
+02713         {
+02714                 // Don't setup VB in this case, since use the VBHeap setuped one.
+02715         }
+02716         else
+02717         {
+02718                 updateVertexBufferHard(drv, _VBufferFinal.getNumVertices());
+02719 
+02720                 // active VB.
+02721                 if(_VBHard)
+02722                 {
+02723                         drv->activeVertexBufferHard(_VBHard);
+02724                 }
+02725                 else
+02726                 {
+02727                         drv->activeVertexBuffer(_VBufferFinal);
+02728                 }
+02729         }
+02730 
+02731 
+02732         // force normalisation of normals..
+02733         _MBRBkupNormalize= drv->isForceNormalize();
+02734         drv->forceNormalize(true);                      
+02735 
+02736 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CMeshMRMGeom::bkupOriginalSkinVertices  )  [private]
+
+ + + + + +
+   + + +

+Skinning: bkup Vertex/Normal into _OriginalSkin* from VBuffer. +

+ +

+Definition at line 2045 of file mesh_mrm.cpp. +

+References _VBufferFinal, bkupOriginalSkinVerticesSubset(), NL3D::CVertexBuffer::getNumVertices(), and nlassert. +

+Referenced by build(). +

+

02046 {
+02047         nlassert(_Skinned);
+02048 
+02049         // bkup the entire array.
+02050         bkupOriginalSkinVerticesSubset(0, _VBufferFinal.getNumVertices());
+02051 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::bkupOriginalSkinVerticesSubset uint  wedgeStart,
uint  wedgeEnd
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 2055 of file mesh_mrm.cpp. +

+References _VBufferFinal, NL3D::CVertexBuffer::getNormalCoordPointer(), NL3D::CVertexBuffer::getNumTexCoordUsed(), NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getTexCoordPointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), nlassert, and uint. +

+Referenced by bkupOriginalSkinVertices(), and serialLodVertexData(). +

+

02056 {
+02057         nlassert(_Skinned);
+02058 
+02059         // Copy VBuffer content into Original vertices normals.
+02060         if(_VBufferFinal.getVertexFormat() & CVertexBuffer::PositionFlag)
+02061         {
+02062                 // copy vertices from VBuffer. (NB: unusefull geomorphed vertices are still copied, but doesn't matter).
+02063                 _OriginalSkinVertices.resize(_VBufferFinal.getNumVertices());
+02064                 for(uint i=wedgeStart; i<wedgeEnd;i++)
+02065                 {
+02066                         _OriginalSkinVertices[i]= *(CVector*)_VBufferFinal.getVertexCoordPointer(i);
+02067                 }
+02068         }
+02069         if(_VBufferFinal.getVertexFormat() & CVertexBuffer::NormalFlag)
+02070         {
+02071                 // copy normals from VBuffer. (NB: unusefull geomorphed normals are still copied, but doesn't matter).
+02072                 _OriginalSkinNormals.resize(_VBufferFinal.getNumVertices());
+02073                 for(uint i=wedgeStart; i<wedgeEnd;i++)
+02074                 {
+02075                         _OriginalSkinNormals[i]= *(CVector*)_VBufferFinal.getNormalCoordPointer(i);
+02076                 }
+02077         }
+02078 
+02079         // is there tangent space added ?
+02080         if (_MeshVertexProgram && _MeshVertexProgram->needTangentSpace())
+02081         {
+02082                 // yes, backup it
+02083                 nlassert(_VBufferFinal.getNumTexCoordUsed() > 0);
+02084                 uint tgSpaceStage = _VBufferFinal.getNumTexCoordUsed() - 1;
+02085                 _OriginalTGSpace.resize(_VBufferFinal.getNumVertices());
+02086                 for(uint i=wedgeStart; i<wedgeEnd;i++)
+02087                 {
+02088                         _OriginalTGSpace[i]= *(CVector*)_VBufferFinal.getTexCoordPointer(i, tgSpaceStage);
+02089                 }
+02090         }
+02091 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::build CMesh::CMeshBuild m,
std::vector< CMesh::CMeshBuild * > &  bsList,
uint  numMaxMaterial,
const CMRMParameters params = CMRMParameters()
+
+ + + + + +
+   + + +

+Build a mesh, replacing old. this is much slower than CMeshGeom::build(), because it computes the MRM.

Parameters:
+ + +
params parameters of the MRM build process.
+
+ +

+Definition at line 246 of file mesh_mrm.cpp. +

+References _LevelDetail, _LodInfos, _Lods, _NbLodLoaded, _SkinWeights, _VBufferFinal, bkupOriginalSkinVertices(), NL3D::CMeshMRMGeom::CMeshBuildMRM::BlendShapes, NL3D::CMeshMorpher::BlendShapes, NL3D::CMesh::CMeshBuild::BonesNames, NL3D::CMRMLevelDetail::compileDistanceSetup(), NL3D::CMRMBuilder::compileMRM(), compileRunTime(), dirtMeshDataId(), NL3D::CMeshMRMGeom::CMeshBuildMRM::DistanceCoarsest, NL3D::CMRMLevelDetail::DistanceCoarsest, NL3D::CMeshMRMGeom::CMeshBuildMRM::DistanceFinest, NL3D::CMRMLevelDetail::DistanceFinest, NL3D::CMeshMRMGeom::CMeshBuildMRM::DistanceMiddle, NL3D::CMRMLevelDetail::DistanceMiddle, NL3D::CMesh::CMeshBuild::Faces, NL3D::CPrimitiveBlock::getNumTriangles(), NL3D::CMeshMRMGeom::CMeshBuildMRM::Lods, NL3D::makeBBox(), matrix, NL3D::CMRMLevelDetail::MaxFaceUsed, NL3D::CMesh::CMeshBuild::MeshVertexProgram, NL3D::CMRMLevelDetail::MinFaceUsed, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, params, NL3D::CMeshMRMGeom::CRdrPass::PBlock, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CVertexBuffer::reserve(), NLMISC::CAABBoxExt::setCenter(), NL3D::CVertexBuffer::setNumVertices(), NLMISC::CAABBoxExt::setSize(), NL3D::CMeshMRMGeom::CMeshBuildMRM::Skinned, NL3D::CMeshMRMGeom::CMeshBuildMRM::SkinWeights, uint, uint32, NL3D::CMeshMRMGeom::CMeshBuildMRM::VBuffer, and NL3D::CMesh::CMeshBuild::Vertices. +

+Referenced by NL3D::CMeshMRM::build(). +

+

00248 {
+00249 
+00250         // Dirt the VBuffer.
+00251         _VertexBufferHardDirty= true;
+00252 
+00253         // Empty geometry?
+00254         if(m.Vertices.size()==0 || m.Faces.size()==0)
+00255         {
+00256                 _VBufferFinal.setNumVertices(0);
+00257                 _VBufferFinal.reserve(0);
+00258                 _Lods.clear();
+00259                 _BBox.setCenter(CVector::Null);
+00260                 _BBox.setSize(CVector::Null);
+00261                 return;
+00262         }
+00263         nlassert(numMaxMaterial>0);
+00264 
+00265 
+00266         // SmartPtr Copy VertexProgram effect.
+00267         //================================================      
+00268         this->_MeshVertexProgram= m.MeshVertexProgram;
+00269 
+00270 
+00272         //======================
+00273         // NB: this is equivalent as building BBox from MRM VBuffer, because CMRMBuilder create new vertices 
+00274         // which are just interpolation of original vertices.
+00275         _BBox= makeBBox(m.Vertices);
+00276 
+00277 
+00279         //================================================
+00280         CMRMBuilder                     mrmBuilder;
+00281         CMeshBuildMRM           meshBuildMRM;
+00282 
+00283         mrmBuilder.compileMRM(m, bsList, params, meshBuildMRM, numMaxMaterial);
+00284 
+00285         // Then just copy result!
+00286         //================================================
+00287         _VBufferFinal= meshBuildMRM.VBuffer;
+00288         _Lods= meshBuildMRM.Lods;
+00289         _Skinned= meshBuildMRM.Skinned;
+00290         _SkinWeights= meshBuildMRM.SkinWeights;
+00291 
+00292         // Compute degradation control.
+00293         //================================================
+00294         _LevelDetail.DistanceFinest= meshBuildMRM.DistanceFinest;
+00295         _LevelDetail.DistanceMiddle= meshBuildMRM.DistanceMiddle;
+00296         _LevelDetail.DistanceCoarsest= meshBuildMRM.DistanceCoarsest;
+00297         nlassert(_LevelDetail.DistanceFinest>=0);
+00298         nlassert(_LevelDetail.DistanceMiddle > _LevelDetail.DistanceFinest);
+00299         nlassert(_LevelDetail.DistanceCoarsest > _LevelDetail.DistanceMiddle);
+00300         // Compute OODistDelta and DistancePow
+00301         _LevelDetail.compileDistanceSetup();
+00302 
+00303 
+00304         // Build the _LodInfos.
+00305         //================================================
+00306         _LodInfos.resize(_Lods.size());
+00307         uint32  precNWedges= 0;
+00308         uint    i;
+00309         for(i=0;i<_Lods.size();i++)
+00310         {
+00311                 _LodInfos[i].StartAddWedge= precNWedges;
+00312                 _LodInfos[i].EndAddWedges= _Lods[i].NWedges;
+00313                 precNWedges= _Lods[i].NWedges;
+00314                 // LodOffset is filled in serial() when stream is input.
+00315         }
+00316         // After build, all lods are present in memory. 
+00317         _NbLodLoaded= _Lods.size();
+00318 
+00319 
+00320         // For load balancing.
+00321         //================================================
+00322         // compute Max Face Used
+00323         _LevelDetail.MaxFaceUsed= 0;
+00324         _LevelDetail.MinFaceUsed= 0;
+00325         // Count of primitive block
+00326         if(_Lods.size()>0)
+00327         {
+00328                 uint    pb;
+00329                 // Compute MinFaces.
+00330                 CLod    &firstLod= _Lods[0];
+00331                 for (pb=0; pb<firstLod.RdrPass.size(); pb++)
+00332                 {
+00333                         CRdrPass &pass= firstLod.RdrPass[pb];
+00334                         // Sum tri
+00335                         _LevelDetail.MinFaceUsed+= pass.PBlock.getNumTriangles ();
+00336                 }
+00337                 // Compute MaxFaces.
+00338                 CLod    &lastLod= _Lods[_Lods.size()-1];
+00339                 for (pb=0; pb<lastLod.RdrPass.size(); pb++)
+00340                 {
+00341                         CRdrPass &pass= lastLod.RdrPass[pb];
+00342                         // Sum tri
+00343                         _LevelDetail.MaxFaceUsed+= pass.PBlock.getNumTriangles ();
+00344                 }
+00345         }
+00346 
+00347 
+00348         // For skinning.
+00349         //================================================
+00350         if( _Skinned )
+00351         {
+00352                 bkupOriginalSkinVertices();
+00353         }
+00354         // Inform that the mesh data has changed
+00355         dirtMeshDataId();
+00356 
+00357 
+00358         // For AGP SKinning optim, and for Render optim
+00359         //================================================
+00360         for(i=0;i<_Lods.size();i++)
+00361         {
+00362                 _Lods[i].buildSkinVertexBlocks();
+00363                 // sort triangles for better cache use.
+00364                 _Lods[i].optimizeTriangleOrder();
+00365         }
+00366 
+00367         // Copy Blend Shapes
+00368         //================================================      
+00369         _MeshMorpher.BlendShapes = meshBuildMRM.BlendShapes;
+00370         
+00371 
+00372         // Compact bone id and build a bone id names
+00373         //================================================      
+00374 
+00375         // Skinned ?
+00376         if (_Skinned)
+00377         {
+00378                 // Remap
+00379                 std::map<uint, uint> remap;
+00380 
+00381                 // Current bone
+00382                 uint currentBone = 0;
+00383 
+00384                 // Reserve memory
+00385                 _BonesName.reserve (m.BonesNames.size());
+00386 
+00387                 // For each vertices
+00388                 uint vert;
+00389                 for (vert=0; vert<_SkinWeights.size(); vert++)
+00390                 {
+00391                         // Found one ?
+00392                         bool found=false;
+00393                         
+00394                         // For each weight
+00395                         uint weight;
+00396                         for (weight=0; weight<NL3D_MESH_SKINNING_MAX_MATRIX; weight++)
+00397                         {
+00398                                 // Active ?
+00399                                 if ((_SkinWeights[vert].Weights[weight]>0)||(weight==0))
+00400                                 {
+00401                                         // Look for it
+00402                                         std::map<uint, uint>::iterator ite = remap.find (_SkinWeights[vert].MatrixId[weight]);
+00403 
+00404                                         // Find ?
+00405                                         if (ite == remap.end())
+00406                                         {
+00407                                                 // Insert it
+00408                                                 remap.insert (std::map<uint, uint>::value_type (_SkinWeights[vert].MatrixId[weight], currentBone));
+00409 
+00410                                                 // Check the id
+00411                                                 nlassert (_SkinWeights[vert].MatrixId[weight]<m.BonesNames.size());
+00412 
+00413                                                 // Set the bone name
+00414                                                 _BonesName.push_back (m.BonesNames[_SkinWeights[vert].MatrixId[weight]]);
+00415 
+00416                                                 // Set the local bone id
+00417                                                 _SkinWeights[vert].MatrixId[weight] = currentBone++;
+00418                                         }
+00419                                         else
+00420                                         {
+00421                                                 // Set the local bone id
+00422                                                 _SkinWeights[vert].MatrixId[weight] = ite->second;
+00423                                         }
+00424 
+00425                                         // Found one
+00426                                         found = true;
+00427                                 }
+00428                         }
+00429 
+00430                         // Found one ?
+00431                         nlassert (found);
+00432                 }
+00433 
+00434                 // Remap the vertex influence by lods
+00435                 uint lod;
+00436                 for (lod=0; lod<_Lods.size(); lod++)
+00437                 {
+00438                         // For each matrix used
+00439                         uint matrix;
+00440                         for (matrix=0; matrix<_Lods[lod].MatrixInfluences.size(); matrix++)
+00441                         {
+00442                                 // Remap
+00443                                 std::map<uint, uint>::iterator ite = remap.find (_Lods[lod].MatrixInfluences[matrix]);
+00444 
+00445                                 // Find ?
+00446                                 nlassert (ite != remap.end());
+00447 
+00448                                 // Remap
+00449                                 _Lods[lod].MatrixInfluences[matrix] = ite->second;
+00450                         }
+00451                 }
+00452         }
+00453 
+00454         // Misc.
+00455         //===================
+00456         // Some runtime not serialized compilation
+00457         compileRunTime();
+00458 
+00459 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CMeshMRMGeom::buildBoneUsageVer2  )  [private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 2482 of file mesh_mrm.cpp. +

+References _SkinWeights, NL3D_MESH_SKINNING_MAX_MATRIX, uint, and uint32. +

+Referenced by loadFirstLod(). +

+

02483 {
+02484         if(_Skinned)
+02485         {
+02486                 // parse all vertices, couting MaxBoneId used.
+02487                 uint32  maxBoneId= 0;
+02488                 // for each vertex
+02489                 uint vert;
+02490                 for (vert=0; vert<_SkinWeights.size(); vert++)
+02491                 {
+02492                         // For each weight
+02493                         for (uint weight=0; weight<NL3D_MESH_SKINNING_MAX_MATRIX; weight++)
+02494                         {
+02495                                 // Active ?
+02496                                 if ((_SkinWeights[vert].Weights[weight]>0)||(weight==0))
+02497                                 {
+02498                                         maxBoneId= max(_SkinWeights[vert].MatrixId[weight], maxBoneId);
+02499                                 }
+02500                         }                               
+02501                 }
+02502 
+02503                 // alloc an array of maxBoneId+1, reset to 0.
+02504                 std::vector<uint8>              boneUsage;
+02505                 boneUsage.resize(maxBoneId+1, 0);
+02506 
+02507                 // reparse all vertices, counting usage for each bone.
+02508                 for (vert=0; vert<_SkinWeights.size(); vert++)
+02509                 {
+02510                         // For each weight
+02511                         for (uint weight=0; weight<NL3D_MESH_SKINNING_MAX_MATRIX; weight++)
+02512                         {
+02513                                 // Active ?
+02514                                 if ((_SkinWeights[vert].Weights[weight]>0)||(weight==0))
+02515                                 {
+02516                                         // mark this bone as used.
+02517                                         boneUsage[_SkinWeights[vert].MatrixId[weight]]= 1;
+02518                                 }
+02519                         }                               
+02520                 }
+02521 
+02522                 // For each bone used
+02523                 _BonesId.clear();
+02524                 for(uint i=0; i<boneUsage.size();i++)
+02525                 {
+02526                         // if the bone is used by the mesh, add it to BoneId.
+02527                         if(boneUsage[i])
+02528                                 _BonesId.push_back(i);
+02529                 }
+02530         }
+02531 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::changeMRMDistanceSetup float  distanceFinest,
float  distanceMiddle,
float  distanceCoarsest
+
+ + + + + +
+   + + +

+Change MRM Distance setup. NB: no-op if distanceFinest<0, distanceMiddle<=distanceFinest or if distanceCoarsest<=distanceMiddle.

Parameters:
+ + + + +
distanceFinest The MRM has its max faces when dist<=distanceFinest.
distanceMiddle The MRM has 50% of its faces at dist==distanceMiddle.
distanceCoarsest The MRM has faces/Divisor (ie near 0) when dist>=distanceCoarsest.
+
+ +

+Definition at line 228 of file mesh_mrm.cpp. +

+References _LevelDetail, NL3D::CMRMLevelDetail::compileDistanceSetup(), NL3D::CMRMLevelDetail::DistanceCoarsest, NL3D::CMRMLevelDetail::DistanceFinest, and NL3D::CMRMLevelDetail::DistanceMiddle. +

+Referenced by NL3D::CMeshMultiLod::changeMRMDistanceSetup(), and NL3D::CMeshMRM::changeMRMDistanceSetup(). +

+

00229 {
+00230         // check input.
+00231         if(distanceFinest<0)    return;
+00232         if(distanceMiddle<=distanceFinest)      return;
+00233         if(distanceCoarsest<=distanceMiddle)    return;
+00234 
+00235         // Change.
+00236         _LevelDetail.DistanceFinest= distanceFinest;
+00237         _LevelDetail.DistanceMiddle= distanceMiddle;
+00238         _LevelDetail.DistanceCoarsest= distanceCoarsest;
+00239 
+00240         // compile 
+00241         _LevelDetail.compileDistanceSetup();
+00242 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
sint NL3D::CMeshMRMGeom::chooseLod float  alphaMRM,
float &  alphaLod
[inline, private]
+
+ + + + + +
+   + + +

+choose the lod according to the alphaMRM [0,1] given. +

+ +

+Definition at line 898 of file mesh_mrm.cpp. +

+References _Lods, _NbLodLoaded, and sint. +

+Referenced by activeInstance(), profileSceneRender(), render(), renderSkin(), and renderSkinGroupGeom(). +

+

00899 {
+00900         // Choose what Lod to draw.
+00901         alphaMRM*= _Lods.size()-1;
+00902         sint    numLod= (sint)ceil(alphaMRM);
+00903         if(numLod==0)
+00904         {
+00905                 numLod= 0;
+00906                 alphaLod= 0;
+00907         }
+00908         else
+00909         {
+00910                 // Lerp beetween lod i-1 and lod i.
+00911                 alphaLod= alphaMRM-(numLod-1);
+00912         }
+00913 
+00914 
+00915         // If lod chosen is not loaded, take the best loaded.
+00916         if(numLod>=(sint)_NbLodLoaded)
+00917         {
+00918                 numLod= _NbLodLoaded-1;
+00919                 alphaLod= 1;
+00920         }
+00921 
+00922         return numLod;
+00923 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
bool NL3D::CMeshMRMGeom::clip const std::vector< CPlane > &  pyramid,
const CMatrix worldMatrix
[virtual]
+
+ + + + + +
+   + + +

+clip this mesh in a driver. true if visible. +

+ +

+Reimplemented from NL3D::IMeshGeom. +

+Definition at line 856 of file mesh_mrm.cpp. +

+References 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::CMeshMRM::clip(). +

+

00857 {
+00858         // Speed Clip: clip just the sphere.
+00859         CBSphere        localSphere(_BBox.getCenter(), _BBox.getRadius());
+00860         CBSphere        worldSphere;
+00861 
+00862         // transform the sphere in WorldMatrix (with nearly good scale info).
+00863         localSphere.applyTransform(worldMatrix, worldSphere);
+00864 
+00865         // if out of only plane, entirely out.
+00866         for(sint i=0;i<(sint)pyramid.size();i++)
+00867         {
+00868                 // We are sure that pyramid has normalized plane normals.
+00869                 // if SpherMax OUT return false.
+00870                 float   d= pyramid[i]*worldSphere.Center;
+00871                 if(d>worldSphere.Radius)
+00872                         return false;
+00873         }
+00874 
+00875         // test if must do a precise clip, according to mesh size.
+00876         if( _PreciseClipping )
+00877         {
+00878                 CPlane  localPlane;
+00879 
+00880                 // if out of only plane, entirely out.
+00881                 for(sint i=0;i<(sint)pyramid.size();i++)
+00882                 {
+00883                         // Transform the pyramid in Object space.
+00884                         localPlane= pyramid[i]*worldMatrix;
+00885                         // localPlane must be normalized, because worldMatrix mya have a scale.
+00886                         localPlane.normalize();
+00887                         // if the box is not partially inside the plane, quit
+00888                         if( !_BBox.clipBack(localPlane) )
+00889                                 return false;
+00890                 }
+00891         }
+00892 
+00893         return true;
+00894 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CMeshMRMGeom::compileRunTime  )  [private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 2554 of file mesh_mrm.cpp. +

+References _Lods, _ShadowSkinVertices, _SupportMeshBlockRendering, _SupportShadowSkinGrouping, _SupportSkinGrouping, _VBufferFinal, NL3D::CMeshMorpher::BlendShapes, NL3D::CPrimitiveBlock::getNumLine(), NL3D::CPrimitiveBlock::getNumQuad(), NL3D::CVertexBuffer::getNumVertices(), NLMISC::CAABBoxExt::getRadius(), NL3D::CVertexBuffer::getVertexFormat(), NL3D_MESH_PRECISE_CLIP_THRESHOLD, NL3D_MESH_SKIN_MANAGER_MAXVERTICES, NL3D_MESH_SKIN_MANAGER_VERTEXFORMAT, NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES, NL3D_SHADOW_MESH_SKIN_MANAGER_VERTEXFORMAT, and uint. +

+Referenced by build(). +

+

02555 {
+02556         _PreciseClipping= _BBox.getRadius() >= NL3D_MESH_PRECISE_CLIP_THRESHOLD;
+02557 
+02558         // Compute if can support SkinGrouping rendering
+02559         if(_Lods.size()==0 || !_Skinned)
+02560         {
+02561                 _SupportSkinGrouping= false;
+02562                 _SupportShadowSkinGrouping= false;
+02563         }
+02564         else
+02565         {
+02566                 // The Mesh must follow those restrictions, to support group skinning
+02567                 _SupportSkinGrouping=
+02568                         _VBufferFinal.getVertexFormat() == NL3D_MESH_SKIN_MANAGER_VERTEXFORMAT &&
+02569                         _VBufferFinal.getNumVertices() < NL3D_MESH_SKIN_MANAGER_MAXVERTICES &&
+02570                         !_MeshVertexProgram;
+02571                 // Additionally, NONE of the RdrPass should have Quads or lines...
+02572                 for(uint i=0;i<_Lods.size();i++)
+02573                 {
+02574                         for(uint j=0;j<_Lods[i].RdrPass.size();j++)
+02575                         {
+02576                                 CPrimitiveBlock         &pb= _Lods[i].RdrPass[j].PBlock;
+02577                                 if( pb.getNumQuad() || pb.getNumLine() )
+02578                                 {
+02579                                         _SupportSkinGrouping= false;
+02580                                         break;
+02581                                 }
+02582                         }
+02583                 }
+02584 
+02585                 // Support Shadow SkinGrouping if Shadow setuped, and if not too many vertices.
+02586                 _SupportShadowSkinGrouping= !_ShadowSkinVertices.empty() &&
+02587                         NL3D_SHADOW_MESH_SKIN_MANAGER_VERTEXFORMAT==CVertexBuffer::PositionFlag &&
+02588                         _ShadowSkinVertices.size() <= NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES;
+02589         }
+02590 
+02591         // Support MeshBlockRendering only if not skinned/meshMorphed.
+02592         _SupportMeshBlockRendering= !_Skinned && _MeshMorpher.BlendShapes.size()==0;
+02593 
+02594         // \todo yoyo: support later MeshVertexProgram 
+02595         _SupportMeshBlockRendering= _SupportMeshBlockRendering && _MeshVertexProgram==NULL;
+02596 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::computeBonesId CSkeletonModel skeleton  ) 
+
+ + + + + +
+   + + +

+Compute skinning id. +

+ +

+Definition at line 2293 of file mesh_mrm.cpp. +

+References _BonesSphere, _Lods, _ShadowSkinVertices, _SkinWeights, NL3D::CSkeletonModel::Bones, NL3D::CSkeletonModel::flagBoneAndParents(), NL3D::CSkeletonModel::getBoneIdByName(), matrix, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, nlwarning, sint32, uint, uint32, and v. +

+Referenced by NL3D::CMeshMRM::computeBonesId(). +

+

02294 {
+02295         // Already computed ?
+02296         if (!_BoneIdComputed)
+02297         {
+02298                 // Get a pointer on the skeleton
+02299                 nlassert (skeleton);
+02300                 if (skeleton)
+02301                 {
+02302                         // Resize boneId to the good size.
+02303                         _BonesId.resize(_BonesName.size());
+02304 
+02305                         // Remap bones id table
+02306                         std::vector<uint> remap (_BonesName.size());
+02307 
+02308                         // **** For each bones, compute remap
+02309                         uint bone;
+02310                         for (bone=0; bone<remap.size(); bone++)
+02311                         {
+02312                                 // Look for the bone
+02313                                 sint32 boneId = skeleton->getBoneIdByName (_BonesName[bone]);
+02314 
+02315                                 // Setup the _BoneId.
+02316                                 _BonesId[bone]= boneId;
+02317 
+02318                                 // Bones found ?
+02319                                 if (boneId != -1)
+02320                                 {
+02321                                         // Set the bone id
+02322                                         remap[bone] = (uint32)boneId;
+02323                                 }
+02324                                 else
+02325                                 {
+02326                                         // Put id 0
+02327                                         remap[bone] = 0;
+02328 
+02329                                         // Error
+02330                                         nlwarning ("Bone %s not found in the skeleton.", _BonesName[bone].c_str());
+02331                                 }
+02332                         }
+02333 
+02334                         // **** Remap the vertices, and compute Bone Spheres.
+02335 
+02336                         // Find the Geomorph space: to process only real vertices, not geomorphed ones.
+02337                         uint    nGeomSpace= 0;
+02338                         uint    lod;
+02339                         for (lod=0; lod<_Lods.size(); lod++)
+02340                         {
+02341                                 nGeomSpace= max(nGeomSpace, (uint)_Lods[lod].Geomorphs.size());
+02342                         }
+02343 
+02344                         // Prepare Sphere compute
+02345                         nlassert(_OriginalSkinVertices.size() == _SkinWeights.size());
+02346                         static std::vector<CAABBox>             boneBBoxes;
+02347                         static std::vector<bool>                boneBBEmpty;
+02348                         boneBBoxes.clear();
+02349                         boneBBEmpty.clear();
+02350                         boneBBoxes.resize(_BonesId.size());
+02351                         boneBBEmpty.resize(_BonesId.size(), true);
+02352 
+02353                         // Remap the vertex, and compute the bone spheres. see CTransform::getSkinBoneSphere() doc.
+02354                         // for true vertices
+02355                         uint vert;
+02356                         for (vert=nGeomSpace; vert<_SkinWeights.size(); vert++)
+02357                         {
+02358                                 // get the vertex position.
+02359                                 CVector         vertex= _OriginalSkinVertices[vert];
+02360 
+02361                                 // For each weight
+02362                                 uint weight;
+02363                                 for (weight=0; weight<NL3D_MESH_SKINNING_MAX_MATRIX; weight++)
+02364                                 {
+02365                                         // Active ?
+02366                                         if ((_SkinWeights[vert].Weights[weight]>0)||(weight==0))
+02367                                         {
+02368                                                 // Check id
+02369                                                 uint    srcId= _SkinWeights[vert].MatrixId[weight];
+02370                                                 nlassert (srcId < remap.size());
+02371                                                 // remap
+02372                                                 _SkinWeights[vert].MatrixId[weight] = remap[srcId];
+02373 
+02374                                                 // if the boneId is valid (ie found)
+02375                                                 if(_BonesId[srcId]>=0)
+02376                                                 {
+02377                                                         // transform the vertex pos in BoneSpace
+02378                                                         CVector         p= skeleton->Bones[_BonesId[srcId]].getBoneBase().InvBindPos * vertex;
+02379                                                         // extend the bone bbox.
+02380                                                         if(boneBBEmpty[srcId])
+02381                                                         {
+02382                                                                 boneBBoxes[srcId].setCenter(p);
+02383                                                                 boneBBEmpty[srcId]= false;
+02384                                                         }
+02385                                                         else
+02386                                                         {
+02387                                                                 boneBBoxes[srcId].extend(p);
+02388                                                         }
+02389                                                 }
+02390                                         }
+02391                                         else
+02392                                                 break;
+02393                                 }                               
+02394                         }
+02395 
+02396                         // Compile spheres
+02397                         _BonesSphere.resize(_BonesId.size());
+02398                         for(bone=0;bone<_BonesSphere.size();bone++)
+02399                         {
+02400                                 // If the bone is empty, mark with -1 in the radius.
+02401                                 if(boneBBEmpty[bone])
+02402                                 {
+02403                                         _BonesSphere[bone].Radius= -1;
+02404                                 }
+02405                                 else
+02406                                 {
+02407                                         _BonesSphere[bone].Center= boneBBoxes[bone].getCenter();
+02408                                         _BonesSphere[bone].Radius= boneBBoxes[bone].getRadius();
+02409                                 }
+02410                         }
+02411 
+02412                         // **** Remap the vertex influence by lods
+02413                         for (lod=0; lod<_Lods.size(); lod++)
+02414                         {
+02415                                 // For each matrix used
+02416                                 uint matrix;
+02417                                 for (matrix=0; matrix<_Lods[lod].MatrixInfluences.size(); matrix++)
+02418                                 {
+02419                                         // Check
+02420                                         nlassert (_Lods[lod].MatrixInfluences[matrix]<remap.size());
+02421 
+02422                                         // Remap
+02423                                         _Lods[lod].MatrixInfluences[matrix] = remap[_Lods[lod].MatrixInfluences[matrix]];
+02424                                 }
+02425                         }
+02426 
+02427                         // **** Remap Shadow Vertices.
+02428                         for(vert=0;vert<_ShadowSkinVertices.size();vert++)
+02429                         {
+02430                                 CShadowVertex   &v= _ShadowSkinVertices[vert];
+02431                                 // Check id
+02432                                 nlassert (v.MatrixId < remap.size());
+02433                                 v.MatrixId= remap[v.MatrixId];
+02434                         }
+02435 
+02436                         // Computed
+02437                         _BoneIdComputed = true;
+02438                 }
+02439         }
+02440 
+02441         // Already extended ?
+02442         if (!_BoneIdExtended)
+02443         {
+02444                 nlassert (skeleton);
+02445                 if (skeleton)
+02446                 {
+02447                         // the total bone Usage of the mesh.
+02448                         vector<bool>    boneUsage;
+02449                         boneUsage.resize(skeleton->Bones.size(), false);
+02450 
+02451                         // for all Bones marked as valid.
+02452                         uint    i;
+02453                         for(i=0; i<_BonesId.size(); i++)
+02454                         {
+02455                                 // if not a valid boneId, skip it.
+02456                                 if(_BonesId[i]<0)
+02457                                         continue;
+02458 
+02459                                 // mark him and his father in boneUsage.
+02460                                 skeleton->flagBoneAndParents(_BonesId[i], boneUsage);
+02461                         }
+02462 
+02463                         // fill _BonesIdExt with bones of _BonesId and their parents.
+02464                         _BonesIdExt.clear();
+02465                         for(i=0; i<boneUsage.size();i++)
+02466                         {
+02467                                 // if the bone is used by the mesh, add it to BoneIdExt.
+02468                                 if(boneUsage[i])
+02469                                         _BonesIdExt.push_back(i);
+02470                         }
+02471 
+02472                 }
+02473 
+02474                 // Extended
+02475                 _BoneIdExtended= true;
+02476         }
+02477 
+02478 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::computeMeshVBHeap void *  dst,
uint  indexStart
[virtual]
+
+ + + + + +
+   + + +

+When the framework succes to allocate a VBHeap space, it call this method to fill this space and compute shifted Primitive block.

Parameters:
+ + + +
the dest VertexBuffer. NB: start to fill at dst[0]
indexStart used to shift primitive block.
+
+ +

+Reimplemented from NL3D::IMeshGeom. +

+Definition at line 2811 of file mesh_mrm.cpp. +

+References _Lods, _VBufferFinal, 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(), NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CPrimitiveBlock::setNumLine(), NL3D::CPrimitiveBlock::setNumQuad(), NL3D::CPrimitiveBlock::setNumTri(), uint, and uint32. +

+

02812 {
+02813         // Fill dst with Buffer content.
+02814         memcpy(dst, _VBufferFinal.getVertexCoordPointer(), _VBufferFinal.getNumVertices()*_VBufferFinal.getVertexSize() );
+02815 
+02816         // For All Lods
+02817         for(uint lodId=0; lodId<_Lods.size();lodId++)
+02818         {
+02819                 CLod    &lod= _Lods[lodId];
+02820 
+02821                 // For all rdrPass.
+02822                 for(uint i=0;i<lod.RdrPass.size();i++)
+02823                 {
+02824                         // shift the PB
+02825                         CPrimitiveBlock &srcPb= lod.RdrPass[i].PBlock;
+02826                         CPrimitiveBlock &dstPb= lod.RdrPass[i].VBHeapPBlock;
+02827                         uint j;
+02828 
+02829                         // Lines.
+02830                         dstPb.setNumLine(srcPb.getNumLine());
+02831                         uint32                  *srcLinePtr= srcPb.getLinePointer();
+02832                         uint32                  *dstLinePtr= dstPb.getLinePointer();
+02833                         for(j=0; j<dstPb.getNumLine()*2;j++)
+02834                         {
+02835                                 dstLinePtr[j]= srcLinePtr[j]+indexStart;
+02836                         }
+02837                         // Tris.
+02838                         dstPb.setNumTri(srcPb.getNumTri());
+02839                         uint32                  *srcTriPtr= srcPb.getTriPointer();
+02840                         uint32                  *dstTriPtr= dstPb.getTriPointer();
+02841                         for(j=0; j<dstPb.getNumTri()*3;j++)
+02842                         {
+02843                                 dstTriPtr[j]= srcTriPtr[j]+indexStart;
+02844                         }
+02845                         // Quads.
+02846                         dstPb.setNumQuad(srcPb.getNumQuad());
+02847                         uint32                  *srcQuadPtr= srcPb.getQuadPointer();
+02848                         uint32                  *dstQuadPtr= dstPb.getQuadPointer();
+02849                         for(j=0; j<dstPb.getNumQuad()*4;j++)
+02850                         {
+02851                                 dstQuadPtr[j]= srcQuadPtr[j]+indexStart;
+02852                         }
+02853                 }
+02854         }
+02855 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CMeshMRMGeom::deleteVertexBufferHard  )  [private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 2209 of file mesh_mrm.cpp. +

+References nlassert. +

+Referenced by ~CMeshMRMGeom(). +

+

02210 {
+02211         // test (refptr) if the object still exist in memory.
+02212         if(_VBHard!=NULL)
+02213         {
+02214                 // A vbufferhard should still exist only if driver still exist.
+02215                 nlassert(_Driver!=NULL);
+02216 
+02217                 // delete it from driver.
+02218                 _Driver->deleteVertexBufferHard(_VBHard);
+02219                 _VBHard= NULL;
+02220         }
+02221 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CMeshMRMGeom::dirtMeshDataId  )  [private]
+
+ + + + + +
+   + + +

+Increment the refCount, so instances RawSkins are no longer valid. +

+ +

+Definition at line 3052 of file mesh_mrm.cpp. +

+References _MeshDataId. +

+Referenced by build(). +

+

03053 {
+03054         // see updateRawSkinNormal()
+03055         _MeshDataId++;
+03056 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::endMesh CMeshGeomRenderContext rdrCtx  )  [virtual]
+
+ + + + + +
+   + + +

+The framework call this method when it has done with this meshGeom +

+Implements NL3D::IMeshGeom. +

+Definition at line 2791 of file mesh_mrm.cpp. +

+References _Lods, _MBRBkupNormalize, NL3D::CMeshGeomRenderContext::Driver, and NL3D::IDriver::forceNormalize(). +

+

02792 {
+02793         if(_Lods.empty())
+02794                 return;
+02795 
+02796         // bkup force normalisation.
+02797         rdrCtx.Driver->forceNormalize(_MBRBkupNormalize);
+02798 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::fillAGPSkinPartWithVBHardPtr CLod lod,
uint8 vertexDst
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 1978 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + + + + + + + + +
const std::vector<std::string>& NL3D::CMeshMRMGeom::getBonesName  )  const [inline]
+
+ + + + + +
+   + + +

+get the bone names of the meshMRM. +

+ +

+Definition at line 182 of file mesh_mrm.h. +

+

00182 {return _BonesName;}
+
+

+ + + + +
+ + + + + + + + + +
const NLMISC::CAABBoxExt& NL3D::CMeshMRMGeom::getBoundingBox  )  const [inline, virtual]
+
+ + + + + +
+   + + +

+get the extended axis aligned bounding box of the mesh +

+ +

+Implements NL3D::IMeshGeom. +

+Definition at line 170 of file mesh_mrm.h. +

+Referenced by NL3D::CMeshMRM::getBoundingBox(). +

+

00171         {
+00172                 return _BBox;
+00173         }
+
+

+ + + + +
+ + + + + + + + + +
virtual std::string NLMISC::IClassable::getClassName  )  [pure virtual, inherited]
+
+ + + + + +
+   + + +

+ +

+Implemented in NLAIAGENT::CNumericIndex, NLAIC::IPointerGestion, NLAIC::CIdentType, and CAutomataDesc. +

+Referenced by NLMISC::CClassRegistry::checkObject(), and NL3D::GetTextureSize().

+

+ + + + +
+ + + + + + + + + + +
const std::vector<CMRMWedgeGeom>& NL3D::CMeshMRMGeom::getGeomorphs uint  lodId  )  const [inline]
+
+ + + + + +
+   + + +

+Advanced. get the geomorphs for a special lod. +

+ +

+Definition at line 216 of file mesh_mrm.h. +

+References _Lods, and uint. +

+

00217         {
+00218                 return _Lods[lodId].Geomorphs;
+00219         }
+
+

+ + + + +
+ + + + + + + + + +
const CMRMLevelDetail& NL3D::CMeshMRMGeom::getLevelDetail  )  const [inline]
+
+ + + + + +
+   + + +

+get the MRM level detail information +

+ +

+Definition at line 275 of file mesh_mrm.h. +

+References _LevelDetail. +

+Referenced by NL3D::CMeshMRMInstance::getMRMLevelDetail(). +

+

00275 {return _LevelDetail;}
+
+

+ + + + +
+ + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNbBlendShapes  )  const [inline]
+
+ + + + + +
+   + + +

+get the number of BlendShapes +

+ +

+Definition at line 222 of file mesh_mrm.h. +

+References NL3D::CMeshMorpher::BlendShapes, and uint. +

+

00222 { return _MeshMorpher.BlendShapes.size(); }
+
+

+ + + + +
+ + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNbLod  )  const [inline]
+
+ + + + + +
+   + + +

+get the number of LOD. +

+Definition at line 186 of file mesh_mrm.h. +

+References _Lods, and uint. +

+Referenced by applyMaterialRemap(), NL3D::CMeshMRM::getNbLod(), and loadNextLod(). +

+

00186 { return _Lods.size() ; }
+
+

+ + + + +
+ + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNbLodLoaded  )  const [inline]
+
+ + + + + +
+   + + +

+get the number of LOD currently loaded. +

+Definition at line 140 of file mesh_mrm.h. +

+References _NbLodLoaded, and uint. +

+Referenced by loadNextLod(), and unloadNextLod(). +

+

00140 { return _NbLodLoaded ; }
+
+

+ + + + +
+ + + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNbRdrPass uint  lodId  )  const [inline]
+
+ + + + + +
+   + + +

+get the number of rendering pass of a LOD.

Parameters:
+ + +
lodId the id of the LOD.
+
+ +

+Definition at line 192 of file mesh_mrm.h. +

+References _Lods, and uint. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), applyMaterialRemap(), and NL3D::CMeshMRM::getNbRdrPass(). +

+

00192 { return _Lods[lodId].RdrPass.size() ; }
+
+

+ + + + +
+ + + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNumRdrPassesForInstance CMeshBaseInstance inst  )  const [virtual]
+
+ + + + + +
+   + + +

+return the number of renderPasses for this instance. Called after activateInstance() Used only if sortPerMaterial()) is false +

+Implements NL3D::IMeshGeom. +

+Definition at line 2700 of file mesh_mrm.cpp. +

+References _Lods, _MBRCurrentLodId, and uint. +

+

02701 {
+02702         return _Lods[_MBRCurrentLodId].RdrPass.size();
+02703 }
+
+

+ + + + +
+ + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNumRdrPassesForMesh  )  const [virtual]
+
+ + + + + +
+   + + +

+return the number of renderPasses for this mesh. Used only if sortPerMaterial()) is true +

+Implements NL3D::IMeshGeom. +

+Definition at line 2693 of file mesh_mrm.cpp. +

+References uint. +

+

02694 {
+02695         // not used...
+02696         return 0;
+02697 
+02698 }
+
+

+ + + + +
+ + + + + + + + + +
uint NL3D::CMeshMRMGeom::getNumShadowSkinVertices  )  const
+
+ + + + + +
+   + + +

+Get the num of shadow skin vertices. +

+ +

+Definition at line 3370 of file mesh_mrm.cpp. +

+References _ShadowSkinVertices, and uint. +

+

03371 {
+03372         return _ShadowSkinVertices.size();
+03373 }
+
+

+ + + + +
+ + + + + + + + + + +
float NL3D::CMeshMRMGeom::getNumTriangles float  distance  )  [virtual]
+
+ + + + + +
+   + + +

+get an approximation of the number of triangles this instance will render for a fixed distance. +

+ +

+Implements NL3D::IMeshGeom. +

+Definition at line 2200 of file mesh_mrm.cpp. +

+References _LevelDetail, and NL3D::CMRMLevelDetail::getNumTriangles(). +

+Referenced by NL3D::CMeshMRM::getNumTriangles(). +

+

02201 {
+02202         // NB: this is an approximation, but this is continious.
+02203         return _LevelDetail.getNumTriangles(distance);
+02204 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
uint32 NL3D::CMeshMRMGeom::getRdrPassMaterial uint  lodId,
uint  renderingPassIndex
const [inline]
+
+ + + + + +
+   + + +

+get the material ID associated with a rendering pass of a LOD.

Parameters:
+ + + +
lodId the id of the LOD.
renderingPassIndex the index of the rendering pass in the matrix block
+
+ +

+Definition at line 209 of file mesh_mrm.h. +

+References _Lods, uint, and uint32. +

+Referenced by NL3D::CZoneLighter::addTriangles(), and NL3D::CMeshMRM::getRdrPassMaterial(). +

+

00210         {
+00211                 return _Lods[lodId].RdrPass[renderingPassIndex].MaterialId ;
+00212         }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
const CPrimitiveBlock& NL3D::CMeshMRMGeom::getRdrPassPrimitiveBlock uint  lodId,
uint  renderingPassIndex
const [inline]
+
+ + + + + +
+   + + +

+get the primitive block associated with a rendering pass of a LOD.

Parameters:
+ + + +
lodId the id of the LOD.
renderingPassIndex the index of the rendering pass
+
+ +

+Definition at line 199 of file mesh_mrm.h. +

+References _Lods, and uint. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), and NL3D::CMeshMRM::getRdrPassPrimitiveBlock(). +

+

00200         {
+00201                 return _Lods[lodId].RdrPass[renderingPassIndex].PBlock ;
+00202         }
+
+

+ + + + +
+ + + + + + + + + +
const std::vector<NLMISC::CBSphere>& NL3D::CMeshMRMGeom::getSkinBoneSphere  )  const [inline]
+
+ + + + + +
+   + + +

+see CTransform::getSkinBoneSphere() doc for the meaning of this value. computeBonesId must has been called before. +

+ +

+Definition at line 246 of file mesh_mrm.h. +

+References _BonesSphere. +

+Referenced by NL3D::CMeshMRMInstance::getSkinBoneSphere(). +

+

00246 {return _BonesSphere;}
+
+

+ + + + +
+ + + + + + + + + +
const std::vector<sint32>& NL3D::CMeshMRMGeom::getSkinBoneUsage  )  const [inline]
+
+ + + + + +
+   + + +

+return array of bones used by the skin. computeBonesId must has been called before. +

+ +

+Definition at line 243 of file mesh_mrm.h. +

+Referenced by NL3D::CMeshMRMInstance::getSkinBoneUsage(). +

+

00243 {return _BonesId;}
+
+

+ + + + +
+ + + + + + + + + +
const std::vector<CMesh::CSkinWeight>& NL3D::CMeshMRMGeom::getSkinWeights  )  const [inline]
+
+ + + + + +
+   + + +

+get the skinWeights used by the mrm mesh. NB: same size of the vertexBuffer. empty if !isSkinned() +

+ +

+Definition at line 179 of file mesh_mrm.h. +

+References _SkinWeights. +

+

00179 {return _SkinWeights;}
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
bool NL3D::CMeshMRMGeom::getVBHeapInfo uint vertexFormat,
uint numVertices
[virtual]
+
+ + + + + +
+   + + +

+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 2802 of file mesh_mrm.cpp. +

+References _SupportMeshBlockRendering, _VBufferFinal, NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getVertexFormat(), and uint. +

+

02803 {
+02804         // CMeshMRMGeom support VBHeap rendering, assuming _SupportMeshBlockRendering is true
+02805         vertexFormat= _VBufferFinal.getVertexFormat();
+02806         numVertices= _VBufferFinal.getNumVertices();
+02807         return _SupportMeshBlockRendering;
+02808 }
+
+

+ + + + +
+ + + + + + + + + +
const CVertexBuffer& NL3D::CMeshMRMGeom::getVertexBuffer  )  const [inline]
+
+ + + + + +
+   + + +

+get the vertex buffer used by the mrm mesh. NB: this VB store all Vertices used by All LODs. +

+ +

+Definition at line 176 of file mesh_mrm.h. +

+References _VBufferFinal. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), and NL3D::CMeshMRM::getVertexBuffer(). +

+

00176 { return _VBufferFinal ; }
+
+

+ + + + +
+ + + + + + + + + +
virtual bool NL3D::CMeshMRMGeom::hasMeshVertexProgram  )  const [inline, virtual]
+
+ + + + + +
+   + + +

+True if this mesh has a vertexProgram. +

+ +

+Reimplemented from NL3D::IMeshGeom. +

+Definition at line 287 of file mesh_mrm.h. +

+Referenced by NL3D::CMeshMRMInstance::initRenderFilterType(). +

+

00287 {return _MeshVertexProgram!=NULL;}
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::initInstance CMeshBaseInstance mbi  )  [virtual]
+
+ + + + + +
+   + + +

+Init instance info. +

+ +

+Implements NL3D::IMeshGeom. +

+Definition at line 847 of file mesh_mrm.cpp. +

+Referenced by NL3D::CMeshMRM::createInstance(). +

+

00848 {
+00849         // init the instance with _MeshVertexProgram infos
+00850         if(_MeshVertexProgram)
+00851                 _MeshVertexProgram->initInstance(mbi);
+00852 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CMeshMRMGeom::isActiveInstanceNeedVBFill  )  const [virtual]
+
+ + + + + +
+   + + +

+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 from NL3D::IMeshGeom. +

+Definition at line 2858 of file mesh_mrm.cpp. +

+

02859 {
+02860         // Yes, need it for geomorph
+02861         return true;
+02862 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::IMeshGeom::isMeshInVBHeap  )  const [inline, inherited]
+
+ + + + + +
+   + + +

+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 profileSceneRender(), and NL3D::CMeshGeom::profileSceneRender(). +

+

00215 {return _MeshVBHeapId!=0;}
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CMeshMRMGeom::isSkinned  )  const [inline]
+
+ + + + + +
+   + + +

+Return true if the mesh is skinned, else return false. +

+ +

+Definition at line 231 of file mesh_mrm.h. +

+Referenced by NL3D::CMeshMRMInstance::isSkinnable(). +

+

00232         {
+00233                 return _Skinned;
+00234         }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::load NLMISC::IStream f  )  throw (NLMISC::EStream) [private]
+
+ + + + + +
+   + + +

+load this mesh. +

+ +

+Definition at line 1757 of file mesh_mrm.cpp. +

+References sint, and uint. +

+

01758 {
+01759 
+01760         // because loading, flag the VertexBufferHard.
+01761         _VertexBufferHardDirty= true;
+01762 
+01763 
+01764         // Load the header of the stream.
+01765         // ==================
+01766         sint    verHeader= loadHeader(f);
+01767 
+01768         // Read All lod subsets.
+01769         // ==================
+01770         for(uint i=0;i<_LodInfos.size(); i++)
+01771         {
+01772                 // read the lod face data.
+01773                 f.serial(_Lods[i]);
+01774                 // read the lod vertex data.
+01775                 serialLodVertexData(f, _LodInfos[i].StartAddWedge, _LodInfos[i].EndAddWedges);
+01776                 // if reading, must bkup all original vertices from VB.
+01777                 // this is done in serialLodVertexData(). by subset
+01778         }
+01779 
+01780         // Now, all lods are loaded.
+01781         _NbLodLoaded= _Lods.size();
+01782 
+01783         // If version doen't have boneNames, must build BoneId now.
+01784         if(verHeader <= 2)
+01785         {
+01786                 buildBoneUsageVer2 ();
+01787         }
+01788 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::loadFirstLod NLMISC::IStream f  ) 
+
+ + + + + +
+   + + +

+Load the header and the first lod of a MRM in a stream.

Parameters:
+ + +
f the input stream to read. NB: after load, f.getPos() return the position of the second lod in the stream.
+
+ +

+Definition at line 1951 of file mesh_mrm.cpp. +

+References _LodInfos, _Lods, _NbLodLoaded, buildBoneUsageVer2(), loadHeader(), NLMISC::IStream::serial(), serialLodVertexData(), sint, and uint. +

+

01952 {
+01953 
+01954         // because loading, flag the VertexBufferHard.
+01955         _VertexBufferHardDirty= true;
+01956 
+01957         // Load the header of the stream.
+01958         // ==================
+01959         sint    verHeader= loadHeader(f);
+01960 
+01961 
+01962         // If empty MRM, quit.
+01963         if(_LodInfos.size()==0)
+01964                 return;
+01965 
+01966         /* If the version is <4, then SkinWeights are serialised per Lod.
+01967                 But for computebonesId(), we must have all SkinWeights RIGHT NOW.
+01968                 Hence, if too old version (<4), serialize all the MRM....
+01969         */
+01970         uint    numLodToLoad;
+01971         if(verHeader<4)
+01972                 numLodToLoad= _LodInfos.size();
+01973         else
+01974                 numLodToLoad= 1;
+01975 
+01976 
+01977         // Read lod subset(s).
+01978         // ==================
+01979         for(uint i=0;i<numLodToLoad; i++)
+01980         {
+01981                 // read the lod face data.
+01982                 f.serial(_Lods[i]);
+01983                 // read the lod vertex data.
+01984                 serialLodVertexData(f, _LodInfos[i].StartAddWedge, _LodInfos[i].EndAddWedges);
+01985                 // if reading, must bkup all original vertices from VB.
+01986                 // this is done in serialLodVertexData(). by subset
+01987         }
+01988 
+01989         // Now, just first lod is loaded (but if too old file)
+01990         _NbLodLoaded= numLodToLoad;
+01991 
+01992         // If version doen't have boneNames, must build BoneId now.
+01993         if(verHeader <= 2)
+01994         {
+01995                 buildBoneUsageVer2 ();
+01996         }
+01997 }
+
+

+ + + + +
+ + + + + + + + + + +
sint NL3D::CMeshMRMGeom::loadHeader NLMISC::IStream f  )  throw (NLMISC::EStream) [private]
+
+ + + + + +
+   + + +

+load the header of this mesh. return the version of the header. +

+ +

+Definition at line 1627 of file mesh_mrm.cpp. +

+References NLMISC::IStreamable::serial(), sint, sint32, uint, and uint32. +

+Referenced by loadFirstLod(). +

+

01628 {
+01629         /*
+01630         Version 5:
+01631                 - Shadow Skinning
+01632         Version 4:
+01633                 - serial SkinWeights per MRM, not per Lod
+01634         Version 3:
+01635                 - Bones names.
+01636         Version 2:
+01637                 - Mesh Vertex Program.
+01638         Version 1:
+01639                 - added blend shapes
+01640         Version 0:
+01641                 - base version.
+01642         */
+01643         sint    ver= f.serialVersion(5);
+01644 
+01645 
+01646         // if >= version 3, serial boens names
+01647         if(ver>=3)
+01648         {
+01649                 f.serialCont (_BonesName);
+01650         }
+01651 
+01652         // Version3-: Bones index are in skeleton model id list
+01653         _BoneIdComputed = (ver < 3);
+01654         // Must always recompute usage of parents of bones used.
+01655         _BoneIdExtended = false;
+01656 
+01657         // Mesh Vertex Program.
+01658         if (ver >= 2)
+01659         {
+01660                 IMeshVertexProgram      *mvp= NULL;
+01661                 f.serialPolyPtr(mvp);
+01662                 _MeshVertexProgram= mvp;
+01663         }
+01664         else
+01665         {
+01666                 // release vp
+01667                 _MeshVertexProgram= NULL;
+01668         }
+01669 
+01670         // blend shapes
+01671         if (ver >= 1)
+01672                 f.serial (_MeshMorpher);
+01673 
+01674         // serial Basic info.
+01675         // ==================
+01676         f.serial(_Skinned);
+01677         f.serial(_BBox);
+01678         f.serial(_LevelDetail.MaxFaceUsed);
+01679         f.serial(_LevelDetail.MinFaceUsed);
+01680         f.serial(_LevelDetail.DistanceFinest);
+01681         f.serial(_LevelDetail.DistanceMiddle);
+01682         f.serial(_LevelDetail.DistanceCoarsest);
+01683         f.serial(_LevelDetail.OODistanceDelta);
+01684         f.serial(_LevelDetail.DistancePow);
+01685         // preload the Lods.
+01686         f.serialCont(_LodInfos);
+01687 
+01688         // read/save number of wedges.
+01689         /* NB: prepare memory space too for vertices.
+01690                 \todo yoyo: TODO_OPTIMIZE. for now there is no Lod memory profit with vertices / skinWeights.
+01691                 But resizing arrays is a problem because of reallocation...
+01692         */
+01693         uint32  nWedges;
+01694         f.serial(nWedges);
+01695         // Prepare the VBuffer.
+01696         _VBufferFinal.serialHeader(f);
+01697         // If skinned, must allocate skinWeights.
+01698         contReset(_SkinWeights);
+01699         if(_Skinned)
+01700         {
+01701                 _SkinWeights.resize(nWedges);
+01702         }
+01703 
+01704 
+01705         // If new version, serial SkinWeights in header, not in lods.
+01706         if(ver >= 4)
+01707         {
+01708                 f.serialCont(_SkinWeights);
+01709         }
+01710 
+01711 
+01712         // if >= version 5, serial Shadow Skin Information
+01713         if(ver>=5)
+01714         {
+01715                 f.serialCont (_ShadowSkinVertices);
+01716                 f.serialCont (_ShadowSkinTriangles);
+01717         }
+01718 
+01719 
+01720         // Serial lod offsets.
+01721         // ==================
+01722         // This is the reference pos, to load / save relative offsets.
+01723         sint32                  startPos = f.getPos();
+01724         // Those are the lodOffsets, relative to startPos.
+01725         vector<sint32>  lodOffsets;
+01726         lodOffsets.resize(_LodInfos.size(), 0);
+01727 
+01728         // read all relative offsets, and build the absolute offset of LodInfos.
+01729         for(uint i=0;i<_LodInfos.size(); i++)
+01730         {
+01731                 f.serial(lodOffsets[i]);
+01732                 _LodInfos[i].LodOffset= startPos + lodOffsets[i];
+01733         }
+01734 
+01735 
+01736         // resest the Lod arrays. NB: each Lod is empty, and ready to receive Lod data.
+01737         // ==================
+01738         contReset(_Lods);
+01739         _Lods.resize(_LodInfos.size());
+01740 
+01741         // Flag the fact that no lod is loaded for now.
+01742         _NbLodLoaded= 0;
+01743 
+01744         // Inform that the mesh data has changed
+01745         dirtMeshDataId();
+01746 
+01747 
+01748         // Some runtime not serialized compilation
+01749         compileRunTime();
+01750 
+01751         // return version of the header
+01752         return ver;
+01753 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::loadNextLod NLMISC::IStream f  ) 
+
+ + + + + +
+   + + +

+Load next lod of a stream. use getNbLodLoaded() to know what Lod will be loaded. NB: if getNbLodLoaded() == getNbLod(), no op.

Parameters:
+ + +
f the same input stream passed to loadFirstLod(). NB: after load, f.getPos() is "unedfined" (actually return the position of the next lod in the stream).
+
+ +

+Definition at line 2001 of file mesh_mrm.cpp. +

+References _LodInfos, _Lods, _NbLodLoaded, getNbLod(), getNbLodLoaded(), NLMISC::IStream::seek(), NLMISC::IStream::serial(), and serialLodVertexData(). +

+

02002 {
+02003 
+02004         // because loading, flag the VertexBufferHard.
+02005         _VertexBufferHardDirty= true;
+02006 
+02007         // If all is loaded, quit.
+02008         if(getNbLodLoaded() == getNbLod())
+02009                 return;
+02010 
+02011         // Set pos to good lod.
+02012         f.seek(_LodInfos[_NbLodLoaded].LodOffset, IStream::begin);
+02013 
+02014         // Serial this lod data.
+02015         // read the lod face data.
+02016         f.serial(_Lods[_NbLodLoaded]);
+02017         // read the lod vertex data.
+02018         serialLodVertexData(f, _LodInfos[_NbLodLoaded].StartAddWedge, _LodInfos[_NbLodLoaded].EndAddWedges);
+02019         // if reading, must bkup all original vertices from VB.
+02020         // this is done in serialLodVertexData(). by subset
+02021 
+02022 
+02023         // Inc LodLoaded count.
+02024         _NbLodLoaded++;
+02025 }
+
+

+ + + + +
+ + + + + + + + + + +
NL3D::CMeshMRMGeom::NLMISC_DECLARE_CLASS CMeshMRMGeom   ) 
+
+ + + + + +
+   + + +

+clip this mesh in a driver. true if visible. +

+

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::profileSceneRender CRenderTrav rdrTrav,
CTransformShape trans,
float  polygonCount,
uint32  rdrFlags
[virtual]
+
+ + + + + +
+   + + +

+Scene profile. +

+ +

+Implements NL3D::IMeshGeom. +

+Definition at line 2600 of file mesh_mrm.cpp. +

+References _LevelDetail, _Lods, _VBufferFinal, NL3D::CScene::BenchRes, chooseLod(), NL3D::CMRMLevelDetail::getLevelDetailFromPolyCount(), NL3D::CPrimitiveBlock::getNumTri(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CScene::incrementProfileTriVBFormat(), NL3D::IMeshGeom::isMeshInVBHeap(), NL3D::CMeshMRMGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, NL3D::UScene::CBenchResults::MeshMRMProfileTriVBFormat, NL3D::UScene::CBenchResults::NumMeshMRMRdrBlock, NL3D::UScene::CBenchResults::NumMeshMRMRdrBlockWithVBHeap, NL3D::UScene::CBenchResults::NumMeshMRMRdrNormal, NL3D::UScene::CBenchResults::NumMeshMRMTriRdrBlock, NL3D::UScene::CBenchResults::NumMeshMRMTriRdrBlockWithVBHeap, NL3D::UScene::CBenchResults::NumMeshMRMTriRdrNormal, NL3D::UScene::CBenchResults::NumMeshMRMVBufferHard, NL3D::UScene::CBenchResults::NumMeshMRMVBufferStd, NL3D::CMeshMRMGeom::CRdrPass::PBlock, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CTraversal::Scene, sint, supportMeshBlockRendering(), uint, and uint32. +

+Referenced by NL3D::CMeshMRM::profileSceneRender(). +

+

02601 {
+02602         // get the result of the Load Balancing.
+02603         float   alphaMRM= _LevelDetail.getLevelDetailFromPolyCount(polygonCount);
+02604 
+02605         // choose the lod.
+02606         float   alphaLod;
+02607         sint    numLod= chooseLod(alphaMRM, alphaLod);
+02608 
+02609         // Render the choosen Lod.
+02610         CLod    &lod= _Lods[numLod];
+02611 
+02612         // get the mesh instance.
+02613         CMeshBaseInstance       *mi= safe_cast<CMeshBaseInstance*>(trans);
+02614 
+02615         // Profile all pass.
+02616         uint    triCount= 0;
+02617         for (uint i=0;i<lod.RdrPass.size();i++)
+02618         {
+02619                 CRdrPass        &rdrPass= lod.RdrPass[i];
+02620                 // Profile with the Materials of the MeshInstance.
+02621                 if ( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) ) ||
+02622                          ( (mi->Materials[rdrPass.MaterialId].getBlend() == true) && (rdrFlags & IMeshGeom::RenderTransparentMaterial) ) )
+02623                 {
+02624                         triCount+= rdrPass.PBlock.getNumTri();
+02625                 }
+02626         }
+02627 
+02628         // Profile
+02629         if(triCount)
+02630         {
+02631                 // tri per VBFormat
+02632                 rdrTrav->Scene->incrementProfileTriVBFormat(rdrTrav->Scene->BenchRes.MeshMRMProfileTriVBFormat, 
+02633                         _VBufferFinal.getVertexFormat(), triCount);
+02634 
+02635                 // VBHard
+02636                 if(_VBHard)
+02637                         rdrTrav->Scene->BenchRes.NumMeshMRMVBufferHard++;
+02638                 else
+02639                         rdrTrav->Scene->BenchRes.NumMeshMRMVBufferStd++;
+02640 
+02641                 // rendered in BlockRendering, only if not transparent pass (known it if RenderTransparentMaterial is set)
+02642                 if(supportMeshBlockRendering() && (rdrFlags & IMeshGeom::RenderTransparentMaterial)==0 )
+02643                 {
+02644                         if(isMeshInVBHeap())
+02645                         {
+02646                                 rdrTrav->Scene->BenchRes.NumMeshMRMRdrBlockWithVBHeap++;
+02647                                 rdrTrav->Scene->BenchRes.NumMeshMRMTriRdrBlockWithVBHeap+= triCount;
+02648                         }
+02649                         else
+02650                         {
+02651                                 rdrTrav->Scene->BenchRes.NumMeshMRMRdrBlock++;
+02652                                 rdrTrav->Scene->BenchRes.NumMeshMRMTriRdrBlock+= triCount;
+02653                         }
+02654                 }
+02655                 else
+02656                 {
+02657                         rdrTrav->Scene->BenchRes.NumMeshMRMRdrNormal++;
+02658                         rdrTrav->Scene->BenchRes.NumMeshMRMTriRdrNormal+= triCount;
+02659                 }
+02660         }
+02661 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::render IDriver drv,
CTransformShape trans,
float  polygonCount,
uint32  rdrFlags,
float  globalAlpha
[virtual]
+
+ + + + + +
+   + + +

+render() this mesh in a driver, given an instance and his materials. +

+ +

+Implements NL3D::IMeshGeom. +

+Definition at line 927 of file mesh_mrm.cpp. +

+References _LevelDetail, _Lods, _VBufferFinal, _VBufferOriginal, NL3D::IDriver::activeVertexBuffer(), NL3D::IDriver::activeVertexBufferHard(), applyGeomorph(), NL3D::CMeshMorpher::BlendShapes, NL3D::CTravCameraScene::CamPos, chooseLod(), NL3D::IDriver::forceNormalize(), NL3D::CMeshMRMGeom::CLod::Geomorphs, NL3D::CMeshBaseInstance::getBlendShapeFactors(), NL3D::CMRMLevelDetail::getLevelDetailFromPolyCount(), NL3D::CVertexBuffer::getNumVertices(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), NL3D::CTransform::getSkeletonModel(), NL3D::CTransform::getWorldMatrix(), H_AUTO, NL3D::CMeshMorpher::init(), NL3D::CMeshMorpher::initSkinned(), NLMISC::CMatrix::inverted(), NL3D::IDriver::isForceNormalize(), NL3D::CTransform::isSkinned(), NL3D::CMeshMRMGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, nlassert, NLMISC::OptFastFloor(), NL3D::CMeshMRMGeom::CLod::OriginalSkinRestored, NL3D::CMeshMRMGeom::CRdrPass::PBlock, NL3D::CMeshBlender::prepareRenderForGlobalAlpha(), NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::IDriver::render(), restoreOriginalSkinPart(), NL3D::CMeshBlender::restoreRender(), NL3D::IDriver::setupModelMatrix(), sint, uint, uint32, uint8, NL3D::CMeshMorpher::update(), NL3D::CMeshMorpher::updateSkinned(), and updateVertexBufferHard(). +

+Referenced by NL3D::CMeshMRM::render(). +

+

00928 {
+00929         nlassert(drv);
+00930         if(_Lods.size()==0)
+00931                 return;
+00932 
+00933 
+00934         // get the meshMRM instance.
+00935         CMeshBaseInstance       *mi= safe_cast<CMeshBaseInstance*>(trans);
+00936         // get a ptr on scene
+00937         CScene                          *ownerScene= mi->getOwnerScene();
+00938         // get a ptr on renderTrav
+00939         CRenderTrav                     *renderTrav= &ownerScene->getRenderTrav();
+00940 
+00941 
+00942         // get the result of the Load Balancing.
+00943         float   alphaMRM= _LevelDetail.getLevelDetailFromPolyCount(polygonCount);
+00944 
+00945         // choose the lod.
+00946         float   alphaLod;
+00947         sint    numLod= chooseLod(alphaMRM, alphaLod);
+00948 
+00949 
+00950         // Render the choosen Lod.
+00951         CLod    &lod= _Lods[numLod];
+00952         if(lod.RdrPass.size()==0)
+00953                 return;
+00954 
+00955 
+00956         // Update the vertexBufferHard (if possible).
+00957         // \toto yoyo: TODO_OPTIMIZE: allocate only what is needed for the current Lod (Max of all instances, like
+00958         // the loading....) (see loadHeader()).
+00959         updateVertexBufferHard(drv, _VBufferFinal.getNumVertices());
+00960         /* currentVBHard is NULL if must disable it temporarily
+00961                 For now, never disable it, but switch of VBHard may be VERY EXPENSIVE if NV_vertex_array_range2 is not
+00962                 supported (old drivers).
+00963         */
+00964         IVertexBufferHard               *currentVBHard= _VBHard;
+00965 
+00966 
+00967         // get the skeleton model to which I am binded (else NULL).
+00968         CSkeletonModel *skeleton;
+00969         skeleton = mi->getSkeletonModel();
+00970         // The mesh must not be skinned for render()
+00971         nlassert(!(_Skinned && mi->isSkinned() && skeleton));
+00972         bool bMorphApplied = _MeshMorpher.BlendShapes.size() > 0;
+00973         bool useTangentSpace = _MeshVertexProgram && _MeshVertexProgram->needTangentSpace();
+00974 
+00975 
+00976         // Profiling
+00977         //===========
+00978         H_AUTO( NL3D_MeshMRMGeom_RenderNormal );
+00979 
+00980 
+00981         // Morphing
+00982         // ========
+00983         if (bMorphApplied)
+00984         {
+00985                 // If _Skinned (NB: the skin is not applied) and if lod.OriginalSkinRestored, then restoreOriginalSkinPart is
+00986                 // not called but mush morpher write changed vertices into VBHard so its ok. The unchanged vertices
+00987                 // are written in the preceding call to restoreOriginalSkinPart.
+00988                 if (_Skinned)
+00989                 {
+00990                         _MeshMorpher.initSkinned(&_VBufferOriginal,
+00991                                                                  &_VBufferFinal,
+00992                                                                  currentVBHard,
+00993                                                                  useTangentSpace,
+00994                                                                  &_OriginalSkinVertices,
+00995                                                                  &_OriginalSkinNormals,
+00996                                                                  useTangentSpace ? &_OriginalTGSpace : NULL,
+00997                                                                  false );
+00998                         _MeshMorpher.updateSkinned (mi->getBlendShapeFactors());
+00999                 }
+01000                 else // Not even skinned so we have to do all the stuff
+01001                 {
+01002                         _MeshMorpher.init(&_VBufferOriginal,
+01003                                                                  &_VBufferFinal,
+01004                                                                  currentVBHard,
+01005                                                                  useTangentSpace);
+01006                         _MeshMorpher.update (mi->getBlendShapeFactors());
+01007                 }
+01008         }
+01009 
+01010         // Skinning.
+01011         //===========
+01012         // if mesh is skinned (but here skin not applied), we must copy vertices/normals from original vertices.
+01013         if (_Skinned)
+01014         {
+01015                 // do it for this Lod only, and if cache say it is necessary.
+01016                 if (!lod.OriginalSkinRestored)
+01017                         restoreOriginalSkinPart(lod, currentVBHard);
+01018         }
+01019 
+01020 
+01021         // set the instance worldmatrix.
+01022         drv->setupModelMatrix(trans->getWorldMatrix());
+01023 
+01024 
+01025         // Geomorph.
+01026         //===========
+01027         // Geomorph the choosen Lod (if not the coarser mesh).
+01028         if(numLod>0)
+01029         {
+01030                 applyGeomorph(lod.Geomorphs, alphaLod, currentVBHard);
+01031         }
+01032 
+01033 
+01034         // force normalisation of normals..
+01035         bool    bkupNorm= drv->isForceNormalize();
+01036         drv->forceNormalize(true);                      
+01037 
+01038 
+01039         // Setup meshVertexProgram
+01040         //===========
+01041 
+01042         // use MeshVertexProgram effect?
+01043         bool    useMeshVP= _MeshVertexProgram != NULL;
+01044         if( useMeshVP )
+01045         {
+01046                 CMatrix         invertedObjectMatrix;
+01047                 invertedObjectMatrix = trans->getWorldMatrix().inverted();
+01048                 // really ok if success to begin VP
+01049                 useMeshVP= _MeshVertexProgram->begin(drv, mi->getOwnerScene(), mi, invertedObjectMatrix, renderTrav->CamPos);
+01050         }
+01051         
+01052 
+01053         // Render the lod.
+01054         //===========
+01055         // active VB.
+01056         if(currentVBHard)
+01057                 drv->activeVertexBufferHard(currentVBHard);
+01058         else
+01059                 drv->activeVertexBuffer(_VBufferFinal);
+01060 
+01061 
+01062         // Global alpha used ?
+01063         uint32  globalAlphaUsed= rdrFlags & IMeshGeom::RenderGlobalAlpha;
+01064         uint8   globalAlphaInt=(uint8)NLMISC::OptFastFloor(globalAlpha*255);
+01065 
+01066         // Render all pass.
+01067         if (globalAlphaUsed)
+01068         {
+01069                 bool    gaDisableZWrite= (rdrFlags & IMeshGeom::RenderGADisableZWrite)?true:false;
+01070 
+01071                 // for all passes
+01072                 for(uint i=0;i<lod.RdrPass.size();i++)
+01073                 {
+01074                         CRdrPass        &rdrPass= lod.RdrPass[i];
+01075 
+01076                         if ( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) ) ||
+01077                                  ( (mi->Materials[rdrPass.MaterialId].getBlend() == true) && (rdrFlags & IMeshGeom::RenderTransparentMaterial) ) )
+01078                         {
+01079                                 // CMaterial Ref
+01080                                 CMaterial &material=mi->Materials[rdrPass.MaterialId];
+01081 
+01082                                 // Use a MeshBlender to modify material and driver.
+01083                                 CMeshBlender    blender;
+01084                                 blender.prepareRenderForGlobalAlpha(material, drv, globalAlpha, globalAlphaInt, gaDisableZWrite);
+01085 
+01086                                 // Setup VP material
+01087                                 if (useMeshVP)
+01088                                 {
+01089                                         if(currentVBHard)
+01090                                                 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, currentVBHard);
+01091                                         else
+01092                                                 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, &_VBufferFinal);
+01093                                 }
+01094 
+01095                                 // Render
+01096                                 drv->render(rdrPass.PBlock, material);
+01097 
+01098                                 // Resetup material/driver
+01099                                 blender.restoreRender(material, drv, gaDisableZWrite);
+01100                         }
+01101                 }
+01102         }
+01103         else
+01104         {
+01105                 for(uint i=0;i<lod.RdrPass.size();i++)
+01106                 {
+01107                         CRdrPass        &rdrPass= lod.RdrPass[i];
+01108 
+01109                         if ( ( (mi->Materials[rdrPass.MaterialId].getBlend() == false) && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) ) ||
+01110                                  ( (mi->Materials[rdrPass.MaterialId].getBlend() == true) && (rdrFlags & IMeshGeom::RenderTransparentMaterial) ) )
+01111                         {
+01112                                 // CMaterial Ref
+01113                                 CMaterial &material=mi->Materials[rdrPass.MaterialId];
+01114 
+01115                                 // Setup VP material
+01116                                 if (useMeshVP)
+01117                                 {
+01118                                         if(currentVBHard)
+01119                                                 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, currentVBHard);
+01120                                         else
+01121                                                 _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, &_VBufferFinal);
+01122                                 }       
+01123 
+01124                                 // Render with the Materials of the MeshInstance.
+01125                                 drv->render(rdrPass.PBlock, material);
+01126                         }
+01127                 }
+01128         }
+01129 
+01130 
+01131         // End VertexProgram effect
+01132         if(useMeshVP)
+01133         {
+01134                 // end it.
+01135                 _MeshVertexProgram->end(drv);
+01136         }
+01137 
+01138 
+01139         // bkup force normalisation.
+01140         drv->forceNormalize(bkupNorm);
+01141 
+01142 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::renderPass CMeshGeomRenderContext rdrCtx,
CMeshBaseInstance inst,
float  polygonCount,
uint  rdrPass
[virtual]
+
+ + + + + +
+   + + +

+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 2768 of file mesh_mrm.cpp. +

+References _Lods, _MBRCurrentLodId, NL3D::CMeshGeomRenderContext::Driver, NL3D::CMeshMRMGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, NL3D::CMeshMRMGeom::CRdrPass::PBlock, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::IDriver::render(), NL3D::CMeshGeomRenderContext::RenderThroughVBHeap, uint, and NL3D::CMeshMRMGeom::CRdrPass::VBHeapPBlock. +

+

02769 {
+02770         if(_Lods.empty())
+02771                 return;
+02772 
+02773         CLod            &lod= _Lods[_MBRCurrentLodId];
+02774         CRdrPass        &rdrPass= lod.RdrPass[rdrPassId];
+02775 
+02776         if ( mi->Materials[rdrPass.MaterialId].getBlend() == false )
+02777         {
+02778                 // CMaterial Ref
+02779                 CMaterial &material=mi->Materials[rdrPass.MaterialId];
+02780 
+02781                 // Render with the Materials of the MeshInstance.
+02782                 if(rdrCtx.RenderThroughVBHeap)
+02783                         // render shifted primitives
+02784                         rdrCtx.Driver->render(rdrPass.VBHeapPBlock, material);
+02785                 else
+02786                         rdrCtx.Driver->render(rdrPass.PBlock, material);
+02787         }
+02788 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
sint NL3D::CMeshMRMGeom::renderShadowSkinGeom CMeshMRMInstance mi,
uint  remainingVertices,
uint8 vbDest
+
+ + + + + +
+   + + +

+Get the num of shadow skin vertices. +

+ +

+Definition at line 3376 of file mesh_mrm.cpp. +

+References _ShadowSkinVertices, applyArrayShadowSkin(), NL3D::CTransform::getSkeletonModel(), H_AUTO_USE, nlassert, sint, uint, and uint8. +

+Referenced by NL3D::CMeshMRMInstance::renderShadowSkinGeom(). +

+

03377 {
+03378         uint    numVerts= _ShadowSkinVertices.size();
+03379 
+03380         if(numVerts==0)
+03381                 return 0;
+03382 
+03383         // If the Lod is too big to render in the VBufferHard
+03384         if(numVerts>remainingVertices)
+03385                 // return Failure
+03386                 return -1;
+03387 
+03388         // get the skeleton model to which I am skinned
+03389         CSkeletonModel *skeleton;
+03390         skeleton = mi->getSkeletonModel();
+03391         // must be skinned for renderSkin()
+03392         nlassert(skeleton);
+03393 
+03394 
+03395         // Profiling
+03396         //===========
+03397         H_AUTO_USE( NL3D_MeshMRMGeom_RenderShadow );
+03398 
+03399 
+03400         // Skinning.
+03401         //===========
+03402 
+03403         // skinning with normal, but no tangent space
+03404         applyArrayShadowSkin(&_ShadowSkinVertices[0], (CVector*)vbDest, skeleton, numVerts);
+03405 
+03406 
+03407         // How many vertices are added to the VBuffer ???
+03408         return numVerts;
+03409 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::renderShadowSkinPrimitives CMeshMRMInstance mi,
CMaterial castMat,
IDriver drv,
uint  baseVertex
+
+ + + + + +
+   + + +

+Get the num of shadow skin vertices. +

+ +

+Definition at line 3412 of file mesh_mrm.cpp. +

+References _ShadowSkinTriangles, H_AUTO_USE, min, nlassert, NL3D::IDriver::renderTriangles(), src, uint, and uint32. +

+Referenced by NL3D::CMeshMRMInstance::renderShadowSkinPrimitives(). +

+

03413 {
+03414         nlassert(drv);
+03415 
+03416         if(_ShadowSkinTriangles.empty())
+03417                 return;
+03418 
+03419         // Profiling
+03420         //===========
+03421         H_AUTO_USE( NL3D_MeshMRMGeom_RenderShadow );
+03422 
+03423         // NB: the skeleton matrix has already been setuped by CSkeletonModel
+03424         // NB: the normalize flag has already been setuped by CSkeletonModel
+03425 
+03426         // TODO_SHADOW: optim: Special triangle cache for shadow!
+03427         static  vector<uint32>          shiftedTris;
+03428         if(shiftedTris.size()<_ShadowSkinTriangles.size())
+03429         {
+03430                 shiftedTris.resize(_ShadowSkinTriangles.size());
+03431         }
+03432         uint32  *src= &_ShadowSkinTriangles[0];
+03433         uint32  *dst= &shiftedTris[0];
+03434         for(uint n= _ShadowSkinTriangles.size();n>0;n--, src++, dst++)
+03435         {
+03436                 *dst= *src + baseVertex;
+03437         }
+03438 
+03439         // Render Triangles with cache
+03440         //===========
+03441 
+03442         uint    numTris= _ShadowSkinTriangles.size()/3;
+03443 
+03444         // This speed up 4 ms for 80K polys.
+03445         uint    memToCache= numTris*12;
+03446         memToCache= min(memToCache, 4096U);
+03447         CFastMem::precache(&shiftedTris[0], memToCache);
+03448 
+03449         // Render with the Materials of the MeshInstance.
+03450         drv->renderTriangles(castMat, &shiftedTris[0], numTris);
+03451 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::renderSkin CTransformShape trans,
float  alphaMRM
[virtual]
+
+ + + + + +
+   + + +

+render() this mesh as a skin +

+ +

+Implements NL3D::IMeshGeom. +

+Definition at line 1146 of file mesh_mrm.cpp. +

+References _Lods, _VBufferFinal, _VBufferOriginal, NL3D::IDriver::activeVertexBuffer(), applyGeomorph(), applySkin(), applySkinWithNormal(), applySkinWithTangentSpace(), NL3D::CMeshMorpher::BlendShapes, NL3D::CTravCameraScene::CamPos, chooseLod(), NL3D::CMeshMRMGeom::CLod::Geomorphs, NL3D::CMeshBaseInstance::getBlendShapeFactors(), NL3D::CRenderTrav::getDriver(), NL3D::CVertexBuffer::getNumTexCoordUsed(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), NL3D::CTransform::getSkeletonModel(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CTransform::getWorldMatrix(), H_AUTO, NL3D::CMeshMorpher::initSkinned(), NLMISC::CMatrix::inverted(), NL3D::CTransform::isSkinned(), NL3D::CMeshMRMGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, nlassert, NL3D::CMeshMRMGeom::CLod::OriginalSkinRestored, NL3D::CMeshMRMGeom::CRdrPass::PBlock, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::IDriver::render(), sint, uint, updateRawSkinNormal(), and NL3D::CMeshMorpher::updateSkinned(). +

+Referenced by NL3D::CMeshMRMInstance::renderSkin(). +

+

01147 {
+01148         H_AUTO( NL3D_MeshMRMGeom_renderSkin );
+01149         
+01150         if(_Lods.size()==0)
+01151                 return;
+01152 
+01153 
+01154         // get the meshMRM instance. only CMeshMRMInstance is possible when skinned (not MultiLod)
+01155         CMeshMRMInstance        *mi= safe_cast<CMeshMRMInstance*>(trans);
+01156         // get a ptr on scene
+01157         CScene                          *ownerScene= mi->getOwnerScene();
+01158         // get a ptr on renderTrav
+01159         CRenderTrav                     *renderTrav= &ownerScene->getRenderTrav();
+01160         // get a ptr on the driver
+01161         IDriver                         *drv= renderTrav->getDriver();
+01162         nlassert(drv);
+01163 
+01164 
+01165         // choose the lod.
+01166         float   alphaLod;
+01167         sint    numLod= chooseLod(alphaMRM, alphaLod);
+01168 
+01169 
+01170         // Render the choosen Lod.
+01171         CLod    &lod= _Lods[numLod];
+01172         if(lod.RdrPass.size()==0)
+01173                 return;
+01174 
+01175 
+01176         /*
+01177                 YOYO: renderSkin() no more support vertexBufferHard()!!! for AGP Memory optimisation concern.
+01178                 AGP Skin rendering is made when supportSkinGrouping() is true
+01179                 Hence if a skin is to be rendered here, because it doesn't have a good vertex format, or it has
+01180                 MeshVertexProgram etc..., it will be rendered WITHOUT VBHard => slower.
+01181         */
+01182 
+01183 
+01184         // get the skeleton model to which I am skinned
+01185         CSkeletonModel *skeleton;
+01186         skeleton = mi->getSkeletonModel();
+01187         // must be skinned for renderSkin()
+01188         nlassert(_Skinned && mi->isSkinned() && skeleton);
+01189         bool bMorphApplied = _MeshMorpher.BlendShapes.size() > 0;
+01190         bool useNormal= (_VBufferFinal.getVertexFormat() & CVertexBuffer::NormalFlag)!=0;
+01191         bool useTangentSpace = _MeshVertexProgram && _MeshVertexProgram->needTangentSpace();
+01192 
+01193 
+01194         // Profiling
+01195         //===========
+01196         H_AUTO( NL3D_MeshMRMGeom_renderSkin_go );
+01197 
+01198 
+01199         // Morphing
+01200         // ========
+01201         if (bMorphApplied)
+01202         {
+01203                 // Since Skinned we must update original skin vertices and normals because skinning use it
+01204                 _MeshMorpher.initSkinned(&_VBufferOriginal,
+01205                                                          &_VBufferFinal,
+01206                                                          NULL,
+01207                                                          useTangentSpace,
+01208                                                          &_OriginalSkinVertices,
+01209                                                          &_OriginalSkinNormals,
+01210                                                          useTangentSpace ? &_OriginalTGSpace : NULL,
+01211                                                          true );
+01212                 _MeshMorpher.updateSkinned (mi->getBlendShapeFactors());
+01213         }
+01214 
+01215         // Skinning.
+01216         //===========
+01217 
+01218         // Never use RawSkin. Actually used in skinGrouping.
+01219         updateRawSkinNormal(false, mi, numLod);
+01220 
+01221         // applySkin.
+01222         //--------
+01223 
+01224         // If skin without normal (rare/usefull?) always simple (slow) case.
+01225         if(!useNormal)
+01226         {
+01227                 // skinning with just position
+01228                 applySkin (lod, skeleton);
+01229         }
+01230         else
+01231         {
+01232                 // apply skin for this Lod only.
+01233                 if (!useTangentSpace)
+01234                 {
+01235                         // skinning with normal, but no tangent space
+01236                         applySkinWithNormal (lod, skeleton);
+01237                 }
+01238                 else
+01239                 {
+01240                         // Tangent space stored in the last texture coordinate
+01241                         applySkinWithTangentSpace(lod, skeleton, _VBufferFinal.getNumTexCoordUsed() - 1);
+01242                 }
+01243         }
+01244 
+01245         // endSkin.
+01246         //--------
+01247         // dirt this lod part. (NB: this is not optimal, but sufficient :) ).
+01248         lod.OriginalSkinRestored= false;
+01249 
+01250 
+01251         // NB: the skeleton matrix has already been setuped by CSkeletonModel
+01252         // NB: the normalize flag has already been setuped by CSkeletonModel
+01253 
+01254 
+01255         // Geomorph.
+01256         //===========
+01257         // Geomorph the choosen Lod (if not the coarser mesh).
+01258         if(numLod>0)
+01259         {
+01260                 applyGeomorph(lod.Geomorphs, alphaLod, NULL);
+01261         }
+01262 
+01263 
+01264         // Setup meshVertexProgram
+01265         //===========
+01266 
+01267         // use MeshVertexProgram effect?
+01268         bool    useMeshVP= _MeshVertexProgram != NULL;
+01269         if( useMeshVP )
+01270         {
+01271                 CMatrix         invertedObjectMatrix;
+01272                 invertedObjectMatrix = skeleton->getWorldMatrix().inverted();
+01273                 // really ok if success to begin VP
+01274                 useMeshVP= _MeshVertexProgram->begin(drv, mi->getOwnerScene(), mi, invertedObjectMatrix, renderTrav->CamPos);
+01275         }
+01276         
+01277 
+01278         // Render the lod.
+01279         //===========
+01280         // active VB.
+01281         drv->activeVertexBuffer(_VBufferFinal);
+01282 
+01283 
+01284         // Render all pass.
+01285         for(uint i=0;i<lod.RdrPass.size();i++)
+01286         {
+01287                 CRdrPass        &rdrPass= lod.RdrPass[i];
+01288 
+01289                 // CMaterial Ref
+01290                 CMaterial &material=mi->Materials[rdrPass.MaterialId];
+01291 
+01292                 // Setup VP material
+01293                 if (useMeshVP)
+01294                 {
+01295                         _MeshVertexProgram->setupForMaterial(material, drv, ownerScene, &_VBufferFinal);
+01296                 }
+01297 
+01298                 // Render with the Materials of the MeshInstance.
+01299                 drv->render(rdrPass.PBlock, material);
+01300         }
+01301 
+01302         // End VertexProgram effect
+01303         if(useMeshVP)
+01304         {
+01305                 // end it.
+01306                 _MeshVertexProgram->end(drv);
+01307         }
+01308 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
sint NL3D::CMeshMRMGeom::renderSkinGroupGeom CMeshMRMInstance mi,
float  alphaMRM,
uint  remainingVertices,
uint8 vbDest
+
+ + + + + +
+   + + +

+ +

+Definition at line 1318 of file mesh_mrm.cpp. +

+References _LastLodComputed, _Lods, NL3D::CMeshMRMInstance::_RawSkinCache, _VBufferFinal, applyRawSkinWithNormal(), NL3D::CMeshMorpher::BlendShapes, chooseLod(), NL3D::CRawSkinNormalCache::Geomorphs, NL3D::CMeshBaseInstance::getBlendShapeFactors(), NL3D::CRenderTrav::getDriver(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), NL3D::CTransform::getSkeletonModel(), NL3D::CVertexBuffer::getVertexFormat(), H_AUTO, NL3D::CTransform::isSkinned(), nlassert, NL3D::CMeshMRMGeom::CLod::NWedges, NL3D::CMeshMRMGeom::CLod::RdrPass, sint, NL3D::CRawSkinNormalCache::TotalHardVertices, NL3D::CRawSkinNormalCache::TotalSoftVertices, uint, uint8, NL3D::CMeshMorpher::updateRawSkin(), updateRawSkinNormal(), and NL3D::CRawSkinNormalCache::VertexRemap. +

+Referenced by NL3D::CMeshMRMInstance::renderSkinGroupGeom(). +

+

01319 {
+01320         H_AUTO( NL3D_MeshMRMGeom_rdrSkinGrpGeom )
+01321 
+01322         // get a ptr on scene
+01323         CScene                          *ownerScene= mi->getOwnerScene();
+01324         // get a ptr on renderTrav
+01325         CRenderTrav                     *renderTrav= &ownerScene->getRenderTrav();
+01326         // get a ptr on the driver
+01327         IDriver                         *drv= renderTrav->getDriver();
+01328         nlassert(drv);
+01329 
+01330 
+01331         // choose the lod.
+01332         float   alphaLod;
+01333         sint    numLod= chooseLod(alphaMRM, alphaLod);
+01334         _LastLodComputed= numLod;
+01335 
+01336 
+01337         // Render the choosen Lod.
+01338         CLod    &lod= _Lods[numLod];
+01339         if(lod.RdrPass.size()==0)
+01340                 // return no vertices added
+01341                 return 0;
+01342 
+01343         // If the Lod is too big to render in the VBufferHard
+01344         if(lod.NWedges>remainingVertices)
+01345                 // return Failure
+01346                 return -1;
+01347 
+01348         // get the skeleton model to which I am skinned
+01349         CSkeletonModel *skeleton;
+01350         skeleton = mi->getSkeletonModel();
+01351         // must be skinned for renderSkin()
+01352         nlassert(_Skinned && mi->isSkinned() && skeleton);
+01353         bool bMorphApplied = _MeshMorpher.BlendShapes.size() > 0;
+01354         bool useNormal= (_VBufferFinal.getVertexFormat() & CVertexBuffer::NormalFlag)!=0;
+01355         nlassert(useNormal);
+01356 
+01357 
+01358         // Profiling
+01359         //===========
+01360         H_AUTO( NL3D_MeshMRMGeom_rdrSkinGrpGeom_go );
+01361 
+01362 
+01363         // Morphing
+01364         // ========
+01365 
+01366         // Use RawSkin?. compute before morphing, cause of updateRawSkin
+01367         updateRawSkinNormal(true, mi, numLod);
+01368         nlassert(mi->_RawSkinCache);
+01369         
+01370         // Apply morph
+01371         if (bMorphApplied)
+01372         {
+01373                 // No need to manage lod.OriginalSkinRestored, since in case of SkinGroupGeom, the VBuffer final is not modified.
+01374                 
+01375                 // copy directly from the original VB, and apply BlendShapes. Dest is directly the RawSkin
+01376                 _MeshMorpher.updateRawSkin(&_VBufferFinal, 
+01377                                                                         mi->_RawSkinCache->VertexRemap, 
+01378                                                                         mi->getBlendShapeFactors());
+01379         }
+01380 
+01381         // Skinning.
+01382         //===========
+01383 
+01384         // NB: the skeleton matrix has already been setuped by CSkeletonModel
+01385         // NB: the normalize flag has already been setuped by CSkeletonModel
+01386 
+01387         // applySkin with RawSkin.
+01388         //--------
+01389         // always RawSkin now in SkinGrouping, even with MeshMorpher
+01390         {
+01391                 H_AUTO( NL3D_RawSkinning );
+01392                 
+01393                 // RawSkin do all the job in optimized way: Skinning, copy to VBHard and Geomorph.
+01394 
+01395                 // skinning with normal, but no tangent space
+01396                 applyRawSkinWithNormal (lod, *(mi->_RawSkinCache), skeleton, vbDest, alphaLod);
+01397 
+01398                 // Vertices are packed in RawSkin mode (ie no holes due to MRM!)
+01399                 return  mi->_RawSkinCache->Geomorphs.size() + 
+01400                                 mi->_RawSkinCache->TotalSoftVertices + 
+01401                                 mi->_RawSkinCache->TotalHardVertices;
+01402         }
+01403 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::renderSkinGroupPrimitives CMeshMRMInstance mi,
uint  baseVertex,
std::vector< CSkinSpecularRdrPass > &  specularRdrPasses,
uint  skinIndex
+
+ + + + + +
+   + + +

+ +

+Definition at line 1406 of file mesh_mrm.cpp. +

+References _LastLodComputed, _Lods, NL3D::CMeshMRMInstance::_ShiftedTriangleCache, NL3D::CRenderTrav::getDriver(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), NL3D::CMaterial::getShader(), NL3D::CMaterial::getTexture(), NL3D::IDriver::getTextureHandle(), H_AUTO, NL3D::CMeshMRMGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, min, nlassert, NL3D::CShiftedTriangleCache::CRdrPass::NumTriangles, NL3D::CShiftedTriangleCache::RdrPass, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CSkinSpecularRdrPass::RdrPassIndex, NL3D::IDriver::renderTriangles(), NL3D::CSkinSpecularRdrPass::SkinIndex, NL3D::CSkinSpecularRdrPass::SpecId, NL3D::CShiftedTriangleCache::CRdrPass::Triangles, uint, and updateShiftedTriangleCache(). +

+Referenced by NL3D::CMeshMRMInstance::renderSkinGroupPrimitives(). +

+

01407 {
+01408         H_AUTO( NL3D_MeshMRMGeom_rdrSkinGrpPrimitives );
+01409         
+01410         // get a ptr on scene
+01411         CScene                          *ownerScene= mi->getOwnerScene();
+01412         // get a ptr on renderTrav
+01413         CRenderTrav                     *renderTrav= &ownerScene->getRenderTrav();
+01414         // get a ptr on the driver
+01415         IDriver                         *drv= renderTrav->getDriver();
+01416         nlassert(drv);
+01417 
+01418         // Get the lod choosen in renderSkinGroupGeom()
+01419         CLod    &lod= _Lods[_LastLodComputed];
+01420 
+01421 
+01422         // must update primitive cache
+01423         updateShiftedTriangleCache(mi, _LastLodComputed, baseVertex);
+01424         nlassert(mi->_ShiftedTriangleCache);
+01425 
+01426 
+01427         // Render Triangles with cache
+01428         //===========
+01429         for(uint i=0;i<lod.RdrPass.size();i++)
+01430         {
+01431                 CRdrPass        &rdrPass= lod.RdrPass[i];
+01432 
+01433                 // CMaterial Ref
+01434                 CMaterial &material=mi->Materials[rdrPass.MaterialId];
+01435 
+01436                 // TestYoyo. Material Speed Test
+01437                 /*if( material.getDiffuse()!=CRGBA(250, 251, 252) )
+01438                 {
+01439                         material.setDiffuse(CRGBA(250, 251, 252));
+01440                         // Set all texture the same.
+01441                         static CSmartPtr<ITexture>      pTexFile= new CTextureFile("fy_hom_visage_c1_fy_e1.tga");
+01442                         material.setTexture(0, pTexFile );
+01443                         // Remove Specular.
+01444                         if(material.getShader()==CMaterial::Specular)
+01445                         {
+01446                                 CSmartPtr<ITexture>     tex= material.getTexture(0);
+01447                                 material.setShader(CMaterial::Normal);
+01448                                 material.setTexture(0, tex );
+01449                         }
+01450                         // Remove MakeUp
+01451                         material.setTexture(1, NULL);
+01452                 }*/
+01453 
+01454                 // If the material is a specular material, don't render it now!
+01455                 if(material.getShader()==CMaterial::Specular)
+01456                 {
+01457                         // Add it to the rdrPass to sort!
+01458                         CSkinSpecularRdrPass    specRdrPass;
+01459                         specRdrPass.SkinIndex= skinIndex;
+01460                         specRdrPass.RdrPassIndex= i;
+01461                         // Get the handle of the specular Map as the sort Key
+01462                         ITexture        *specTex= material.getTexture(1);
+01463                         if(!specTex)
+01464                                 specRdrPass.SpecId= 0;
+01465                         else
+01466                                 specRdrPass.SpecId= drv->getTextureHandle( *specTex );
+01467                         // Append it to the list
+01468                         specularRdrPasses.push_back(specRdrPass);
+01469                 }
+01470                 else
+01471                 {
+01472                         // Get the shifted triangles.
+01473                         CShiftedTriangleCache::CRdrPass         &shiftedRdrPass= mi->_ShiftedTriangleCache->RdrPass[i];
+01474 
+01475                         // This speed up 4 ms for 80K polys.
+01476                         uint    memToCache= shiftedRdrPass.NumTriangles*12;
+01477                         memToCache= min(memToCache, 4096U);
+01478                         CFastMem::precache(shiftedRdrPass.Triangles, memToCache);
+01479 
+01480                         // Render with the Materials of the MeshInstance.
+01481                         drv->renderTriangles(material, shiftedRdrPass.Triangles, shiftedRdrPass.NumTriangles);
+01482                 }
+01483         }
+01484 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::renderSkinGroupSpecularRdrPass CMeshMRMInstance mi,
uint  rdrPassId
+
+ + + + + +
+   + + +

+ +

+Definition at line 1488 of file mesh_mrm.cpp. +

+References _LastLodComputed, _Lods, NL3D::CMeshMRMInstance::_ShiftedTriangleCache, NL3D::CRenderTrav::getDriver(), NL3D::CTransform::getOwnerScene(), NL3D::CScene::getRenderTrav(), H_AUTO, NL3D::CMeshMRMGeom::CRdrPass::MaterialId, NL3D::CMeshBaseInstance::Materials, min, nlassert, NL3D::CShiftedTriangleCache::CRdrPass::NumTriangles, NL3D::CShiftedTriangleCache::RdrPass, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::IDriver::renderTriangles(), NL3D::CShiftedTriangleCache::CRdrPass::Triangles, and uint. +

+Referenced by NL3D::CMeshMRMInstance::renderSkinGroupSpecularRdrPass(). +

+

01489 {
+01490         H_AUTO( NL3D_MeshMRMGeom_rdrSkinGrpSpecularRdrPass );
+01491         
+01492         // get a ptr on scene
+01493         CScene                          *ownerScene= mi->getOwnerScene();
+01494         // get a ptr on renderTrav
+01495         CRenderTrav                     *renderTrav= &ownerScene->getRenderTrav();
+01496         // get a ptr on the driver
+01497         IDriver                         *drv= renderTrav->getDriver();
+01498         nlassert(drv);
+01499 
+01500         // Get the lod choosen in renderSkinGroupGeom()
+01501         CLod    &lod= _Lods[_LastLodComputed];
+01502 
+01503 
+01504         // _ShiftedTriangleCache must have been computed in renderSkinGroupPrimitives
+01505         nlassert(mi->_ShiftedTriangleCache);
+01506 
+01507 
+01508         // Render Triangles with cache
+01509         //===========
+01510         CRdrPass        &rdrPass= lod.RdrPass[rdrPassId];
+01511 
+01512         // CMaterial Ref
+01513         CMaterial &material=mi->Materials[rdrPass.MaterialId];
+01514 
+01515         // Get the shifted triangles.
+01516         CShiftedTriangleCache::CRdrPass         &shiftedRdrPass= mi->_ShiftedTriangleCache->RdrPass[rdrPassId];
+01517 
+01518         // This speed up 4 ms for 80K polys.
+01519         uint    memToCache= shiftedRdrPass.NumTriangles*12;
+01520         memToCache= min(memToCache, 4096U);
+01521         CFastMem::precache(shiftedRdrPass.Triangles, memToCache);
+01522 
+01523         // Render with the Materials of the MeshInstance.
+01524         drv->renderTriangles(material, shiftedRdrPass.Triangles, shiftedRdrPass.NumTriangles);
+01525 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::restoreOriginalSkinPart CLod lod,
IVertexBufferHard currentVBHard
[private]
+
+ + + + + +
+   + + +

+Skinning: same as restoreOriginalSkinVertices(), but for one Lod only. +

+ +

+Definition at line 2131 of file mesh_mrm.cpp. +

+References _VBufferFinal, NL3D::CVertexBuffer::getNormalOff(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), NL3D::CVertexBuffer::getVertexSize(), index, NL3D::CMeshMRMGeom::CLod::InfluencedVertices, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NL3D::CMeshMRMGeom::CLod::OriginalSkinRestored, sint32, uint, uint32, and uint8. +

+Referenced by render(). +

+

02132 {
+02133         nlassert(_Skinned);
+02134 
+02135 
+02136         /*
+02137                 YOYO: _Skinned mrms no more support vertexBufferHard
+02138                 see note in renderSkin()
+02139         */
+02140 
+02141         // get vertexPtr / normalOff.
+02142         //===========================
+02143         uint8           *destVertexPtr= (uint8*)_VBufferFinal.getVertexCoordPointer();
+02144         uint            flags= _VBufferFinal.getVertexFormat();
+02145         sint32          vertexSize= _VBufferFinal.getVertexSize();
+02146         // must have XYZ.
+02147         nlassert(flags & CVertexBuffer::PositionFlag);
+02148 
+02149         // Compute offset of each component of the VB.
+02150         sint32          normalOff;
+02151         if(flags & CVertexBuffer::NormalFlag)
+02152                 normalOff= _VBufferFinal.getNormalOff();
+02153         else
+02154                 normalOff= 0;
+02155 
+02156 
+02157         // compute src array.
+02158         CVector                         *srcVertexPtr;
+02159         CVector                         *srcNormalPtr= NULL;
+02160         srcVertexPtr= &_OriginalSkinVertices[0];
+02161         if(normalOff)
+02162                 srcNormalPtr= &(_OriginalSkinNormals[0]);
+02163 
+02164 
+02165         // copy skinning.
+02166         //===========================
+02167         for(uint i=0;i<NL3D_MESH_SKINNING_MAX_MATRIX;i++)
+02168         {
+02169                 uint            nInf= lod.InfluencedVertices[i].size();
+02170                 if( nInf==0 )
+02171                         continue;
+02172                 uint32          *infPtr= &(lod.InfluencedVertices[i][0]);
+02173 
+02174                 //  for all InfluencedVertices only.
+02175                 for(;nInf>0;nInf--, infPtr++)
+02176                 {
+02177                         uint    index= *infPtr;
+02178                         CVector                         *srcVertex= srcVertexPtr + index;
+02179                         CVector                         *srcNormal= srcNormalPtr + index;
+02180                         uint8                           *dstVertexVB= destVertexPtr + index * vertexSize;
+02181                         CVector                         *dstVertex= (CVector*)(dstVertexVB);
+02182                         CVector                         *dstNormal= (CVector*)(dstVertexVB + normalOff);
+02183 
+02184 
+02185                         // Vertex.
+02186                         *dstVertex= *srcVertex;
+02187                         // Normal.
+02188                         if(normalOff)
+02189                                 *dstNormal= *srcNormal;
+02190                 }
+02191         }
+02192 
+02193 
+02194         // clean this lod part. (NB: this is not optimal, but sufficient :) ).
+02195         lod.OriginalSkinRestored= true;
+02196 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CMeshMRMGeom::restoreOriginalSkinVertices  )  [private]
+
+ + + + + +
+   + + +

+Skinning: restore Vertex/Normal from _OriginalSkin* to VBuffer. +

+ +

+Definition at line 2095 of file mesh_mrm.cpp. +

+References _VBufferFinal, NL3D::CVertexBuffer::getNormalCoordPointer(), NL3D::CVertexBuffer::getNumTexCoordUsed(), NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getTexCoordPointer(), NL3D::CVertexBuffer::getVertexCoordPointer(), NL3D::CVertexBuffer::getVertexFormat(), nlassert, and uint. +

+

02096 {
+02097         nlassert(_Skinned);
+02098 
+02099         // Copy VBuffer content into Original vertices normals.
+02100         if(_VBufferFinal.getVertexFormat() & CVertexBuffer::PositionFlag)
+02101         {
+02102                 // copy vertices from VBuffer. (NB: unusefull geomorphed vertices are still copied, but doesn't matter).
+02103                 for(uint i=0; i<_VBufferFinal.getNumVertices();i++)
+02104                 {
+02105                         *(CVector*)_VBufferFinal.getVertexCoordPointer(i)= _OriginalSkinVertices[i];
+02106                 }
+02107         }
+02108         if(_VBufferFinal.getVertexFormat() & CVertexBuffer::NormalFlag)
+02109         {
+02110                 // copy normals from VBuffer. (NB: unusefull geomorphed normals are still copied, but doesn't matter).
+02111                 for(uint i=0; i<_VBufferFinal.getNumVertices();i++)
+02112                 {
+02113                         *(CVector*)_VBufferFinal.getNormalCoordPointer(i)= _OriginalSkinNormals[i];
+02114                 }
+02115         }
+02116         if (_MeshVertexProgram && _MeshVertexProgram->needTangentSpace())
+02117         {
+02118                 uint numTexCoords = _VBufferFinal.getNumTexCoordUsed();
+02119                 nlassert(numTexCoords >= 2);
+02120                 nlassert(_OriginalTGSpace.size() == _VBufferFinal.getNumVertices());
+02121                 // copy tangent space vectors
+02122                 for(uint i = 0; i < _VBufferFinal.getNumVertices(); ++i)
+02123                 {
+02124                         *(CVector*)_VBufferFinal.getTexCoordPointer(i, numTexCoords - 1)= _OriginalTGSpace[i];
+02125                 }
+02126         }
+02127 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::save NLMISC::IStream f  )  throw (NLMISC::EStream) [private]
+
+ + + + + +
+   + + +

+save the entire mesh. +

+ +

+Definition at line 1792 of file mesh_mrm.cpp. +

+References nlassert, sint, sint32, uint, and uint32. +

+

01793 {
+01794         /*
+01795         Version 5:
+01796                 - Shadow Skinning
+01797         Version 4:
+01798                 - serial SkinWeights per MRM, not per Lod
+01799         Version 3:
+01800                 - Bones names.
+01801         Version 2:
+01802                 - Mesh Vertex Program.
+01803         Version 1:
+01804                 - added blend shapes
+01805         Version 0:
+01806                 - base version.
+01807         */
+01808         sint    ver= f.serialVersion(5);
+01809         uint    i;
+01810 
+01811         // if >= version 3, serial bones names
+01812         f.serialCont (_BonesName);
+01813 
+01814         // Warning, if you have skinned this shape, you can't write it anymore because skinning id have been changed! 
+01815         nlassert (_BoneIdComputed==false);
+01816 
+01817         // Mesh Vertex Program.
+01818         if (ver >= 2)
+01819         {
+01820                 IMeshVertexProgram      *mvp= NULL;
+01821                 mvp= _MeshVertexProgram;
+01822                 f.serialPolyPtr(mvp);
+01823         }
+01824 
+01825         // blend shapes
+01826         if (ver >= 1)
+01827                 f.serial (_MeshMorpher);
+01828 
+01829         // must have good original Skinned Vertex before writing.
+01830         if( _Skinned )
+01831         {
+01832                 restoreOriginalSkinVertices();
+01833         }
+01834 
+01835 
+01836         // serial Basic info.
+01837         // ==================
+01838         f.serial(_Skinned);
+01839         f.serial(_BBox);
+01840         f.serial(_LevelDetail.MaxFaceUsed);
+01841         f.serial(_LevelDetail.MinFaceUsed);
+01842         f.serial(_LevelDetail.DistanceFinest);
+01843         f.serial(_LevelDetail.DistanceMiddle);
+01844         f.serial(_LevelDetail.DistanceCoarsest);
+01845         f.serial(_LevelDetail.OODistanceDelta);
+01846         f.serial(_LevelDetail.DistancePow);
+01847         f.serialCont(_LodInfos);
+01848 
+01849         // save number of wedges.
+01850         uint32  nWedges;
+01851         nWedges= _VBufferFinal.getNumVertices();
+01852         f.serial(nWedges);
+01853         // Save the VBuffer header.
+01854         _VBufferFinal.serialHeader(f);
+01855 
+01856 
+01857         // If new version, serial SkinWeights in header, not in lods.
+01858         if(ver >= 4)
+01859         {
+01860                 f.serialCont(_SkinWeights);
+01861         }
+01862 
+01863         // if >= version 5, serial Shadow Skin Information
+01864         if(ver>=5)
+01865         {
+01866                 f.serialCont (_ShadowSkinVertices);
+01867                 f.serialCont (_ShadowSkinTriangles);
+01868         }
+01869 
+01870         // Serial lod offsets.
+01871         // ==================
+01872         // This is the reference pos, to load / save relative offsets.
+01873         sint32                  startPos = f.getPos();
+01874         // Those are the lodOffsets, relative to startPos.
+01875         vector<sint32>  lodOffsets;
+01876         lodOffsets.resize(_LodInfos.size(), 0);
+01877 
+01878         // write all dummy offset. For now (since we don't know what to set), compute the offset of 
+01879         // the sint32 to come back in serial lod parts below.
+01880         for(i=0;i<_LodInfos.size(); i++)
+01881         {
+01882                 lodOffsets[i]= f.getPos();
+01883                 f.serial(lodOffsets[i]);
+01884         }
+01885 
+01886         // Serial lod subsets.
+01887         // ==================
+01888 
+01889         // Save all the lods.
+01890         for(i=0;i<_LodInfos.size(); i++)
+01891         {
+01892                 // get current absolute position.
+01893                 sint32  absCurPos= f.getPos();
+01894 
+01895                 // come back to "relative lodOffset" absolute position in the stream. (temp stored in lodOffset[i]).
+01896                 f.seek(lodOffsets[i], IStream::begin);
+01897 
+01898                 // write the relative position of the lod to the stream.
+01899                 sint32  relCurPos= absCurPos - startPos;
+01900                 f.serial(relCurPos);
+01901 
+01902                 // come back to absCurPos, to save the lod.
+01903                 f.seek(absCurPos, IStream::begin);
+01904 
+01905                 // And so now, save the lod.
+01906                 // write the lod face data.
+01907                 f.serial(_Lods[i]);
+01908                 // write the lod vertex data.
+01909                 serialLodVertexData(f, _LodInfos[i].StartAddWedge, _LodInfos[i].EndAddWedges);
+01910         }
+01911 
+01912 
+01913 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::serial NLMISC::IStream f  )  throw (NLMISC::EStream) [virtual]
+
+ + + + + +
+   + + +

+serial this meshGeom. +

+ +

+Implements NLMISC::IStreamable. +

+Definition at line 1613 of file mesh_mrm.cpp. +

+

01614 {
+01615         // because of complexity, serial is separated in save / load.
+01616 
+01617         if(f.isReading())
+01618                 load(f);
+01619         else
+01620                 save(f);
+01621 
+01622 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::serialLodVertexData NLMISC::IStream f,
uint  startWedge,
uint  endWedge
[private]
+
+ + + + + +
+   + + +

+serial a subset of the vertices. +

+ +

+Definition at line 1918 of file mesh_mrm.cpp. +

+References _SkinWeights, _VBufferFinal, bkupOriginalSkinVerticesSubset(), NLMISC::IStream::isReading(), NLMISC::IStream::serial(), NL3D::CVertexBuffer::serialSubset(), NLMISC::IStream::serialVersion(), sint, and uint. +

+Referenced by loadFirstLod(), and loadNextLod(). +

+

01919 {
+01920         /*
+01921         Version 1:
+01922                 - serial SkinWeights per MRM, not per Lod
+01923         */
+01924         sint    ver= f.serialVersion(1);
+01925 
+01926         // VBuffer part.
+01927         _VBufferFinal.serialSubset(f, startWedge, endWedge);
+01928 
+01929         // SkinWeights.
+01930         if(_Skinned)
+01931         {
+01932                 // Serialize SkinWeight per lod only for old versions.
+01933                 if(ver<1)
+01934                 {
+01935                         for(uint i= startWedge; i<endWedge; i++)
+01936                         {
+01937                                 f.serial(_SkinWeights[i]);
+01938                         }
+01939                 }
+01940                 // if reading, must copy original vertices from VB.
+01941                 if( f.isReading())
+01942                 {
+01943                         bkupOriginalSkinVerticesSubset(startWedge, endWedge);
+01944                 }
+01945         }
+01946 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::setShadowMesh const std::vector< CShadowVertex > &  shadowVertices,
const std::vector< uint32 > &  triangles
+
+ + + + + +
+   + + +

+Setup the ShadowMesh. +

+ +

+Definition at line 3359 of file mesh_mrm.cpp. +

+References _ShadowSkinTriangles, _ShadowSkinVertices, _SupportShadowSkinGrouping, NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES, and NL3D_SHADOW_MESH_SKIN_MANAGER_VERTEXFORMAT. +

+

03360 {
+03361         _ShadowSkinVertices= shadowVertices;
+03362         _ShadowSkinTriangles= triangles;
+03363         // update flag. Support Shadow SkinGrouping if Shadow setuped, and if not too many vertices.
+03364         _SupportShadowSkinGrouping= !_ShadowSkinVertices.empty() &&
+03365                 NL3D_SHADOW_MESH_SKIN_MANAGER_VERTEXFORMAT==CVertexBuffer::PositionFlag &&
+03366                 _ShadowSkinVertices.size() <= NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES;
+03367 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CMeshMRMGeom::sortPerMaterial  )  const [virtual]
+
+ + + + + +
+   + + +

+true if the sort criterion must be by material. Else, sort per instance. +

+Implements NL3D::IMeshGeom. +

+Definition at line 2687 of file mesh_mrm.cpp. +

+

02688 {
+02689         // Can't do it per material since 2 lods may not have the same number of RdrPass!!
+02690         return false;
+02691 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CMeshMRMGeom::supportMeshBlockRendering  )  const [virtual]
+
+ + + + + +
+   + + +

+true if this meshGeom support meshBlock rendering. return false if skinned/meshMorphed. +

+Implements NL3D::IMeshGeom. +

+Definition at line 2673 of file mesh_mrm.cpp. +

+Referenced by profileSceneRender(), and NL3D::CMeshMRM::supportMeshBlockRendering(). +

+

02674 {
+02675         /*
+02676                 Yoyo: Don't Support It for MRM because too Slow!!
+02677                 The problem is that lock() unlock() on each instance, on the same VBHeap IS AS SLOWER AS
+02678                 VB switching.
+02679 
+02680                 TODO_OPTIMIZE: find a way to optimize MRM.
+02681         */
+02682         return false;
+02683         //return _SupportMeshBlockRendering;
+02684 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CMeshMRMGeom::supportShadowSkinGrouping  )  const [inline]
+
+ + + + + +
+   + + +

+Render the ShadowSkin (SkinGroup like). +

+ +

+Definition at line 325 of file mesh_mrm.h. +

+References _SupportShadowSkinGrouping. +

+Referenced by NL3D::CMeshMRMInstance::supportShadowSkinGrouping(). +

+

00325 {return _SupportShadowSkinGrouping;}
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CMeshMRMGeom::supportSkinGrouping  )  const
+
+ + + + + +
+   + + +

+ +

+Definition at line 1312 of file mesh_mrm.cpp. +

+References _SupportSkinGrouping. +

+Referenced by NL3D::CMeshMRMInstance::supportSkinGrouping(). +

+

01313 {
+01314         return _SupportSkinGrouping;
+01315 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CMeshMRMGeom::unloadNextLod NLMISC::IStream f  ) 
+
+ + + + + +
+   + + +

+UnLoad Lod getNbLodLoaded()-1 from memory. use getNbLodLoaded()-1 to know what Lod will be unloaded. NB: if getNbLodLoaded() <= 1, no op. +

+Definition at line 2029 of file mesh_mrm.cpp. +

+References _Lods, _NbLodLoaded, and getNbLodLoaded(). +

+

02030 {
+02031         // If just first lod remain (or no lod), quit
+02032         if(getNbLodLoaded() <= 1)
+02033                 return;
+02034 
+02035         // Reset the entire Lod object. (Free Memory).
+02036         contReset(_Lods[_NbLodLoaded-1]);
+02037 
+02038 
+02039         // Dec LodLoaded count.
+02040         _NbLodLoaded--;
+02041 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::updateRawSkinNormal bool  enabled,
CMeshMRMInstance mi,
sint  curLodId
[private]
+
+ + + + + +
+   + + +

+compute RawSkin info in the MRMInstance according to current skin setup. +

+ +

+Definition at line 3060 of file mesh_mrm.cpp. +

+References _Lods, _MeshDataId, NL3D::CMeshMRMInstance::_RawSkinCache, _SkinWeights, _VBufferFinal, NL3D::CMeshMorpher::BlendShapes, NL3D::CRawSkinNormalCache::clearArrays(), NL3D::CMeshMRMInstance::clearRawSkinCache(), NL3D::CRawSkinNormalCache::Geomorphs, NL3D::CMeshMRMGeom::CLod::Geomorphs, NL3D::CVertexBuffer::getNumVertices(), NL3D::CVertexBuffer::getTexCoordPointer(), H_AUTO, NL3D::CRawSkinNormalCache::HardVertices, NL3D::CMeshMRMGeom::CLod::InfluencedVertices, NL3D::CRawSkinNormalCache::LodId, NL3D::CRawSkinNormalCache::MeshDataId, NL3D_MESH_SKINNING_MAX_MATRIX, nlassert, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CRawSkinNormalCache::RdrPass, NLMISC::CObjectVector< CRawSkinVertex *, false >::resize(), NLMISC::CObjectVector< CRawVertexNormalSkin4, false >::resize(), NLMISC::CObjectVector< CRawVertexNormalSkin3, false >::resize(), NLMISC::CObjectVector< CRawVertexNormalSkin2, false >::resize(), NLMISC::CObjectVector< CRawVertexNormalSkin1, false >::resize(), sint, NLMISC::CObjectVector< CRawVertexNormalSkin4, false >::size(), NLMISC::CObjectVector< CRawVertexNormalSkin3, false >::size(), NLMISC::CObjectVector< CRawVertexNormalSkin2, false >::size(), NLMISC::CObjectVector< CRawVertexNormalSkin1, false >::size(), NL3D::CRawSkinNormalCache::SoftVertices, NL3D::CRawSkinNormalCache::TotalHardVertices, NL3D::CRawSkinNormalCache::TotalSoftVertices, uint, uint32, NL3D::CRawSkinNormalCache::VertexRemap, NL3D::CRawSkinNormalCache::Vertices1, NL3D::CRawSkinNormalCache::Vertices2, NL3D::CRawSkinNormalCache::Vertices3, and NL3D::CRawSkinNormalCache::Vertices4. +

+Referenced by renderSkin(), and renderSkinGroupGeom(). +

+

03061 {
+03062         if(!enabled)
+03063         {
+03064                 // if the instance cache is not cleared, must clear.
+03065                 if(mi->_RawSkinCache)
+03066                         mi->clearRawSkinCache();
+03067         }
+03068         else
+03069         {
+03070                 // If the instance has no RawSkin, or has a too old RawSkin cache, must delete it, and recreate
+03071                 if( !mi->_RawSkinCache || mi->_RawSkinCache->MeshDataId!=_MeshDataId)
+03072                 {
+03073                         // first delete if too old.
+03074                         if(mi->_RawSkinCache)
+03075                                 mi->clearRawSkinCache();
+03076                         // Then recreate, and use _MeshDataId to verify that the instance works with same data.
+03077                         mi->_RawSkinCache= new CRawSkinNormalCache;
+03078                         mi->_RawSkinCache->MeshDataId= _MeshDataId;
+03079                         mi->_RawSkinCache->LodId= -1;
+03080                 }
+03081 
+03082 
+03083                 /* If the instance rawSkin has a different Lod (or if -1), then must recreate it.
+03084                         NB: The lod may change each frame per instance, but suppose not so many change, so we can cache those data.
+03085                 */
+03086                 if( mi->_RawSkinCache->LodId != curLodId )
+03087                 {
+03088                         H_AUTO( NL3D_CMeshMRMGeom_updateRawSkinNormal );
+03089 
+03090                         CRawSkinNormalCache     &skinLod= *mi->_RawSkinCache;
+03091                         CLod                            &lod= _Lods[curLodId];
+03092                         uint                            i;
+03093                         sint                            rawIdx;
+03094 
+03095                         // Clear the raw skin mesh.
+03096                         skinLod.clearArrays();
+03097 
+03098                         // Cache this lod
+03099                         mi->_RawSkinCache->LodId= curLodId;
+03100 
+03101                         // For each matrix influence.
+03102                         nlassert(NL3D_MESH_SKINNING_MAX_MATRIX==4);
+03103 
+03104                         // For each vertex, acknowledge if it is a src for geomorph.
+03105                         static  vector<uint8>   softVertices;
+03106                         softVertices.clear();
+03107                         softVertices.resize( _VBufferFinal.getNumVertices(), 0 );
+03108                         for(i=0;i<lod.Geomorphs.size();i++)
+03109                         {
+03110                                 softVertices[lod.Geomorphs[i].Start]= 1;
+03111                                 softVertices[lod.Geomorphs[i].End]= 1;
+03112                         }
+03113 
+03114                         // The remap from old index in _VBufferFinal to RawSkin vertices (without Geomorphs).
+03115                         static  vector<uint32>  vertexRemap;
+03116                         vertexRemap.resize( _VBufferFinal.getNumVertices() );
+03117                         sint    softSize[4];
+03118                         sint    hardSize[4];
+03119                         sint    softStart[4];
+03120                         sint    hardStart[4];
+03121                         // count vertices
+03122                         skinLod.TotalSoftVertices= 0;
+03123                         skinLod.TotalHardVertices= 0;
+03124                         for(i=0;i<4;i++)
+03125                         {
+03126                                 softSize[i]= 0;
+03127                                 hardSize[i]= 0;
+03128                                 // Count.
+03129                                 for(uint j=0;j<lod.InfluencedVertices[i].size();j++)
+03130                                 {
+03131                                         uint    vid= lod.InfluencedVertices[i][j];
+03132                                         if(softVertices[vid])
+03133                                                 softSize[i]++;
+03134                                         else
+03135                                                 hardSize[i]++;
+03136                                 }
+03137                                 skinLod.TotalSoftVertices+= softSize[i];
+03138                                 skinLod.TotalHardVertices+= hardSize[i];
+03139                                 skinLod.SoftVertices[i]= softSize[i];
+03140                                 skinLod.HardVertices[i]= hardSize[i];
+03141                         }
+03142                         // compute offsets
+03143                         softStart[0]= 0;
+03144                         hardStart[0]= skinLod.TotalSoftVertices;
+03145                         for(i=1;i<4;i++)
+03146                         {
+03147                                 softStart[i]= softStart[i-1]+softSize[i-1];
+03148                                 hardStart[i]= hardStart[i-1]+hardSize[i-1];
+03149                         }
+03150                         // compute remap
+03151                         for(i=0;i<4;i++)
+03152                         {
+03153                                 uint    softIdx= softStart[i];
+03154                                 uint    hardIdx= hardStart[i];
+03155                                 for(uint j=0;j<lod.InfluencedVertices[i].size();j++)
+03156                                 {
+03157                                         uint    vid= lod.InfluencedVertices[i][j];
+03158                                         if(softVertices[vid])
+03159                                                 vertexRemap[vid]= softIdx++;
+03160                                         else
+03161                                                 vertexRemap[vid]= hardIdx++;
+03162                                 }
+03163                         }
+03164 
+03165 
+03166                         // Resize the dest array.
+03167                         skinLod.Vertices1.resize(lod.InfluencedVertices[0].size());
+03168                         skinLod.Vertices2.resize(lod.InfluencedVertices[1].size());
+03169                         skinLod.Vertices3.resize(lod.InfluencedVertices[2].size());
+03170                         skinLod.Vertices4.resize(lod.InfluencedVertices[3].size());
+03171 
+03172                         // Remap for BlendShape. Lasts 2 bits tells what RawSkin Array to seek (1 to 4), 
+03173                         // low Bits indicate the number in them. 0xFFFFFFFF is a special value indicating "NotUsed in this lod"
+03174                         static  vector<uint32>  vertexFinalRemap;
+03175                         vertexFinalRemap.clear();
+03176                         vertexFinalRemap.resize(vertexRemap.size(), 0xFFFFFFFF);
+03177 
+03178                         // 1 Matrix skinning.
+03179                         //========
+03180                         for(i=0;i<skinLod.Vertices1.size();i++)
+03181                         {
+03182                                 // get the dest vertex.
+03183                                 uint    vid= lod.InfluencedVertices[0][i];
+03184                                 // where to store?
+03185                                 rawIdx= vertexRemap[vid];
+03186                                 if(softVertices[vid])
+03187                                         rawIdx-= softStart[0];
+03188                                 else
+03189                                         rawIdx+= softSize[0]-hardStart[0];
+03190                                 // for BlendShapes remapping
+03191                                 vertexFinalRemap[vid]= (0<<30) + rawIdx;
+03192                                 // fill raw struct
+03193                                 skinLod.Vertices1[rawIdx].MatrixId[0]= _SkinWeights[vid].MatrixId[0];
+03194                                 skinLod.Vertices1[rawIdx].Vertex.Pos= _OriginalSkinVertices[vid];
+03195                                 skinLod.Vertices1[rawIdx].Vertex.Normal= _OriginalSkinNormals[vid];
+03196                                 skinLod.Vertices1[rawIdx].Vertex.UV= *(CUV*)_VBufferFinal.getTexCoordPointer(vid);
+03197                         }
+03198 
+03199                         // 2 Matrix skinning.
+03200                         //========
+03201                         for(i=0;i<skinLod.Vertices2.size();i++)
+03202                         {
+03203                                 // get the dest vertex.
+03204                                 uint    vid= lod.InfluencedVertices[1][i];
+03205                                 // where to store?
+03206                                 rawIdx= vertexRemap[vid];
+03207                                 if(softVertices[vid])
+03208                                         rawIdx-= softStart[1];
+03209                                 else
+03210                                         rawIdx+= softSize[1]-hardStart[1];
+03211                                 // for BlendShapes remapping
+03212                                 vertexFinalRemap[vid]= (1<<30) + rawIdx;
+03213                                 // fill raw struct
+03214                                 skinLod.Vertices2[rawIdx].MatrixId[0]= _SkinWeights[vid].MatrixId[0];
+03215                                 skinLod.Vertices2[rawIdx].MatrixId[1]= _SkinWeights[vid].MatrixId[1];
+03216                                 skinLod.Vertices2[rawIdx].Weights[0]= _SkinWeights[vid].Weights[0];
+03217                                 skinLod.Vertices2[rawIdx].Weights[1]= _SkinWeights[vid].Weights[1];
+03218                                 skinLod.Vertices2[rawIdx].Vertex.Pos= _OriginalSkinVertices[vid];
+03219                                 skinLod.Vertices2[rawIdx].Vertex.Normal= _OriginalSkinNormals[vid];
+03220                                 skinLod.Vertices2[rawIdx].Vertex.UV= *(CUV*)_VBufferFinal.getTexCoordPointer(vid);
+03221                         }
+03222 
+03223                         // 3 Matrix skinning.
+03224                         //========
+03225                         for(i=0;i<skinLod.Vertices3.size();i++)
+03226                         {
+03227                                 // get the dest vertex.
+03228                                 uint    vid= lod.InfluencedVertices[2][i];
+03229                                 // where to store?
+03230                                 rawIdx= vertexRemap[vid];
+03231                                 if(softVertices[vid])
+03232                                         rawIdx-= softStart[2];
+03233                                 else
+03234                                         rawIdx+= softSize[2]-hardStart[2];
+03235                                 // for BlendShapes remapping
+03236                                 vertexFinalRemap[vid]= (2<<30) + rawIdx;
+03237                                 // fill raw struct
+03238                                 skinLod.Vertices3[rawIdx].MatrixId[0]= _SkinWeights[vid].MatrixId[0];
+03239                                 skinLod.Vertices3[rawIdx].MatrixId[1]= _SkinWeights[vid].MatrixId[1];
+03240                                 skinLod.Vertices3[rawIdx].MatrixId[2]= _SkinWeights[vid].MatrixId[2];
+03241                                 skinLod.Vertices3[rawIdx].Weights[0]= _SkinWeights[vid].Weights[0];
+03242                                 skinLod.Vertices3[rawIdx].Weights[1]= _SkinWeights[vid].Weights[1];
+03243                                 skinLod.Vertices3[rawIdx].Weights[2]= _SkinWeights[vid].Weights[2];
+03244                                 skinLod.Vertices3[rawIdx].Vertex.Pos= _OriginalSkinVertices[vid];
+03245                                 skinLod.Vertices3[rawIdx].Vertex.Normal= _OriginalSkinNormals[vid];
+03246                                 skinLod.Vertices3[rawIdx].Vertex.UV= *(CUV*)_VBufferFinal.getTexCoordPointer(vid);
+03247                         }
+03248 
+03249                         // 4 Matrix skinning.
+03250                         //========
+03251                         for(i=0;i<skinLod.Vertices4.size();i++)
+03252                         {
+03253                                 // get the dest vertex.
+03254                                 uint    vid= lod.InfluencedVertices[3][i];
+03255                                 // where to store?
+03256                                 rawIdx= vertexRemap[vid];
+03257                                 if(softVertices[vid])
+03258                                         rawIdx-= softStart[3];
+03259                                 else
+03260                                         rawIdx+= softSize[3]-hardStart[3];
+03261                                 // for BlendShapes remapping
+03262                                 vertexFinalRemap[vid]= (3<<30) + rawIdx;
+03263                                 // fill raw struct
+03264                                 skinLod.Vertices4[rawIdx].MatrixId[0]= _SkinWeights[vid].MatrixId[0];
+03265                                 skinLod.Vertices4[rawIdx].MatrixId[1]= _SkinWeights[vid].MatrixId[1];
+03266                                 skinLod.Vertices4[rawIdx].MatrixId[2]= _SkinWeights[vid].MatrixId[2];
+03267                                 skinLod.Vertices4[rawIdx].MatrixId[3]= _SkinWeights[vid].MatrixId[3];
+03268                                 skinLod.Vertices4[rawIdx].Weights[0]= _SkinWeights[vid].Weights[0];
+03269                                 skinLod.Vertices4[rawIdx].Weights[1]= _SkinWeights[vid].Weights[1];
+03270                                 skinLod.Vertices4[rawIdx].Weights[2]= _SkinWeights[vid].Weights[2];
+03271                                 skinLod.Vertices4[rawIdx].Weights[3]= _SkinWeights[vid].Weights[3];
+03272                                 skinLod.Vertices4[rawIdx].Vertex.Pos= _OriginalSkinVertices[vid];
+03273                                 skinLod.Vertices4[rawIdx].Vertex.Normal= _OriginalSkinNormals[vid];
+03274                                 skinLod.Vertices4[rawIdx].Vertex.UV= *(CUV*)_VBufferFinal.getTexCoordPointer(vid);
+03275                         }
+03276 
+03277                         // Remap Geomorphs.
+03278                         //========
+03279                         uint    numGeoms= lod.Geomorphs.size();
+03280                         skinLod.Geomorphs.resize( numGeoms );
+03281                         for(i=0;i<numGeoms;i++)
+03282                         {
+03283                                 // NB: don't add "numGeoms" to the index because RawSkin look in a TempArray in RAM, wich start at 0...
+03284                                 skinLod.Geomorphs[i].Start= vertexRemap[lod.Geomorphs[i].Start];
+03285                                 skinLod.Geomorphs[i].End= vertexRemap[lod.Geomorphs[i].End];
+03286                         }
+03287 
+03288                         // Remap RdrPass.
+03289                         //========
+03290                         skinLod.RdrPass.resize(lod.RdrPass.size());
+03291                         for(i=0;i<skinLod.RdrPass.size();i++)
+03292                         {
+03293                                 // NB: since RawSkin is possible only with SkinGrouping, and since SkniGrouping is 
+03294                                 // possible only with no Quads/Lines, we should have only Tris here.
+03295                                 nlassert( lod.RdrPass[i].PBlock.getNumQuad()== 0);
+03296                                 nlassert( lod.RdrPass[i].PBlock.getNumLine()== 0);
+03297                                 // remap tris.
+03298                                 skinLod.RdrPass[i].setNumTri(lod.RdrPass[i].PBlock.getNumTri());
+03299                                 uint32  *srcTriPtr= lod.RdrPass[i].PBlock.getTriPointer();
+03300                                 uint32  *dstTriPtr= skinLod.RdrPass[i].getTriPointer();
+03301                                 uint32  numIndices= lod.RdrPass[i].PBlock.getNumTri()*3;
+03302                                 for(uint j=0;j<numIndices;j++, srcTriPtr++, dstTriPtr++)
+03303                                 {
+03304                                         uint    vid= *srcTriPtr;
+03305                                         // If this index refers to a Geomorphed vertex, don't modify!
+03306                                         if(vid<numGeoms)
+03307                                                 *dstTriPtr= vid;
+03308                                         else
+03309                                                 *dstTriPtr= vertexRemap[vid] + numGeoms;
+03310                                 }
+03311                         }
+03312 
+03313                         // Case of MeshMorpher
+03314                         //========
+03315                         if(_MeshMorpher.BlendShapes.size()>0)
+03316                         {
+03317                                 skinLod.VertexRemap.resize(vertexFinalRemap.size());
+03318 
+03319                                 for(i=0;i<vertexFinalRemap.size();i++)
+03320                                 {
+03321                                         uint    vfr= vertexFinalRemap[i];
+03322                                         if(vfr!=0xFFFFFFFF)
+03323                                         {
+03324                                                 uint    rsArrayId= vfr >> 30;
+03325                                                 uint    rsIndex= vfr & ((1<<30)-1);
+03326                                                 switch(rsArrayId)
+03327                                                 {
+03328                                                 case 0:
+03329                                                         skinLod.VertexRemap[i]= &skinLod.Vertices1[rsIndex].Vertex;
+03330                                                         break;
+03331                                                 case 1:
+03332                                                         skinLod.VertexRemap[i]= &skinLod.Vertices2[rsIndex].Vertex;
+03333                                                         break;
+03334                                                 case 2:
+03335                                                         skinLod.VertexRemap[i]= &skinLod.Vertices3[rsIndex].Vertex;
+03336                                                         break;
+03337                                                 case 3:
+03338                                                         skinLod.VertexRemap[i]= &skinLod.Vertices4[rsIndex].Vertex;
+03339                                                         break;
+03340                                                 };
+03341                                         }
+03342                                         else
+03343                                                 skinLod.VertexRemap[i]= NULL;
+03344                                 }
+03345                         }
+03346                 }
+03347         }
+03348 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::updateShiftedTriangleCache CMeshMRMInstance mi,
sint  curLodId,
uint  baseVertex
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 1529 of file mesh_mrm.cpp. +

+References _Lods, _MeshDataId, NL3D::CMeshMRMInstance::_RawSkinCache, NL3D::CMeshMRMInstance::_ShiftedTriangleCache, NL3D::CShiftedTriangleCache::BaseVertex, NL3D::CMeshMRMInstance::clearShiftedTriangleCache(), NLMISC::CObjectVector< uint32, false >::getPtr(), NL3D::CShiftedTriangleCache::LodId, NL3D::CShiftedTriangleCache::MeshDataId, NL3D::CShiftedTriangleCache::CRdrPass::NumTriangles, NL3D::CShiftedTriangleCache::RawIndices, NL3D::CShiftedTriangleCache::RdrPass, NL3D::CMeshMRMGeom::CLod::RdrPass, NL3D::CRawSkinNormalCache::RdrPass, NLMISC::CObjectVector< uint32, false >::resize(), NLMISC::CObjectVector< CRdrPass, false >::resize(), sint, NL3D::CShiftedTriangleCache::CRdrPass::Triangles, uint, and uint32. +

+Referenced by renderSkinGroupPrimitives(). +

+

01530 {
+01531         // if the instance has a cache, but not sync to us, delete it.
+01532         if( mi->_ShiftedTriangleCache && (
+01533                 mi->_ShiftedTriangleCache->MeshDataId != _MeshDataId ||
+01534                 mi->_ShiftedTriangleCache->LodId != curLodId ||
+01535                 mi->_ShiftedTriangleCache->BaseVertex != baseVertex) )
+01536         {
+01537                 mi->clearShiftedTriangleCache();
+01538         }
+01539 
+01540         // If the instance has not a valid cache, must create it.
+01541         if( !mi->_ShiftedTriangleCache )
+01542         {
+01543                 mi->_ShiftedTriangleCache= new CShiftedTriangleCache;
+01544                 // Fill the cache Key.
+01545                 mi->_ShiftedTriangleCache->MeshDataId= _MeshDataId;
+01546                 mi->_ShiftedTriangleCache->LodId= curLodId;
+01547                 mi->_ShiftedTriangleCache->BaseVertex= baseVertex;
+01548 
+01549                 // Build list of PBlock. From Lod, or from RawSkin cache.
+01550                 static  vector<CPrimitiveBlock*>        pbList;
+01551                 pbList.clear();
+01552                 if(mi->_RawSkinCache)
+01553                 {
+01554                         pbList.resize(mi->_RawSkinCache->RdrPass.size());
+01555                         for(uint i=0;i<pbList.size();i++)
+01556                         {
+01557                                 pbList[i]= &mi->_RawSkinCache->RdrPass[i];
+01558                         }
+01559                 }
+01560                 else
+01561                 {
+01562                         CLod    &lod= _Lods[curLodId];
+01563                         pbList.resize(lod.RdrPass.size());
+01564                         for(uint i=0;i<pbList.size();i++)
+01565                         {
+01566                                 pbList[i]= &lod.RdrPass[i].PBlock;
+01567                         }
+01568                 }
+01569 
+01570                 // Build RdrPass
+01571                 mi->_ShiftedTriangleCache->RdrPass.resize(pbList.size());
+01572 
+01573                 // First pass, count number of triangles, and fill header info
+01574                 uint    totalTri= 0;
+01575                 uint    i;
+01576                 for(i=0;i<pbList.size();i++)
+01577                 {
+01578                         mi->_ShiftedTriangleCache->RdrPass[i].NumTriangles= pbList[i]->getNumTri();
+01579                         totalTri+= pbList[i]->getNumTri();
+01580                 }
+01581 
+01582                 // Allocate triangles indices.
+01583                 mi->_ShiftedTriangleCache->RawIndices.resize(totalTri*3);
+01584                 uint32          *rawPtr= mi->_ShiftedTriangleCache->RawIndices.getPtr();
+01585 
+01586                 // Second pass, fill ptrs, and fill Arrays
+01587                 uint    indexTri= 0;
+01588                 for(i=0;i<pbList.size();i++)
+01589                 {
+01590                         CShiftedTriangleCache::CRdrPass &dstRdrPass= mi->_ShiftedTriangleCache->RdrPass[i];
+01591                         dstRdrPass.Triangles= rawPtr + indexTri*3;
+01592 
+01593                         // Fill the array
+01594                         uint    numTris= pbList[i]->getNumTri();
+01595                         if(numTris)
+01596                         {
+01597                                 uint    nIds= numTris*3;
+01598                                 // index, and fill
+01599                                 uint32  *pSrcTri= pbList[i]->getTriPointer();
+01600                                 uint32  *pDstTri= dstRdrPass.Triangles;
+01601                                 for(;nIds>0;nIds--,pSrcTri++,pDstTri++)
+01602                                         *pDstTri= *pSrcTri + baseVertex;
+01603                         }
+01604 
+01605                         // Next
+01606                         indexTri+= dstRdrPass.NumTriangles;
+01607                 }
+01608         }
+01609 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::updateSkeletonUsage CSkeletonModel sm,
bool  increment
+
+ + + + + +
+   + + +

+update Skeleton Usage. increment or decrement. computeBonesId must has been called before. +

+ +

+Definition at line 2535 of file mesh_mrm.cpp. +

+References NL3D::CSkeletonModel::Bones, NL3D::CSkeletonModel::decBoneUsage(), NL3D::CSkeletonModel::incBoneUsage(), nlerror, and uint. +

+Referenced by NL3D::CMeshMRM::updateSkeletonUsage(). +

+

02536 {
+02537         // For all Bones used.
+02538         for(uint i=0; i<_BonesIdExt.size();i++)
+02539         {
+02540                 uint    boneId= _BonesIdExt[i];
+02541                 // Some explicit Error.
+02542                 if(boneId>=sm->Bones.size())
+02543                         nlerror(" Skin is incompatible with Skeleton: tries to use bone %d", boneId);
+02544                 // increment or decrement not Forced, because CMeshGeom use getActiveBoneSkinMatrix().
+02545                 if(increment)
+02546                         sm->incBoneUsage(boneId, CSkeletonModel::UsageNormal);
+02547                 else
+02548                         sm->decBoneUsage(boneId, CSkeletonModel::UsageNormal);
+02549         }
+02550 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CMeshMRMGeom::updateVertexBufferHard IDriver drv,
uint32  numVertices
[private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 2224 of file mesh_mrm.cpp. +

+References _VBufferFinal, 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(), NL3D::IDriver::supportVertexBufferHard(), and uint32. +

+Referenced by beginMesh(), and render(). +

+

02225 {
+02226         if(!drv->supportVertexBufferHard() || numVertices==0)
+02227                 return;
+02228 
+02229 
+02239         bool    avoidVBHard;
+02240         avoidVBHard= _Skinned || ( _MeshMorpher.BlendShapes.size()>0 && drv->slowUnlockVertexBufferHard() );
+02241         if( _VertexBufferHardDirty && avoidVBHard )
+02242         {
+02243                 // delete possible old VBHard.
+02244                 if(_VBHard!=NULL)
+02245                 {
+02246                         // VertexBufferHard lifetime < Driver lifetime.
+02247                         nlassert(_Driver!=NULL);
+02248                         _Driver->deleteVertexBufferHard(_VBHard);
+02249                 }
+02250                 return;
+02251         }
+02252 
+02253 
+02254         // If the vbufferhard is not here, or if dirty, or if do not have enough vertices.
+02255         if(_VBHard==NULL || _VertexBufferHardDirty || _VBHard->getNumVertices() < numVertices)
+02256         {
+02257                 _VertexBufferHardDirty= false;
+02258 
+02259                 // delete possible old _VBHard.
+02260                 if(_VBHard!=NULL)
+02261                 {
+02262                         // VertexBufferHard lifetime < Driver lifetime.
+02263                         nlassert(_Driver!=NULL);
+02264                         _Driver->deleteVertexBufferHard(_VBHard);
+02265                 }
+02266 
+02267                 // bkup drv in a refptr. (so we know if the vbuffer hard has to be deleted).
+02268                 _Driver= drv;
+02269                 // try to create new one, in AGP Ram
+02270                 _VBHard= _Driver->createVertexBufferHard(_VBufferFinal.getVertexFormat(), _VBufferFinal.getValueTypePointer (), numVertices, IDriver::VBHardAGP, _VBufferFinal.getUVRouting());
+02271 
+02272 
+02273                 // If KO, use normal VertexBuffer, else, Fill it with VertexBuffer.
+02274                 if(_VBHard!=NULL)
+02275                 {
+02276                         void    *vertexPtr= _VBHard->lock();
+02277 
+02278                         nlassert(_VBufferFinal.getVertexFormat() == _VBHard->getVertexFormat());
+02279                         nlassert(_VBufferFinal.getNumVertices() >= numVertices);
+02280                         nlassert(_VBufferFinal.getVertexSize() == _VBHard->getVertexSize());
+02281 
+02282                         // \todo yoyo: TODO_DX8 and DX8 ???
+02283                         // Because same internal format, just copy all block.
+02284                         memcpy(vertexPtr, _VBufferFinal.getVertexCoordPointer(), numVertices * _VBufferFinal.getVertexSize() );
+02285 
+02286                         _VBHard->unlock();
+02287                 }
+02288         }
+02289 
+02290 }
+
+


Friends And Related Function Documentation

+

+ + + + +
+ + +
friend class CLod [friend] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 416 of file mesh_mrm.h.

+

+ + + + +
+ + +
friend class CMRMBuilder [friend] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 333 of file mesh_mrm.h.

+


Field Documentation

+

+ + + + +
+ + +
NLMISC::CAABBoxExt NL3D::CMeshMRMGeom::_BBox [private] +
+
+ + + + + +
+   + + +

+For clipping. this is the BB of all vertices of all Lods. +

+ +

+Definition at line 515 of file mesh_mrm.h.

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_BoneIdComputed [private] +
+
+ + + + + +
+   + + +

+This boolean is true if the bones id have been passed in the skeleton. +

+ +

+Definition at line 493 of file mesh_mrm.h.

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_BoneIdExtended [private] +
+
+ + + + + +
+   + + +

+true if the _BonesIdExt have been computed (for bone Usage). +

+ +

+Definition at line 495 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<sint32> NL3D::CMeshMRMGeom::_BonesId [private] +
+
+ + + + + +
+   + + +

+This array give the index in the skeleton of the local bones used. computed at first computeBoneId(). +

+ +

+Definition at line 506 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<sint32> NL3D::CMeshMRMGeom::_BonesIdExt [private] +
+
+ + + + + +
+   + + +

+Same as _BonesId but with parent of bones added. (used for bone usage). +

+ +

+Definition at line 508 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<std::string> NL3D::CMeshMRMGeom::_BonesName [private] +
+
+ + + + + +
+   + + +

+This array give the name of the local bones. +

+ +

+Definition at line 504 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<NLMISC::CBSphere> NL3D::CMeshMRMGeom::_BonesSphere [private] +
+
+ + + + + +
+   + + +

+see CTransform::getSkinBoneSphere() doc for the meaning of this value +

+ +

+Definition at line 510 of file mesh_mrm.h. +

+Referenced by computeBonesId(), and getSkinBoneSphere().

+

+ + + + +
+ + +
CRefPtr<IDriver> NL3D::CMeshMRMGeom::_Driver [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 534 of file mesh_mrm.h.

+

+ + + + +
+ + +
uint8 NL3D::CMeshMRMGeom::_LastLodComputed [private] +
+
+ + + + + +
+   + + +

+Last lod rendered. used with renderSkinGroup*() only. +

+ +

+Definition at line 501 of file mesh_mrm.h. +

+Referenced by renderSkinGroupGeom(), renderSkinGroupPrimitives(), and renderSkinGroupSpecularRdrPass().

+

+ + + + +
+ + +
CMRMLevelDetail NL3D::CMeshMRMGeom::_LevelDetail [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 525 of file mesh_mrm.h. +

+Referenced by activeInstance(), build(), changeMRMDistanceSetup(), getLevelDetail(), getNumTriangles(), profileSceneRender(), and render().

+

+ + + + +
+ + +
std::vector<CLodInfo> NL3D::CMeshMRMGeom::_LodInfos [private] +
+
+ + + + + +
+   + + +

+Info for pre-loading Lods. +

+ +

+Definition at line 519 of file mesh_mrm.h. +

+Referenced by build(), loadFirstLod(), and loadNextLod().

+

+ + + + +
+ + +
std::vector<CLod> NL3D::CMeshMRMGeom::_Lods [private] +
+
+ + + + + +
+   + + +

+List of Lods. +

+ +

+Definition at line 513 of file mesh_mrm.h. +

+Referenced by activeInstance(), applyArrayShadowSkin(), applyMaterialRemap(), beginMesh(), build(), chooseLod(), compileRunTime(), computeBonesId(), computeMeshVBHeap(), endMesh(), getGeomorphs(), getNbLod(), getNbRdrPass(), getNumRdrPassesForInstance(), getRdrPassMaterial(), getRdrPassPrimitiveBlock(), loadFirstLod(), loadNextLod(), profileSceneRender(), render(), renderPass(), renderSkin(), renderSkinGroupGeom(), renderSkinGroupPrimitives(), renderSkinGroupSpecularRdrPass(), unloadNextLod(), updateRawSkinNormal(), and updateShiftedTriangleCache().

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_MBRBkupNormalize [private] +
+
+ + + + + +
+   + + +

+BeginMesh setup. +

+ +

+Definition at line 562 of file mesh_mrm.h. +

+Referenced by beginMesh(), and endMesh().

+

+ + + + +
+ + +
sint NL3D::CMeshMRMGeom::_MBRCurrentLodId [private] +
+
+ + + + + +
+   + + +

+global setup at activateInstance() +

+ +

+Definition at line 564 of file mesh_mrm.h. +

+Referenced by activeInstance(), CMeshMRMGeom(), getNumRdrPassesForInstance(), and renderPass().

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::_MeshDataId [private] +
+
+ + + + + +
+   + + +

+Each time the mesh is loaded/built, this increment. +

+ +

+Definition at line 639 of file mesh_mrm.h. +

+Referenced by CMeshMRMGeom(), dirtMeshDataId(), updateRawSkinNormal(), and updateShiftedTriangleCache().

+

+ + + + +
+ + +
CMeshMorpher NL3D::CMeshMRMGeom::_MeshMorpher [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 552 of file mesh_mrm.h.

+

+ + + + +
+ + +
NLMISC::CSmartPtr<IMeshVertexProgram> NL3D::CMeshMRMGeom::_MeshVertexProgram [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 555 of file mesh_mrm.h.

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::_NbLodLoaded [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 520 of file mesh_mrm.h. +

+Referenced by build(), chooseLod(), CMeshMRMGeom(), getNbLodLoaded(), loadFirstLod(), loadNextLod(), and unloadNextLod().

+

+ + + + +
+ + +
std::vector<CVector> NL3D::CMeshMRMGeom::_OriginalSkinNormals [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 481 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<CVector> NL3D::CMeshMRMGeom::_OriginalSkinVertices [private] +
+
+ + + + + +
+   + + +

+Skinning: this is the list of vertices (mirror of VBuffer), at the bind Pos. +

+ +

+Definition at line 480 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<CVector> NL3D::CMeshMRMGeom::_OriginalTGSpace [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 482 of file mesh_mrm.h.

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_PreciseClipping [private] +
+
+ + + + + +
+   + + +

+NB: HERE FOR PACKING ONLY. For clipping. Estimate if we must do a Precise clipping (ie with bboxes). +

+ +

+Definition at line 538 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<uint32> NL3D::CMeshMRMGeom::_ShadowSkinTriangles [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 571 of file mesh_mrm.h. +

+Referenced by renderShadowSkinPrimitives(), and setShadowMesh().

+

+ + + + +
+ + +
std::vector<CShadowVertex> NL3D::CMeshMRMGeom::_ShadowSkinVertices [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 570 of file mesh_mrm.h. +

+Referenced by compileRunTime(), computeBonesId(), getNumShadowSkinVertices(), renderShadowSkinGeom(), and setShadowMesh().

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_Skinned [private] +
+
+ + + + + +
+   + + +

+Skinning: This tells if the mesh is correctly skinned (suuport skinning). +

+ +

+Definition at line 478 of file mesh_mrm.h.

+

+ + + + +
+ + +
std::vector<CMesh::CSkinWeight> NL3D::CMeshMRMGeom::_SkinWeights [private] +
+
+ + + + + +
+   + + +

+This is the array of SkinWeights, same size as the VB. +

+ +

+Definition at line 490 of file mesh_mrm.h. +

+Referenced by applySkin(), build(), buildBoneUsageVer2(), computeBonesId(), getSkinWeights(), serialLodVertexData(), and updateRawSkinNormal().

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_SupportMeshBlockRendering [private] +
+
+ + + + + +
+   + + +

+setuped at compileRunTime. +

+ +

+Definition at line 560 of file mesh_mrm.h. +

+Referenced by CMeshMRMGeom(), compileRunTime(), and getVBHeapInfo().

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_SupportShadowSkinGrouping [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 572 of file mesh_mrm.h. +

+Referenced by CMeshMRMGeom(), compileRunTime(), setShadowMesh(), and supportShadowSkinGrouping().

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_SupportSkinGrouping [private] +
+
+ + + + + +
+   + + +

+if true, then maybe use faster render +

+ +

+Definition at line 498 of file mesh_mrm.h. +

+Referenced by CMeshMRMGeom(), compileRunTime(), and supportSkinGrouping().

+

+ + + + +
+ + +
CRefPtr<IVertexBufferHard> NL3D::CMeshMRMGeom::_VBHard [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 532 of file mesh_mrm.h.

+

+ + + + +
+ + +
CVertexBuffer NL3D::CMeshMRMGeom::_VBufferFinal [private] +
+
+ + + + + +
+   + + +

+The Final VBuffer. +

+ +

+Definition at line 487 of file mesh_mrm.h. +

+Referenced by applyGeomorph(), applyGeomorphWithVBHardPtr(), applySkin(), beginMesh(), bkupOriginalSkinVertices(), bkupOriginalSkinVerticesSubset(), build(), compileRunTime(), computeMeshVBHeap(), getVBHeapInfo(), getVertexBuffer(), profileSceneRender(), render(), renderSkin(), renderSkinGroupGeom(), restoreOriginalSkinPart(), restoreOriginalSkinVertices(), serialLodVertexData(), updateRawSkinNormal(), and updateVertexBufferHard().

+

+ + + + +
+ + +
CVertexBuffer NL3D::CMeshMRMGeom::_VBufferOriginal [private] +
+
+ + + + + +
+   + + +

+The Original VBuffer. +

+ +

+Definition at line 485 of file mesh_mrm.h. +

+Referenced by render(), and renderSkin().

+

+ + + + +
+ + +
bool NL3D::CMeshMRMGeom::_VertexBufferHardDirty [private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 535 of file mesh_mrm.h.

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::NumCacheVertexNormal1 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin1) [static] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 380 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::NumCacheVertexNormal2 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin2) [static] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 382 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::NumCacheVertexNormal3 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin3) [static] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 384 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::NumCacheVertexNormal4 = NL_BlockByteL1 / sizeof(CRawVertexNormalSkin4) [static] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 386 of file mesh_mrm_skin.cpp.

+

+ + + + +
+ + +
uint NL3D::CMeshMRMGeom::NumCacheVertexShadow = NL_BlockByteL1 / sizeof(CMeshMRMGeom::CShadowVertex) [static] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 389 of file mesh_mrm_skin.cpp. +

+Referenced by applyArrayShadowSkin().

+


The documentation for this class was generated from the following files: +
Generated on Tue Mar 16 06:53:13 2004 for NeL by + +doxygen +1.3.6
+ + -- cgit v1.2.1