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_base_instance.h"
00029 #include "3d/mesh_base.h"
00030 #include "3d/scene.h"
00031 #include "3d/animation.h"
00032 #include "nel/misc/debug.h"
00033 #include "3d/anim_detail_trav.h"
00034 #include "3d/texture_file.h"
00035 #include "3d/async_texture_manager.h"
00036
00037
00038 using namespace NLMISC;
00039
00040 namespace NL3D
00041 {
00042
00043
00044
00045 CMeshBaseInstance::CMeshBaseInstance()
00046 {
00047 IAnimatable::resize(AnimValueLast);
00048 _OwnerScene= NULL;
00049 _AsyncTextureToLoadRefCount= 0;
00050 _AsyncTextureMode= false;
00051 _AsyncTextureReady= true;
00052 _AsyncTextureDirty= false;
00053 _AsyncTextureDistance= 0;
00054
00055
00056 CTransform::setIsMeshBaseInstance(true);
00057 }
00058
00059
00060 CMeshBaseInstance::~CMeshBaseInstance()
00061 {
00062
00063
00064 if(_AsyncTextureMode)
00065 enableAsyncTextureMode(false);
00066 }
00067
00068
00069
00070 void CMeshBaseInstance::registerBasic()
00071 {
00072 CMOT::registerModel(MeshBaseInstanceId, TransformShapeId, CMeshBaseInstance::creator);
00073 CMOT::registerObs(AnimDetailTravId, MeshBaseInstanceId, CMeshBaseInstanceAnimDetailObs::creator);
00074 }
00075
00076
00077
00078 void CMeshBaseInstance::registerToChannelMixer(CChannelMixer *chanMixer, const std::string &prefix)
00079 {
00080 uint32 i;
00081 CTransformShape::registerToChannelMixer(chanMixer, prefix);
00082
00083
00084 for (i = 0; i < _AnimatedMaterials.size(); i++)
00085 {
00086
00087 _AnimatedMaterials[i].registerToChannelMixer(chanMixer, prefix + _AnimatedMaterials[i].getMaterialName() + ".");
00088 }
00089
00090
00091 for (i = 0; i < _AnimatedMorphFactor.size(); i++)
00092 {
00093 _AnimatedMorphFactor[i].registerToChannelMixer(chanMixer, prefix + _AnimatedMorphFactor[i].getName());
00094 }
00095 }
00096
00097
00098
00099 ITrack* CMeshBaseInstance::getDefaultTrack (uint valueId)
00100 {
00101
00102 CMeshBase* pMesh=(CMeshBase*)(IShape*)Shape;
00103
00104
00105 switch (valueId)
00106 {
00107 case CTransform::PosValue:
00108 return pMesh->getDefaultPos();
00109 case CTransform::RotEulerValue:
00110 return pMesh->getDefaultRotEuler();
00111 case CTransform::RotQuatValue:
00112 return pMesh->getDefaultRotQuat();
00113 case CTransform::ScaleValue:
00114 return pMesh->getDefaultScale();
00115 case CTransform::PivotValue:
00116 return pMesh->getDefaultPivot();
00117 default:
00118
00119 nlstop;
00120 };
00121 return NULL;
00122 }
00123
00124
00125
00126 uint32 CMeshBaseInstance::getNbLightMap()
00127 {
00128 CMeshBase* pMesh=(CMeshBase*)(IShape*)Shape;
00129 return pMesh->_LightInfos.size();
00130 }
00131
00132
00133 void CMeshBaseInstance::getLightMapName( uint32 nLightMapNb, std::string &LightMapName )
00134 {
00135 CMeshBase* pMesh=(CMeshBase*)(IShape*)Shape;
00136 if( nLightMapNb >= pMesh->_LightInfos.size() )
00137 return;
00138 CMeshBase::TLightInfoMap::iterator itMap = pMesh->_LightInfos.begin();
00139 for( uint32 i = 0; i < nLightMapNb; ++i ) ++itMap;
00140 LightMapName = itMap->first;
00141 }
00142
00143
00144 void CMeshBaseInstance::setLightMapFactor( const std::string &LightMapName, CRGBA Factor )
00145 {
00146 CMeshBase* pMesh=(CMeshBase*)(IShape*)Shape;
00147 CMeshBase::TLightInfoMap::iterator itMap = pMesh->_LightInfos.find( LightMapName );
00148 if( itMap == pMesh->_LightInfos.end() )
00149 return;
00150 CMeshBase::CLightInfoMapList::iterator itList = itMap->second.begin();
00151 uint32 nNbElt = itMap->second.size();
00152 for( uint32 i = 0; i < nNbElt; ++i )
00153 {
00154 Materials[itList->nMatNb].setLightMapFactor( itList->nStageNb, Factor );
00155 ++itList;
00156 }
00157 }
00158
00159
00160 uint32 CMeshBaseInstance::getNbBlendShape()
00161 {
00162 return _AnimatedMorphFactor.size();
00163 }
00164
00165
00166 void CMeshBaseInstance::getBlendShapeName (uint32 nBlendShapeNb, std::string &BlendShapeName )
00167 {
00168 if (nBlendShapeNb >= _AnimatedMorphFactor.size())
00169 return;
00170 BlendShapeName = _AnimatedMorphFactor[nBlendShapeNb].getName();
00171 }
00172
00173
00174 void CMeshBaseInstance::setBlendShapeFactor (const std::string &BlendShapeName, float rFactor)
00175 {
00176 for (uint32 i = 0; i < _AnimatedMorphFactor.size(); ++i)
00177 if (BlendShapeName == _AnimatedMorphFactor[i].getName())
00178 {
00179 _AnimatedMorphFactor[i].setFactor (rFactor);
00180 }
00181 }
00182
00183
00184
00185 void CMeshBaseInstanceAnimDetailObs::traverse(IObs *caller)
00186 {
00187
00188 CMeshBaseInstance *mi = (CMeshBaseInstance*)Model;
00189 CMeshBase *mb = NLMISC::safe_cast<CMeshBase *>((IShape *) mi->Shape);
00190
00191
00192 if (mb->getAutoAnim())
00193 {
00194
00195 CChannelMixer *chanMix = mi->getChannelMixer();
00196 if (chanMix)
00197 {
00198 ITravScene *ts = NLMISC::safe_cast<ITravScene *>(Trav);
00199 nlassert(ts->Scene);
00200 const CAnimation *anim = chanMix->getSlotAnimation(0);
00204 if (anim)
00205 {
00206 float animLenght = anim->getEndTime() - anim->getBeginTime();
00207 if (animLenght > 0)
00208 {
00209 float currTime = (TAnimationTime) ts->Scene->getCurrentTime();
00210 float startTime = (uint) (currTime / animLenght) * animLenght;
00211
00212 chanMix->setSlotTime(0, anim->getBeginTime() + currTime - startTime);
00213 }
00214 else
00215 {
00216 chanMix->setSlotTime(0, anim->getBeginTime());
00217 }
00218
00223 chanMix->eval(false);
00224 }
00225 }
00226 }
00227
00228 CTransformAnimDetailObs::traverse(caller);
00229
00230
00231
00232
00233 if(mi->IAnimatable::isTouched(CMeshBaseInstance::OwnerBit))
00234 {
00235
00236 for(uint i=0;i<mi->_AnimatedMaterials.size();i++)
00237 {
00238
00239 mi->_AnimatedMaterials[i].update();
00240 }
00241
00242 mi->IAnimatable::clearFlag(CMeshBaseInstance::OwnerBit);
00243 }
00244
00245
00246 for( uint i = 0; i < mi->_AnimatedLightmap.size(); ++i )
00247 {
00248 const char *LightGroupName = strchr( mi->_AnimatedLightmap[i]->getName().c_str(), '.' )+1;
00249 mi->setLightMapFactor( LightGroupName,
00250 mi->_AnimatedLightmap[i]->getFactor() );
00251 }
00252 }
00253
00254
00255
00256 void CMeshBaseInstance::selectTextureSet(uint id)
00257 {
00258 nlassert(Shape);
00259 CMeshBase *mb = NLMISC::safe_cast<CMeshBase *>((IShape *) Shape);
00260 const uint numMat = mb->getNbMaterial();
00261 nlassert(numMat == Materials.size());
00262
00263 for(uint k = 0; k < numMat; ++k)
00264 {
00265 CMaterial &mat = mb->getMaterial(k);
00266 for(uint l = 0; l < IDRV_MAT_MAXTEXTURES; ++l)
00267 {
00268 if (mat.getTexture(l) && mat.getTexture(l)->isSelectable())
00269 {
00270
00271 CSmartPtr<ITexture> texNSV= mat.getTexture(l)->buildNonSelectableVersion(id);
00272
00273
00274 if(!_AsyncTextureMode)
00275 {
00276 Materials[k].setTexture(l, texNSV);
00277 }
00278
00279 else
00280 {
00281
00282 if(AsyncTextures[k].IsTextureFile[l])
00283 {
00284 CTextureFile *textFile= safe_cast<CTextureFile*>((ITexture*)texNSV);
00285 AsyncTextures[k].TextureNames[l]= textFile->getFileName();
00286 }
00287
00288 else
00289 Materials[k].setTexture(l, texNSV);
00290 }
00291 }
00292 }
00293 }
00294
00295
00296 if(_AsyncTextureMode)
00297 {
00298 setAsyncTextureDirty(true);
00299 }
00300 }
00301
00302
00303
00304 void CMeshBaseInstance::setAnimatedLightmap (CAnimatedLightmap *alm)
00305 {
00306 _AnimatedLightmap.push_back( alm );
00307
00308 CTransform::setIsForceAnimDetail(true);
00309 }
00310
00311
00312
00313 uint CMeshBaseInstance::getNumMaterial () const
00314 {
00315 return Materials.size ();
00316 }
00317
00318
00319
00320 const CMaterial *CMeshBaseInstance::getMaterial (uint materialId) const
00321 {
00322 return &(Materials[materialId]);
00323 }
00324
00325
00326
00327 CMaterial *CMeshBaseInstance::getMaterial (uint materialId)
00328 {
00329 return &(Materials[materialId]);
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 void CMeshBaseInstance::enableAsyncTextureMode(bool enable)
00342 {
00343
00344 if(_AsyncTextureMode==enable)
00345 return;
00346 _AsyncTextureMode= enable;
00347
00348
00349 if(_AsyncTextureMode)
00350 {
00351 _AsyncTextureReady= true;
00352
00353
00354 for(uint i=0;i<Materials.size();i++)
00355 {
00356 for(uint stage=0;stage<IDRV_MAT_MAXTEXTURES;stage++)
00357 {
00358
00359 CTextureFile *text= dynamic_cast<CTextureFile*>(Materials[i].getTexture(stage));
00360 if(text)
00361 {
00362
00363 AsyncTextures[i].IsTextureFile[stage]= true;
00364 AsyncTextures[i].TextureNames[stage]= text->getFileName();
00365
00366 CTextureFile *tf = new CTextureFile(*text);
00367
00368 tf->setFileName("blank.tga");
00369 Materials[i].setTexture(stage, tf);
00370 }
00371 else
00372 {
00373 AsyncTextures[i].IsTextureFile[stage]= false;
00374 }
00375 }
00376 }
00377
00378
00379 setAsyncTextureDirty(true);
00380 }
00381
00382 else
00383 {
00384
00385 releaseCurrentAsyncTextures();
00386 nlassert(_AsyncTextureToLoadRefCount==0);
00387
00388 contReset(_CurrentAsyncTextures);
00389
00390
00391 for(uint i=0;i<Materials.size();i++)
00392 {
00393 for(uint stage=0;stage<IDRV_MAT_MAXTEXTURES;stage++)
00394 {
00395
00396 if(AsyncTextures[i].IsTextureFile[stage])
00397 {
00398
00399 CTextureFile *text= safe_cast<CTextureFile*>(Materials[i].getTexture(stage));
00400 text->setFileName(AsyncTextures[i].TextureNames[stage]);
00401
00402 AsyncTextures[i].TextureNames[stage].clear();
00403 }
00404 }
00405 }
00406 }
00407 }
00408
00409
00410
00411 void CMeshBaseInstance::startAsyncTextureLoading()
00412 {
00413 if(!getAsyncTextureMode())
00414 return;
00415
00416
00417 CAsyncTextureManager *asyncTextMgr= _OwnerScene->getAsyncTextureManager();
00418 if(!asyncTextMgr)
00419 return;
00420
00421 uint i;
00422
00423
00424
00425
00426
00427 for(i=0;i<AsyncTextures.size();i++)
00428 {
00429 for(uint stage=0;stage<IDRV_MAT_MAXTEXTURES;stage++)
00430 {
00431 if(AsyncTextures[i].IsTextureFile[stage])
00432 {
00433 uint id;
00434 id= asyncTextMgr->addTextureRef(AsyncTextures[i].TextureNames[stage], this);
00435 AsyncTextures[i].TextIds[stage]= id;
00436 }
00437 }
00438 }
00439
00440
00441
00442 releaseCurrentAsyncTextures();
00443
00444
00445 _CurrentAsyncTextures= AsyncTextures;
00446
00447
00448 _AsyncTextureReady= false;
00449 }
00450
00451
00452 void CMeshBaseInstance::releaseCurrentAsyncTextures()
00453 {
00454
00455 CAsyncTextureManager *asyncTextMgr= _OwnerScene->getAsyncTextureManager();
00456 if(!asyncTextMgr)
00457 return;
00458
00459
00460 for(uint i=0;i<_CurrentAsyncTextures.size();i++)
00461 {
00462 for(uint stage=0;stage<IDRV_MAT_MAXTEXTURES;stage++)
00463 {
00464 if(_CurrentAsyncTextures[i].IsTextureFile[stage])
00465 {
00466 asyncTextMgr->releaseTexture(_CurrentAsyncTextures[i].TextIds[stage], this);
00467 }
00468 }
00469 }
00470 }
00471
00472
00473 bool CMeshBaseInstance::isAsyncTextureReady()
00474 {
00475
00476 if(_AsyncTextureReady)
00477 return true;
00478
00479
00480 if(_AsyncTextureToLoadRefCount==0)
00481 {
00482
00483 for(uint i=0;i<_CurrentAsyncTextures.size();i++)
00484 {
00485 for(uint stage=0;stage<IDRV_MAT_MAXTEXTURES;stage++)
00486 {
00487 if(_CurrentAsyncTextures[i].IsTextureFile[stage])
00488 {
00489
00490 CTextureFile *text= safe_cast<CTextureFile*>(Materials[i].getTexture(stage));
00491
00492
00493 text->setFileName(_CurrentAsyncTextures[i].TextureNames[stage]);
00494
00495
00496
00497
00498 text->releaseDriverSetup();
00499 }
00500 }
00501 }
00502
00503
00504 _AsyncTextureReady= true;
00505 return true;
00506 }
00507 else
00508 return false;
00509 }
00510
00511
00512
00513 sint CMeshBaseInstance::getAsyncTextureId(uint matId, uint stage) const
00514 {
00515 if(matId>=_CurrentAsyncTextures.size())
00516 return -1;
00517 if(!_CurrentAsyncTextures[matId].isTextureFile(stage))
00518 return -1;
00519 return _CurrentAsyncTextures[matId].TextIds[stage];
00520 }
00521
00522
00523
00524 }