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 "nel/misc/vector_2d.h"
00029 #include "nel/misc/vector_h.h"
00030 #include "nel/misc/hierarchical_timer.h"
00031 #include "nel/3d/animation_time.h"
00032 #include "3d/water_model.h"
00033 #include "3d/water_shape.h"
00034 #include "3d/water_pool_manager.h"
00035 #include "3d/water_height_map.h"
00036 #include "3d/dru.h"
00037 #include "3d/scene.h"
00038 #include "3d/driver.h"
00039 #include "3d/render_trav.h"
00040 #include "3d/anim_detail_trav.h"
00041
00042
00043
00044
00045 namespace NL3D {
00046
00047
00048
00049
00050 CWaterModel::CWaterModel() : _Scene(NULL)
00051 {
00052 setOpacity(false);
00053 setTransparency(true);
00054 setOrderingLayer(1);
00055 }
00056
00057
00058
00059 void CWaterModel::registerBasic()
00060 {
00061 CMOT::registerModel(WaterModelClassId, TransformShapeId, CWaterModel::creator);
00062 CMOT::registerObs(RenderTravId, WaterModelClassId, CWaterRenderObs::creator);
00063 }
00064
00065
00066
00067
00068 ITrack* CWaterModel::getDefaultTrack (uint valueId)
00069 {
00070 nlassert(Shape);
00071 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00072 switch (valueId)
00073 {
00074 case PosValue: return ws->getDefaultPos(); break;
00075 case ScaleValue: return ws->getDefaultScale(); break;
00076 case RotQuatValue: return ws->getDefaultRotQuat(); break;
00077 default:
00078 return CTransformShape::getDefaultTrack(valueId);
00079 break;
00080 }
00081 }
00082
00083
00084
00085 uint32 CWaterModel::getWaterHeightMapID() const
00086 {
00087 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00088 return ws->_WaterPoolID;
00089 }
00090
00091
00092
00093 float CWaterModel::getHeightFactor() const
00094 {
00095 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00096 return ws->_WaveHeightFactor;
00097 }
00098
00099
00100
00101
00102 float CWaterModel::getHeight(const NLMISC::CVector2f &pos)
00103 {
00104 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00105 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(ws->_WaterPoolID);
00106 const float height = whm.getHeight(pos);
00107 return height * ws->_WaveHeightFactor + this->getPos().z;
00108 }
00109
00110
00111
00112 float CWaterModel::getAttenuatedHeight(const NLMISC::CVector2f &pos, const NLMISC::CVector &viewer)
00113 {
00114 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) Shape);
00115 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(ws->_WaterPoolID);
00116 const float maxDist = whm.getUnitSize() * (whm.getSize() >> 1);
00117 const NLMISC::CVector planePos(pos.x, pos.y, this->getPos().z);
00118 const float userDist = (planePos - viewer).norm();
00119
00120 if (userDist > maxDist)
00121 {
00122 return this->getPos().z;
00123 }
00124 else
00125 {
00126 const float height = whm.getHeight(pos);
00127 return ws->_WaveHeightFactor * height * (1.f - userDist / maxDist) + this->getPos().z;
00128 }
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138 static float inline BilinFilter(float v0, float v1, float v2, float v3, float u, float v)
00139 {
00140 float g = v * v3 + (1.f - v) * v0;
00141 float h = v * v2 + (1.f - v) * v1;
00142 return u * h + (1.f - u) * g;
00143 }
00144
00145
00146
00147
00148
00150 static void inline FillWaterVB(uint8 *&vbPointer, float x, float y, float z, float nx, float ny)
00151 {
00152 * (float *) vbPointer = x;
00153 ((float *) vbPointer)[1] = y;
00154 ((float *) vbPointer)[2] = z;
00155 *((float *) (vbPointer + 3 * sizeof(float))) = nx;
00156 *((float *) (vbPointer + 4 * sizeof(float))) = ny;
00157 vbPointer += 5 * sizeof(float);
00158 }
00159
00160
00161
00162
00164 #ifdef NL_OS_WINDOWS
00165 __forceinline
00166 #endif
00167 static void SetupWaterVertex( sint qLeft,
00168 sint qRight,
00169 sint qUp,
00170 sint qDown,
00171 sint qSubLeft,
00172 sint qSubDown,
00173 const NLMISC::CVector &inter,
00174 float invWaterRatio,
00175 sint doubleWaterHeightMapSize,
00176 CWaterHeightMap &whm,
00177 uint8 *&vbPointer,
00178 float offsetX,
00179 float offsetY
00180 )
00181 {
00182 const float wXf = invWaterRatio * (inter.x + offsetX);
00183 const float wYf = invWaterRatio * (inter.y + offsetY);
00184
00185 sint wx = (sint) floorf(wXf);
00186 sint wy = (sint) floorf(wYf);
00187
00188
00189
00190 if (!
00191 (wx >= qLeft && wx < qRight && wy < qUp && wy >= qDown)
00192 )
00193 {
00194
00195 FillWaterVB(vbPointer, inter.x, inter.y, 0, 0, 0);
00196 }
00197 else
00198 {
00199
00200
00201
00202 const sint stride = doubleWaterHeightMapSize;
00203
00204
00205 const uint xm = (uint) (wx - qSubLeft);
00206 const uint ym = (uint) (wy - qSubDown);
00207 const sint offset = xm + stride * ym;
00208 const float *ptWater = whm.getPointer() + offset;
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 float deltaU = wXf - wx;
00219 float deltaV = wYf - wy;
00220 nlassert(deltaU >= 0.f && deltaU <= 1.f && deltaV >= 0.f && deltaV <= 1.f);
00221 const float *ptWaterPrev = whm.getPrevPointer() + offset;
00222
00223
00224
00225 float g0x, g1x, g2x, g3x;
00226 float g0xp, g1xp, g2xp, g3xp;
00227
00228 float gradCurrX, gradCurrY;
00229
00230 float g0y, g1y, g2y, g3y;
00231 float g0yp, g1yp, g2yp, g3yp;
00232
00233 float gradPrevX, gradPrevY;
00234
00236
00237 g0x = ptWater[ 1] - ptWater[ - 1];
00238 g1x = ptWater[ 2] - ptWater[ 0 ];
00239 g2x = ptWater[ 2 + stride] - ptWater[ stride];
00240 g3x = ptWater[ 1 + stride] - ptWater[ - 1 + stride];
00241
00242 gradCurrX = BilinFilter(g0x, g1x, g2x, g3x, deltaU, deltaV);
00243
00244
00245 g0y = ptWater[ stride] - ptWater[ - stride];
00246 g1y = ptWater[ stride + 1] - ptWater[ - stride + 1];
00247 g2y = ptWater[ (stride << 1) + 1] - ptWater[ 1];
00248 g3y = ptWater[ (stride << 1)] - ptWater[0];
00249
00250 gradCurrY = BilinFilter(g0y, g1y, g2y, g3y, deltaU, deltaV);
00251
00253
00254 g0xp = ptWaterPrev[ 1] - ptWaterPrev[ - 1];
00255 g1xp = ptWaterPrev[ 2] - ptWaterPrev[ 0 ];
00256 g2xp = ptWaterPrev[ 2 + stride] - ptWaterPrev[ + stride];
00257 g3xp = ptWaterPrev[ 1 + stride] - ptWaterPrev[ - 1 + stride];
00258
00259 gradPrevX = BilinFilter(g0xp, g1xp, g2xp, g3xp, deltaU, deltaV);
00260
00261
00262 g0yp = ptWaterPrev[ stride] - ptWaterPrev[ - stride];
00263 g1yp = ptWaterPrev[ stride + 1] - ptWaterPrev[ - stride + 1];
00264 g2yp = ptWaterPrev[ (stride << 1) + 1] - ptWaterPrev[ 1 ];
00265 g3yp = ptWaterPrev[ (stride << 1)] - ptWaterPrev[ 0 ];
00266
00267 gradPrevY = BilinFilter(g0yp, g1yp, g2yp, g3yp, deltaU, deltaV);
00268
00269
00271 float h = BilinFilter(ptWater[ 0 ], ptWater[ + 1], ptWater[ 1 + stride], ptWater[stride], deltaU, deltaV);
00272
00274 float hPrev = BilinFilter(ptWaterPrev[ 0 ], ptWaterPrev[ 1], ptWaterPrev[ 1 + stride], ptWaterPrev[stride], deltaU, deltaV);
00275
00276
00277 float timeRatio = whm.getBufferRatio();
00278
00279
00280 FillWaterVB(vbPointer, inter.x, inter.y, timeRatio * h + (1.f - timeRatio) * hPrev,
00281 4.5f * (timeRatio * gradCurrX + (1.f - timeRatio) * gradPrevX),
00282 4.5f * (timeRatio * gradCurrY + (1.f - timeRatio) * gradPrevY)
00283 );
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 }
00318 }
00319
00320
00321
00322 static void ComputeUpMatrix(const NLMISC::CVector &J, NLMISC::CMatrix &dest, const NLMISC::CMatrix &defaultMat)
00323 {
00324
00325 const float JdotK = J.z;
00326 if ( (1.0f - fabsf(J.z)) < 10E-6)
00327 {
00328 dest.setRot(defaultMat.getRot());
00329 }
00330 else
00331 {
00332 NLMISC::CVector up = (NLMISC::CVector::K - JdotK * J).normed();
00333 NLMISC::CVector right = J ^ up;
00334 dest.setRot(right, J, up);
00335 }
00336 }
00337
00338
00339
00340 static void DrawPoly2D(CVertexBuffer &vb, IDriver *drv, const NLMISC::CMatrix &mat, const NLMISC::CPolygon &p)
00341 {
00342 uint k;
00343
00344 for (k = 0; k < p.Vertices.size(); ++k)
00345 {
00346 NLMISC::CVector tPos = mat * NLMISC::CVector(p.Vertices[k].x, p.Vertices[k].y, 0);
00347 vb.setValueFloat3Ex (WATER_VB_POS, k, tPos.x, tPos.y, tPos.z);
00348 vb.setValueFloat2Ex (WATER_VB_DX, k, 0, 0);
00349 }
00350 static std::vector<uint32> ib;
00351 ib.resize(3 * p.Vertices.size());
00352
00353 for (k = 0; k < p.Vertices.size() - 2; ++k)
00354 {
00355 ib[ k * 3 ] = 0;
00356 ib[ k * 3 + 1 ] = k + 1;
00357 ib[ k * 3 + 2 ] = k + 2;
00358 }
00359 drv->renderSimpleTriangles(&ib[0], p.Vertices.size() - 2);
00360 }
00361
00362
00363
00364 void CWaterRenderObs::traverse(IObs *caller)
00365 {
00366 H_AUTO( NL3D_Water_Render );
00367
00368 CRenderTrav *trav = NLMISC::safe_cast<CRenderTrav *>(Trav);
00369 CWaterModel *m = NLMISC::safe_cast<CWaterModel *>(Model);
00370 CWaterShape *shape = NLMISC::safe_cast<CWaterShape *>((IShape *) m->Shape);
00371 IDriver *drv = trav->getDriver();
00372 const std::vector<CPlane> &worldPyramid = ((NLMISC::safe_cast<CClipTrav *>(ClipObs->Trav))->WorldFrustumPyramid);
00373
00374 if (shape->_GridSizeTouched)
00375 {
00376 shape->setupVertexBuffer();
00377 }
00378
00379
00380
00381
00382
00383
00384 const NLMISC::CVector &obsPos = trav->CamPos;
00385
00386
00387 const NLMISC::CMatrix &camMat = trav->CamMatrix;
00388
00389
00390 const NLMISC::CMatrix &viewMat = trav->ViewMatrix;
00391
00392
00393 NLMISC::CMatrix camMatUp;
00394 ComputeUpMatrix(camMat.getJ(), camMatUp, camMat);
00395 camMatUp.setPos(camMat.getPos());
00396
00397 const NLMISC::CMatrix matViewUp = camMatUp.inverted();
00398
00399
00400 const float zHeight = HrcObs->WorldMatrix.getPos().z;
00401
00402 const sint numStepX = CWaterShape::getScreenXGridSize();
00403 const sint numStepY = CWaterShape::getScreenYGridSize();
00404
00405 const float invNumStepX = 1.f / numStepX;
00406 const float invNumStepY = 1.f / numStepY;
00407
00408 const uint rotBorderSize = (shape->_MaxGridSize + (shape->_XGridBorder << 1) - numStepX) >> 1;
00409
00410 const sint isAbove = obsPos.z > zHeight ? 1 : 0;
00411
00412
00413
00414
00415
00416
00417
00418 uint k;
00419 static NLMISC::CPolygon clippedPoly, endClippedPoly;
00420 clippedPoly.Vertices.resize(shape->_Poly.Vertices.size());
00421 for (k = 0; k < shape->_Poly.Vertices.size(); ++k)
00422 {
00423 clippedPoly.Vertices[k].set(shape->_Poly.Vertices[k].x,
00424 shape->_Poly.Vertices[k].y,
00425 0
00426 );
00427 }
00428
00429 endClippedPoly = clippedPoly;
00430
00431
00432
00433
00434 static NLMISC::CPlane plvect[6];
00435
00436 const float borderFactor = 0.67f;
00437 const float fRight = trav->Right * (2.f * borderFactor * (float) CWaterShape::_XGridBorder + (float) numStepX) / numStepX;
00438 const float fTop = trav->Top * (2.f * borderFactor * (float) CWaterShape::_YGridBorder + (float) numStepY) / numStepY;
00439
00440
00441 const float nearDist = trav->Near;
00442 const float farDist = trav->Far;
00443 const float transitionDist = shape->_TransitionRatio * farDist;
00444
00445 const NLMISC::CVector pfoc(0,0,0);
00446 const NLMISC::CVector lb(-fRight, nearDist, - fTop );
00447 const NLMISC::CVector lt(-fRight, nearDist, fTop );
00448 const NLMISC::CVector rb( fRight, nearDist, -fTop );
00449 const NLMISC::CVector rt(fRight, nearDist, fTop );
00450
00451 const NLMISC::CVector lbfarDist(-fRight, transitionDist, -fTop);
00452 const NLMISC::CVector ltfarDist(-fRight, transitionDist, fTop );
00453 const NLMISC::CVector rtfarDist(fRight , transitionDist, fTop );
00454
00455
00456 plvect[0].make(lt, lb, rt);
00457 plvect[1].make(lbfarDist, ltfarDist, rtfarDist);
00458
00459 plvect[2].make(pfoc, lt, lb);
00460 plvect[3].make(pfoc, rt, lt);
00461 plvect[4].make(pfoc, rb, rt);
00462 plvect[5].make(pfoc, lb, rb);
00463
00464
00465 const NLMISC::CMatrix pyramidMat = viewMat * HrcObs->WorldMatrix;
00466 for (k = 0; k < worldPyramid.size(); ++k)
00467 {
00468 plvect[k] = plvect[k] * pyramidMat;
00469 }
00470
00471 clippedPoly.clip(plvect, 6);
00472
00473
00474 plvect[0].d += (transitionDist - nearDist);
00475
00476
00477 endClippedPoly.clip(plvect, 1);
00478 endClippedPoly.clip(plvect + 2, 4);
00479
00480
00481
00483 if (clippedPoly.Vertices.size() == 0 && endClippedPoly.Vertices.size() == 0)
00484 {
00485 return;
00486 }
00487
00488
00489 NLMISC::CMatrix modelMat;
00490 modelMat.setPos(NLMISC::CVector(obsPos.x, obsPos.y, zHeight));
00491 drv->setupModelMatrix(modelMat);
00492
00493
00494
00495
00496
00497
00498 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(shape->_WaterPoolID);
00499 setupMaterialNVertexShader(drv, shape, obsPos, isAbove > 0, whm.getUnitSize() * (whm.getSize() >> 1), zHeight);
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 drv->activeVertexBuffer(shape->_VB);
00510
00511
00512
00513
00514
00515 if (clippedPoly.Vertices.size())
00516 {
00517
00518
00519
00520
00521
00522 static NLMISC::CPolygon2D projPoly;
00523 projPoly.Vertices.resize(clippedPoly.Vertices.size());
00524 const float Near = trav->Near;
00525 const float xFactor = (numStepX >> 1) * Near / trav->Right;
00526 const float xOffset = (float) (numStepX >> 1) + 0.5f;
00527 const float yFactor = - (numStepX >> 1) * Near / trav->Top;
00528 const float yOffset = (float) (numStepY >> 1) - 0.5f * isAbove;
00529
00530 const NLMISC::CMatrix projMat = matViewUp * HrcObs->WorldMatrix;
00531 for (k = 0; k < clippedPoly.Vertices.size(); ++k)
00532 {
00533
00534 NLMISC::CVector t = projMat * clippedPoly.Vertices[k];
00535 float invY = 1.f / t.y;
00536 projPoly.Vertices[k].set(xFactor * t.x * invY + xOffset, yFactor * t.z * invY + yOffset);
00537 }
00538
00539
00540
00541
00542
00543
00544
00545 NLMISC::CPolygon2D::TRasterVect rasters;
00546 sint startY;
00547 projPoly.computeBorders(rasters, startY);
00548
00549 if (rasters.size())
00550 {
00551
00552
00553
00554
00555 const float WaterRatio = whm.getUnitSize();
00556 const float invWaterRatio = 1.f / WaterRatio;
00557 const uint WaterHeightMapSize = whm.getSize();
00558 const uint doubleWaterHeightMapSize = (WaterHeightMapSize << 1);
00559
00560
00561 sint64 idate = (NLMISC::safe_cast<CHrcTrav *>(HrcObs->Trav))->CurrentDate;
00562
00563
00564
00565 if (idate != whm.Date)
00566 {
00567 whm.setUserPos((sint) (obsPos.x * invWaterRatio) - (WaterHeightMapSize >> 1),
00568 (sint) (obsPos.y * invWaterRatio) - (WaterHeightMapSize >> 1)
00569 );
00570 nlassert(m->_Scene);
00571 whm.animate((float) (m->_Scene->getEllapsedTime()));
00572 whm.Date = idate;
00573 }
00574
00575
00576
00577
00578
00579
00580
00588 sint mapPosX, mapPosY;
00589
00592 whm.getUserPos(mapPosX, mapPosY);
00593
00594 const uint mapBorder = 3;
00595
00596
00597
00598
00599
00600
00601 const sint qRight = (sint) mapPosX + WaterHeightMapSize - mapBorder;
00602 sint qLeft = (sint) mapPosX;
00603 const sint qUp = (sint) mapPosY + WaterHeightMapSize - mapBorder;
00604 sint qDown = (sint) mapPosY;
00605
00607 const sint qSubLeft = qLeft - (uint) qLeft % WaterHeightMapSize;
00608 const sint qSubDown = qDown - (uint) qDown % WaterHeightMapSize;
00609
00610 qLeft += mapBorder;
00611 qDown += mapBorder;
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 CVector currHV = trav->Left * camMatUp.getI() + trav->Near * camMatUp.getJ() + trav->Top * camMatUp.getK();
00623 CVector currV;
00624 CVector xStep = (trav->Right - trav->Left) * invNumStepX * camMatUp.getI();
00625 CVector yStep = (trav->Bottom - trav->Top) * invNumStepY * camMatUp.getK();
00626
00627
00628
00629
00630
00631
00632
00633
00634 currHV += (startY - 0.5f * isAbove) * yStep;
00635
00636
00637 std::vector<uint32> *currIB = &CWaterShape::_IBUpDown, *otherIB = &CWaterShape::_IBDownUp;
00638
00639
00640 sint vIndex = 0;
00641
00642
00643 sint oldStartX, oldEndX, realStartX, realEndX;
00644
00645
00646
00647
00648
00649 const uint wqHeight = rasters.size();
00650 if (wqHeight)
00651 {
00652
00653 const float denom = - obsPos.z + zHeight;
00654
00655
00656 const float horizonEpsilon = 10E-4f;
00657
00658
00659 float t;
00660
00661
00662
00663
00664 NLMISC::CPolygon2D::TRasterVect::const_iterator it = rasters.begin();
00665 for (uint l = 0; l <= wqHeight; ++l)
00666 {
00667
00668 const sint startX = it->first;
00669 const sint endX = (it->second + 1);
00670
00671 nlassert(startX >= - (sint) rotBorderSize);
00672 nlassert(endX <= (sint) (numStepX + rotBorderSize));
00673
00674 if (l != 0)
00675 {
00676 realStartX = std::min(startX, oldStartX);
00677 realEndX = std::max(endX, oldEndX);
00678 }
00679 else
00680 {
00681 realStartX = startX;
00682 realEndX = endX;
00683 }
00684
00685
00686
00687 currV = currHV + (realStartX - 0.5f) * xStep;
00688
00689 if (l == 0)
00690 {
00691 if (isAbove)
00692 {
00693
00694
00695 if (denom * currV.z <= 0)
00696 {
00697
00698 currV += yStep * ((denom > 0 ? horizonEpsilon : - horizonEpsilon) - currV.z) / yStep.z;
00699 }
00700
00701
00702
00703 t = denom / currV.z;
00704 const float VJ = camMat.getJ() * currV;
00705 if ( t * VJ > transitionDist)
00706 {
00707 float delta = (1.f / yStep.z) * ( denom * VJ / transitionDist - currV.z);
00708
00709 currV += delta * yStep;
00710 }
00711 }
00712 }
00713
00714
00715 uint8 *vbPointer = (uint8 *) shape->_VB.getVertexCoordPointer() + shape->_VB.getVertexSize() * (vIndex + realStartX + rotBorderSize);
00716
00717
00718 for (sint k = realStartX; k <= realEndX; ++k)
00719 {
00720 t = denom / currV.z;
00721
00722 CVector inter = t * currV;
00723 inter.z += obsPos.z;
00724 SetupWaterVertex(qLeft, qRight, qUp, qDown, qSubLeft, qSubDown, inter, invWaterRatio, doubleWaterHeightMapSize, whm, vbPointer, obsPos.x, obsPos.y);
00725 currV += xStep;
00726 }
00727
00728 if (l != 0)
00729 {
00730 sint count = oldEndX - oldStartX;
00731 if (count > 0)
00732 {
00733 drv->renderSimpleTriangles(&((*currIB)[(oldStartX + rotBorderSize) * 6]),
00734 2 * count );
00735 }
00736 }
00737
00738 oldStartX = startX;
00739 oldEndX = endX;
00740 currHV += yStep;
00741 vIndex = (numStepX + 2 * rotBorderSize + 1) - vIndex;
00742 std::swap(currIB, otherIB);
00743 if (l < (wqHeight - 1))
00744 {
00745 ++it;
00746 }
00747 else
00748 {
00749 if (!isAbove)
00750 {
00751
00752
00753 if (denom * currHV.z <= 0)
00754 {
00755
00756 currHV += yStep * ((denom > 0 ? horizonEpsilon : - horizonEpsilon) - currHV.z) / yStep.z;
00757 }
00758
00759
00760
00761 t = denom / currHV.z;
00762 const float VJ = camMat.getJ() * currHV;
00763 if ( t * VJ > transitionDist)
00764 {
00765 float delta = (1.f / yStep.z) * ( denom * VJ / transitionDist - currHV.z);
00766
00767 currHV += delta * yStep;
00768 }
00769 }
00770
00771 }
00772 }
00773
00774 }
00775
00776 }
00777 }
00778
00779
00780
00781
00782
00783 if (endClippedPoly.Vertices.size() != 0)
00784 {
00785 CMatrix mtx;
00786
00787
00788 mtx.setPos(HrcObs->WorldMatrix.getPos() + NLMISC::CVector(-obsPos.x, -obsPos.y, 0));
00789
00790 drv->setConstant(7, 0, 0, obsPos.z , 0.f);
00791
00792 DrawPoly2D(shape->_VB, drv, mtx, endClippedPoly);
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802 if (drv->isVertexProgramSupported())
00803 {
00804 bool result = drv->activeVertexProgram(NULL);
00805 if (!result) nlwarning("no vertex program setupped");
00806 }
00807
00808
00809 this->traverseSons();
00810 }
00811
00812
00813
00814
00815
00816 void CWaterRenderObs::setupMaterialNVertexShader(IDriver *drv, CWaterShape *shape, const NLMISC::CVector &obsPos, bool above, float maxDist, float zHeight)
00817 {
00818 CMaterial WaterMat;
00819 WaterMat.setLighting(false);
00820 WaterMat.setDoubleSided(true);
00821 WaterMat.setColor(NLMISC::CRGBA::White);
00822
00823 WaterMat.setBlend(true);
00824 WaterMat.setSrcBlend(CMaterial::srcalpha);
00825 WaterMat.setDstBlend(CMaterial::invsrcalpha);
00826 WaterMat.setZWrite(true);
00827
00828 if (drv->isVertexProgramSupported())
00829 {
00830 const uint cstOffset = 4;
00831 NLMISC::CVectorH cst[13];
00832
00833
00834
00835
00836
00837
00838 uint alphaMapStage, envMapStage;
00839 WaterMat.setColor(NLMISC::CRGBA::White);
00840
00841 bool useBumpedVersion = false;
00842 bool useEMBM = false;
00843 if (drv->getNbTextureStages() >= 4 && (drv->supportTextureShaders() || drv->supportEMBM()))
00844 {
00845 if (drv->supportTextureShaders())
00846 {
00847 useBumpedVersion = true;
00848 }
00849 else
00850 {
00851 if (drv->isEMBMSupportedAtStage(0) && drv->isEMBMSupportedAtStage(1))
00852 {
00853 useBumpedVersion = true;
00854 useEMBM = true;
00855 }
00856 }
00857 }
00858
00859
00860 if (!useBumpedVersion)
00861 {
00862 WaterMat.texEnvOpRGB(0, CMaterial::Modulate);
00863 alphaMapStage = 1;
00864 envMapStage = 0;
00865 }
00866 else
00867 {
00868 shape->updateHeightMapNormalizationFactors();
00869
00870
00871 const float idMat[] = {0.25f * shape->_HeightMapNormalizationFactor[0], 0, 0, 0.25f * shape->_HeightMapNormalizationFactor[0]};
00872 const float idMat2[] = {shape->_HeightMapNormalizationFactor[1], 0, 0, shape->_HeightMapNormalizationFactor[1]};
00873
00874 WaterMat.setTexture(0, shape->_BumpMap[0]);
00875 WaterMat.setTexture(1, shape->_BumpMap[1]);
00876 WaterMat.texEnvOpRGB(2, CMaterial::Replace);
00877 alphaMapStage = 3;
00878 envMapStage = 2;
00879
00880
00881 if (!useEMBM)
00882 {
00883 drv->setMatrix2DForTextureOffsetAddrMode(1, idMat);
00884 drv->setMatrix2DForTextureOffsetAddrMode(2, idMat2);
00885
00886
00887
00888
00889
00890
00891
00892 WaterMat.enableTexAddrMode();
00893 WaterMat.setTexAddressingMode(0, CMaterial::FetchTexture);
00894 WaterMat.setTexAddressingMode(1, CMaterial::OffsetTexture);
00895 WaterMat.setTexAddressingMode(2, CMaterial::OffsetTexture);
00896 WaterMat.setTexAddressingMode(3, shape->_ColorMap ? CMaterial::FetchTexture : CMaterial::TextureOff);
00897 }
00898 else
00899 {
00900 drv->setEMBMMatrix(0, idMat2);
00901 drv->setEMBMMatrix(1, idMat2);
00902 WaterMat.texEnvOpRGB(0, CMaterial::EMBM);
00903
00904
00905 WaterMat.texEnvOpRGB(1, CMaterial::EMBM);
00906 WaterMat.setTexture(0, NULL);
00907 }
00908 }
00909
00910
00911 if (!above && shape->_EnvMap[1])
00912 {
00913 WaterMat.setTexture(envMapStage, shape->_EnvMap[1]);
00914
00915 }
00916 else
00917 {
00918 WaterMat.setTexture(envMapStage, shape->_EnvMap[0]);
00919 }
00920 shape->envMapUpdate();
00921
00922
00923 if (shape->_ColorMap)
00924 {
00925 WaterMat.setTexture(alphaMapStage, shape->_ColorMap);
00926
00927
00928
00929
00930 cst[13 - cstOffset].set(shape->_ColorMapMatColumn0.x, shape->_ColorMapMatColumn1.x, 0, shape->_ColorMapMatColumn0.x * obsPos.x + shape->_ColorMapMatColumn1.x * obsPos.y + shape->_ColorMapMatPos.x);
00931 cst[14 - cstOffset].set(shape->_ColorMapMatColumn0.y, shape->_ColorMapMatColumn1.y, 0, shape->_ColorMapMatColumn0.y * obsPos.x + shape->_ColorMapMatColumn1.y * obsPos.y + shape->_ColorMapMatPos.y);
00932 WaterMat.texEnvOpRGB(alphaMapStage, CMaterial::Modulate);
00933 WaterMat.texEnvOpAlpha(alphaMapStage, CMaterial::Modulate);
00934 }
00935 else
00936 {
00937 cst[13 - cstOffset].set(0, 0, 0, 0);
00938 cst[14 - cstOffset].set(0, 0, 0, 0);
00939 }
00940
00941 cst[16 - cstOffset].set(0.1f, 0.1f, 0.1f, 0.1f);
00942
00943
00944
00945
00946
00947 cst[5 - cstOffset].set(0.f, 0.f, 0.f, 0.f);
00948
00949
00950 const float invMaxDist = shape->_WaveHeightFactor / maxDist;
00951 cst[6 - cstOffset].set(invMaxDist, shape->_WaveHeightFactor, 0, 0);
00952
00953
00954
00955
00956
00957
00958
00959
00961 drv->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
00962
00963
00964 float date = 0.001f * NLMISC::CTime::getLocalTime();
00965
00966 cst[9 - cstOffset].set(obsPos.x * shape->_HeightMapScale[0].x + date * shape->_HeightMapSpeed[0].x, shape->_HeightMapScale[0].y * obsPos.y + date * shape->_HeightMapSpeed[0].y, 0.f, 0.f);
00967 cst[10 - cstOffset].set(shape->_HeightMapScale[0].x, shape->_HeightMapScale[0].y, 0, 0);
00968 cst[11 - cstOffset].set(shape->_HeightMapScale[1].x * obsPos.x + date * shape->_HeightMapSpeed[1].x, shape->_HeightMapScale[1].y * obsPos.y + date * shape->_HeightMapSpeed[0].y, 0.f, 0.f);
00969 cst[12 - cstOffset].set(shape->_HeightMapScale[1].x, shape->_HeightMapScale[1].y, 0, 0);
00970
00971
00972
00973
00974
00975
00976 cst[4 - cstOffset].set(1.f, 1.f, 1.f, 1.f);
00977 cst[7 - cstOffset].set(0, 0, obsPos.z - zHeight, 0.f);
00978 cst[8 - cstOffset].set(0.5f, 0.5f, 0.f, 0.f);
00979
00980
00981
00982
00984 drv->setConstant(4, sizeof(cst) / sizeof(cst[0]), (float *) &cst[0]);
00985
00986 shape->initVertexProgram();
00987 bool result;
00988 if (useBumpedVersion)
00989 {
00990 if (!useEMBM)
00991 {
00992 result = shape->getColorMap() ? drv->activeVertexProgram((shape->_VertexProgramBump2Diffuse).get())
00993 : drv->activeVertexProgram((shape->_VertexProgramBump2).get());
00994 }
00995 else
00996 {
00997 result = shape->getColorMap() ? drv->activeVertexProgram((shape->_VertexProgramBump1Diffuse).get())
00998 : drv->activeVertexProgram((shape->_VertexProgramBump1).get());
00999 }
01000 }
01001 else
01002 {
01003 result = shape->getColorMap() ? drv->activeVertexProgram((shape->_VertexProgramNoBumpDiffuse).get())
01004 : drv->activeVertexProgram((shape->_VertexProgramNoBump).get());
01005 }
01006 if (!result) nlwarning("no vertex program setupped");
01007 }
01008 else
01009 {
01010 WaterMat.setColor(NLMISC::CRGBA(0, 32, 190, 128));
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 drv->setupMaterial(WaterMat);
01028 }
01029
01030
01031
01032
01033
01034
01035 CWaveMakerModel::CWaveMakerModel() : _Time(0), _Scene(NULL)
01036 {
01037
01038 CTransform::setIsForceAnimDetail(true);
01039 }
01040
01041
01042
01043 void CWaveMakerModel::registerBasic()
01044 {
01045 CMOT::registerModel(WaveMakerModelClassId, TransformShapeId, CWaveMakerModel::creator);
01046 CMOT::registerObs(AnimDetailTravId, WaveMakerModelClassId, CWaveMakerDetailObs::creator);
01047 }
01048
01049
01050
01051 ITrack* CWaveMakerModel::getDefaultTrack (uint valueId)
01052 {
01053 nlassert(Shape);
01054 CWaveMakerShape *ws = NLMISC::safe_cast<CWaveMakerShape *>((IShape *) Shape);
01055 switch (valueId)
01056 {
01057 case PosValue: return ws->getDefaultPos(); break;
01058 default:
01059 return CTransformShape::getDefaultTrack(valueId);
01060 break;
01061 }
01062 }
01063
01064
01065
01066 void CWaveMakerDetailObs::traverse(IObs *caller)
01067 {
01068 CTransformAnimDetailObs::traverse(caller);
01070 CWaveMakerModel *wmm = NLMISC::safe_cast<CWaveMakerModel *>(Model);
01071 nlassert(wmm->_Scene);
01073 CWaveMakerShape *wms = NLMISC::safe_cast<CWaveMakerShape *>((IShape *) wmm->Shape);
01074 const NLMISC::CVector worldPos = this->ClipObs->HrcObs->WorldMatrix.getPos();
01075 const NLMISC::CVector2f pos2d(worldPos.x, worldPos.y);
01077 CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(wms->_PoolID);
01078
01079 const TAnimationTime deltaT = std::min(wmm->_Scene->getEllapsedTime(), (TAnimationTime) whm.getPropagationTime());
01080 wmm->_Time += deltaT;
01081 if (!wms->_ImpulsionMode)
01082 {
01083 whm.perturbate(pos2d, wms->_Intensity * cosf(2.f / wms->_Period * (float) NLMISC::Pi * wmm->_Time), wms->_Radius);
01084 }
01085 else
01086 {
01087 if (wmm->_Time > wms->_Period)
01088 {
01089 wmm->_Time -= wms->_Period;
01090 whm.perturbate(pos2d, wms->_Intensity, wms->_Radius);
01091 }
01092 }
01093 this->traverseSons();
01094 }
01095
01096
01097 }