Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / animated_material.cpp
blob8e33a3a9fa9811feee933953a916f873fe1fa22b
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/animated_material.h"
20 #include "nel/misc/common.h"
22 using namespace NLMISC;
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 namespace NL3D
32 // ***************************************************************************
33 // ***************************************************************************
34 // ***************************************************************************
35 // ***************************************************************************
39 // ***************************************************************************
40 void CMaterialBase::CAnimatedTexture::serial(NLMISC::IStream &f)
42 ITexture *text= NULL;
43 if(f.isReading())
45 f.serialPolyPtr(text);
46 Texture= text;
48 else
50 text= Texture;
51 f.serialPolyPtr(text);
57 // ***************************************************************************
58 CMaterialBase::CMaterialBase()
60 DefaultAmbient.setDefaultValue(CRGBA(64,64,64));
61 DefaultDiffuse.setDefaultValue(CRGBA(128,128,128));
62 DefaultSpecular.setDefaultValue(CRGBA(0,0,0));
63 DefaultShininess.setDefaultValue(10);
64 DefaultEmissive.setDefaultValue(CRGBA(128,128,128));
65 DefaultOpacity.setDefaultValue(1);
66 DefaultTexture.setDefaultValue(0x7FFFFFFF);
67 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
69 DefaultTexAnimTracks[k].setDefaultValue();
74 // ***************************************************************************
75 void CMaterialBase::serial(NLMISC::IStream &f)
77 sint ver= f.serialVersion(1);
79 f.serial(Name);
80 f.serial(DefaultAmbient, DefaultDiffuse, DefaultSpecular);
81 f.serial(DefaultShininess, DefaultEmissive, DefaultOpacity, DefaultTexture);
82 f.serialCont(_AnimatedTextures);
83 if (ver > 0)
85 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
87 f.serial(DefaultTexAnimTracks[k]);
93 // ***************************************************************************
94 void CMaterialBase::copyFromMaterial(CMaterial *pMat)
96 DefaultAmbient.setDefaultValue(pMat->getAmbient());
97 DefaultDiffuse.setDefaultValue(pMat->getDiffuse());
98 DefaultSpecular.setDefaultValue(pMat->getSpecular());
99 DefaultShininess.setDefaultValue(pMat->getShininess());
100 DefaultEmissive.setDefaultValue(pMat->getEmissive());
101 DefaultOpacity.setDefaultValue(pMat->getDiffuse().A/255.f);
103 /// get uv value from material
104 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
106 if (pMat->isUserTexMatEnabled(k))
108 float uTrans, vTrans, uScale, vScale, wRot;
109 pMat->decompUserTexMat(k, uTrans, vTrans, wRot, uScale, vScale);
110 DefaultTexAnimTracks[k].DefaultUTrans.setDefaultValue(uTrans);
111 DefaultTexAnimTracks[k].DefaultVTrans.setDefaultValue(vTrans);
112 DefaultTexAnimTracks[k].DefaultUScale.setDefaultValue(uScale);
113 DefaultTexAnimTracks[k].DefaultVScale.setDefaultValue(vScale);
114 DefaultTexAnimTracks[k].DefaultWRot.setDefaultValue(wRot);
120 // ***************************************************************************
121 void CMaterialBase::setAnimatedTexture(uint32 id, CSmartPtr<ITexture> pText)
123 // add or replace the texture.
124 _AnimatedTextures[id].Texture= pText;
126 // ***************************************************************************
127 bool CMaterialBase::validAnimatedTexture(uint32 id)
129 TAnimatedTextureMap::iterator it;
130 it= _AnimatedTextures.find(id);
131 return it!=_AnimatedTextures.end();
133 // ***************************************************************************
134 ITexture* CMaterialBase::getAnimatedTexture(uint32 id)
136 TAnimatedTextureMap::iterator it;
137 it= _AnimatedTextures.find(id);
138 if( it!=_AnimatedTextures.end() )
139 return it->second.Texture;
140 else
141 return NULL;
147 // ***************************************************************************
148 // ***************************************************************************
149 // ***************************************************************************
150 // ***************************************************************************
153 // ***************************************************************************
154 CAnimatedMaterial::CAnimatedMaterial(CMaterialBase *baseMat)
156 nlassert(baseMat);
157 _MaterialBase= baseMat;
159 // IAnimatable.
160 IAnimatable::resize(AnimValueLast);
162 _Ambient.Value= _MaterialBase->DefaultAmbient.getDefaultValue();
163 _Diffuse.Value= _MaterialBase->DefaultDiffuse.getDefaultValue();
164 _Specular.Value= _MaterialBase->DefaultSpecular.getDefaultValue();
165 _Shininess.Value= _MaterialBase->DefaultShininess.getDefaultValue();
166 _Emissive.Value= _MaterialBase->DefaultEmissive.getDefaultValue();
167 _Opacity.Value= _MaterialBase->DefaultOpacity.getDefaultValue();
169 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
171 _TexAnimatedMatValues[k].affect(baseMat->DefaultTexAnimTracks[k]);
176 // ***************************************************************************
177 void CAnimatedMaterial::setMaterial(CMaterial *pMat)
179 _Material= pMat;
183 // ***************************************************************************
184 std::string CAnimatedMaterial::getMaterialName() const
186 nlassert(_MaterialBase);
187 return _MaterialBase->Name;
191 // ***************************************************************************
192 void CAnimatedMaterial::update()
194 if(isTouched(OwnerBit) && _Material!=NULL /*&& _Material->isLighted()*/)
197 // well, just update all... :)
199 // diffuse part.
200 CRGBA diff= _Diffuse.Value;
201 sint c= (sint)(_Opacity.Value*255);
202 clamp(c, 0, 255);
203 diff.A= c;
205 // setup material.
206 if (_Material->isLighted())
208 _Material->setLighting(true, _Emissive.Value, _Ambient.Value, diff, _Specular.Value, _Shininess.Value);
210 else
212 _Material->setColor(diff);
215 // clear flags.
216 clearFlag(AmbientValue);
217 clearFlag(DiffuseValue);
218 clearFlag(SpecularValue);
219 clearFlag(ShininessValue);
220 clearFlag(EmissiveValue);
221 clearFlag(OpacityValue);
224 // Texture Anim.
225 if(isTouched(TextureValue))
227 nlassert(_MaterialBase);
229 uint32 id= _Texture.Value;
230 if(_MaterialBase->validAnimatedTexture(id))
232 _Material->setTexture(0, _MaterialBase->getAnimatedTexture(id) );
234 clearFlag(TextureValue);
237 // Get texture matrix from animated value to setup the material
238 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
240 if (_Material->isUserTexMatEnabled(k))
242 const CTexAnimatedMatValues &texMatAV = _TexAnimatedMatValues[k];
244 CMatrix convMat; // exported v are already inverted (todo : optim this if needed, this matrix shouldn't be necessary)
245 convMat.setRot(CVector::I, -CVector::J, CVector::K);
246 convMat.setPos(CVector::J);
247 float fCos = cosf(texMatAV._WRot.Value);
248 float fSin = sinf(texMatAV._WRot.Value);
249 CMatrix SR;
250 SR.setRot(CVector(texMatAV._UScale.Value * fCos, texMatAV._VScale.Value * fSin, 0.f),
251 CVector(- texMatAV._UScale.Value * fSin, texMatAV._VScale.Value * fCos, 0.f),
252 CVector::K);
253 CVector half(0.5f, 0.5f, 0.f);
254 SR.setPos(SR.mulVector(- half - CVector(texMatAV._UTrans.Value, texMatAV._VTrans.Value, 0.f)) + half);
255 _Material->setUserTexMat(k, convMat * SR * convMat);
259 // We are OK!
260 IAnimatable::clearFlag(OwnerBit);
265 // ***************************************************************************
266 IAnimatedValue* CAnimatedMaterial::getValue (uint valueId)
268 switch(valueId)
270 case AmbientValue: return &_Ambient;
271 case DiffuseValue: return &_Diffuse;
272 case SpecularValue: return &_Specular;
273 case ShininessValue: return &_Shininess;
274 case EmissiveValue: return &_Emissive;
275 case OpacityValue: return &_Opacity;
276 case TextureValue: return &_Texture;
277 default: // this may be a texture animated value...
278 if (valueId >= TextureMatValues && valueId < AnimValueLast)
280 const uint baseId = valueId - TextureMatValues;
281 const uint texNum = baseId / NumTexAnimatedValues; // stage index
282 const uint argID = baseId % NumTexAnimatedValues; // value for this stage
283 switch(argID)
285 case 0: return &_TexAnimatedMatValues[texNum]._UTrans;
286 case 1: return &_TexAnimatedMatValues[texNum]._VTrans;
287 case 2: return &_TexAnimatedMatValues[texNum]._UScale;
288 case 3: return &_TexAnimatedMatValues[texNum]._VScale;
289 case 4: return &_TexAnimatedMatValues[texNum]._WRot;
292 break;
295 // shoudl not be here!!
296 nlstop;
297 return NULL;
299 // ***************************************************************************
300 const char *CAnimatedMaterial::getValueName (uint valueId) const
302 switch(valueId)
304 case AmbientValue: return getAmbientValueName();
305 case DiffuseValue: return getDiffuseValueName();
306 case SpecularValue: return getSpecularValueName();
307 case ShininessValue: return getShininessValueName();
308 case EmissiveValue: return getEmissiveValueName();
309 case OpacityValue: return getOpacityValueName();
310 case TextureValue: return getTextureValueName();
311 default: // this may be a texture animated value...
312 if (valueId >= TextureMatValues && valueId < AnimValueLast)
314 const uint baseId = valueId - TextureMatValues;
315 const uint texNum = baseId / NumTexAnimatedValues;
316 const uint argID = baseId % NumTexAnimatedValues;
317 switch(argID)
319 case 0: return getTexMatUTransName (texNum);
320 case 1: return getTexMatVTransName(texNum);
321 case 2: return getTexMatUScaleName(texNum);
322 case 3: return getTexMatVScaleName(texNum);
323 case 4: return getTexMatWRotName(texNum);
326 break;
329 // shoudl not be here!!
330 nlstop;
331 return "";
333 // ***************************************************************************
334 ITrack* CAnimatedMaterial::getDefaultTrack (uint valueId)
336 nlassert(_MaterialBase);
338 switch(valueId)
340 case AmbientValue: return &_MaterialBase->DefaultAmbient;
341 case DiffuseValue: return &_MaterialBase->DefaultDiffuse;
342 case SpecularValue: return &_MaterialBase->DefaultSpecular;
343 case ShininessValue: return &_MaterialBase->DefaultShininess;
344 case EmissiveValue: return &_MaterialBase->DefaultEmissive;
345 case OpacityValue: return &_MaterialBase->DefaultOpacity;
346 case TextureValue: return &_MaterialBase->DefaultTexture;
347 default: // this may be a texture animated value...
348 if (valueId >= TextureMatValues && valueId < AnimValueLast)
350 const uint baseId = valueId - TextureMatValues;
351 const uint texNum = baseId / NumTexAnimatedValues;
352 const uint argID = baseId % NumTexAnimatedValues;
353 switch(argID)
355 case 0: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultUTrans;
356 case 1: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultVTrans;
357 case 2: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultUTrans;
358 case 3: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultVTrans;
359 case 4: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultWRot;
362 break;
365 // shoudl not be here!!
366 nlstop;
367 return NULL;
369 // ***************************************************************************
370 void CAnimatedMaterial::registerToChannelMixer(CChannelMixer *chanMixer, const std::string &prefix)
372 // For CAnimatedMaterial, channels are detailled (material rendered after clip)!
373 addValue(chanMixer, AmbientValue, OwnerBit, prefix, true);
374 addValue(chanMixer, DiffuseValue, OwnerBit, prefix, true);
375 addValue(chanMixer, SpecularValue, OwnerBit, prefix, true);
376 addValue(chanMixer, ShininessValue, OwnerBit, prefix, true);
377 addValue(chanMixer, EmissiveValue, OwnerBit, prefix, true);
378 addValue(chanMixer, OpacityValue, OwnerBit, prefix, true);
379 addValue(chanMixer, TextureValue, OwnerBit, prefix, true);
380 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
382 for (uint l = 0; l < NumTexAnimatedValues; ++l)
384 addValue(chanMixer, TextureMatValues + l + k * NumTexAnimatedValues, OwnerBit, prefix, true);
389 // ***************************************************************************
390 const char *CAnimatedMaterial::getTexMatUTransName(uint stage)
392 static char names[IDRV_MAT_MAXTEXTURES][16];
393 static bool init = false;
394 nlassert(stage < IDRV_MAT_MAXTEXTURES);
395 if (!init) // where name initialized ?
397 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
399 sprintf(&names[k][0], "UTrans%d", k);
401 init = true;
403 return names[stage];
406 // ***************************************************************************
407 const char *CAnimatedMaterial::getTexMatVTransName(uint stage)
409 nlassert(stage < IDRV_MAT_MAXTEXTURES);
410 static char names[IDRV_MAT_MAXTEXTURES][16];
411 static bool init = false;
412 nlassert(stage < IDRV_MAT_MAXTEXTURES);
413 if (!init) // where name initialized ?
415 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
417 sprintf(&names[k][0], "VTrans%d", k);
419 init = true;
421 return names[stage];
425 // ***************************************************************************
426 const char *CAnimatedMaterial::getTexMatUScaleName(uint stage)
428 static char names[IDRV_MAT_MAXTEXTURES][16];
429 static bool init = false;
430 nlassert(stage < IDRV_MAT_MAXTEXTURES);
431 if (!init) // where name initialized ?
433 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
435 sprintf(&names[k][0], "UScale%d", k);
437 init = true;
439 return names[stage];
442 // ***************************************************************************
443 const char *CAnimatedMaterial::getTexMatVScaleName(uint stage)
445 nlassert(stage < IDRV_MAT_MAXTEXTURES);
446 static char names[IDRV_MAT_MAXTEXTURES][16];
447 static bool init = false;
448 nlassert(stage < IDRV_MAT_MAXTEXTURES);
449 if (!init) // where name initialized ?
451 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
453 sprintf(&names[k][0], "VScale%d", k);
455 init = true;
457 return names[stage];
461 // ***************************************************************************
462 const char *CAnimatedMaterial::getTexMatWRotName(uint stage)
464 nlassert(stage < IDRV_MAT_MAXTEXTURES);
465 static char names[IDRV_MAT_MAXTEXTURES][16];
466 static bool init = false;
467 nlassert(stage < IDRV_MAT_MAXTEXTURES);
468 if (!init) // where name initialized ?
470 for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
472 sprintf(&names[k][0], "WRot%d", k);
474 init = true;
476 return names[stage];
481 } // NL3D