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().

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