# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

mesh_multi_lod.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/mesh_multi_lod.h"
00029 #include "3d/mesh_multi_lod_instance.h"
00030 #include "3d/mesh_instance.h"
00031 #include "3d/mesh_mrm.h"
00032 #include "3d/scene.h"
00033 #include "3d/coarse_mesh_manager.h"
00034 #include "3d/skeleton_model.h"
00035 #include "3d/fast_floor.h"
00036 #include "3d/mesh_blender.h"
00037 
00038 #include "nel/misc/debug.h"
00039 
00040 using namespace NLMISC;
00041 
00042 namespace NL3D 
00043 {
00044 
00045 
00046 
00047 
00048 // ***************************************************************************
00049 
00050 void CMeshMultiLod::build(CMeshMultiLodBuild &mbuild)
00051 {
00052         // Clear the mesh
00053         clear ();
00054 
00055         // Build the base mesh
00056         CMeshBase::buildMeshBase (mbuild.BaseMesh);
00057 
00058         // Static flag
00059         _StaticLod=mbuild.StaticLod;
00060 
00061         // Resize the array
00062         _MeshVector.resize (mbuild.LodMeshes.size());
00063 
00064         // Number of coarse meshes
00065         uint coarse=0;
00066 
00067         // For each slots
00068         for (uint slot=0; slot<mbuild.LodMeshes.size(); slot++)
00069         {
00070                 // Dist max
00071                 _MeshVector[slot].DistMax=mbuild.LodMeshes[slot].DistMax;
00072 
00073                 // BlendLength
00074                 _MeshVector[slot].BlendLength=mbuild.LodMeshes[slot].BlendLength;
00075 
00076                 // Flags
00077                 _MeshVector[slot].Flags=0;
00078 
00079                 // Blend in ?
00080                 if (mbuild.LodMeshes[slot].Flags & CMeshMultiLodBuild::CBuildSlot::BlendIn)
00081                         _MeshVector[slot].Flags|=CMeshSlot::BlendIn;
00082 
00083                 // Blend out ?
00084                 if (mbuild.LodMeshes[slot].Flags & CMeshMultiLodBuild::CBuildSlot::BlendOut)
00085                         _MeshVector[slot].Flags|=CMeshSlot::BlendOut;
00086 
00087                 // Coarse mesh ?
00088                 if (mbuild.LodMeshes[slot].Flags & CMeshMultiLodBuild::CBuildSlot::CoarseMesh)
00089                 {
00090                         // Warning: no more than 2 coarse meshes in a lod mesh!
00091                         nlassert (coarse<=1);
00092 
00093                         // Flag
00094                         _MeshVector[slot].Flags|=CMeshSlot::CoarseMesh;
00095 
00096                         // Flag coarse ID
00097                         if (coarse==1)
00098                                 _MeshVector[slot].Flags|=CMeshSlot::CoarseMeshId;
00099 
00100                         // One more
00101                         coarse++;
00102                 }
00103 
00104                 // Is opaque
00105                 if (mbuild.LodMeshes[slot].Flags & CMeshMultiLodBuild::CBuildSlot::IsOpaque)
00106                         _MeshVector[slot].Flags|=CMeshSlot::IsOpaque;
00107 
00108                 // Is transparent
00109                 if (mbuild.LodMeshes[slot].Flags & CMeshMultiLodBuild::CBuildSlot::IsTransparent)
00110                         _MeshVector[slot].Flags|=CMeshSlot::IsTransparent;
00111 
00112                 // MeshGeom
00113                 nlassert (mbuild.LodMeshes[slot].MeshGeom);
00114 
00115                 // Valid pointer ?
00116                 if (_MeshVector[slot].Flags&CMeshSlot::CoarseMesh)
00117                 {
00118                         // If it is a coarse mesh, it must be a CMeshGeom.
00119                         if (dynamic_cast<CMeshGeom*>(mbuild.LodMeshes[slot].MeshGeom)==NULL)
00120                         {
00121                                 // If it is a coarse mesh, it must be a CMeshGeom.
00122                                 _MeshVector[slot].MeshGeom = NULL;
00123                                 delete mbuild.LodMeshes[slot].MeshGeom;
00124                         }
00125                         else
00126                                 // Ok, no prb
00127                                 _MeshVector[slot].MeshGeom = mbuild.LodMeshes[slot].MeshGeom;
00128                 }
00129                 else
00130                         // Ok, no prb
00131                         _MeshVector[slot].MeshGeom = mbuild.LodMeshes[slot].MeshGeom;   
00132         }
00133 
00134         // Sort the slot by the distance...
00135         for (int i=mbuild.LodMeshes.size()-1; i>0; i--)
00136         for (int j=0; j<i; j++)
00137         {
00138                 // Bad sort ?
00139                 if (_MeshVector[j].DistMax>_MeshVector[j+1].DistMax)
00140                 {
00141                         // Exchange slots
00142                         CMeshSlot tmp=_MeshVector[j];
00143                         _MeshVector[j]=_MeshVector[j+1];
00144                         _MeshVector[j+1]=tmp;
00145                         tmp.MeshGeom=NULL;
00146                 }
00147         }
00148 
00149         // Calc start and end polygon count
00150         for (uint k=0; k<mbuild.LodMeshes.size(); k++)
00151         {
00152                 // Get start distance
00153                 float startDist;
00154                 if (k==0)
00155                         startDist=0;
00156                 else 
00157                         startDist=_MeshVector[k-1].DistMax;
00158 
00159                 // Get start poly count
00160                 float startPolyCount;
00161                 startPolyCount=_MeshVector[k].MeshGeom->getNumTriangles (startDist);
00162 
00163                 // Get end distance
00164                 float endDist=_MeshVector[k].DistMax;
00165 
00166                 // Get end poly count
00167                 if (k==mbuild.LodMeshes.size()-1)
00168                 {
00169                         _MeshVector[k].EndPolygonCount=_MeshVector[k].MeshGeom->getNumTriangles (endDist);
00170                         if (startPolyCount==_MeshVector[k].EndPolygonCount)
00171                                 _MeshVector[k].EndPolygonCount=startPolyCount/2;
00172                 }
00173                 else 
00174                         _MeshVector[k].EndPolygonCount=_MeshVector[k+1].MeshGeom->getNumTriangles (endDist);
00175 
00176                 // Calc A
00177                 if (endDist==startDist)
00178                         _MeshVector[k].A=0;
00179                 else
00180                         _MeshVector[k].A=(_MeshVector[k].EndPolygonCount-startPolyCount)/(endDist-startDist);
00181 
00182                 // Calc A
00183                 _MeshVector[k].B=_MeshVector[k].EndPolygonCount-_MeshVector[k].A*endDist;
00184         }
00185 
00186         // End: compile the max distance of display
00187         compileDistMax();
00188 }
00189 
00190 // ***************************************************************************
00191 
00192 CTransformShape *CMeshMultiLod::createInstance(CScene &scene)
00193 {
00194         // Create a CMeshInstance, an instance of a multi lod mesh.
00195         CMeshMultiLodInstance *mi=(CMeshMultiLodInstance*)scene.createModel(NL3D::MeshMultiLodInstanceId);
00196         mi->Shape= this;
00197         mi->_LastLodMatrixDate[0]=0;
00198         mi->_LastLodMatrixDate[1]=0;
00199 
00200         // instanciate the material part of the Mesh, ie the CMeshBase.
00201         CMeshBase::instanciateMeshBase(mi, &scene);
00202 
00203 
00204         // For all lods, do some instance init for MeshGeom
00205         for(uint i=0; i<_MeshVector.size(); i++)
00206         {
00207                 if(_MeshVector[i].MeshGeom)
00208                         _MeshVector[i].MeshGeom->initInstance(mi);
00209         }
00210 
00211 
00212         return mi;
00213 }
00214 
00215 // ***************************************************************************
00216 
00217 bool CMeshMultiLod::clip(const std::vector<CPlane>      &pyramid, const CMatrix &worldMatrix)
00218 {
00219         // Look for the biggest mesh
00220         uint meshCount=_MeshVector.size();
00221         for (uint i=0; i<meshCount; i++)
00222         {
00223                 // Ref on slot
00224                 CMeshSlot &slot=_MeshVector[i];
00225 
00226                 // Is mesh present ?
00227                 if (slot.MeshGeom)
00228                 {
00229                         // Clip this mesh
00230                         return slot.MeshGeom->clip (pyramid, worldMatrix);
00231                 }
00232         }
00233         return true;
00234 }
00235 
00236 // ***************************************************************************
00237 
00238 void CMeshMultiLod::render(IDriver *drv, CTransformShape *trans, bool passOpaque)
00239 {
00240         // Render good meshes
00241         CMeshMultiLodInstance *instance=safe_cast<CMeshMultiLodInstance*>(trans);
00242 
00243         // Static or dynamic coarse mesh ?
00244         CCoarseMeshManager *manager;
00245         if (_StaticLod)
00246         {
00247                 // Get the static coarse mesh manager
00248                 manager=instance->getScene()->getStaticCoarseMeshManager();
00249         }
00250         else
00251         {
00252                 // Get the dynamic coarse mesh manager
00253                 manager=instance->getScene()->getDynamicCoarseMeshManager();
00254         }
00255 
00256         // *** Render Lods
00257 
00258         // Second lod ?
00259         if ( (instance->Lod1!=0xffffffff) && (passOpaque==false) )
00260         {
00261                 // build rdrFlags to rdr both transparent and opaque materials, 
00262                 // use globalAlphaBlend, and disable ZWrite for Lod1
00263                 uint32  rdrFlags= IMeshGeom::RenderOpaqueMaterial | IMeshGeom::RenderTransparentMaterial |
00264                         IMeshGeom::RenderGlobalAlpha | IMeshGeom::RenderGADisableZWrite;
00265                 // NB: very important to render Lod1 first, because Lod0 is still rendered with ZWrite enabled.
00266                 renderMeshGeom (instance->Lod1, drv, instance, instance->PolygonCountLod1, rdrFlags, 1.f-instance->BlendFactor, manager);
00267         }
00268 
00269 
00270         // Have an opaque pass ?
00271         if ( (instance->Flags&CMeshMultiLodInstance::Lod0Blend) == 0)
00272         {
00273                 // Is this slot a CoarseMesh?
00274                 if ( _MeshVector[instance->Lod0].Flags&CMeshSlot::CoarseMesh )
00275                 {
00276                         // render as a CoarseMesh the lod 0, only in opaque pass
00277                         if(passOpaque)
00278                                 renderCoarseMesh (instance->Lod0, drv, instance, manager);
00279                 }
00280                 else
00281                 {
00282                         // build rdrFlags the normal way (as CMesh::render() for example)
00283                         uint32  mask= (0-(uint32)passOpaque);
00284                         uint32  rdrFlags;
00285                         // select rdrFlags, without ifs.
00286                         rdrFlags=       mask & (IMeshGeom::RenderOpaqueMaterial | IMeshGeom::RenderPassOpaque);
00287                         rdrFlags|=      ~mask & (IMeshGeom::RenderTransparentMaterial);
00288                         // Only render the normal way the first lod
00289                         renderMeshGeom (instance->Lod0, drv, instance, instance->PolygonCountLod0, rdrFlags, 1, manager);
00290                 }
00291         }
00292         else
00293         {
00294                 // Should not be in opaque
00295                 nlassert (passOpaque==false);
00296 
00297                 // build rdrFlags to rdr both transparent and opaque materials, 
00298                 // use globalAlphaBlend, BUT Don't disable ZWrite for Lod0
00299                 uint32  rdrFlags= IMeshGeom::RenderOpaqueMaterial | IMeshGeom::RenderTransparentMaterial |
00300                         IMeshGeom::RenderGlobalAlpha;
00301 
00302                 // Render first lod in blend mode. Don't disable ZWrite for Lod0
00303                 renderMeshGeom (instance->Lod0, drv, instance, instance->PolygonCountLod0, rdrFlags, instance->BlendFactor, manager);
00304         }
00305 
00306         // *** Remove unused coarse meshes.
00307         // Manager must exist beacuse a mesh has been loaded...
00308         if (manager)
00309         {
00310                 uint meshCount=_MeshVector.size();
00311                 for (uint j=0; j<meshCount; j++)
00312                 {
00313                         // Is this slot a CoarseMesh?
00314                         if ( _MeshVector[j].Flags&CMeshSlot::CoarseMesh )
00315                         {
00316                                 // Are we in Alpha Blend Transition?
00317                                 bool    alphaTrans= instance->Flags&CMeshMultiLodInstance::Lod0Blend;
00318                                 // we must remove coarse if the slot is not used, or if we are in Alpha Transition.
00319                                 // NB: only Lod0 can use CoarseMesh (see code before)
00320                                 if ( alphaTrans || (j!=instance->Lod0) )
00321                                 {
00322                                         // Get coarse id
00323                                         uint coarseId=(_MeshVector[j].Flags&CMeshSlot::CoarseMeshId)?1:0;
00324                                         uint flag=CMeshMultiLodInstance::Coarse0Loaded<<coarseId;
00325                                         
00326                                         // Coarse mesh loaded ?
00327                                         if ( instance->Flags&flag )
00328                                         {
00329                                                 // Yes, remove it..
00330 
00331                                                 // Remove the lod
00332                                                 manager->removeMesh (instance->CoarseMeshId[coarseId]);
00333 
00334                                                 // Clear the flag
00335                                                 instance->Flags&=~flag;
00336                                         }
00337                                 }
00338                         }
00339                 }
00340         }
00341 }
00342 
00343 // ***************************************************************************
00344 
00345 void CMeshMultiLod::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00346 {
00347         // Serial a version number
00348         (void)f.serialVersion (0);
00349 
00350         // serial Materials infos contained in CMeshBase.
00351         CMeshBase::serialMeshBase(f);
00352 
00353         // Static lod flag
00354         f.serial (_StaticLod);
00355 
00356         // Serial the values
00357         f.serialCont (_MeshVector);
00358 
00359 
00360         // if reading, compile the new max distance of display
00361         if (f.isReading())
00362         {
00363                 compileDistMax();
00364         }
00365 }
00366 
00367 // ***************************************************************************
00368 
00369 float CMeshMultiLod::getNumTriangles (float distance)
00370 {
00371         // Look in the table for good distances..
00372         uint meshCount=_MeshVector.size();
00373 
00374         // At least on mesh
00375         if (meshCount>0)
00376         {
00377                 uint i=0;
00378 
00379                 // Look for good i
00380                 while ( _MeshVector[i].DistMax<distance )
00381                 {
00382                         if (i==meshCount-1)
00383                                 // Abort if last one
00384                                 break;
00385                         i++;
00386                 }
00387 
00388                 // Ref on slot
00389                 CMeshSlot &slot=_MeshVector[i];
00390 
00391                 // Is mesh present ?
00392                 if (slot.MeshGeom)
00393                 {
00394                         // Get the polygon count with the distance
00395                         float polyCount=slot.A * distance + slot.B;
00396 
00397                         /*// Get the perfect polygon count in this slot for the asked distance
00398                         float goodPolyCount=slot.MeshGeom->getNumTriangles (distance);
00399 
00400                         // Get the next slot perfect polygon count
00401                         float realEndPolyCount;
00402 
00403                         // Last slot ?
00404                         if ( (i<meshCount-1) && _MeshVector[i+1].MeshGeom )
00405                                 // Take end number polygon count in the next slot
00406                                 realEndPolyCount=_MeshVector[i+1].MeshGeom->getNumTriangles (slot.DistMax);
00407                         else
00408                                 // Take end number polygon count in the this slot
00409                                 realEndPolyCount=slot.EndPolygonCount;
00410 
00411                         // Return blended polygon count to have a continous decreasing function
00412                         return (goodPolyCount-slot.BeginPolygonCount) * (realEndPolyCount-slot.BeginPolygonCount) / 
00413                                 (slot.EndPolygonCount-slot.BeginPolygonCount) + slot.BeginPolygonCount;*/
00414                         return polyCount;
00415                 }
00416         }
00417 
00418         return 0;
00419 }
00420 
00421 // ***************************************************************************
00422 
00423 void CMeshMultiLod::getAABBox(NLMISC::CAABBox &bbox) const
00424 {
00425         // Get count
00426         uint count=_MeshVector.size();
00427         for (uint slot=0; slot<count; slot++)
00428         {
00429                 // Shape ?
00430                 if (_MeshVector[slot].MeshGeom)
00431                 {
00432                         // Get the bounding box
00433                         bbox=_MeshVector[slot].MeshGeom->getBoundingBox().getAABBox();
00434 
00435                         // ok
00436                         break;
00437                 }
00438         }
00439 }
00440 
00441 // ***************************************************************************
00442 
00443 void CMeshMultiLod::clear ()
00444 {
00445         _MeshVector.clear ();
00446 }
00447 
00448 // ***************************************************************************
00449 
00450 void CMeshMultiLod::CMeshSlot::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00451 {
00452         // Check version
00453         (void)f.serialVersion (0);
00454 
00455         f.serialPolyPtr (MeshGeom);
00456         f.serial (A);
00457         f.serial (B);
00458         f.serial (DistMax);
00459         f.serial (EndPolygonCount);
00460         f.serial (BlendLength);
00461         f.serial (Flags);
00462 
00463         if (f.isReading())
00464         {
00465         }
00466 }
00467 
00468 // ***************************************************************************
00469 
00470 CMeshMultiLod::CMeshSlot::CMeshSlot ()
00471 {
00472         MeshGeom=NULL;
00473 }
00474 
00475 // ***************************************************************************
00476 
00477 CMeshMultiLod::CMeshSlot::~CMeshSlot ()
00478 {
00479         if (MeshGeom)
00480                 delete MeshGeom;
00481 }
00482 
00483 // ***************************************************************************
00484 
00485 void CMeshMultiLod::renderMeshGeom (uint slot, IDriver *drv, CMeshMultiLodInstance *trans, float numPoylgons, uint32 rdrFlags, float alpha, CCoarseMeshManager *manager)
00486 {
00487         // Ref
00488         CMeshSlot &slotRef=_MeshVector[slot];
00489 
00490         // MeshGeom exist?
00491         if (slotRef.MeshGeom)
00492         {
00493                 // NB Here, the meshGeom may still be a coarseMesh, but rendered through CMeshGeom
00494                 if(slotRef.Flags&CMeshSlot::CoarseMesh)
00495                 {
00496                         // Render only for opaque material
00497                         if(manager && (rdrFlags & IMeshGeom::RenderOpaqueMaterial) )
00498                         {
00499                                 bool    gaDisableZWrite= (rdrFlags & IMeshGeom::RenderGADisableZWrite)?true:false;
00500 
00501                                 // Render the CoarseMesh with the manager material
00502                                 CMaterial       &material= manager->getMaterial();
00503 
00504                                 // modulate material for alphaBlend transition
00505                                 // ----------
00506                                 // get average sun color for this coarseMesh
00507                                 CRGBA   newCol= trans->getCoarseMeshLighting();
00508 
00509                                 // Use a CMeshBlender to modify material and driver.
00510                                 CMeshBlender    blender;
00511                                 blender.prepareRenderForGlobalAlphaCoarseMesh(material, drv, newCol, alpha, gaDisableZWrite);
00512                                 
00513 
00514                                 // render simple the coarseMesh
00515                                 CMeshGeom *meshGeom= safe_cast<CMeshGeom*>(slotRef.MeshGeom);
00516                                 meshGeom->renderSimpleWithMaterial(drv, trans->getWorldMatrix(), material);
00517 
00518 
00519                                 // resetup standard CoarseMeshMaterial material values
00520                                 // ----------
00521                                 // blender restore
00522                                 blender.restoreRenderCoarseMesh(material, drv, gaDisableZWrite);
00523                         }
00524                 }
00525                 else
00526                 {
00527                         // Render the geom mesh
00528                         // Disable ZWrite only if in transition and for rendering Lod1
00529                         slotRef.MeshGeom->render (drv, trans, numPoylgons, rdrFlags, alpha);
00530                 }
00531         }
00532 }
00533 // ***************************************************************************
00534 
00535 void CMeshMultiLod::renderCoarseMesh (uint slot, IDriver *drv, CMeshMultiLodInstance *trans, CCoarseMeshManager *manager)
00536 {
00537         // if the manager is NULL, quit.
00538         if(manager==NULL)
00539                 return;
00540 
00541         // Ref
00542         CMeshSlot &slotRef=_MeshVector[slot];
00543 
00544         // the slot must be a Coarse mesh
00545         nlassert(slotRef.Flags&CMeshSlot::CoarseMesh);
00546 
00547         // Mask
00548         uint coarseId=(slotRef.Flags&CMeshSlot::CoarseMeshId)?1:0;
00549         uint maskFlag = CMeshMultiLodInstance::Coarse0Loaded<<coarseId;
00550 
00551         // Get a pointer on the geom mesh
00552         CMeshGeom *meshGeom= safe_cast<CMeshGeom*>(slotRef.MeshGeom);
00553 
00554         // Added in the manager ?
00555         if ( (trans->Flags&maskFlag) == 0)
00556         {
00557                 // Add to the manager
00558                 trans->CoarseMeshId[coarseId]=manager->addMesh (*meshGeom);
00559                         
00560                 // Added ?
00561                 if (trans->CoarseMeshId[coarseId]!=CCoarseMeshManager::CantAddCoarseMesh)
00562                         // Flag it
00563                         trans->Flags|=maskFlag;
00564 
00565                 // Dirt the matrix
00566                 trans->_LastLodMatrixDate[coarseId]=0;
00567                 // Dirt the lighting. NB: period maximum is 255. Hence the -256, to ensure lighting compute now
00568                 trans->_LastLodLightingDate[coarseId]= -0x100;
00569         }
00570 
00571         // Finally loaded ?
00572         if (trans->Flags&maskFlag)
00573         {
00574                 // Matrix has changed ?
00575                 if ( trans->ITransformable::compareMatrixDate (trans->_LastLodMatrixDate[coarseId]) )
00576                 {
00577                         // Get date
00578                         trans->_LastLodMatrixDate[coarseId] = trans->ITransformable::getMatrixDate();
00579 
00580                         // Set matrix
00581                         manager->setMatrixMesh ( trans->CoarseMeshId[coarseId], *meshGeom, trans->getMatrix() );
00582                 }
00583 
00584                 // Lighting: test if must update lighting, according to date of HrcTrav (num of CScene::render() call).
00585                 CScene  *scene= trans->getScene();
00586                 if(scene)
00587                 {
00588                         sint64  currentDate= scene->getHrcTrav()->CurrentDate;
00589                         if( trans->_LastLodLightingDate[coarseId] < currentDate - scene->getCoarseMeshLightingUpdate() )
00590                         {
00591                                 // reset the date.
00592                                 trans->_LastLodLightingDate[coarseId]= currentDate;
00593 
00594                                 // get average sun color
00595                                 CRGBA   sunContrib= trans->getCoarseMeshLighting();
00596 
00597                                 // Set color
00598                                 manager->setColorMesh ( trans->CoarseMeshId[coarseId], *meshGeom, sunContrib );
00599                         }
00600                 }
00601         }
00602 }
00603 
00604 // ***************************************************************************
00605 void    CMeshMultiLod::compileDistMax()
00606 {
00607         // Last element
00608         std::vector<CMeshSlot>::const_iterator ite=_MeshVector.end();
00609         ite--;
00610         if (ite!=_MeshVector.end())
00611                 IShape::_DistMax= ite->DistMax;
00612         else
00613                 IShape::_DistMax= -1;
00614 }
00615 
00616 // ***************************************************************************
00617 const IMeshGeom& CMeshMultiLod::getMeshGeom (uint slot) const
00618 {
00619         // Checks
00620         nlassert (slot<getNumSlotMesh ());
00621 
00622         return *_MeshVector[slot].MeshGeom;
00623 }
00624 
00625 
00626 // ***************************************************************************
00627 void                    CMeshMultiLod::changeMRMDistanceSetup(float distanceFinest, float distanceMiddle, float distanceCoarsest)
00628 {
00629         // no-op if empty.
00630         if(getNumSlotMesh ()==0)
00631                 return;
00632 
00633         // If not NULL
00634         if(_MeshVector[0].MeshGeom==NULL)
00635                 return;
00636 
00637         // verify it is a CMeshMRMGeom. else no-op.
00638         CMeshMRMGeom    *mgeom= dynamic_cast<CMeshMRMGeom*>(_MeshVector[0].MeshGeom);
00639         if(mgeom==NULL)
00640                 return;
00641         
00642         // ok, setup.
00643         mgeom->changeMRMDistanceSetup(distanceFinest, distanceMiddle, distanceCoarsest);
00644 }
00645 
00646 
00647 // ***************************************************************************
00648 IMeshGeom               *CMeshMultiLod::supportMeshBlockRendering (CTransformShape *trans, float &polygonCount ) const
00649 {
00650         IMeshGeom       *ret= NULL;
00651 
00652         // get the instance
00653         CMeshMultiLodInstance *instance=safe_cast<CMeshMultiLodInstance*>(trans);
00654 
00655         // Must not be in blend transition.
00656         if ( (instance->Flags&CMeshMultiLodInstance::Lod0Blend) == 0)
00657         {
00658                 uint    slot= instance->Lod0;
00659                 // The slot must not be a CoarseMesh
00660                 if ( (_MeshVector[slot].Flags&CMeshSlot::CoarseMesh)==0 )
00661                 {
00662                         // MeshGeom exist?
00663                         ret= _MeshVector[slot].MeshGeom;
00664                 }
00665         }
00666 
00667         // Ok if meshGeom is ok.
00668         if( ret && ret->supportMeshBlockRendering() )
00669         {
00670                 polygonCount= instance->PolygonCountLod0;
00671                 return ret;
00672         }
00673         else
00674                 return NULL;
00675 }
00676 
00677 
00678 } // NL3D