478 lines
15 KiB
C++
478 lines
15 KiB
C++
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as
|
||
|
// published by the Free Software Foundation, either version 3 of the
|
||
|
// License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include "std3d.h"
|
||
|
|
||
|
#include "nel/3d/animated_material.h"
|
||
|
#include "nel/misc/common.h"
|
||
|
|
||
|
using namespace NLMISC;
|
||
|
|
||
|
namespace NL3D
|
||
|
{
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// ***************************************************************************
|
||
|
// ***************************************************************************
|
||
|
// ***************************************************************************
|
||
|
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
void CMaterialBase::CAnimatedTexture::serial(NLMISC::IStream &f)
|
||
|
{
|
||
|
ITexture *text= NULL;
|
||
|
if(f.isReading())
|
||
|
{
|
||
|
f.serialPolyPtr(text);
|
||
|
Texture= text;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
text= Texture;
|
||
|
f.serialPolyPtr(text);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
CMaterialBase::CMaterialBase()
|
||
|
{
|
||
|
DefaultAmbient.setDefaultValue(CRGBA(64,64,64));
|
||
|
DefaultDiffuse.setDefaultValue(CRGBA(128,128,128));
|
||
|
DefaultSpecular.setDefaultValue(CRGBA(0,0,0));
|
||
|
DefaultShininess.setDefaultValue(10);
|
||
|
DefaultEmissive.setDefaultValue(CRGBA(128,128,128));
|
||
|
DefaultOpacity.setDefaultValue(1);
|
||
|
DefaultTexture.setDefaultValue(0x7FFFFFFF);
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
DefaultTexAnimTracks[k].setDefaultValue();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
void CMaterialBase::serial(NLMISC::IStream &f)
|
||
|
{
|
||
|
sint ver= f.serialVersion(1);
|
||
|
|
||
|
f.serial(Name);
|
||
|
f.serial(DefaultAmbient, DefaultDiffuse, DefaultSpecular);
|
||
|
f.serial(DefaultShininess, DefaultEmissive, DefaultOpacity, DefaultTexture);
|
||
|
f.serialCont(_AnimatedTextures);
|
||
|
if (ver > 0)
|
||
|
{
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
f.serial(DefaultTexAnimTracks[k]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
void CMaterialBase::copyFromMaterial(CMaterial *pMat)
|
||
|
{
|
||
|
DefaultAmbient.setDefaultValue(pMat->getAmbient());
|
||
|
DefaultDiffuse.setDefaultValue(pMat->getDiffuse());
|
||
|
DefaultSpecular.setDefaultValue(pMat->getSpecular());
|
||
|
DefaultShininess.setDefaultValue(pMat->getShininess());
|
||
|
DefaultEmissive.setDefaultValue(pMat->getEmissive());
|
||
|
DefaultOpacity.setDefaultValue(pMat->getDiffuse().A/255.f);
|
||
|
|
||
|
/// get uv value from material
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
if (pMat->isUserTexMatEnabled(k))
|
||
|
{
|
||
|
float uTrans, vTrans, uScale, vScale, wRot;
|
||
|
pMat->decompUserTexMat(k, uTrans, vTrans, wRot, uScale, vScale);
|
||
|
DefaultTexAnimTracks[k].DefaultUTrans.setDefaultValue(uTrans);
|
||
|
DefaultTexAnimTracks[k].DefaultVTrans.setDefaultValue(vTrans);
|
||
|
DefaultTexAnimTracks[k].DefaultUScale.setDefaultValue(uScale);
|
||
|
DefaultTexAnimTracks[k].DefaultVScale.setDefaultValue(vScale);
|
||
|
DefaultTexAnimTracks[k].DefaultWRot.setDefaultValue(wRot);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
void CMaterialBase::setAnimatedTexture(uint32 id, CSmartPtr<ITexture> pText)
|
||
|
{
|
||
|
// add or replace the texture.
|
||
|
_AnimatedTextures[id].Texture= pText;
|
||
|
}
|
||
|
// ***************************************************************************
|
||
|
bool CMaterialBase::validAnimatedTexture(uint32 id)
|
||
|
{
|
||
|
TAnimatedTextureMap::iterator it;
|
||
|
it= _AnimatedTextures.find(id);
|
||
|
return it!=_AnimatedTextures.end();
|
||
|
}
|
||
|
// ***************************************************************************
|
||
|
ITexture* CMaterialBase::getAnimatedTexture(uint32 id)
|
||
|
{
|
||
|
TAnimatedTextureMap::iterator it;
|
||
|
it= _AnimatedTextures.find(id);
|
||
|
if( it!=_AnimatedTextures.end() )
|
||
|
return it->second.Texture;
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
// ***************************************************************************
|
||
|
// ***************************************************************************
|
||
|
// ***************************************************************************
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
CAnimatedMaterial::CAnimatedMaterial(CMaterialBase *baseMat)
|
||
|
{
|
||
|
nlassert(baseMat);
|
||
|
_MaterialBase= baseMat;
|
||
|
|
||
|
// IAnimatable.
|
||
|
IAnimatable::resize(AnimValueLast);
|
||
|
|
||
|
_Ambient.Value= _MaterialBase->DefaultAmbient.getDefaultValue();
|
||
|
_Diffuse.Value= _MaterialBase->DefaultDiffuse.getDefaultValue();
|
||
|
_Specular.Value= _MaterialBase->DefaultSpecular.getDefaultValue();
|
||
|
_Shininess.Value= _MaterialBase->DefaultShininess.getDefaultValue();
|
||
|
_Emissive.Value= _MaterialBase->DefaultEmissive.getDefaultValue();
|
||
|
_Opacity.Value= _MaterialBase->DefaultOpacity.getDefaultValue();
|
||
|
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
_TexAnimatedMatValues[k].affect(baseMat->DefaultTexAnimTracks[k]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
void CAnimatedMaterial::setMaterial(CMaterial *pMat)
|
||
|
{
|
||
|
_Material= pMat;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
std::string CAnimatedMaterial::getMaterialName() const
|
||
|
{
|
||
|
nlassert(_MaterialBase);
|
||
|
return _MaterialBase->Name;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
void CAnimatedMaterial::update()
|
||
|
{
|
||
|
if(isTouched(OwnerBit) && _Material!=NULL /*&& _Material->isLighted()*/)
|
||
|
{
|
||
|
|
||
|
// well, just update all... :)
|
||
|
|
||
|
// diffuse part.
|
||
|
CRGBA diff= _Diffuse.Value;
|
||
|
sint c= (sint)(_Opacity.Value*255);
|
||
|
clamp(c, 0, 255);
|
||
|
diff.A= c;
|
||
|
|
||
|
// setup material.
|
||
|
if (_Material->isLighted())
|
||
|
{
|
||
|
_Material->setLighting(true, _Emissive.Value, _Ambient.Value, diff, _Specular.Value, _Shininess.Value);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_Material->setColor(diff);
|
||
|
}
|
||
|
|
||
|
// clear flags.
|
||
|
clearFlag(AmbientValue);
|
||
|
clearFlag(DiffuseValue);
|
||
|
clearFlag(SpecularValue);
|
||
|
clearFlag(ShininessValue);
|
||
|
clearFlag(EmissiveValue);
|
||
|
clearFlag(OpacityValue);
|
||
|
|
||
|
|
||
|
// Texture Anim.
|
||
|
if(isTouched(TextureValue))
|
||
|
{
|
||
|
nlassert(_MaterialBase);
|
||
|
|
||
|
uint32 id= _Texture.Value;
|
||
|
if(_MaterialBase->validAnimatedTexture(id))
|
||
|
{
|
||
|
_Material->setTexture(0, _MaterialBase->getAnimatedTexture(id) );
|
||
|
}
|
||
|
clearFlag(TextureValue);
|
||
|
}
|
||
|
|
||
|
// Get texture matrix from animated value to setup the material
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
if (_Material->isUserTexMatEnabled(k))
|
||
|
{
|
||
|
const CTexAnimatedMatValues &texMatAV = _TexAnimatedMatValues[k];
|
||
|
|
||
|
CMatrix convMat; // exported v are already inverted (todo : optim this if needed, this matrix shouldn't be necessary)
|
||
|
convMat.setRot(CVector::I, -CVector::J, CVector::K);
|
||
|
convMat.setPos(CVector::J);
|
||
|
float fCos = cosf(texMatAV._WRot.Value);
|
||
|
float fSin = sinf(texMatAV._WRot.Value);
|
||
|
CMatrix SR;
|
||
|
SR.setRot(CVector(texMatAV._UScale.Value * fCos, texMatAV._VScale.Value * fSin, 0.f),
|
||
|
CVector(- texMatAV._UScale.Value * fSin, texMatAV._VScale.Value * fCos, 0.f),
|
||
|
CVector::K);
|
||
|
CVector half(0.5f, 0.5f, 0.f);
|
||
|
SR.setPos(SR.mulVector(- half - CVector(texMatAV._UTrans.Value, texMatAV._VTrans.Value, 0.f)) + half);
|
||
|
_Material->setUserTexMat(k, convMat * SR * convMat);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We are OK!
|
||
|
IAnimatable::clearFlag(OwnerBit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
IAnimatedValue* CAnimatedMaterial::getValue (uint valueId)
|
||
|
{
|
||
|
switch(valueId)
|
||
|
{
|
||
|
case AmbientValue: return &_Ambient;
|
||
|
case DiffuseValue: return &_Diffuse;
|
||
|
case SpecularValue: return &_Specular;
|
||
|
case ShininessValue: return &_Shininess;
|
||
|
case EmissiveValue: return &_Emissive;
|
||
|
case OpacityValue: return &_Opacity;
|
||
|
case TextureValue: return &_Texture;
|
||
|
default: // this may be a texture animated value...
|
||
|
if (valueId >= TextureMatValues && valueId < AnimValueLast)
|
||
|
{
|
||
|
const uint baseId = valueId - TextureMatValues;
|
||
|
const uint texNum = baseId / NumTexAnimatedValues; // stage index
|
||
|
const uint argID = baseId % NumTexAnimatedValues; // value for this stage
|
||
|
switch(argID)
|
||
|
{
|
||
|
case 0: return &_TexAnimatedMatValues[texNum]._UTrans;
|
||
|
case 1: return &_TexAnimatedMatValues[texNum]._VTrans;
|
||
|
case 2: return &_TexAnimatedMatValues[texNum]._UScale;
|
||
|
case 3: return &_TexAnimatedMatValues[texNum]._VScale;
|
||
|
case 4: return &_TexAnimatedMatValues[texNum]._WRot;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
// shoudl not be here!!
|
||
|
nlstop;
|
||
|
return NULL;
|
||
|
}
|
||
|
// ***************************************************************************
|
||
|
const char *CAnimatedMaterial::getValueName (uint valueId) const
|
||
|
{
|
||
|
switch(valueId)
|
||
|
{
|
||
|
case AmbientValue: return getAmbientValueName();
|
||
|
case DiffuseValue: return getDiffuseValueName();
|
||
|
case SpecularValue: return getSpecularValueName();
|
||
|
case ShininessValue: return getShininessValueName();
|
||
|
case EmissiveValue: return getEmissiveValueName();
|
||
|
case OpacityValue: return getOpacityValueName();
|
||
|
case TextureValue: return getTextureValueName();
|
||
|
default: // this may be a texture animated value...
|
||
|
if (valueId >= TextureMatValues && valueId < AnimValueLast)
|
||
|
{
|
||
|
const uint baseId = valueId - TextureMatValues;
|
||
|
const uint texNum = baseId / NumTexAnimatedValues;
|
||
|
const uint argID = baseId % NumTexAnimatedValues;
|
||
|
switch(argID)
|
||
|
{
|
||
|
case 0: return getTexMatUTransName (texNum);
|
||
|
case 1: return getTexMatVTransName(texNum);
|
||
|
case 2: return getTexMatUScaleName(texNum);
|
||
|
case 3: return getTexMatVScaleName(texNum);
|
||
|
case 4: return getTexMatWRotName(texNum);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
// shoudl not be here!!
|
||
|
nlstop;
|
||
|
return "";
|
||
|
}
|
||
|
// ***************************************************************************
|
||
|
ITrack* CAnimatedMaterial::getDefaultTrack (uint valueId)
|
||
|
{
|
||
|
nlassert(_MaterialBase);
|
||
|
|
||
|
switch(valueId)
|
||
|
{
|
||
|
case AmbientValue: return &_MaterialBase->DefaultAmbient;
|
||
|
case DiffuseValue: return &_MaterialBase->DefaultDiffuse;
|
||
|
case SpecularValue: return &_MaterialBase->DefaultSpecular;
|
||
|
case ShininessValue: return &_MaterialBase->DefaultShininess;
|
||
|
case EmissiveValue: return &_MaterialBase->DefaultEmissive;
|
||
|
case OpacityValue: return &_MaterialBase->DefaultOpacity;
|
||
|
case TextureValue: return &_MaterialBase->DefaultTexture;
|
||
|
default: // this may be a texture animated value...
|
||
|
if (valueId >= TextureMatValues && valueId < AnimValueLast)
|
||
|
{
|
||
|
const uint baseId = valueId - TextureMatValues;
|
||
|
const uint texNum = baseId / NumTexAnimatedValues;
|
||
|
const uint argID = baseId % NumTexAnimatedValues;
|
||
|
switch(argID)
|
||
|
{
|
||
|
case 0: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultUTrans;
|
||
|
case 1: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultVTrans;
|
||
|
case 2: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultUTrans;
|
||
|
case 3: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultVTrans;
|
||
|
case 4: return &_MaterialBase->DefaultTexAnimTracks[texNum].DefaultWRot;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
// shoudl not be here!!
|
||
|
nlstop;
|
||
|
return NULL;
|
||
|
}
|
||
|
// ***************************************************************************
|
||
|
void CAnimatedMaterial::registerToChannelMixer(CChannelMixer *chanMixer, const std::string &prefix)
|
||
|
{
|
||
|
// For CAnimatedMaterial, channels are detailled (material rendered after clip)!
|
||
|
addValue(chanMixer, AmbientValue, OwnerBit, prefix, true);
|
||
|
addValue(chanMixer, DiffuseValue, OwnerBit, prefix, true);
|
||
|
addValue(chanMixer, SpecularValue, OwnerBit, prefix, true);
|
||
|
addValue(chanMixer, ShininessValue, OwnerBit, prefix, true);
|
||
|
addValue(chanMixer, EmissiveValue, OwnerBit, prefix, true);
|
||
|
addValue(chanMixer, OpacityValue, OwnerBit, prefix, true);
|
||
|
addValue(chanMixer, TextureValue, OwnerBit, prefix, true);
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
for (uint l = 0; l < NumTexAnimatedValues; ++l)
|
||
|
{
|
||
|
addValue(chanMixer, TextureMatValues + l + k * NumTexAnimatedValues, OwnerBit, prefix, true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
const char *CAnimatedMaterial::getTexMatUTransName(uint stage)
|
||
|
{
|
||
|
static char names[IDRV_MAT_MAXTEXTURES][16];
|
||
|
static bool init = false;
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
if (!init) // where name initialized ?
|
||
|
{
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
sprintf(&names[k][0], "UTrans%d", k);
|
||
|
}
|
||
|
init = true;
|
||
|
}
|
||
|
return names[stage];
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
const char *CAnimatedMaterial::getTexMatVTransName(uint stage)
|
||
|
{
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
static char names[IDRV_MAT_MAXTEXTURES][16];
|
||
|
static bool init = false;
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
if (!init) // where name initialized ?
|
||
|
{
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
sprintf(&names[k][0], "VTrans%d", k);
|
||
|
}
|
||
|
init = true;
|
||
|
}
|
||
|
return names[stage];
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
const char *CAnimatedMaterial::getTexMatUScaleName(uint stage)
|
||
|
{
|
||
|
static char names[IDRV_MAT_MAXTEXTURES][16];
|
||
|
static bool init = false;
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
if (!init) // where name initialized ?
|
||
|
{
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
sprintf(&names[k][0], "UScale%d", k);
|
||
|
}
|
||
|
init = true;
|
||
|
}
|
||
|
return names[stage];
|
||
|
}
|
||
|
|
||
|
// ***************************************************************************
|
||
|
const char *CAnimatedMaterial::getTexMatVScaleName(uint stage)
|
||
|
{
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
static char names[IDRV_MAT_MAXTEXTURES][16];
|
||
|
static bool init = false;
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
if (!init) // where name initialized ?
|
||
|
{
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
sprintf(&names[k][0], "VScale%d", k);
|
||
|
}
|
||
|
init = true;
|
||
|
}
|
||
|
return names[stage];
|
||
|
}
|
||
|
|
||
|
|
||
|
// ***************************************************************************
|
||
|
const char *CAnimatedMaterial::getTexMatWRotName(uint stage)
|
||
|
{
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
static char names[IDRV_MAT_MAXTEXTURES][16];
|
||
|
static bool init = false;
|
||
|
nlassert(stage < IDRV_MAT_MAXTEXTURES);
|
||
|
if (!init) // where name initialized ?
|
||
|
{
|
||
|
for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
|
||
|
{
|
||
|
sprintf(&names[k][0], "WRot%d", k);
|
||
|
}
|
||
|
init = true;
|
||
|
}
|
||
|
return names[stage];
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
} // NL3D
|