# 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_instance.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_instance.h"
00029 #include "3d/mesh_multi_lod.h"
00030 #include "3d/coarse_mesh_manager.h"
00031 #include "3d/scene.h"
00032 
00033 #include "nel/misc/debug.h"
00034 
00035 using namespace NLMISC;
00036 
00037 namespace NL3D 
00038 {
00039 
00040 // ***************************************************************************
00041 
00042         CMeshMultiLodInstance::CMeshMultiLodInstance ()
00043 {
00044         // No flags
00045         Flags=0;
00046         _CoarseMeshDistance = -1.f;
00047 }
00048 
00049 // ***************************************************************************
00050 
00051 CMeshMultiLodInstance::~CMeshMultiLodInstance ()
00052 {
00053         // delete instances from manager
00054         deleteCoarseInstances();
00055 }
00056 
00057 
00058 // ***************************************************************************
00059 
00060 void            CMeshMultiLodInstance::registerBasic()
00061 {
00062         CMOT::registerModel (MeshMultiLodInstanceId, MeshBaseInstanceId, CMeshMultiLodInstance::creator);
00063         CMOT::registerObs (LoadBalancingTravId, MeshMultiLodInstanceId, CMeshMultiLodBalancingObs::creator);
00064         CMOT::registerObs (ClipTravId, MeshMultiLodInstanceId, CMeshMultiLodClipObs::creator);
00065 }
00066 
00067 
00068 // ***************************************************************************
00069 void            CMeshMultiLodInstance::deleteCoarseInstances()
00070 {
00071         // If at least one coarse instance is created
00072         if( Flags & (Coarse0Loaded|Coarse1Loaded) )
00073         {
00074                 // Cast shape
00075                 CMeshMultiLod *shape=safe_cast<CMeshMultiLod*> ((IShape*)Shape);
00076 
00077                 // Manager pointer
00078                 CCoarseMeshManager *manager;
00079 
00080                 // Get the manager
00081                 if (shape->isStatic ())
00082                         manager=getScene()->getStaticCoarseMeshManager ();
00083                 else
00084                         manager=getScene()->getDynamicCoarseMeshManager ();
00085 
00086                 // Manager ok ?
00087                 if (manager)
00088                 {
00089                         // Coarse mesh loaded ?
00090                         if (Flags&Coarse0Loaded)
00091                         {
00092                                 manager->removeMesh (CoarseMeshId[0]);
00093                                 Flags&= ~Coarse0Loaded;
00094                         }
00095                         if (Flags&Coarse1Loaded)
00096                         {
00097                                 manager->removeMesh (CoarseMeshId[1]);
00098                                 Flags&= ~Coarse1Loaded;
00099                         }
00100                 }
00101         }
00102 }
00103 
00104 
00105 // ***************************************************************************
00106 CRGBA           CMeshMultiLodInstance::getCoarseMeshLighting()
00107 {
00108         CScene  *scene= getScene();
00109         nlassert(scene);
00110 
00111         // compute his sun contribution result, and update
00112         CRGBA   sunContrib= scene->getSunDiffuse();
00113         // simulate/average diffuse lighting over the mesh by dividing diffuse by 2.
00114         sunContrib.modulateFromuiRGBOnly(sunContrib, getLightContribution().SunContribution/2 );
00115         // Add Ambient
00116         sunContrib.addRGBOnly(sunContrib, scene->getSunAmbient());
00117         sunContrib.A= 255;
00118 
00119         return sunContrib;
00120 }
00121 
00122 
00123 // ***************************************************************************
00124 bool            CMeshMultiLodClipObs::clip(IBaseClipObs *caller)
00125 {
00126         // Call Base method. If clipped
00127         if( !CTransformShapeClipObs::clip(caller) )
00128         {
00129                 // If the clip is due to a DistMax reason, must delete Coarses instances.
00130                 if(CTransformShapeClipObs::isLastClipDueToDistMax())
00131                 {
00132                         CMeshMultiLodInstance   *inst= (CMeshMultiLodInstance*)Model;
00133                         inst->deleteCoarseInstances();
00134                 }
00135 
00136                 // return result of clip
00137                 return false;
00138         }
00139         else
00140                 // return result of clip
00141                 return true;
00142 }
00143 
00144 
00145 // ***************************************************************************
00146 void            CMeshMultiLodClipObs::forceClip(TClipReason clipReason)
00147 {
00148         // If the clip is due to a DistMax reason, must delete Coarses instances.
00149         if(clipReason == IBaseClipObs::DistMaxClip)
00150         {
00151                 CMeshMultiLodInstance   *inst= (CMeshMultiLodInstance*)Model;
00152                 inst->deleteCoarseInstances();
00153         }
00154 
00155         // Call Base method (traverse Sons)
00156         CTransformShapeClipObs::forceClip(clipReason);
00157 }
00158 
00159 
00160 // ***************************************************************************
00161 
00162 void            CMeshMultiLodBalancingObs::traverse(IObs *caller)
00163 {
00164         // Call previous
00165         CTransformShapeLoadBalancingObs::traverse (caller);
00166 
00167         // If this is the second pass of LoadBalancing, choose the Lods, according to getNumTrianglesAfterLoadBalancing()
00168         CLoadBalancingTrav              *loadTrav= (CLoadBalancingTrav*)Trav;
00169         if(loadTrav->getLoadPass()==1)
00170         {
00171                 // Get a pointer on the model
00172                 CMeshMultiLodInstance *model=safe_cast<CMeshMultiLodInstance*> (Model);
00173 
00174                 // Get a pointer on the shape
00175                 CMeshMultiLod *shape=safe_cast<CMeshMultiLod*> ((IShape*)model->Shape);
00176 
00177                 // Reset render pass
00178                 model->setTransparency(false);
00179                 model->setOpacity(false);
00180 
00181                 // Get the wanted number of polygons
00182                 float polygonCount=model->getNumTrianglesAfterLoadBalancing ();
00183 
00184                 // Look for the good slot
00185                 uint meshCount=shape->_MeshVector.size();
00186                 model->Lod0=0;
00187                 if (meshCount>1)
00188                 {
00189                         // Look for good i
00190                         while ( polygonCount < shape->_MeshVector[model->Lod0].EndPolygonCount )
00191                         {
00192                                 model->Lod0++;
00193                                 if (model->Lod0==meshCount-1)
00194                                         break;
00195                         }
00196                 }
00197                 
00198                 // The slot
00199                 CMeshMultiLod::CMeshSlot        &slot=shape->_MeshVector[model->Lod0];
00200 
00201                 // Get the distance with polygon count
00202                 float distance=(polygonCount-slot.B)/slot.A;
00203 
00204                 // Get the final polygon count
00205                 if (slot.MeshGeom)
00206                         model->PolygonCountLod0=slot.MeshGeom->getNumTriangles (distance);
00207 
00208                 // Second slot in use ?
00209                 model->Lod1=0xffffffff;
00210 
00211                 // The next slot
00212                 CMeshMultiLod::CMeshSlot        *nextSlot=NULL;
00213 
00214                 // Next slot exist ?
00215                 if (model->Lod0!=meshCount-1)
00216                 {
00217                         nextSlot=&(shape->_MeshVector[model->Lod0+1]);
00218                 }
00219 
00220                 // Max dist before blend
00221                 float startBlend;
00222                 if (nextSlot)
00223                         startBlend=slot.DistMax-nextSlot->BlendLength;
00224                 else
00225                         startBlend=slot.DistMax-slot.BlendLength;
00226 
00227                 // In blend zone ?
00228                 if ( startBlend < distance )
00229                 {
00230                         // Alpha factor for main Lod
00231                         model->BlendFactor = (slot.DistMax-distance)/(slot.DistMax-startBlend);
00232                         if (model->BlendFactor<0)
00233                                 model->BlendFactor=0;
00234                         nlassert (model->BlendFactor<=1);
00235 
00236                         // Render this mesh
00237                         if (slot.MeshGeom)
00238                         {
00239                                 if (slot.Flags&CMeshMultiLod::CMeshSlot::BlendOut)
00240                                 {
00241                                         // Render the geom mesh with alpha blending with goodPolyCount
00242                                         model->setTransparency(true);
00243                                         model->Flags|=CMeshMultiLodInstance::Lod0Blend;
00244                                 }
00245                                 else
00246                                 {
00247                                         // Render the geom mesh without alpha blending with goodPolyCount
00248                                         model->setTransparency (slot.isTransparent());
00249                                         model->setOpacity (slot.isOpaque());
00250                                         model->Flags&=~CMeshMultiLodInstance::Lod0Blend;
00251                                 }
00252                         }
00253                         else
00254                                 model->Lod0=0xffffffff;
00255 
00256                         // Next mesh, BlendIn actived ?
00257                         if (nextSlot && shape->_MeshVector[model->Lod0+1].MeshGeom && (nextSlot->Flags&CMeshMultiLod::CMeshSlot::BlendIn))
00258                         {
00259                                 // Render the geom mesh with alpha blending with nextSlot->BeginPolygonCount
00260                                 model->PolygonCountLod1=nextSlot->MeshGeom->getNumTriangles (distance);
00261                                 model->Lod1=model->Lod0+1;
00262                                 model->setTransparency(true);
00263                         }
00264                 }
00265                 else
00266                 {
00267                         if (slot.MeshGeom)
00268                         {
00269                                 // Render without blend with goodPolyCount
00270                                 model->setTransparency (slot.isTransparent());
00271                                 model->setOpacity (slot.isOpaque());
00272                                 model->Flags&=~CMeshMultiLodInstance::Lod0Blend;
00273                         }
00274                         else
00275                                 model->Lod0=0xffffffff;
00276                 }
00277         }
00278 }
00279 
00280 // ***************************************************************************
00281 void            CMeshMultiLodInstance::changeMRMDistanceSetup(float distanceFinest, float distanceMiddle, float distanceCoarsest)
00282 {
00283         if(Shape)
00284         {
00285                 // Get a pointer on the shape.
00286                 CMeshMultiLod *pMesh =safe_cast<CMeshMultiLod*> ((IShape*)Shape);
00287                 // Affect the mesh directly.
00288                 pMesh->changeMRMDistanceSetup(distanceFinest, distanceMiddle, distanceCoarsest);
00289         }
00290 }
00291 
00292 
00293 // ***************************************************************************
00294 float      CMeshMultiLodInstance::getNumTriangles (float distance)
00295 {
00296         CMeshMultiLod *shape = safe_cast<CMeshMultiLod*> ((IShape*)Shape);
00297         return shape->getNumTrianglesWithCoarsestDist(distance, _CoarseMeshDistance);   
00298 }
00299 
00300 } // NL3D