Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / mesh_base.cpp
blobfdb4d6c8fe007d0053df46cf799665ec200581e8
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/mesh_base.h"
20 #include "nel/3d/mesh_base_instance.h"
21 #include "nel/3d/lod_character_texture.h"
22 #include "nel/3d/visual_collision_mesh.h"
25 using namespace std;
26 using namespace NLMISC;
28 #ifdef DEBUG_NEW
29 #define new DEBUG_NEW
30 #endif
32 namespace NL3D
37 // ***************************************************************************
38 CMeshBase::CMeshBase()
40 /* ***********************************************
41 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
42 * It can be loaded/called through CAsyncFileManager for instance
43 * ***********************************************/
45 _UseLightingLocalAttenuation= false;
47 // To have same functionnality than previous version, init to identity.
48 _DefaultPos.setDefaultValue(CVector(0,0,0));
49 _DefaultPivot.setDefaultValue(CVector(0,0,0));
50 _DefaultRotEuler.setDefaultValue(CVector(0,0,0));
51 _DefaultRotQuat.setDefaultValue(CQuat::Identity);
52 _DefaultScale.setDefaultValue(CVector(1,1,1));
53 _DefaultLMFactor.setDefaultValue(CRGBA(255,255,255,255));
55 _AutoAnim = false;
57 _LodCharacterTexture= NULL;
59 _CollisionMeshGeneration= AutoCameraCol;
61 _VisualCollisionMesh= NULL;
63 _DefaultOpacity= false;
64 _DefaultTransparency= false;
68 // ***************************************************************************
69 CMeshBase::~CMeshBase()
71 /* ***********************************************
72 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
73 * It can be loaded/called through CAsyncFileManager for instance
74 * ***********************************************/
76 // free if exist
77 resetLodCharacterTexture();
78 // delete the Col mesh if created
79 if(_VisualCollisionMesh)
81 delete _VisualCollisionMesh;
82 _VisualCollisionMesh= NULL;
87 // ***************************************************************************
88 // ***************************************************************************
89 // Animated material.
90 // ***************************************************************************
91 // ***************************************************************************
94 // ***************************************************************************
95 void CMeshBase::setAnimatedMaterial(uint id, const std::string &matName)
97 nlassert(!matName.empty());
98 if(id<_Materials.size())
100 // add / replace animated material.
101 _AnimatedMaterials[id].Name= matName;
102 // copy Material default.
103 _AnimatedMaterials[id].copyFromMaterial(&_Materials[id]);
107 // ***************************************************************************
108 CMaterialBase *CMeshBase::getAnimatedMaterial(uint id)
110 TAnimatedMaterialMap::iterator it;
111 it= _AnimatedMaterials.find(id);
112 if(it!=_AnimatedMaterials.end())
113 return &it->second;
114 else
115 return NULL;
119 // ***************************************************************************
120 // ***************************************************************************
121 // Serial - buildBase.
122 // ***************************************************************************
123 // ***************************************************************************
126 // ***************************************************************************
127 CMeshBase::CMeshBaseBuild::CMeshBaseBuild()
129 DefaultPos.set(0,0,0);
130 DefaultPivot.set(0,0,0);
131 DefaultRotEuler.set(0,0,0);
132 DefaultScale.set(1,1,1);
134 bCastShadows= false;
135 bRcvShadows= false;
136 UseLightingLocalAttenuation= false;
137 CollisionMeshGeneration= CMeshBase::AutoCameraCol;
140 // ***************************************************************************
141 #if 0
142 void CMeshBase::CMeshBaseBuild::serial(NLMISC::IStream &f)
145 Version 1:
146 - Cut in version because of badly coded ITexture* serialisation. throw an exception if
147 find a version < 1.
148 Version 0:
149 - 1st version.
151 sint ver= f.serialVersion(1);
153 if(ver<1)
154 throw NLMISC::EStream(f, "MeshBuild in Stream is too old (MeshBaseBuild version < 1)");
156 f.serial( DefaultPos );
157 f.serial( DefaultPivot );
158 f.serial( DefaultRotEuler );
159 f.serial( DefaultRotQuat );
160 f.serial( DefaultScale );
162 f.serialCont( Materials );
164 #endif
166 // ***************************************************************************
167 void CMeshBase::serialMeshBase(NLMISC::IStream &f)
169 /* ***********************************************
170 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
171 * It can be loaded/called through CAsyncFileManager for instance
172 * ***********************************************/
175 Version 9:
176 - _CollisionMeshGeneration
177 Version 8:
178 - new format for CLightMapInfoList
179 Version 7:
180 - _LodCharacterTexture
181 Version 6:
182 - _DistMax
183 Version 5:
184 - _AutoAnim
185 Version 4:
186 - _UseLightingLocalAttenuation
187 Version 3:
188 - _IsLightable
189 Version 2:
190 - Added Blend Shapes factors
191 Version 1:
192 - Cut in version because of badly coded ITexture* serialisation. throw an exception if
193 find a version < 1.
194 Version 0:
195 - 1st version.
197 sint ver = f.serialVersion(9);
199 if (ver >= 2)
201 f.serialCont (_AnimatedMorph);
204 if(ver<1)
205 throw NLMISC::EStream(f, "Mesh in Stream is too old (MeshBase version < 1)");
207 f.serial (_DefaultPos);
208 f.serial (_DefaultPivot);
209 f.serial (_DefaultRotEuler);
210 f.serial (_DefaultRotQuat);
211 f.serial (_DefaultScale);
213 f.serialCont(_Materials);
214 f.serialCont(_AnimatedMaterials);
216 if(ver >= 8)
217 f.serialCont(_LightInfos);
218 else
220 TLightInfoMapV7 temp;
221 f.serialCont(temp);
224 if(ver>=3)
225 // read/write _IsLightable flag.
226 f.serial(_IsLightable);
227 else if( f.isReading() )
228 // update _IsLightable flag.
229 computeIsLightable();
231 if(ver>=4)
232 f.serial(_UseLightingLocalAttenuation);
233 else if( f.isReading() )
234 _UseLightingLocalAttenuation= false;
236 if (ver >= 5)
238 f.serial(_AutoAnim);
241 if(ver >= 6)
242 f.serial(_DistMax);
244 if(ver >= 7)
245 f.serialPtr(_LodCharacterTexture);
247 if(ver >= 9)
248 f.serialEnum(_CollisionMeshGeneration);
249 else
250 _CollisionMeshGeneration= AutoCameraCol;
252 // Some runtime not serialized compilation
253 if(f.isReading())
254 compileRunTime();
258 // ***************************************************************************
259 void CMeshBase::buildMeshBase(CMeshBaseBuild &m)
261 // Copy light information
262 _LightInfos = m.LightInfoMap;
264 // copy the materials.
265 _Materials= m.Materials;
267 // clear the animated materials.
268 _AnimatedMaterials.clear();
270 /// Copy default position values
271 _DefaultPos.setDefaultValue (m.DefaultPos);
272 _DefaultPivot.setDefaultValue (m.DefaultPivot);
273 _DefaultRotEuler.setDefaultValue (m.DefaultRotEuler);
274 _DefaultRotQuat.setDefaultValue (m.DefaultRotQuat);
275 _DefaultScale.setDefaultValue (m.DefaultScale);
277 _AnimatedMorph .resize(m.DefaultBSFactors.size());
278 for (uint32 i = 0; i < m.DefaultBSFactors.size(); ++i)
280 _AnimatedMorph[i].DefaultFactor.setDefaultValue (m.DefaultBSFactors[i]);
281 _AnimatedMorph[i].Name = m.BSNames[i];
284 // update _IsLightable flag.
285 computeIsLightable();
286 // copy _UseLightingLocalAttenuation
287 _UseLightingLocalAttenuation= m.UseLightingLocalAttenuation;
289 // copy CollisionMeshGeneration
290 _CollisionMeshGeneration= m.CollisionMeshGeneration;
292 // Some runtime not serialized compilation
293 compileRunTime();
299 // ***************************************************************************
300 void CMeshBase::instanciateMeshBase(CMeshBaseInstance *mi, CScene *ownerScene)
302 uint32 i;
305 // setup animated blendShapes
306 //===========================
307 mi->_AnimatedMorphFactor.reserve(_AnimatedMorph.size());
308 for(i = 0; i < _AnimatedMorph.size(); ++i)
310 CAnimatedMorph am(&_AnimatedMorph[i]);
311 mi->_AnimatedMorphFactor.push_back (am);
314 // setup materials.
315 //=================
316 // Copy material. Textures are referenced only
317 mi->Materials= _Materials;
319 // Instanciate selectable textures (use default set)
320 mi->selectTextureSet(0);
322 // prepare possible AsyncTextures
323 mi->AsyncTextures.resize(_Materials.size());
325 // setup animated materials.
326 //==========================
327 TAnimatedMaterialMap::iterator it;
328 mi->_AnimatedMaterials.reserve(_AnimatedMaterials.size());
329 for(it= _AnimatedMaterials.begin(); it!= _AnimatedMaterials.end(); it++)
331 CAnimatedMaterial aniMat(&it->second);
333 // set the target instance material.
334 nlassert(it->first < mi->Materials.size());
335 aniMat.setMaterial(&mi->Materials[it->first]);
337 // Must set the Animatable father of the animated material (the mesh_base_instance!).
338 aniMat.setFather(mi, CMeshBaseInstance::OwnerBit);
340 // Append this animated material.
341 mi->_AnimatedMaterials.push_back(aniMat);
344 // Misc
345 //==========================
347 // Setup position with the default value
348 mi->ITransformable::setPos( _DefaultPos.getDefaultValue() );
349 mi->ITransformable::setRotQuat( _DefaultRotQuat.getDefaultValue() );
350 mi->ITransformable::setScale( _DefaultScale.getDefaultValue() );
351 mi->ITransformable::setPivot( _DefaultPivot.getDefaultValue() );
353 // Setup default opcaity / transparency state
354 mi->setOpacity( this->getDefaultOpacity() );
355 mi->setTransparency( this->getDefaultTransparency() );
357 // if the mesh is lightable, then the instance is
358 mi->setIsLightable(this->isLightable());
360 // a mesh is considered big for lightable if it uses localAttenuation
361 mi->setIsBigLightable(this->useLightingLocalAttenuation());
363 // The mesh support fast intersect, if the system geometry has been built
364 mi->enableFastIntersectSupport(!_SystemGeometry.empty());
368 // ***************************************************************************
369 void CMeshBase::applyMaterialUsageOptim(const std::vector<bool> &materialUsed, std::vector<sint> &remap)
371 nlassert(_Materials.size()==materialUsed.size());
373 // security reset
374 resetLodCharacterTexture();
375 _AnimatedMaterials.clear();
377 // init all ids to "Not Used"
378 remap.clear();
379 remap.resize(_Materials.size(), -1);
381 // remove unused materials and build remap
382 vector<CMaterial>::iterator itMat= _Materials.begin();
383 uint dstIdx= 0;
384 uint i;
385 for(i=0;i<materialUsed.size();i++)
387 // if used, still use it, and remap.
388 if(materialUsed[i])
390 remap[i]= dstIdx;
391 itMat++;
392 dstIdx++;
394 // remove from the array
395 else
397 itMat= _Materials.erase(itMat);
401 // apply the remap to LightMaps infos
402 const uint count = (uint)_LightInfos.size ();
403 for (i=0; i<count; i++)
405 CLightMapInfoList &mapInfoList = _LightInfos[i];
406 std::list<CMeshBase::CLightMapInfoList::CMatStage>::iterator ite = mapInfoList.StageList.begin ();
407 while (ite != mapInfoList.StageList.end ())
409 sint newId= remap[ite->MatId];
410 // If material used
411 if(newId>=0)
413 // apply remap on the material id
414 ite->MatId= newId;
415 ite++;
417 else
419 // remove it from list of light infos
420 ite= mapInfoList.StageList.erase(ite);
427 // ***************************************************************************
428 void CMeshBase::flushTextures(IDriver &driver, uint selectedTexture)
430 // Mat count
431 uint matCount=(uint)_Materials.size();
433 // Flush each material textures
434 for (uint mat=0; mat<matCount; mat++)
436 /// Flush material textures
437 _Materials[mat].flushTextures (driver, selectedTexture);
442 // ***************************************************************************
443 void CMeshBase::computeIsLightable()
445 // by default the mesh is not lightable
446 _IsLightable= false;
448 // Mat count
449 uint matCount=(uint)_Materials.size();
451 // for each material
452 for (uint mat=0; mat<matCount; mat++)
454 // if this one is not a lightmap, then OK, the mesh is lightable
455 if( _Materials[mat].getShader()!=CMaterial::LightMap )
457 _IsLightable= true;
458 break;
464 // ***************************************************************************
465 bool CMeshBase::useLightingLocalAttenuation () const
467 return _UseLightingLocalAttenuation;
471 // ***************************************************************************
472 void CMeshBase::resetLodCharacterTexture()
474 if(_LodCharacterTexture)
476 delete _LodCharacterTexture;
477 _LodCharacterTexture= NULL;
481 // ***************************************************************************
482 void CMeshBase::setupLodCharacterTexture(CLodCharacterTexture &lodText)
484 // delete old
485 resetLodCharacterTexture();
486 // seutp new
487 _LodCharacterTexture= new CLodCharacterTexture;
488 *_LodCharacterTexture= lodText;
491 // ***************************************************************************
492 CVisualCollisionMesh *CMeshBase::getVisualCollisionMesh() const
494 return _VisualCollisionMesh;
497 // ***************************************************************************
498 void CMeshBase::compileRunTime()
500 _DefaultTransparency= false;
501 _DefaultOpacity= false;
502 for( uint i = 0; i < _Materials.size(); ++i )
503 if( _Materials[i].getBlend() )
504 _DefaultTransparency= true;
505 else
506 _DefaultOpacity= true;
510 } // NL3D