# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

material.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/material.h"
00029 #include "3d/texture.h"
00030 #include "3d/shader.h"
00031 #include "3d/driver.h"
00032 #include "nel/misc/stream.h"
00033 
00034 using namespace std;
00035 using namespace NLMISC;
00036 
00037 namespace NL3D
00038 {
00039 
00040 // ***************************************************************************
00041 CMaterial::CMaterial()
00042 {
00043         _Touched= 0;
00044         _Flags= IDRV_MAT_ZWRITE;
00045         // Must init All the flags by default.
00046         _ShaderType= Normal;
00047         _SrcBlend= srcalpha;
00048         _DstBlend= invsrcalpha;
00049         _ZFunction= lessequal;
00050         _ZBias= 0;
00051         _Color.set(255,255,255,255);
00052         _StainedGlassWindow = false;
00053         _AlphaTestThreshold= 0.5f;      
00054 }
00055 
00056 // ***************************************************************************
00057 void                    CMaterial::initUnlit()
00058 {
00059         setShader(Normal);
00060         setLighting(false);
00061         setColor(CRGBA(255,255,255,255));
00062         for(uint32 i=0;i<IDRV_MAT_MAXTEXTURES;i++)
00063                 setTexture((uint8)i ,NULL);
00064         setZBias(0);
00065         setZFunc(lessequal);
00066         setZWrite(true);
00067         setBlend(false);
00068         setAlphaTestThreshold(0.5f);
00069 }
00070 
00071 // ***************************************************************************
00072 
00073 void                    CMaterial::initLighted()
00074 {
00075         initUnlit();
00076         setLighting(true);
00077 }
00078 
00079 
00080 // ***************************************************************************
00081 CMaterial               &CMaterial::operator=(const CMaterial &mat)
00082 {
00083         _ShaderType= mat._ShaderType;
00084         _Flags= mat._Flags;
00085         _SrcBlend= mat._SrcBlend;
00086         _DstBlend= mat._DstBlend;
00087         _ZFunction= mat._ZFunction;
00088         _ZBias= mat._ZBias;
00089         _Color= mat._Color;
00090         _Emissive= mat._Emissive;
00091         _Ambient= mat._Ambient;
00092         _Diffuse= mat._Diffuse;
00093         _Specular= mat._Specular;
00094         _Shininess= mat._Shininess;
00095         _AlphaTestThreshold= mat._AlphaTestThreshold;
00096 
00097         for(uint32 i=0;i<IDRV_MAT_MAXTEXTURES;i++)
00098         {
00099                 _Textures[i]= mat._Textures[i];
00100                 _TexEnvs[i]= mat._TexEnvs[i];
00101                 _TexAddrMode[i] = mat._TexAddrMode[i];
00102         }
00103 
00104         // copy lightmaps.
00105         _LightMaps= mat._LightMaps;
00106 
00107         // copy texture matrix if there.
00108         if (mat._TexUserMat.get())
00109         {
00110                 std::auto_ptr<CUserTexMat> texMatClone( new CUserTexMat(*(mat._TexUserMat))); // make cpy
00111                 std::swap(texMatClone, _TexUserMat); // swap with old
00112         }
00113         else
00114         {
00115                 _TexUserMat.reset();    
00116         }
00117 
00118         // Must do not copy drv info.
00119 
00120         // All states of material is modified.
00121         _Touched= IDRV_TOUCHED_ALL;
00122 
00123         return *this;
00124 }
00125 
00126 
00127 // ***************************************************************************
00128 CMaterial::~CMaterial()
00129 {
00130         // Must kill the drv mirror of this material.
00131         pShader.kill(); 
00132 }
00133 
00134 
00135 // ***************************************************************************
00136 void            CMaterial::serial(NLMISC::IStream &f)
00137 {
00138         /*
00139         Version 6:
00140                 - Texture matrix animation
00141         Version 5:
00142                 - AlphaTest threshold
00143         Version 4:
00144                 - Texture Addressing modes
00145         Version 3:
00146                 - LightMaps.
00147         Version 2:
00148                 - Shininess.
00149         Version 1:
00150                 - texture environement.
00151         Version 0:
00152                 - base version.
00153         */
00154 
00155         sint    ver= f.serialVersion(6);
00156         // For the version <=1:
00157         nlassert(IDRV_MAT_MAXTEXTURES==4);
00158 
00159         f.serialEnum(_ShaderType);
00160         f.serial(_Flags);
00161         f.serialEnum(_SrcBlend);
00162         f.serialEnum(_DstBlend);
00163         f.serialEnum(_ZFunction);
00164         f.serial(_ZBias);
00165         f.serial(_Color);
00166         f.serial(_Emissive, _Ambient, _Diffuse, _Specular);
00167         if(ver>=2)
00168         {
00169                 f.serial(_Shininess);
00170         }
00171         if(ver>=5)
00172         {
00173                 f.serial(_AlphaTestThreshold);
00174         }
00175 
00176 
00177         for(uint32 i=0;i<IDRV_MAT_MAXTEXTURES;i++)
00178         {
00179                 // Serial texture descriptor.
00180                 ITexture*       text;
00181                 if(f.isReading())
00182                 {
00183                         f.serialPolyPtr(text);
00184                         _Textures[i]= text;
00185                 }
00186                 else
00187                 {
00188                         text= _Textures[i];
00189                         f.serialPolyPtr(text);
00190                 }
00191 
00192                 // Read texture environnement, or setup them.
00193                 if(ver>=1)
00194                 {
00195                         f.serial(_TexEnvs[i]);
00196                 }
00197                 else
00198                 {
00199                         // Else setup as default behavior, like before...
00200                         if(f.isReading())
00201                                 _TexEnvs[i].setDefault();
00202                 }
00203         }
00204 
00205         if(ver>=3)
00206         {
00207                 f.serialCont(_LightMaps);
00208         }
00209 
00210         if (ver >= 4)
00211         {
00212                 if (_Flags & IDRV_MAT_TEX_ADDR)
00213                 {
00214                         for(uint32 i=0;i<IDRV_MAT_MAXTEXTURES;i++)
00215                         {
00216                                 f.serial(_TexAddrMode[i]);
00217                         }
00218                 }
00219         }
00220 
00221         if(f.isReading())
00222         {
00223                 // Converte Deprecated DEFMAT to std Mat.
00224                 if(_Flags & IDRV_MAT_DEFMAT)
00225                 {
00226                         setEmissive(CRGBA::Black);
00227                         setAmbient(CRGBA::White);
00228                         setDiffuse(CRGBA::White);
00229                         setSpecular(CRGBA::Black);
00230                 }
00231 
00232                 // All states of material are modified.
00233                 _Touched= IDRV_TOUCHED_ALL;
00234 
00235                 if ((_Flags & IDRV_MAT_USER_TEX_MAT_ALL)) // are there user textrue coordinates matrix ?
00236                 {
00237                         std::auto_ptr<CUserTexMat> newPtr(new CUserTexMat); // create new                       
00238                         std::swap(_TexUserMat, newPtr); // replace old
00239                 }
00240         }
00241 
00242         if (ver >= 6)
00243         {
00244                 for(uint i=0; i < IDRV_MAT_MAXTEXTURES; ++i)
00245                 {
00246                         if (isUserTexMatEnabled(i))
00247                         {                               
00248                                 f.serial(_TexUserMat->TexMat[i]);                               
00249                         }                       
00250                 }
00251         }
00252 
00253 }
00254 
00255 
00256 // ***************************************************************************
00257 void            CMaterial::setShader(TShader val)
00258 {
00259         // First, reset all textures.
00260         uint    nTexts= IDRV_MAT_MAXTEXTURES;
00261         // If user color or lightmap, set only the 1st.
00262         if(_ShaderType==LightMap || _ShaderType==UserColor)
00263                 nTexts=1;
00264         // reset all needed
00265         for(uint i=0;i<nTexts;i++)
00266                 setTexture(i ,NULL);
00267 
00268         // If userColor, use TexEnv caps (we got it, so use it :) ).
00269         if(val== CMaterial::UserColor)
00270         {
00271                 // force normal, to setup TexEnvMode correclty. 
00272                 _ShaderType=CMaterial::Normal;
00273 
00274                 // First stage, interpolate Constant and texture with Alpha of texture.
00275                 texEnvOpRGB(0, InterpolateTexture);
00276                 texEnvArg0RGB(0, Texture, SrcColor);
00277                 texEnvArg1RGB(0, Constant, SrcColor);
00278                 // And just use Alpha Diffuse.
00279                 texEnvOpAlpha(0, Replace);
00280                 texEnvArg0Alpha(0, Previous, SrcAlpha);
00281 
00282                 // Second stage, modulate result with diffuse color.
00283                 texEnvOpRGB(1, Modulate);
00284                 texEnvArg0RGB(1, Previous, SrcColor);
00285                 texEnvArg1RGB(1, Diffuse, SrcColor);
00286                 // And just use Alpha Diffuse.
00287                 texEnvOpAlpha(1, Replace);
00288                 texEnvArg0Alpha(1, Previous, SrcAlpha);
00289         }
00290 
00291         _ShaderType= val;
00292         _Touched|=IDRV_TOUCHED_SHADER;
00293 }
00294 
00295 
00296 // ***************************************************************************
00297 void CMaterial::setTexture(uint8 n, ITexture* ptex)
00298 {
00299         nlassert(n<IDRV_MAT_MAXTEXTURES);
00300 
00301         // User Color material?
00302         if( _ShaderType== CMaterial::UserColor)
00303         {
00304                 // user color. Only texture 0 can be set.
00305                 nlassert( n==0 );
00306 
00307                 // Affect the 2 first textures.
00308                 _Textures[0]=ptex;
00309                 _Textures[1]=ptex;
00310                 _Touched|=IDRV_TOUCHED_TEX[0];
00311                 _Touched|=IDRV_TOUCHED_TEX[1];
00312         }
00313         else if( _ShaderType== CMaterial::LightMap)
00314         {
00315                 // Only texture 0 can be set.
00316                 nlassert( n==0 );
00317                 _Textures[n]=ptex;
00318                 _Touched|=IDRV_TOUCHED_TEX[n];
00319         }
00320         // Normal material?
00321         else
00322         {
00323                 _Textures[n]=ptex;
00324                 _Touched|=IDRV_TOUCHED_TEX[n];
00325         }
00326 }
00327 
00328 
00329 // ***************************************************************************
00330 void                    CMaterial::flushTextures (IDriver &driver)
00331 {
00332         // For each textures
00333         for (uint tex=0; tex<IDRV_MAT_MAXTEXTURES; tex++)
00334         {
00335                 // Texture exist ?
00336                 if (_Textures[tex])
00337                 {
00338                         // Force setup texture
00339                         driver.setupTexture (*_Textures[tex]);
00340                 }
00341         }
00342 
00343         // If Lightmap material
00344         if(_ShaderType==LightMap)
00345         {
00346                 // For each lightmap
00347                 for (uint lmap=0; lmap<_LightMaps.size(); lmap++)
00348                 {
00349                         // Texture exist?
00350                         if(_LightMaps[lmap].Texture)
00351                         {
00352                                 // Force setup texture
00353                                 driver.setupTexture (*_LightMaps[lmap].Texture);
00354                         }
00355                 }
00356         }
00357 
00358 }
00359 
00360 
00361 // ***************************************************************************
00362 void                                    CMaterial::setLightMap(uint lmapId, ITexture *lmap)
00363 {
00364         nlassert(_ShaderType==CMaterial::LightMap);
00365         if(lmapId>=_LightMaps.size())
00366                 _LightMaps.resize(lmapId+1);
00367         _LightMaps[lmapId].Texture= lmap;
00368 
00369         _Touched|=IDRV_TOUCHED_LIGHTMAP;
00370 }
00371 
00372 // ***************************************************************************
00373 ITexture                                *CMaterial::getLightMap(uint lmapId) const
00374 {
00375         nlassert(_ShaderType==CMaterial::LightMap);
00376         if(lmapId<_LightMaps.size())
00377                 return _LightMaps[lmapId].Texture;
00378         else
00379                 return NULL;    
00380 }
00381 
00382 // ***************************************************************************
00383 void                                    CMaterial::setLightMapFactor(uint lmapId, CRGBA factor)
00384 {
00385         if (_ShaderType==CMaterial::LightMap)
00386         {
00387                 if(lmapId>=_LightMaps.size())
00388                         _LightMaps.resize(lmapId+1);
00389                 _LightMaps[lmapId].Factor= factor;
00390 
00391                 _Touched|=IDRV_TOUCHED_LIGHTMAP;
00392         }
00393 }
00394 
00395 
00396 // ***************************************************************************
00397 void                    CMaterial::CLightMap::serial(NLMISC::IStream &f)
00398 {
00399         f.serial(Factor);
00400         // Serial texture descriptor.
00401         ITexture*       text= NULL;
00402         if(f.isReading())
00403         {
00404                 f.serialPolyPtr(text);
00405                 Texture= text;
00406         }
00407         else
00408         {
00409                 text= Texture;
00410                 f.serialPolyPtr(text);
00411         }
00412 }
00413 
00414 
00415 
00416 // ***************************************************************************
00417 void                            CMaterial::enableTexAddrMode(bool enable /*= true*/)
00418 {
00419         if (enable)
00420         {
00421                 if (!(_Flags & IDRV_MAT_TEX_ADDR))
00422                 {
00423                         _Flags |= IDRV_MAT_TEX_ADDR;
00424                         for (uint32 k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
00425                         {
00426                                 _TexAddrMode[k] = (uint8) FetchTexture;
00427                         }                       
00428                 }               
00429         }
00430         else
00431         {
00432                 _Flags &= ~IDRV_MAT_TEX_ADDR;                   
00433         }
00434 }
00435 
00436 // ***************************************************************************
00437 bool                        CMaterial::texAddrEnabled() const
00438 {
00439         return( _Flags & IDRV_MAT_TEX_ADDR) != 0;
00440 }
00441 
00442 // ***************************************************************************
00443 void                            CMaterial::setTexAddressingMode(uint8 stage, TTexAddressingMode mode)
00444 {
00445         nlassert(_Flags & IDRV_MAT_TEX_ADDR);
00446         nlassert(stage < IDRV_MAT_MAXTEXTURES);
00447         nlassert(mode < TexAddrCount);
00448         _TexAddrMode[stage] = (uint8) mode;     
00449 }
00450 
00451 
00452 // ***************************************************************************
00453 CMaterial::TTexAddressingMode   CMaterial::getTexAddressingMode(uint8 stage)
00454 {
00455         nlassert(_Flags & IDRV_MAT_TEX_ADDR);
00456         nlassert(stage < IDRV_MAT_MAXTEXTURES);
00457         return (TTexAddressingMode) _TexAddrMode[stage];
00458 }
00459 
00460 // ***************************************************************************
00461 void                                    CMaterial::decompUserTexMat(uint stage, float &uTrans, float &vTrans, float &wRot, float &uScale, float &vScale)
00462 {
00463         nlassert(stage < IDRV_MAT_MAXTEXTURES);
00464         nlassert(isUserTexMatEnabled(stage)); // must activate animated texture matrix for this stage
00465         const NLMISC::CMatrix texMat = _TexUserMat->TexMat[stage];
00466         uTrans = texMat.getPos().x;
00467         vTrans = texMat.getPos().y;
00469         NLMISC::CVector i = texMat.getI();
00470         NLMISC::CVector j = texMat.getJ();
00471         float  normI = i.norm();
00472         float  normJ = i.norm();
00473         i /= normI;
00474         j /= normJ;     
00475         float angle = ::acosf(i.x);
00476         if (i.y < 0)
00477         {
00478                 angle = 2.f * (float) NLMISC::Pi - angle;
00479         }
00480         wRot   = angle; 
00481         uScale = normI;
00482         vScale = normJ;
00483 }
00484 
00485 // ***************************************************************************
00486 void            CMaterial::selectTextureSet(uint index)
00487 {
00488         for (uint k = 0; k < IDRV_MAT_MAXTEXTURES; ++k)
00489         {
00490                 if (_Textures[k] != NULL) _Textures[k]->selectTexture(index);
00491         }
00492 }
00493 
00494 }
00495