# 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  

meshvp_wind_tree.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000-2002 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/meshvp_wind_tree.h"
00029 #include "3d/mesh_base_instance.h"
00030 #include "3d/scene.h"
00031 #include "3d/driver.h"
00032 #include <math.h>
00033 #include "nel/misc/common.h"
00034 #include "3d/render_trav.h"
00035 
00036 
00037 using namespace NLMISC;
00038 using namespace std;
00039 
00040 
00041 namespace NL3D 
00042 {
00043 
00044 
00045 // ***************************************************************************
00046 // Light VP fragment constants start at 24
00047 static  const uint      VPLightConstantStart= 24;
00048 
00049 
00050 // ***************************************************************************
00051 std::auto_ptr<CVertexProgram>   CMeshVPWindTree::_VertexProgram[CMeshVPWindTree::NumVp];
00052 
00053 static const char*      WindTreeVPCodeWave=
00054 "!!VP1.0                                                                                                                                                                \n\
00055         # extract from color.R the 3 factors into R0.xyz                                                                        \n\
00056         MAD     R0, v[3].x, c[9].x, c[9].yzww;  # col.R*3                                                                               \n\
00057         MIN     R0, R0, c[8].yyyy;                              # clamp each to 0,1                                                             \n\
00058         MAX     R0, R0, c[8].xxxx;                                                                                                                              \n\
00059                                                                                                                                                                                 \n\
00060         # Add influence of Bone Level1                                                                                                          \n\
00061         MAD     R5, c[15], R0.x, v[0];                                                                                                                  \n\
00062                                                                                                                                                                                 \n\
00063         # Sample LevelPhase into R7.yz: 0 to 3.                                                                                         \n\
00064         MUL     R7, v[3].xyzw, c[10].x;                                                                                                                 \n\
00065                                                                                                                                                                                 \n\
00066         # Add influence of Bone Level2                                                                                                          \n\
00067         ARL     A0.x, R7.y;                                                                                                                                             \n\
00068         MAD     R5, c[A0.x+16], R0.y, R5;                                                                                                               \n\
00069                                                                                                                                                                                 \n\
00070         # Add influence of Bone Level3                                                                                                          \n\
00071         ARL     A0.x, R7.z;                                                                                                                                             \n\
00072         MAD     R5, c[A0.x+20], R0.z, R5;                                                                                                               \n\
00073                                                                                                                                                                                 \n\
00074         # Get normal in R6 for lighting.                                                                                                        \n\
00075         MOV     R6, v[2];                                                                                                                                               \n\
00076 ";
00077 
00078 static const char*      WindTreeVPCodeEnd=
00079 "       # compute in Projection space                                                                                                           \n\
00080         DP4 o[HPOS].x, c[0], R5;                                                                                                                        \n\
00081         DP4 o[HPOS].y, c[1], R5;                                                                                                                        \n\
00082         DP4 o[HPOS].z, c[2], R5;                                                                                                                        \n\
00083         DP4 o[HPOS].w, c[3], R5;                                                                                                                        \n\
00084         MOV o[TEX0].xy, v[8];                                                                                                                           \n\
00085         MOV o[TEX1].xy, v[9];                                                                                                                           \n\
00086         DP4     o[FOGC].x, c[6], -R5;           # fogc>0 => fogc= - (ModelView*R1).z                            \n\
00087         END                                                                                                                                                                     \n\
00088 ";
00089 
00090 
00091 // ***************************************************************************
00092 float   CMeshVPWindTree::speedCos(float angle)
00093 {
00094         // \todo yoyo TODO_OPTIM
00095         return cosf(angle * 2*(float)Pi);
00096 }
00097 
00098 
00099 // ***************************************************************************
00100 CMeshVPWindTree::CMeshVPWindTree()
00101 {
00102         for(uint i=0; i<HrcDepth; i++)
00103         {
00104                 Frequency[i]= 1;
00105                 FrequencyWindFactor[i]= 0;
00106                 PowerXY[i]= 0;
00107                 PowerZ[i]= 0;
00108                 Bias[i]= 0;
00109                 // Init currentTime.
00110                 _CurrentTime[i]= 0;
00111         }
00112         SpecularLighting= false;
00113 
00114         _LastSceneTime= 0;
00115 }
00116 
00117 
00118 // ***************************************************************************
00119 CMeshVPWindTree::~CMeshVPWindTree()
00120 {
00121 }
00122 
00123 
00124 // ***************************************************************************
00125 void    CMeshVPWindTree::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00126 {
00127         (void)f.serialVersion(0);
00128 
00129         nlassert(HrcDepth==3);
00130         for(uint i=0; i<HrcDepth; i++)
00131         {
00132                 f.serial(Frequency[i]);
00133                 f.serial(FrequencyWindFactor[i]);
00134                 f.serial(PowerXY[i]);
00135                 f.serial(PowerZ[i]);
00136                 f.serial(Bias[i]);
00137         }
00138         f.serial(SpecularLighting);
00139 }
00140 
00141 
00142 // ***************************************************************************
00143 void    CMeshVPWindTree::initInstance(CMeshBaseInstance *mbi)
00144 {
00145         // init the vertexProgram code.
00146         static  bool    vpCreated= false;
00147         if(!vpCreated)
00148         {
00149                 vpCreated= true;
00150                 // All vpcode and begin() written for HrcDepth==3
00151                 nlassert(HrcDepth==3);
00152 
00153                 // combine fragments.
00154                 string  vpCode;
00155 
00156                 // For all possible VP.
00157                 for(uint i=0;i<NumVp;i++)
00158                 {
00159                         // setup of the VPLight fragment
00160                         uint    numPls= i/4;
00161                         bool    normalize= (i&1)!=0;
00162                         bool    specular= (i&2)!=0;
00163 
00164                         // combine fragments
00165                         vpCode= string(WindTreeVPCodeWave) 
00166                                         + CRenderTrav::getLightVPFragment(numPls, VPLightConstantStart, specular, normalize) 
00167                                         + WindTreeVPCodeEnd;
00168                         _VertexProgram[i]= std::auto_ptr<CVertexProgram>(new CVertexProgram(vpCode.c_str()));
00169                 }
00170         }
00171 
00172         // init a random phase.
00173         mbi->_VPWindTreePhase= frand(1);
00174 }
00175 // ***************************************************************************
00176 bool    CMeshVPWindTree::begin(IDriver *driver, CScene *scene, CMeshBaseInstance *mbi, const NLMISC::CMatrix &invertedModelMat, const NLMISC::CVector & /*viewerPos*/)
00177 {
00178         if (!(driver->isVertexProgramSupported() && !driver->isVertexProgramEmulated())) return false;
00179 
00180 
00181         // precompute mesh/instance.
00182         //===============
00183 
00184 
00185         // Get info from scene/instance
00186         float   windPower= scene->getGlobalWindPower();
00187         float   instancePhase= mbi->_VPWindTreePhase;
00188 
00189 
00190         // process current times and current power. Only one time per render() and per CMeshVPWindTree.
00191         if(scene->getCurrentTime() != _LastSceneTime)
00192         {
00193                 float   dt= (float)(scene->getCurrentTime() - _LastSceneTime);
00194                 _LastSceneTime= scene->getCurrentTime();
00195 
00196                 // Update each boneLevel time according to frequency.
00197                 uint i;
00198                 for(i=0; i<HrcDepth; i++)
00199                 {
00200                         _CurrentTime[i]+= dt*(Frequency[i] + FrequencyWindFactor[i]*windPower);
00201                         // get it between 0 and 1. Important for float precision problems.
00202                         _CurrentTime[i]= (float)fmod(_CurrentTime[i], 1);
00203                 }
00204 
00205                 // Update each boneLevel maximum amplitude vector.
00206                 for(i=0; i<HrcDepth; i++)
00207                 {
00208                         _MaxDeltaPos[i]= scene->getGlobalWindDirection() * PowerXY[i] * windPower;
00209                         _MaxDeltaPos[i].z= PowerZ[i] * windPower;
00210                 }
00211         }
00212 
00213 
00214         // maxDeltaPos in ObjectSpace. So same world Wind direction is applied to all objects
00215         static  CMatrix         invWorldMatrix;
00216         // Keep only rotation part. (just need it and faster invert)
00217         invWorldMatrix.setRot(mbi->getWorldMatrix());
00218         invWorldMatrix.invert();
00219         static  CVector         maxDeltaPosOS[HrcDepth];
00220         for(uint i=0; i<HrcDepth; i++)
00221         {
00222                 maxDeltaPosOS[i]= invWorldMatrix.mulVector(_MaxDeltaPos[i]);
00223         }
00224 
00225 
00226         // Setup constants
00227         //===============
00228 
00229         // Setup lighting and lighting constants
00230         setupLighting(scene, mbi, invertedModelMat);
00231 
00232         // c[0..3] take the ModelViewProjection Matrix. After setupModelMatrix();
00233         driver->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
00234         // c[4..7] take the ModelView Matrix. After setupModelMatrix();
00235         driver->setConstantMatrix(4, IDriver::ModelView, IDriver::Identity);
00236         // c[8] take usefull constants.
00237         static  float   ct8[4]= {0, 1, 0.5f, 2};
00238         driver->setConstant(8, 1, ct8);
00239         // c[9] take other usefull constants.
00240         static  float   ct9[4]= {3.f, 0.f, -1.f, -2.f};
00241         driver->setConstant(9, 1, ct9);
00242         // c[10] take Number of phase (4) for level2 and 3. -0.01 to avoid int value == 4.
00243         static  float   ct10[4]= {4-0.01f, 0, 0, 0};
00244         driver->setConstant(10, 1, ct10);
00245 
00246 
00247         // c[15] take Wind of level 0.
00248         float   f;
00249         f= _CurrentTime[0] + instancePhase;
00250         f= speedCos(f) + Bias[0];
00251         driver->setConstant(15, maxDeltaPosOS[0]*f );
00252 
00253 
00254         // c[16-19] take Wind of level 1.
00255         // Unrolled. 
00256         float   instTime1= _CurrentTime[1] + instancePhase;
00257         // phase 0.
00258         f= speedCos( instTime1+0 ) + Bias[1];
00259         driver->setConstant(16+0, maxDeltaPosOS[1]*f);
00260         // phase 1.
00261         f= speedCos( instTime1+0.25f ) + Bias[1];
00262         driver->setConstant(16+1, maxDeltaPosOS[1]*f);
00263         // phase 2.
00264         f= speedCos( instTime1+0.50f ) + Bias[1];
00265         driver->setConstant(16+2, maxDeltaPosOS[1]*f);
00266         // phase 3.
00267         f= speedCos( instTime1+0.75f ) + Bias[1];
00268         driver->setConstant(16+3, maxDeltaPosOS[1]*f);
00269 
00270 
00271         // c[20, 23] take Wind of level 2.
00272         // Unrolled. 
00273         float   instTime2= _CurrentTime[2] + instancePhase;
00274         // phase 0.
00275         f= speedCos( instTime2+0 ) + Bias[2];
00276         driver->setConstant(20+0, maxDeltaPosOS[2]*f);
00277         // phase 1.
00278         f= speedCos( instTime2+0.25f ) + Bias[2];
00279         driver->setConstant(20+1, maxDeltaPosOS[2]*f);
00280         // phase 2.
00281         f= speedCos( instTime2+0.50f ) + Bias[2];
00282         driver->setConstant(20+2, maxDeltaPosOS[2]*f);
00283         // phase 3.
00284         f= speedCos( instTime2+0.75f ) + Bias[2];
00285         driver->setConstant(20+3, maxDeltaPosOS[2]*f);
00286 
00287 
00288         // Activate the good VertexProgram
00289         //===============
00290 
00291         // Get how many pointLights are setuped now.
00292         nlassert(scene != NULL);
00293         CRenderTrav             *renderTrav= scene->getRenderTrav();
00294         sint    numPls= renderTrav->getNumVPLights()-1;
00295         clamp(numPls, 0, CRenderTrav::MaxVPLight-1);
00296 
00297         // Enable normalize only if requested by user. Because lighting don't manage correct "scale lighting"
00298         uint    idVP= (SpecularLighting?2:0) + (driver->isForceNormalize()?1:0) ;
00299         // correct VP id for correct unmber of pls.
00300         idVP= numPls*4 + idVP;
00301 
00302         // activate VP.
00303         driver->activeVertexProgram(_VertexProgram[idVP].get());
00304 
00305 
00306         return true;
00307 }
00308 // ***************************************************************************
00309 void    CMeshVPWindTree::end(IDriver *driver)
00310 {
00311         // Disable the VertexProgram
00312         driver->activeVertexProgram(NULL);
00313 }
00314 
00315 // ***************************************************************************
00316 // tool fct
00317 static inline void SetupForMaterial(const CMaterial &mat, CScene *scene)
00318 {
00319         CRenderTrav             *renderTrav= scene->getRenderTrav();
00320         renderTrav->changeVPLightSetupMaterial(mat, false /* don't exclude strongest */);
00321 }
00322 
00323 // ***************************************************************************
00324 void    CMeshVPWindTree::setupForMaterial(const CMaterial &mat,
00325                                                                                   IDriver *drv,
00326                                                                               CScene *scene,
00327                                                                                   CVertexBuffer *)
00328 {       
00329         SetupForMaterial(mat, scene);   
00330 }
00331 
00332 // ***************************************************************************
00333 void    CMeshVPWindTree::setupForMaterial(const CMaterial &mat,
00334                                                                                   IDriver *drv,
00335                                                                                   CScene *scene,
00336                                                                                   IVertexBufferHard *vb)
00337 {
00338         SetupForMaterial(mat, scene);
00339 }
00340 
00341 // ***************************************************************************
00342 void    CMeshVPWindTree::setupLighting(CScene *scene, CMeshBaseInstance *mbi, const NLMISC::CMatrix &invertedModelMat)
00343 {
00344         nlassert(scene != NULL);
00345         CRenderTrav             *renderTrav= scene->getRenderTrav();
00346         // setup cte for lighting
00347         renderTrav->beginVPLightSetup(VPLightConstantStart, SpecularLighting, invertedModelMat);
00348 }
00349 
00350 } // NL3D