00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00045 Flags=0;
00046 _CoarseMeshDistance = -1.f;
00047 }
00048
00049
00050
00051 CMeshMultiLodInstance::~CMeshMultiLodInstance ()
00052 {
00053
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
00072 if( Flags & (Coarse0Loaded|Coarse1Loaded) )
00073 {
00074
00075 CMeshMultiLod *shape=safe_cast<CMeshMultiLod*> ((IShape*)Shape);
00076
00077
00078 CCoarseMeshManager *manager;
00079
00080
00081 if (shape->isStatic ())
00082 manager=getScene()->getStaticCoarseMeshManager ();
00083 else
00084 manager=getScene()->getDynamicCoarseMeshManager ();
00085
00086
00087 if (manager)
00088 {
00089
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
00112 CRGBA sunContrib= scene->getSunDiffuse();
00113
00114 sunContrib.modulateFromuiRGBOnly(sunContrib, getLightContribution().SunContribution/2 );
00115
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
00127 if( !CTransformShapeClipObs::clip(caller) )
00128 {
00129
00130 if(CTransformShapeClipObs::isLastClipDueToDistMax())
00131 {
00132 CMeshMultiLodInstance *inst= (CMeshMultiLodInstance*)Model;
00133 inst->deleteCoarseInstances();
00134 }
00135
00136
00137 return false;
00138 }
00139 else
00140
00141 return true;
00142 }
00143
00144
00145
00146 void CMeshMultiLodClipObs::forceClip(TClipReason clipReason)
00147 {
00148
00149 if(clipReason == IBaseClipObs::DistMaxClip)
00150 {
00151 CMeshMultiLodInstance *inst= (CMeshMultiLodInstance*)Model;
00152 inst->deleteCoarseInstances();
00153 }
00154
00155
00156 CTransformShapeClipObs::forceClip(clipReason);
00157 }
00158
00159
00160
00161
00162 void CMeshMultiLodBalancingObs::traverse(IObs *caller)
00163 {
00164
00165 CTransformShapeLoadBalancingObs::traverse (caller);
00166
00167
00168 CLoadBalancingTrav *loadTrav= (CLoadBalancingTrav*)Trav;
00169 if(loadTrav->getLoadPass()==1)
00170 {
00171
00172 CMeshMultiLodInstance *model=safe_cast<CMeshMultiLodInstance*> (Model);
00173
00174
00175 CMeshMultiLod *shape=safe_cast<CMeshMultiLod*> ((IShape*)model->Shape);
00176
00177
00178 model->setTransparency(false);
00179 model->setOpacity(false);
00180
00181
00182 float polygonCount=model->getNumTrianglesAfterLoadBalancing ();
00183
00184
00185 uint meshCount=shape->_MeshVector.size();
00186 model->Lod0=0;
00187 if (meshCount>1)
00188 {
00189
00190 while ( polygonCount < shape->_MeshVector[model->Lod0].EndPolygonCount )
00191 {
00192 model->Lod0++;
00193 if (model->Lod0==meshCount-1)
00194 break;
00195 }
00196 }
00197
00198
00199 CMeshMultiLod::CMeshSlot &slot=shape->_MeshVector[model->Lod0];
00200
00201
00202 float distance=(polygonCount-slot.B)/slot.A;
00203
00204
00205 if (slot.MeshGeom)
00206 model->PolygonCountLod0=slot.MeshGeom->getNumTriangles (distance);
00207
00208
00209 model->Lod1=0xffffffff;
00210
00211
00212 CMeshMultiLod::CMeshSlot *nextSlot=NULL;
00213
00214
00215 if (model->Lod0!=meshCount-1)
00216 {
00217 nextSlot=&(shape->_MeshVector[model->Lod0+1]);
00218 }
00219
00220
00221 float startBlend;
00222 if (nextSlot)
00223 startBlend=slot.DistMax-nextSlot->BlendLength;
00224 else
00225 startBlend=slot.DistMax-slot.BlendLength;
00226
00227
00228 if ( startBlend < distance )
00229 {
00230
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
00237 if (slot.MeshGeom)
00238 {
00239 if (slot.Flags&CMeshMultiLod::CMeshSlot::BlendOut)
00240 {
00241
00242 model->setTransparency(true);
00243 model->Flags|=CMeshMultiLodInstance::Lod0Blend;
00244 }
00245 else
00246 {
00247
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
00257 if (nextSlot && shape->_MeshVector[model->Lod0+1].MeshGeom && (nextSlot->Flags&CMeshMultiLod::CMeshSlot::BlendIn))
00258 {
00259
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
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
00286 CMeshMultiLod *pMesh =safe_cast<CMeshMultiLod*> ((IShape*)Shape);
00287
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 }