00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
00146 static bool vpCreated= false;
00147 if(!vpCreated)
00148 {
00149 vpCreated= true;
00150
00151 nlassert(HrcDepth==3);
00152
00153
00154 string vpCode;
00155
00156
00157 for(uint i=0;i<NumVp;i++)
00158 {
00159
00160 uint numPls= i/4;
00161 bool normalize= (i&1)!=0;
00162 bool specular= (i&2)!=0;
00163
00164
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
00173 mbi->_VPWindTreePhase= frand(1);
00174 }
00175
00176 bool CMeshVPWindTree::begin(IDriver *driver, CScene *scene, CMeshBaseInstance *mbi, const NLMISC::CMatrix &invertedModelMat, const NLMISC::CVector & )
00177 {
00178 if (!(driver->isVertexProgramSupported() && !driver->isVertexProgramEmulated())) return false;
00179
00180
00181
00182
00183
00184
00185
00186 float windPower= scene->getGlobalWindPower();
00187 float instancePhase= mbi->_VPWindTreePhase;
00188
00189
00190
00191 if(scene->getCurrentTime() != _LastSceneTime)
00192 {
00193 float dt= (float)(scene->getCurrentTime() - _LastSceneTime);
00194 _LastSceneTime= scene->getCurrentTime();
00195
00196
00197 uint i;
00198 for(i=0; i<HrcDepth; i++)
00199 {
00200 _CurrentTime[i]+= dt*(Frequency[i] + FrequencyWindFactor[i]*windPower);
00201
00202 _CurrentTime[i]= (float)fmod(_CurrentTime[i], 1);
00203 }
00204
00205
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
00215 static CMatrix invWorldMatrix;
00216
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
00227
00228
00229
00230 setupLighting(scene, mbi, invertedModelMat);
00231
00232
00233 driver->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
00234
00235 driver->setConstantMatrix(4, IDriver::ModelView, IDriver::Identity);
00236
00237 static float ct8[4]= {0, 1, 0.5f, 2};
00238 driver->setConstant(8, 1, ct8);
00239
00240 static float ct9[4]= {3.f, 0.f, -1.f, -2.f};
00241 driver->setConstant(9, 1, ct9);
00242
00243 static float ct10[4]= {4-0.01f, 0, 0, 0};
00244 driver->setConstant(10, 1, ct10);
00245
00246
00247
00248 float f;
00249 f= _CurrentTime[0] + instancePhase;
00250 f= speedCos(f) + Bias[0];
00251 driver->setConstant(15, maxDeltaPosOS[0]*f );
00252
00253
00254
00255
00256 float instTime1= _CurrentTime[1] + instancePhase;
00257
00258 f= speedCos( instTime1+0 ) + Bias[1];
00259 driver->setConstant(16+0, maxDeltaPosOS[1]*f);
00260
00261 f= speedCos( instTime1+0.25f ) + Bias[1];
00262 driver->setConstant(16+1, maxDeltaPosOS[1]*f);
00263
00264 f= speedCos( instTime1+0.50f ) + Bias[1];
00265 driver->setConstant(16+2, maxDeltaPosOS[1]*f);
00266
00267 f= speedCos( instTime1+0.75f ) + Bias[1];
00268 driver->setConstant(16+3, maxDeltaPosOS[1]*f);
00269
00270
00271
00272
00273 float instTime2= _CurrentTime[2] + instancePhase;
00274
00275 f= speedCos( instTime2+0 ) + Bias[2];
00276 driver->setConstant(20+0, maxDeltaPosOS[2]*f);
00277
00278 f= speedCos( instTime2+0.25f ) + Bias[2];
00279 driver->setConstant(20+1, maxDeltaPosOS[2]*f);
00280
00281 f= speedCos( instTime2+0.50f ) + Bias[2];
00282 driver->setConstant(20+2, maxDeltaPosOS[2]*f);
00283
00284 f= speedCos( instTime2+0.75f ) + Bias[2];
00285 driver->setConstant(20+3, maxDeltaPosOS[2]*f);
00286
00287
00288
00289
00290
00291
00292 nlassert(scene != NULL);
00293 CRenderTrav *renderTrav= scene->getRenderTrav();
00294 sint numPls= renderTrav->getNumVPLights()-1;
00295 clamp(numPls, 0, CRenderTrav::MaxVPLight-1);
00296
00297
00298 uint idVP= (SpecularLighting?2:0) + (driver->isForceNormalize()?1:0) ;
00299
00300 idVP= numPls*4 + idVP;
00301
00302
00303 driver->activeVertexProgram(_VertexProgram[idVP].get());
00304
00305
00306 return true;
00307 }
00308
00309 void CMeshVPWindTree::end(IDriver *driver)
00310 {
00311
00312 driver->activeVertexProgram(NULL);
00313 }
00314
00315
00316
00317 static inline void SetupForMaterial(const CMaterial &mat, CScene *scene)
00318 {
00319 CRenderTrav *renderTrav= scene->getRenderTrav();
00320 renderTrav->changeVPLightSetupMaterial(mat, false );
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
00347 renderTrav->beginVPLightSetup(VPLightConstantStart, SpecularLighting, invertedModelMat);
00348 }
00349
00350 }