00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/misc/vector_2f.h"
00027 #include "nel/misc/vector_h.h"
00028 #include "nel/misc/hierarchical_timer.h"
00029 #include "nel/3d/animation_time.h"
00030 #include "nel/3d/water_model.h"
00031 #include "nel/3d/water_shape.h"
00032 #include "nel/3d/water_pool_manager.h"
00033 #include "nel/3d/water_height_map.h"
00034 #include "nel/3d/dru.h"
00035 #include "nel/3d/scene.h"
00036 #include "nel/3d/driver.h"
00037 #include "nel/3d/render_trav.h"
00038 #include "nel/3d/anim_detail_trav.h"
00039 #include "nel/3d/texture_emboss.h"
00040 #include "nel/3d/texture_bump.h"
00041 #include "nel/3d/water_env_map.h"
00042
00043
00044 using NLMISC::CVector2f;
00045
00046
00047 namespace NL3D {
00048
00049
00050 CMaterial CWaterModel::_WaterMat;
00051
00052 CMaterial CWaterModel::_SimpleWaterMat;
00053 const uint WATER_MODEL_DEFAULT_NUM_VERTICES = 5000;
00054
00055 NLMISC::CRefPtr<IDriver> CWaterModel::_CurrDrv;
00056
00057
00058
00059
00060 volatile bool forceWaterSimpleRender = false;
00061
00062
00063 void CWaterModel::setupVertexBuffer(CVertexBuffer &vb, uint numWantedVertices, IDriver *drv)
00064 {
00065 if (!numWantedVertices) return;
00066 if (vb.getNumVertices() == 0 || drv != _CurrDrv)
00067 {
00068 vb.setNumVertices(0);
00069 vb.setName("Water");
00070 vb.setPreferredMemory(CVertexBuffer::AGPPreferred, false);
00071 if (drv->isWaterShaderSupported())
00072 {
00073 vb.setVertexFormat(CVertexBuffer::PositionFlag);
00074 }
00075 else
00076 {
00077 vb.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag);
00078 }
00079 _CurrDrv = drv;
00080 }
00081 uint numVerts = std::max(numWantedVertices, WATER_MODEL_DEFAULT_NUM_VERTICES);
00082 if (numVerts > vb.getNumVertices())
00083 {
00084 const uint vb_INCREASE_SIZE = 1000;
00085 numVerts = vb_INCREASE_SIZE * ((numVerts + (vb_INCREASE_SIZE - 1)) / vb_INCREASE_SIZE);
00086 vb.setNumVertices((uint32) numVerts);
00087 }
00088 }
00089
00090
00091 CWaterModel::CWaterModel()
00092 {
00093 setOpacity(false);
00094 setTransparency(true);
00095 setOrderingLayer(1);
00096
00097 _RenderFilterType= UScene::FilterWater;
00098 _Prev = NULL;
00099 _Next = NULL;
00100 _MatrixUpdateDate = 0;
00101 }
00102
00103
00104 CWaterModel::~CWaterModel()
00105 {
00106 CScene *scene = getOwnerScene();
00107 if (scene && scene->getWaterCallback())
00108 {
00109 nlassert(Shape);
00110 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00111 scene->getWaterCallback()->waterSurfaceRemoved(ws->getUseSceneWaterEnvMap(0) || ws->getUseSceneWaterEnvMap(1));
00112 }
00113
00114 unlink();
00115 }
00116
00117
00118 void CWaterModel::registerBasic()
00119 {
00120 CScene::registerModel(WaterModelClassId, TransformShapeId, CWaterModel::creator);
00121 }
00122
00123
00124
00125 ITrack* CWaterModel::getDefaultTrack (uint valueId)
00126 {
00127 nlassert(Shape);
00128 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00129 switch (valueId)
00130 {
00131 case PosValue: return ws->getDefaultPos(); break;
00132 case ScaleValue: return ws->getDefaultScale(); break;
00133 case RotQuatValue: return ws->getDefaultRotQuat(); break;
00134 default:
00135 return CTransformShape::getDefaultTrack(valueId);
00136 break;
00137 }
00138 }
00139
00140
00141
00142 uint32 CWaterModel::getWaterHeightMapID() const
00143 {
00144 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00145 return ws->_WaterPoolID;
00146 }
00147
00148
00149 float CWaterModel::getHeightFactor() const
00150 {
00151 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00152 return ws->_WaveHeightFactor;
00153 }
00154
00155
00156
00157 float CWaterModel::getHeight(const CVector2f &pos)
00158 {
00159 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00160 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(ws->_WaterPoolID);
00161 const float height = whm.getHeight(pos);
00162 return height * ws->_WaveHeightFactor + this->getPos().z;
00163 }
00164
00165
00166 float CWaterModel::getAttenuatedHeight(const CVector2f &pos, const NLMISC::CVector &viewer)
00167 {
00168 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00169 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(ws->_WaterPoolID);
00170 const float maxDist = whm.getUnitSize() * (whm.getSize() >> 1);
00171 const NLMISC::CVector planePos(pos.x, pos.y, this->getMatrix().getPos().z);
00172 const float userDist = (planePos - viewer).norm();
00173
00174 if (userDist > maxDist)
00175 {
00176 return this->getMatrix().getPos().z;
00177 }
00178 else
00179 {
00180 const float height = whm.getHeight(pos);
00181 return ws->_WaveHeightFactor * height * (1.f - userDist / maxDist) + this->getMatrix().getPos().z;
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00321
00322
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00552
00553
00554
00555
00556
00557
00558
00559
00560
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 void CWaterModel::setupMaterialNVertexShader(IDriver *drv, CWaterShape *shape, const NLMISC::CVector &obsPos, bool above, float zHeight)
00900 {
00901 static bool matSetupped = false;
00902 if (!matSetupped)
00903 {
00904 _WaterMat.setLighting(false);
00905 _WaterMat.setDoubleSided(true);
00906 _WaterMat.setColor(NLMISC::CRGBA::White);
00907 _WaterMat.setBlend(true);
00908 _WaterMat.setSrcBlend(CMaterial::srcalpha);
00909 _WaterMat.setDstBlend(CMaterial::invsrcalpha);
00910 _WaterMat.setZWrite(true);
00911 _WaterMat.setShader(CMaterial::Water);
00912 }
00913 const uint cstOffset = 5;
00914 NLMISC::CVectorH cst[13];
00915
00916
00917
00918 CWaterModel::_WaterMat.setTexture(0, shape->_BumpMap[0]);
00919 CWaterModel::_WaterMat.setTexture(1, shape->_BumpMap[1]);
00920 CWaterModel::_WaterMat.setTexture(3, shape->_ColorMap);
00921 CScene *scene = getOwnerScene();
00922 if (!above && shape->_EnvMap[1])
00923 {
00924 if (shape->_UsesSceneWaterEnvMap[1])
00925 {
00926 if (scene->getWaterEnvMap())
00927 {
00928 CWaterModel::_WaterMat.setTexture(2, scene->getWaterEnvMap()->getEnvMap2D());
00929 }
00930 else
00931 {
00932 CWaterModel::_WaterMat.setTexture(2, shape->_EnvMap[1]);
00933 }
00934 }
00935 else
00936 {
00937 CWaterModel::_WaterMat.setTexture(2, shape->_EnvMap[1]);
00938 }
00939 }
00940 else
00941 {
00942 if (shape->_UsesSceneWaterEnvMap[0])
00943 {
00944 if (scene->getWaterEnvMap())
00945 {
00946 CWaterModel::_WaterMat.setTexture(2, scene->getWaterEnvMap()->getEnvMap2D());
00947 }
00948 else
00949 {
00950 CWaterModel::_WaterMat.setTexture(2, shape->_EnvMap[0]);
00951 }
00952 }
00953 else
00954 {
00955 CWaterModel::_WaterMat.setTexture(2, shape->_EnvMap[0]);
00956 }
00957 }
00958 shape->envMapUpdate();
00959 if (shape->_ColorMap)
00960 {
00961
00962 updateDiffuseMapMatrix();
00963 cst[11].set(_ColorMapMatColumn0.x, _ColorMapMatColumn1.x, 0, _ColorMapMatColumn0.x * obsPos.x + _ColorMapMatColumn1.x * obsPos.y + _ColorMapMatPos.x);
00964 cst[12].set(_ColorMapMatColumn0.y, _ColorMapMatColumn1.y, 0, _ColorMapMatColumn0.y * obsPos.x + _ColorMapMatColumn1.y * obsPos.y + _ColorMapMatPos.y);
00965 }
00967 drv->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
00968
00969 double date = scene->getCurrentTime();
00970
00971 cst[6].set(fmodf(obsPos.x * shape->_HeightMapScale[0].x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[0].x, 1), fmodf(shape->_HeightMapScale[0].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[0].y, 1), 0.f, 1.f);
00972 cst[5].set(shape->_HeightMapScale[0].x, shape->_HeightMapScale[0].y, 0, 0);
00973 cst[8].set(fmodf(shape->_HeightMapScale[1].x * obsPos.x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].x, 1), fmodf(shape->_HeightMapScale[1].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].y, 1), 0.f, 1.f);
00974 cst[7].set(shape->_HeightMapScale[1].x, shape->_HeightMapScale[1].y, 0, 0);
00975 cst[9].set(0, 0, obsPos.z - zHeight, 1.f);
00976 cst[10].set(0.5f, 0.5f, 0.f, 1.f);
00978 drv->setConstant(cstOffset, sizeof(cst) / sizeof(cst[0]) - cstOffset, (float *) &cst[cstOffset]);
00979 shape->initVertexProgram();
00980 drv->activeVertexProgram(shape->_ColorMap ? CWaterShape::_VertexProgramNoWaveDiffuse.get() : CWaterShape::_VertexProgramNoWave.get());
00981 drv->setConstantFog(4);
00982 }
00983
00984
00985 void CWaterModel::setupSimpleRender(CWaterShape *shape, const NLMISC::CVector &obsPos, bool above)
00986 {
00987
00988 static bool init = false;
00989 if (!init)
00990 {
00991
00992 _SimpleWaterMat.setLighting(false);
00993 _SimpleWaterMat.setDoubleSided(true);
00994 _SimpleWaterMat.setColor(NLMISC::CRGBA::White);
00995
00996 _SimpleWaterMat.setBlend(true);
00997 _SimpleWaterMat.setSrcBlend(CMaterial::srcalpha);
00998 _SimpleWaterMat.setDstBlend(CMaterial::invsrcalpha);
00999 _SimpleWaterMat.setZWrite(true);
01000 _SimpleWaterMat.setShader(CMaterial::Normal);
01001
01002
01003 _SimpleWaterMat.texEnvOpRGB(0, CMaterial::Replace);
01004 _SimpleWaterMat.texEnvOpAlpha(0, CMaterial::Replace);
01005 _SimpleWaterMat.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor);
01006 _SimpleWaterMat.texEnvArg0Alpha(0, CMaterial::Texture, CMaterial::SrcAlpha);
01007
01008
01009 _SimpleWaterMat.texEnvOpRGB(1, CMaterial::Modulate);
01010 _SimpleWaterMat.texEnvOpAlpha(1, CMaterial::Modulate);
01011 _SimpleWaterMat.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor);
01012 _SimpleWaterMat.texEnvArg0Alpha(0, CMaterial::Texture, CMaterial::SrcAlpha);
01013 _SimpleWaterMat.texEnvArg1RGB(0, CMaterial::Previous, CMaterial::SrcColor);
01014 _SimpleWaterMat.texEnvArg1Alpha(0, CMaterial::Previous, CMaterial::SrcAlpha);
01015
01016 init = true;
01017 }
01018
01019 CScene *scene = getOwnerScene();
01020 if (!above && shape->_EnvMap[1])
01021 {
01022 if (shape->_UsesSceneWaterEnvMap[1])
01023 {
01024 if (scene->getWaterEnvMap())
01025 {
01026 _SimpleWaterMat.setTexture(0, scene->getWaterEnvMap()->getEnvMap2D());
01027 }
01028 else
01029 {
01030 _SimpleWaterMat.setTexture(0, shape->_EnvMap[1]);
01031 }
01032 }
01033 else
01034 {
01035 _SimpleWaterMat.setTexture(0, shape->_EnvMap[1]);
01036 }
01037 }
01038 else
01039 {
01040 if (shape->_UsesSceneWaterEnvMap[0])
01041 {
01042 if (scene->getWaterEnvMap())
01043 {
01044 _SimpleWaterMat.setTexture(0, scene->getWaterEnvMap()->getEnvMap2D());
01045 }
01046 else
01047 {
01048 _SimpleWaterMat.setTexture(0, shape->_EnvMap[0]);
01049 }
01050 }
01051 else
01052 {
01053 _SimpleWaterMat.setTexture(0, shape->_EnvMap[0]);
01054 }
01055 }
01056
01057 if (shape->_ColorMap == NULL)
01058 {
01059
01060 if (!_EmbossTexture)
01061 {
01062 _EmbossTexture = new CTextureEmboss;
01063 _EmbossTexture->setSlopeFactor(4.f);
01064 }
01065 if (shape->_BumpMap[1] && shape->_BumpMap[1]->isBumpMap())
01066 {
01067 CTextureBump *bm = static_cast<CTextureBump *>((ITexture *) shape->_BumpMap[1]);
01068 if (bm->getHeightMap())
01069 {
01070 _EmbossTexture->setHeightMap(bm->getHeightMap());
01071 }
01072 }
01073 _SimpleWaterMat.setTexture(1, _EmbossTexture);
01074 _SimpleWaterMat.setTexCoordGen(1, true);
01075 _SimpleWaterMat.setTexCoordGenMode(1, CMaterial::TexCoordGenObjectSpace);
01076 double date = scene->getCurrentTime();
01077 CMatrix texMat;
01078 texMat.scale(CVector(shape->_HeightMapScale[1].x, shape->_HeightMapScale[1].y, 1.f));
01079 texMat.setPos(CVector(fmodf(shape->_HeightMapScale[1].x * obsPos.x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].x, 1),
01080 fmodf(shape->_HeightMapScale[1].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].y, 1),
01081 1.f)
01082 );
01083 _SimpleWaterMat.enableUserTexMat(1, true);
01084 _SimpleWaterMat.setUserTexMat(1, texMat);
01085 }
01086 else
01087 {
01088 updateDiffuseMapMatrix();
01089
01090 _SimpleWaterMat.setTexture(1, shape->_ColorMap);
01091 _SimpleWaterMat.setTexCoordGen(1, true);
01092 _SimpleWaterMat.setTexCoordGenMode(1, CMaterial::TexCoordGenObjectSpace);
01093 CMatrix texMat;
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 float mat[16] =
01104 {
01105 _ColorMapMatColumn0.x, _ColorMapMatColumn0.y, 0.f, 0.f,
01106 _ColorMapMatColumn1.x, _ColorMapMatColumn1.y, 0.f, 0.f,
01107 0.f, 0.f, 1.f, 0.f,
01108 _ColorMapMatColumn0.x * obsPos.x + _ColorMapMatColumn1.x * obsPos.y + _ColorMapMatPos.x, _ColorMapMatColumn0.y * obsPos.x + _ColorMapMatColumn1.y * obsPos.y + _ColorMapMatPos.y, 0.f, 1.f
01109 };
01110 texMat.set(mat);
01111 _SimpleWaterMat.enableUserTexMat(1, true);
01112 _SimpleWaterMat.setUserTexMat(1, texMat);
01113 }
01114 }
01115
01116
01117
01118 void CWaterModel::computeClippedPoly()
01119 {
01120 CWaterShape *shape = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
01121 const std::vector<CPlane> &worldPyramid = getOwnerScene()->getClipTrav().WorldFrustumPyramid;
01122 _ClippedPoly.Vertices.resize(shape->_Poly.Vertices.size());
01123 uint k;
01124 for (k = 0; k < shape->_Poly.Vertices.size(); ++k)
01125 {
01126 _ClippedPoly.Vertices[k].set(shape->_Poly.Vertices[k].x,
01127 shape->_Poly.Vertices[k].y,
01128 0.f
01129 );
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 static std::vector<CPlane> tp;
01171 tp.resize(worldPyramid.size());
01172 for(uint k = 0; k < tp.size(); ++k)
01173 {
01174 tp[k] = worldPyramid[k] * getWorldMatrix();
01175 }
01176 _ClippedPoly.clip(tp);
01177 }
01178
01179
01180 void CWaterModel::unlink()
01181 {
01182 if (!_Prev)
01183 {
01184 nlassert(!_Next);
01185 return;
01186 }
01187 if (_Next)
01188 {
01189 _Next->_Prev = _Prev;
01190 }
01191 *_Prev = _Next;
01192 _Next = NULL;
01193 _Prev = NULL;
01194 }
01195
01196
01197 void CWaterModel::link()
01198 {
01199 nlassert(_Next == NULL);
01200 CScene *scene = getOwnerScene();
01201 nlassert(scene);
01202 CRenderTrav &rt = scene->getRenderTrav();
01203 _Prev = &rt._FirstWaterModel;
01204 _Next = rt._FirstWaterModel;
01205 if (_Next)
01206 {
01207 _Next->_Prev = &_Next;
01208 }
01209 rt._FirstWaterModel = this;
01210 }
01211
01212
01213
01214
01215 uint CWaterModel::getNumWantedVertices()
01216 {
01217 H_AUTO( NL3D_Water_Render );
01218 nlassert(!_ClippedPoly.Vertices.empty());
01219
01220 CRenderTrav &renderTrav = getOwnerScene()->getRenderTrav();
01221 if (!renderTrav.Perspective || forceWaterSimpleRender) return 0;
01222
01223 const NLMISC::CVector &obsPos = renderTrav.CamPos;
01224
01225 const NLMISC::CMatrix &viewMat = renderTrav.ViewMatrix;
01226
01227 const float zHeight = getWorldMatrix().getPos().z;
01228 const sint numStepX = CWaterShape::getScreenXGridSize();
01229 const sint numStepY = CWaterShape::getScreenYGridSize();
01230 NLMISC::CMatrix modelMat;
01231 modelMat.setPos(NLMISC::CVector(obsPos.x, obsPos.y, zHeight));
01232 static NLMISC::CPolygon2D projPoly;
01233 projPoly.Vertices.resize(_ClippedPoly.Vertices.size());
01234
01235 const float xFactor = numStepX * renderTrav.Near / (renderTrav.Right - renderTrav.Left);
01236 const float yFactor = numStepY * renderTrav.Near / (renderTrav.Top - renderTrav.Bottom);
01237
01238 const NLMISC::CMatrix &projMat = viewMat * getWorldMatrix();
01239 uint k;
01240 for (k = 0; k < _ClippedPoly.Vertices.size(); ++k)
01241 {
01242
01243 NLMISC::CVector t = projMat * _ClippedPoly.Vertices[k];
01244 float invY = 1.f / t.y;
01245 projPoly.Vertices[k].set(xFactor * t.x * invY, yFactor * t.z * invY);
01246 }
01247
01248 projPoly.computeInnerBorders(_Inside, _MinYInside);
01249
01250 static NLMISC::CPolygon2D::TRasterVect border;
01251 sint minYBorder;
01252 projPoly.computeOuterBorders(border, minYBorder);
01253
01254
01255 sint height = border.size();
01256 if (_Inside.empty())
01257 {
01258 _MinYInside = minYBorder;
01259 }
01260 sint bottomGap = border.size() - _Inside.size();
01261 _Inside.resize(height);
01262 nlassert(minYBorder == _MinYInside);
01263
01264 nlassert(bottomGap >= 0);
01265 if (bottomGap)
01266 {
01267 for(sint y = height - bottomGap; y < height; ++y)
01268 {
01269 nlassert (y >= 0 && y < (sint)_Inside.size());
01270 _Inside[y].first = border[y].first;
01271 _Inside[y].second = border[y].first - 1;
01272 }
01273 }
01274
01275 for(sint y = 0; y < height - bottomGap; ++y)
01276 {
01277 if (_Inside[y].first > _Inside[y].second)
01278 {
01279 nlassert (y >= 0 && y < (sint)_Inside.size());
01280 _Inside[y].first = border[y].first;
01281 _Inside[y].second = border[y].first - 1;
01282 }
01283 else if (border[y].first > border[y].second)
01284 {
01285 nlassert (y >= 0 && y < (sint)_Inside.size());
01286 border[y].first = _Inside[y].first;
01287 border[y].second = _Inside[y].first - 1;
01288 }
01289 }
01290
01291 static std::vector<CPlane> clipPlanes;
01292
01293 const CVector2f *prevVert = &projPoly.Vertices.back();
01294 const CVector2f *currVert = &projPoly.Vertices.front();
01295 uint numVerts = projPoly.Vertices.size();
01296 bool ccw = projPoly.isCCWOriented();
01297 clipPlanes.resize(numVerts);
01298 for(uint k = 0; k < numVerts; ++k)
01299 {
01300 NLMISC::CVector v0;
01301 NLMISC::CVector v1;
01302 NLMISC::CVector v2;
01303 v0.set(prevVert->x, prevVert->y, 0.f);
01304 v1.set(currVert->x, currVert->y, 0.f);
01305 v2.set(prevVert->x, prevVert->y, (*currVert - *prevVert).norm());
01306 clipPlanes[k].make(v0, v1, v2);
01307 if (!ccw)
01308 {
01309 clipPlanes[k].invert();
01310 }
01311 prevVert = currVert;
01312 ++ currVert;
01313 }
01314
01315 _ClippedTriNumVerts.clear();
01316 _ClippedTris.clear();
01317 static NLMISC::CPolygon clipPoly;
01318 uint totalNumVertices = 0;
01319
01320 for(sint k = 0; k < (sint) border.size(); ++k)
01321 {
01322
01323 for (sint x = border[k].first; x < _Inside[k].first; ++x)
01324 {
01325 clipPoly.Vertices.resize(4);
01326 clipPoly.Vertices[0].set((float) x, (float) (k + _MinYInside), 0.f);
01327 clipPoly.Vertices[1].set((float) (x + 1), (float) (k + _MinYInside), 0.f);
01328 clipPoly.Vertices[2].set((float) (x + 1), (float) (k + _MinYInside + 1), 0.f);
01329 clipPoly.Vertices[3].set((float) x, (float) (k + _MinYInside + 1), 0.f);
01330 clipPoly.clip(clipPlanes);
01331 if (!clipPoly.Vertices.empty())
01332 {
01333
01334 _ClippedTriNumVerts.push_back(clipPoly.Vertices.size());
01335 uint prevSize = _ClippedTris.size();
01336 _ClippedTris.resize(_ClippedTris.size() + clipPoly.Vertices.size());
01337 std::copy(clipPoly.Vertices.begin(), clipPoly.Vertices.end(), _ClippedTris.begin() + prevSize);
01338 totalNumVertices += (clipPoly.Vertices.size() - 2) * 3;
01339 }
01340 }
01341
01342 if (_Inside[k].first <= _Inside[k].second)
01343 {
01344 totalNumVertices += 6 * (_Inside[k].second - _Inside[k].first + 1);
01345 }
01346
01347 for (sint x = _Inside[k].second + 1; x <= border[k].second; ++x)
01348 {
01349 clipPoly.Vertices.resize(4);
01350 clipPoly.Vertices[0].set((float) x, (float) (k + _MinYInside), 0.f);
01351 clipPoly.Vertices[1].set((float) (x + 1), (float) (k + _MinYInside), 0.f);
01352 clipPoly.Vertices[2].set((float) (x + 1), (float) (k + _MinYInside + 1), 0.f);
01353 clipPoly.Vertices[3].set((float) x, (float) (k + _MinYInside + 1), 0.f);
01354 clipPoly.clip(clipPlanes);
01355 if (!clipPoly.Vertices.empty())
01356 {
01357
01358 _ClippedTriNumVerts.push_back(clipPoly.Vertices.size());
01359 uint prevSize = _ClippedTris.size();
01360 _ClippedTris.resize(_ClippedTris.size() + clipPoly.Vertices.size());
01361 std::copy(clipPoly.Vertices.begin(), clipPoly.Vertices.end(), _ClippedTris.begin() + prevSize);
01362 totalNumVertices += (clipPoly.Vertices.size() - 2) * 3;
01363 }
01364 }
01365 }
01366 return totalNumVertices;
01367 }
01368
01369
01370 uint CWaterModel::fillVB(void *datas, uint startTri, IDriver &drv)
01371 {
01372 H_AUTO( NL3D_Water_Render );
01373 if (drv.isWaterShaderSupported())
01374 {
01375 return fillVBHard(datas, startTri);
01376 }
01377 else
01378 {
01379 return fillVBSoft(datas, startTri);
01380 }
01381 }
01382
01383
01384
01385 static const double WATER_WAVE_SPEED = 1.7;
01386 static const double WATER_WAVE_SCALE = 0.05;
01387 static const double WATER_WAVE_FREQ = 0.3;
01388 static const float WATER_WAVE_ATTEN = 0.2f;
01389
01390
01391
01392
01393
01394 static
01395 #ifndef NL_DEBUG
01396 inline
01397 #endif
01398 void computeWaterVertexSoft(float px, float py, CVector &pos, CVector2f &envMapTexCoord, const CVector &camI, const CVector &camJ, const CVector &camK, float denom, double date, const CVector &camPos)
01399 {
01400 CVector d = px * camI + py * camK + camJ;
01401
01402 float intersectionDist = denom / d.z;
01403 pos.x = intersectionDist * d.x;
01404 pos.y = intersectionDist * d.y;
01405 pos.z = 0.f;
01406
01407 CVector R(- pos.x,
01408 - pos.y,
01409 - denom
01410 );
01411 float dist = R.norm();
01412 if (dist)
01413 {
01414 R /= dist;
01415 }
01416 envMapTexCoord.set(- 0.5f * R.x + 0.5f, - 0.5f * R.y + 0.5f);
01417 if (dist)
01418 {
01419 float invDist = 1.f / (WATER_WAVE_ATTEN * dist);
01420 if (invDist > 1.f) invDist = 1.f;
01421
01422 envMapTexCoord.x += (float) (invDist * WATER_WAVE_SCALE * (float) cos(date + WATER_WAVE_FREQ * (camPos.x + pos.x)));
01423 }
01424 }
01425
01426
01427 uint CWaterModel::fillVBSoft(void *datas, uint startTri)
01428 {
01429 _StartTri = (uint32) startTri;
01430 CRenderTrav &renderTrav = getOwnerScene()->getRenderTrav();
01431 const NLMISC::CMatrix &camMat = renderTrav.CamMatrix;
01432 const sint numStepX = CWaterShape::getScreenXGridSize();
01433 const sint numStepY = CWaterShape::getScreenYGridSize();
01434 CVector camI = camMat.getI() * (1.f / numStepX) * (renderTrav.Right - renderTrav.Left) / renderTrav.Near;
01435 CVector camJ = camMat.getJ();
01436 CVector camK = camMat.getK() * (1.f / numStepY) * (renderTrav.Top - renderTrav.Bottom) / renderTrav.Near;
01437 float obsZ = camMat.getPos().z;
01438 float denom = getWorldMatrix().getPos().z - obsZ;
01439 uint8 *dest = (uint8 *) datas + startTri * 3 * WATER_VERTEX_SOFT_SIZE;
01440
01441
01442 NLMISC::CVector eye(0.f, 0.f, - denom);
01443 CVector R;
01444 CScene *scene = getOwnerScene();
01445 double date = WATER_WAVE_SPEED * scene->getCurrentTime();
01446 if (!_ClippedTriNumVerts.empty())
01447 {
01448 const CVector2f *currVert = &_ClippedTris.front();
01449 static std::vector<CVector> unprojectedTriSoft;
01450 static std::vector<CVector2f> envMap;
01451 for(uint k = 0; k < _ClippedTriNumVerts.size(); ++k)
01452 {
01453 unprojectedTriSoft.resize(_ClippedTriNumVerts[k]);
01454 envMap.resize(_ClippedTriNumVerts[k]);
01455 uint numVerts = _ClippedTriNumVerts[k];
01456 for(uint l = 0; l < _ClippedTriNumVerts[k]; ++l)
01457 {
01458 computeWaterVertexSoft(currVert->x, currVert->y, unprojectedTriSoft[l], envMap[l], camI, camJ, camK, denom, date, camMat.getPos());
01459 ++ currVert;
01460 }
01461 for(uint l = 0; l < numVerts - 2; ++l)
01462 {
01463 *(CVector *) dest = unprojectedTriSoft[0];
01464 dest += sizeof(float[3]);
01465 *(CVector2f *) dest = envMap[0];
01466 dest += sizeof(float[2]);
01467 *(CVector *) dest = unprojectedTriSoft[l + 1];
01468 dest += sizeof(float[3]);
01469 *(CVector2f *) dest = envMap[l + 1];
01470 dest += sizeof(float[2]);
01471 *(CVector *) dest = unprojectedTriSoft[l + 2];
01472 dest += sizeof(float[3]);
01473 *(CVector2f *) dest = envMap[l + 2];
01474 dest += sizeof(float[2]);
01475 }
01476 }
01477 }
01478
01479 for(sint k = 0; k < (sint) _Inside.size(); ++k)
01480 {
01481 sint y = k + _MinYInside;
01482 CVector proj[4];
01483 CVector2f envMap[4];
01484 if (_Inside[k].first <= _Inside[k].second)
01485 {
01486
01487 for(sint x = _Inside[k].first; x <= _Inside[k].second; ++x)
01488 {
01489 computeWaterVertexSoft((float) x, (float) y, proj[0], envMap[0], camI, camJ, camK, denom, date, camMat.getPos());
01490 computeWaterVertexSoft((float)(x + 1), (float) y, proj[1], envMap[1], camI, camJ, camK, denom, date, camMat.getPos());
01491 computeWaterVertexSoft((float) (x + 1), (float) (y + 1), proj[2], envMap[2], camI, camJ, camK, denom, date, camMat.getPos());
01492 computeWaterVertexSoft((float) x, (float) (y + 1), proj[3], envMap[3], camI, camJ, camK, denom, date, camMat.getPos());
01493
01494 *(CVector *) dest = proj[0];
01495 dest += sizeof(float[3]);
01496 *(CVector2f *) dest = envMap[0];
01497 dest += sizeof(float[2]);
01498 *(CVector *) dest = proj[2];
01499 dest += sizeof(float[3]);
01500 *(CVector2f *) dest = envMap[2];
01501 dest += sizeof(float[2]);
01502 *(CVector *) dest = proj[1];
01503 dest += sizeof(float[3]);
01504 *(CVector2f *) dest = envMap[1];
01505 dest += sizeof(float[2]);
01506 *(CVector *) dest = proj[0];
01507 dest += sizeof(float[3]);
01508 *(CVector2f *) dest = envMap[0];
01509 dest += sizeof(float[2]);
01510 *(CVector *) dest = proj[3];
01511 dest += sizeof(float[3]);
01512 *(CVector2f *) dest = envMap[3];
01513 dest += sizeof(float[2]);
01514 *(CVector *) dest = proj[2];
01515 dest += sizeof(float[3]);
01516 *(CVector2f *) dest = envMap[2];
01517 dest += sizeof(float[2]);
01518 }
01519 }
01520 }
01521 nlassert((dest - (uint8 * ) datas) % (3 * WATER_VERTEX_SOFT_SIZE) == 0);
01522 uint endTri = (dest - (uint8 * ) datas) / (3 * WATER_VERTEX_SOFT_SIZE);
01523 _NumTris = endTri - _StartTri;
01524 return endTri;
01525 }
01526
01527
01528 static
01529 #ifndef NL_DEBUG
01530 inline
01531 #endif
01532 void computeWaterVertexHard(float px, float py, CVector &pos, const CVector &camI, const CVector &camJ, const CVector &camK, float denom)
01533 {
01534 CVector d = px * camI + py * camK + camJ;
01535 float intersectionDist = denom / d.z;
01536 pos.x = intersectionDist * d.x;
01537 pos.y = intersectionDist * d.y;
01538 pos.z = 0.f;
01539 }
01540
01541
01542 uint CWaterModel::fillVBHard(void *datas, uint startTri)
01543 {
01544 _StartTri = (uint32) startTri;
01545 CRenderTrav &renderTrav = getOwnerScene()->getRenderTrav();
01546 const NLMISC::CMatrix &camMat = renderTrav.CamMatrix;
01547 const sint numStepX = CWaterShape::getScreenXGridSize();
01548 const sint numStepY = CWaterShape::getScreenYGridSize();
01549 CVector camI = camMat.getI() * (1.f / numStepX) * (renderTrav.Right - renderTrav.Left) / renderTrav.Near;
01550 CVector camJ = camMat.getJ();
01551 CVector camK = camMat.getK() * (1.f / numStepY) * (renderTrav.Top - renderTrav.Bottom) / renderTrav.Near;
01552 float obsZ = camMat.getPos().z;
01553 float denom = getWorldMatrix().getPos().z - obsZ;
01554 uint8 *dest = (uint8 *) datas + startTri * WATER_VERTEX_HARD_SIZE * 3;
01555 if (!_ClippedTriNumVerts.empty())
01556 {
01557 const CVector2f *currVert = &_ClippedTris.front();
01558 static std::vector<CVector> unprojectedTri;
01559 for(uint k = 0; k < _ClippedTriNumVerts.size(); ++k)
01560 {
01561 unprojectedTri.resize(_ClippedTriNumVerts[k]);
01562 uint numVerts = _ClippedTriNumVerts[k];
01563 for(uint l = 0; l < _ClippedTriNumVerts[k]; ++l)
01564 {
01565 computeWaterVertexHard(currVert->x, currVert->y, unprojectedTri[l], camI, camJ, camK, denom);
01566 ++ currVert;
01567 }
01568 for(uint l = 0; l < numVerts - 2; ++l)
01569 {
01570 *(CVector *) dest = unprojectedTri[0];
01571 dest += WATER_VERTEX_HARD_SIZE;
01572 *(CVector *) dest = unprojectedTri[l + 1];
01573 dest += WATER_VERTEX_HARD_SIZE;
01574 *(CVector *) dest = unprojectedTri[l + 2];
01575 dest += WATER_VERTEX_HARD_SIZE;
01576 }
01577 }
01578 }
01579
01580 for(sint k = 0; k < (sint) _Inside.size(); ++k)
01581 {
01582 sint y = k + _MinYInside;
01583 CVector proj[4];
01584 if (_Inside[k].first <= _Inside[k].second)
01585 {
01586
01587 for(sint x = _Inside[k].first; x <= _Inside[k].second; ++x)
01588 {
01589 computeWaterVertexHard((float) x, (float) y, proj[0], camI, camJ, camK, denom);
01590 computeWaterVertexHard((float) (x + 1), (float) y, proj[1], camI, camJ, camK, denom);
01591 computeWaterVertexHard((float) (x + 1), (float) (y + 1), proj[2], camI, camJ, camK, denom);
01592 computeWaterVertexHard((float) x, (float) (y + 1), proj[3], camI, camJ, camK, denom);
01593
01594 *(CVector *) dest = proj[0];
01595 dest += WATER_VERTEX_HARD_SIZE;
01596 *(CVector *) dest = proj[2];
01597 dest += WATER_VERTEX_HARD_SIZE;
01598 *(CVector *) dest = proj[1];
01599 dest += WATER_VERTEX_HARD_SIZE;
01600 *(CVector *) dest = proj[0];
01601 dest += WATER_VERTEX_HARD_SIZE;
01602 *(CVector *) dest = proj[3];
01603 dest += WATER_VERTEX_HARD_SIZE;
01604 *(CVector *) dest = proj[2];
01605 dest += WATER_VERTEX_HARD_SIZE;
01606 }
01607 }
01608 }
01609 nlassert((dest - (uint8 * ) datas) % (3 * WATER_VERTEX_HARD_SIZE) == 0);
01610 uint endTri = (dest - (uint8 * ) datas) / (3 * WATER_VERTEX_HARD_SIZE);
01611 _NumTris = endTri - _StartTri;
01612 return endTri;
01613 }
01614
01615
01616
01617
01618
01619
01620 void CWaterModel::traverseRender()
01621 {
01622 H_AUTO( NL3D_Water_Render );
01623
01624 CRenderTrav &renderTrav = getOwnerScene()->getRenderTrav();
01625 IDriver *drv = renderTrav.getDriver();
01626 CWaterShape *shape = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
01627 const NLMISC::CVector &obsPos = renderTrav.CamPos;
01628 const float zHeight = getWorldMatrix().getPos().z;
01629
01630 if (!renderTrav.Perspective || forceWaterSimpleRender)
01631 {
01632
01633 drv->setupModelMatrix(getWorldMatrix());
01634 static CMaterial waterMat;
01635 static bool initDone = false;
01636 if (!initDone)
01637 {
01638 waterMat.initUnlit();
01639 waterMat.setBlend(true);
01640 waterMat.setSrcBlend(CMaterial::srcalpha);
01641 waterMat.setDstBlend(CMaterial::invsrcalpha);
01642 waterMat.setBlend(true);
01643 waterMat.setDoubleSided(true);
01644 waterMat.setLighting(false);
01645 }
01646 waterMat.setColor(shape->computeEnvMapMeanColor());
01647 static std::vector<NLMISC::CTriangleUV> tris;
01648 const NLMISC::CPolygon2D &poly = shape->getShape();
01649 tris.clear();
01650 for(sint k = 0; k < (sint) poly.Vertices.size() - 2; ++k)
01651 {
01652 NLMISC::CTriangleUV truv;
01653 truv.V0.set(poly.Vertices[0].x, poly.Vertices[0].y, 0.f);
01654 truv.V1.set(poly.Vertices[k + 1].x, poly.Vertices[k + 1].y, 0.f);
01655 truv.V2.set(poly.Vertices[k + 2].x, poly.Vertices[k + 2].y, 0.f);
01656 tris.push_back(truv);
01657 }
01658 CDRU::drawTrianglesUnlit(tris, waterMat, *drv);
01659 }
01660 else
01661 {
01662 NLMISC::CMatrix modelMat;
01663 modelMat.setPos(NLMISC::CVector(obsPos.x, obsPos.y, zHeight));
01664 drv->setupModelMatrix(modelMat);
01665 bool isAbove = obsPos.z > getWorldMatrix().getPos().z;
01666 CVertexBuffer &vb = renderTrav.Scene->getWaterVB();
01667 if (drv->isWaterShaderSupported())
01668 {
01669 setupMaterialNVertexShader(drv, shape, obsPos, isAbove, zHeight);
01670 nlassert(vb.getNumVertices() > 0);
01671 drv->activeVertexBuffer(vb);
01672 drv->renderRawTriangles(CWaterModel::_WaterMat, _StartTri, _NumTris);
01673 drv->activeVertexProgram(NULL);
01674 }
01675 else
01676 {
01677 setupSimpleRender(shape, obsPos, isAbove);
01678 drv->activeVertexBuffer(vb);
01679 drv->activeVertexProgram(NULL);
01680 drv->renderRawTriangles(CWaterModel::_SimpleWaterMat, _StartTri, _NumTris);
01681 }
01682 }
01683 }
01684
01685
01686
01687
01688 bool CWaterModel::clip()
01689 {
01690 H_AUTO( NL3D_Water_Render );
01691 CRenderTrav &renderTrav= getOwnerScene()->getRenderTrav();
01692 if (renderTrav.CamPos.z == getWorldMatrix().getPos().z) return false;
01693 if(Shape)
01694 {
01695 computeClippedPoly();
01696 if (_ClippedPoly.Vertices.empty()) return false;
01697
01698 unlink();
01699
01700 link();
01701 return true;
01702 }
01703 else
01704 return false;
01705 }
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926 void CWaterModel::updateDiffuseMapMatrix(bool force )
01927 {
01928 if (compareMatrixDate(_MatrixUpdateDate) ||force)
01929 {
01930 CWaterShape *shape = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
01931 if (shape)
01932 {
01933 _MatrixUpdateDate = getMatrixDate();
01934
01935 CMatrix uvMat;
01936 uvMat.setRot(CVector(shape->_ColorMapMatColumn0.x, shape->_ColorMapMatColumn0.y, 0.f),
01937 CVector(shape->_ColorMapMatColumn1.x, shape->_ColorMapMatColumn1.y, 0.f),
01938 CVector(shape->_ColorMapMatPos.x, shape->_ColorMapMatPos.y, 1.f));
01939 CMatrix xformMat;
01940 CMatrix invMat = this->getWorldMatrix().inverted();
01941 xformMat.setRot(CVector(invMat.getI().x, invMat.getI().y, 0.f),
01942 CVector(invMat.getJ().x, invMat.getJ().y, 0.f),
01943 CVector(invMat.getPos().x, invMat.getPos().y, 1.f));
01944 uvMat = uvMat * xformMat;
01945 _ColorMapMatColumn0.set(uvMat.getI().x, uvMat.getI().y);
01946 _ColorMapMatColumn1.set(uvMat.getJ().x, uvMat.getJ().y);
01947 _ColorMapMatPos.set(uvMat.getK().x, uvMat.getK().y);
01948 }
01949 }
01950 }
01951
01952
01953 void CWaterModel::debugDumpMem(void* &clippedPolyBegin, void* &clippedPolyEnd)
01954 {
01955 clippedPolyBegin= (void*)(&*_ClippedPoly.Vertices.begin());
01956 clippedPolyEnd= (void*)(&*_ClippedPoly.Vertices.end());
01957 }
01958
01959
01960 void CWaterModel::debugClearClippedPoly()
01961 {
01962 _ClippedPoly.Vertices.clear();
01963 }
01964
01965
01966
01967
01968
01969 CWaveMakerModel::CWaveMakerModel() : _Time(0)
01970 {
01971
01972 CTransform::setIsForceAnimDetail(true);
01973 }
01974
01975
01976
01977 void CWaveMakerModel::registerBasic()
01978 {
01979 CScene::registerModel(WaveMakerModelClassId, TransformShapeId, CWaveMakerModel::creator);
01980 }
01981
01982
01983
01984 ITrack* CWaveMakerModel::getDefaultTrack (uint valueId)
01985 {
01986 nlassert(Shape);
01987 CWaveMakerShape *ws = NLMISC::safe_cast<CWaveMakerShape *>((IShape *) Shape);
01988 switch (valueId)
01989 {
01990 case PosValue: return ws->getDefaultPos(); break;
01991 default:
01992 return CTransformShape::getDefaultTrack(valueId);
01993 break;
01994 }
01995 }
01996
01997
01998 void CWaveMakerModel::traverseAnimDetail()
01999 {
02000 CTransformShape::traverseAnimDetail();
02001 nlassert(getOwnerScene());
02003 CWaveMakerShape *wms = NLMISC::safe_cast<CWaveMakerShape *>((IShape *) Shape);
02004 const NLMISC::CVector worldPos = getWorldMatrix().getPos();
02005 const CVector2f pos2d(worldPos.x, worldPos.y);
02007 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(wms->_PoolID);
02008
02009 const TAnimationTime deltaT = std::min(getOwnerScene()->getEllapsedTime(), (TAnimationTime) whm.getPropagationTime());
02010 _Time += deltaT;
02011 if (!wms->_ImpulsionMode)
02012 {
02013 whm.perturbate(pos2d, wms->_Intensity * cosf(2.f / wms->_Period * (float) NLMISC::Pi * _Time), wms->_Radius);
02014 }
02015 else
02016 {
02017 if (_Time > wms->_Period)
02018 {
02019 _Time -= wms->_Period;
02020 whm.perturbate(pos2d, wms->_Intensity, wms->_Radius);
02021 }
02022 }
02023 }
02024
02025 }