Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / water_shape.cpp
blob32eb21eeb24728acafa895818b51010c04b0542c
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/3d/water_shape.h"
23 #include "nel/3d/water_model.h"
24 #include "nel/3d/vertex_buffer.h"
25 #include "nel/3d/texture_bump.h"
26 #include "nel/3d/texture_blend.h"
27 #include "nel/3d/scene.h"
28 #include "nel/3d/water_pool_manager.h"
29 #include "nel/3d/water_height_map.h"
30 #include <memory>
32 #ifdef DEBUG_NEW
33 #define new DEBUG_NEW
34 #endif
36 namespace NL3D {
41 // globals
44 /////////////////////////
45 // WATER WITH NO WAVES //
46 /////////////////////////
48 static const char *WaterVPNoWave =
49 "!!VP1.0 \n\
50 DP4 o[HPOS].x, c[0], v[0]; #transform vertex in view space \n\
51 DP4 o[HPOS].y, c[1], v[0]; \n\
52 DP4 o[HPOS].z, c[2], v[0]; \n\
53 DP4 o[HPOS].w, c[3], v[0]; \n\
54 # MUL R1, R2.x, R1; \n\
55 DP4 o[FOGC].x, c[4], v[0]; #setup fog \n\
56 MUL R3, v[0], c[5]; #compute bump 0 uv's \n\
57 ADD o[TEX0], R3, c[6]; \n\
58 MUL R3, v[0], c[7]; #compute bump 1 uv's \n\
59 ADD o[TEX1], R3, c[8]; \n\
60 ADD R0, c[9], -v[0]; #r1 = eye - vertex \n\
61 DP3 R1, R0, R0; #r1 = eye - vertex, r2 = (eye - vertex)^2 \n\
62 RSQ R1, R1.x; #r1 = eye - vertex, r2 = 1/d(eye, vertex) \n\
63 MUL R0, R0, R1; \n\
64 DP3 R1.x, R0.xyww, R0.xyww; \n\
65 MAD o[TEX2], -R0, c[10], c[10]; #envmap tex coord \n\
66 END";
68 // a diffuse texture is added
69 static const char *WaterVPNoWaveDiffuse =
70 "!!VP1.0\n\
71 DP4 o[HPOS].x, c[0], v[0]; #transform vertex in view space \n\
72 DP4 o[HPOS].y, c[1], v[0]; \n\
73 DP4 o[HPOS].z, c[2], v[0]; \n\
74 DP4 o[HPOS].w, c[3], v[0]; \n\
75 # MUL R1, R2.x, R1; \n\
76 DP4 o[FOGC].x, c[4], v[0]; #setup fog \n\
77 MUL R3, v[0], c[5]; #compute bump 0 uv's \n\
78 ADD o[TEX0], R3, c[6]; \n\
79 MUL R3, v[0], c[7]; #compute bump 1 uv's \n\
80 ADD o[TEX1], R3, c[8]; \n\
81 ADD R0, c[9], -v[0]; #r1 = eye - vertex \n\
82 DP3 R1, R0, R0; #r1 = eye - vertex, r2 = (eye - vertex)^2 \n\
83 RSQ R1, R1.x; #r1 = eye - vertex, r2 = 1/d(eye, vertex) \n\
84 MUL R0, R0, R1; \n\
85 MAD o[TEX2], -R0, c[10], c[10]; #envmap tex coord \n\
86 DP4 o[TEX3].x, v[0], c[11]; #compute uv for diffuse texture \n\
87 DP4 o[TEX3].y, v[0], c[12]; \n\
88 END";
90 CVertexProgramWaterVPNoWave::CVertexProgramWaterVPNoWave(bool diffuse)
92 m_Diffuse = diffuse;
93 // nelvp
95 CSource *source = new CSource();
96 source->Profile = nelvp;
97 source->DisplayName = "WaterVPNoWave/nelvp";
98 source->ParamIndices["modelViewProjection"] = 0;
99 source->ParamIndices["fog"] = 4;
100 source->ParamIndices["bumpMap0Scale"] = 5;
101 source->ParamIndices["bumpMap0Offset"] = 6;
102 source->ParamIndices["bumpMap1Scale"] = 7;
103 source->ParamIndices["bumpMap1Offset"] = 8;
104 source->ParamIndices["observerHeight"] = 9;
105 source->ParamIndices["scaleReflectedRay"] = 10;
106 if (diffuse)
108 source->DisplayName += "/diffuse";
109 source->ParamIndices["diffuseMapVector0"] = 11;
110 source->ParamIndices["diffuseMapVector1"] = 12;
111 source->setSourcePtr(WaterVPNoWaveDiffuse);
113 else
115 source->setSourcePtr(WaterVPNoWave);
117 addSource(source);
119 // glsl330v
121 // TODO_VP_GLSL
122 // CSource *source = new CSource();
123 // source->Profile = glsl330v;
124 // source->DisplayName = "WaterVPNoWave/glsl330v";
125 // if (diffuse) source->DisplayName += "/diffuse";
126 // source->setSource...
127 // addSource(source);
131 void CVertexProgramWaterVPNoWave::buildInfo()
133 m_Idx.BumpMap0Scale = getUniformIndex("bumpMap0Scale");
134 nlassert(m_Idx.BumpMap0Scale != std::numeric_limits<uint>::max());
135 m_Idx.BumpMap0Offset = getUniformIndex("bumpMap0Offset");
136 nlassert(m_Idx.BumpMap0Offset != std::numeric_limits<uint>::max());
137 m_Idx.BumpMap1Scale = getUniformIndex("bumpMap1Scale");
138 nlassert(m_Idx.BumpMap1Scale != std::numeric_limits<uint>::max());
139 m_Idx.BumpMap1Offset = getUniformIndex("bumpMap1Offset");
140 nlassert(m_Idx.BumpMap1Offset != std::numeric_limits<uint>::max());
141 m_Idx.ObserverHeight = getUniformIndex("observerHeight");
142 nlassert(m_Idx.ObserverHeight != std::numeric_limits<uint>::max());
143 m_Idx.ScaleReflectedRay = getUniformIndex("scaleReflectedRay");
144 nlassert(m_Idx.ScaleReflectedRay != std::numeric_limits<uint>::max());
145 if (m_Diffuse)
147 m_Idx.DiffuseMapVector0 = getUniformIndex("diffuseMapVector0");
148 nlassert(m_Idx.DiffuseMapVector0 != std::numeric_limits<uint>::max());
149 m_Idx.DiffuseMapVector1 = getUniformIndex("diffuseMapVector1");
150 nlassert(m_Idx.DiffuseMapVector1 != std::numeric_limits<uint>::max());
154 ////////////////
155 // WAVY WATER //
156 ////////////////
158 // common start for Water vertex programs
159 /** The first part of the program does the following :
160 * - Compute linear distance to eye
161 * - Attenuate height with distance
162 * - Attenuate normal with distance (e.g at max distance, the normal is (0, 0, 1)
163 * - Transform vertex pos into view space
164 * - compute fog coordinate
165 * At the end of the program we got :
166 * R1 = (eye - vertex).normed()
167 * R0 = Attenuated normal at vertex
168 * R4 = position of point with attenuated height
171 static const char *WaterVPStartCode =
172 "!!VP1.0\n\
173 ADD R1, c[7], -v[0]; #r1 = eye - vertex \n\
174 DP3 R2, R1, R1; #r1 = eye - vertex, r2 = (eye - vertex)^2 \n\
175 MAX R2, R2, c[16]; # avoid imprecision around 0 \n\
176 RSQ R2, R2.x; #r1 = eye - vertex, r2 = 1/d(eye, vertex) \n\
177 RCP R3, R2.x; \n\
178 MAD R3, c[6].xxxx, -R3, c[6].yyyy; \n\
179 MAX R3, c[5], R3; \n\
180 MUL R0, R3, v[8]; #attenuate normal with distance \n\
181 MUL R4.z, R3, v[0]; #attenuate height with distance \n\
182 MOV R4.xyw, v[0]; \n\
183 MOV R0.z, c[4].x; #set normal z to 1 \n\
184 DP3 R3.x, R0, R0; \n\
185 RSQ R3.x, R3.x; #normalize normal in R3 \n\
186 MUL R0, R0, R3.x; \n\
187 DP4 o[HPOS].x, c[0], R4; #transform vertex in view space \n\
188 DP4 o[HPOS].y, c[1], R4; \n\
189 DP4 o[HPOS].z, c[2], R4; \n\
190 DP4 o[HPOS].w, c[3], R4; \n\
191 MUL R1, R1, R2.x; #normalize r1, r1 = (eye - vertex).normed \n\
192 # DP3 R2.x, R1.xyww, R1.xyww; \n\
193 # MUL R1, R2.x, R1; \n\
194 DP4 o[FOGC].x, c[18], R4; #setup fog \n\
196 /** This part of vertex program compute 2 layers of bump (for use with texture shaders)
198 static const char *WaterVpBump2LayersCode =
199 " MUL R3, v[0], c[10]; #compute bump 0 uv's \n\
200 ADD o[TEX0], R3, c[9]; \n\
201 MUL R3, v[0], c[12]; #compute bump 1 uv's \n\
202 ADD o[TEX1], R3, c[11]; \n\
203 DP3 R2.x, R1, R0; \n\
204 MUL R0, R0, R2.x; \n\
205 ADD R2, R0, R0; \n\
206 ADD R0, R2, -R1; #compute reflection vector \n\
207 MAD o[TEX2], R0, c[8], c[8]; \n\
209 /** Version with one bump map only (Texture shaders support chaining of offset textures, EMBM does not)
211 static const char *WaterVpBump1LayersCode =
212 "MUL R3, v[0], c[12]; #compute bump 1 uv's \n\
213 ADD o[TEX0], R3, c[11]; \n\
214 DP3 R2.x, R1, R0; \n\
215 MUL R0, R0, R2.x; \n\
216 ADD R2, R0, R0; \n\
217 ADD R0, R2, -R1; #compute reflection vector \n\
218 MAD o[TEX1], R0, c[8], c[8]; \n\
220 /** Optional diffuse texture in stage 3
222 static const char *WaterVpDiffuseMapStage3Code =
223 "DP4 o[TEX3].x, R4, c[13]; #compute uv for diffuse texture \n\
224 DP4 o[TEX3].y, R4, c[14]; \n\
226 /** Optional diffuse texture in stage 2
228 static const char *WaterVpDiffuseMapStage2Code =
229 "DP4 o[TEX2].x, R4, c[13]; #compute uv for diffuse texture \n\
230 DP4 o[TEX2].y, R4, c[14]; \n\
233 /** Optional diffuse texture in stage 1
235 static const char *WaterVpDiffuseMapStage1Code =
236 "DP4 o[TEX1].x, R4, c[13]; #compute uv for diffuse texture \n\
237 DP4 o[TEX1].y, R4, c[14]; \n\
240 // Envmap is setup in texture 0, no bump is used
241 static const char *WaterVpNoBumpCode =
242 " DP3 R2.x, R1, R0; #project view vector on normal for symetry \n\
243 MUL R0, R0, R2.x; \n\
244 ADD R2, R0, R0; \n\
245 ADD R0, R2, -R1; #compute reflection vector \n\
246 MAD o[TEX0], R0, c[8], c[8]; \n\
247 DP4 o[FOGC].x, c[18], R4; #setup fog \n\
251 // static members
252 uint32 CWaterShape::_XScreenGridSize = 20;
253 uint32 CWaterShape::_YScreenGridSize = 20;
255 uint32 CWaterShape::_XGridBorder = 4;
256 uint32 CWaterShape::_YGridBorder = 4;
257 uint32 CWaterShape::_MaxGridSize;
258 bool CWaterShape::_GridSizeTouched = true;
259 /*NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump1;
260 NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump2;
261 NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump1Diffuse;
262 NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump2Diffuse;
263 NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramNoBump;
264 NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramNoBumpDiffuse;*/
265 // water with no waves
266 NLMISC::CSmartPtr<CVertexProgramWaterVPNoWave> CWaterShape::_VertexProgramNoWave;
267 NLMISC::CSmartPtr<CVertexProgramWaterVPNoWave> CWaterShape::_VertexProgramNoWaveDiffuse;
270 /** Build a vertex program for water depending on requirements
271 *//*
272 static CVertexProgram *BuildWaterVP(bool diffuseMap, bool bumpMap, bool use2BumpMap)
274 std::string vp = WaterVPStartCode;
275 if (bumpMap && use2BumpMap)
277 vp += WaterVpBump2LayersCode;
278 if (diffuseMap) vp += WaterVpDiffuseMapStage3Code;
280 else
281 if (bumpMap)
283 vp += WaterVpBump2LayersCode;
284 if (diffuseMap) vp += WaterVpDiffuseMapStage2Code;
286 else
288 vp += WaterVpNoBumpCode;
289 if (diffuseMap) vp += WaterVpDiffuseMapStage1Code;
292 vp += "\nEND";
293 return new CVertexProgram(vp.c_str());
298 //============================================
300 * Constructor
302 CWaterShape::CWaterShape() : _WaterPoolID(0), _TransitionRatio(0.6f), _WaveHeightFactor(3), _ComputeLightmap(false), _SplashEnabled(true)
304 /* ***********************************************
305 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
306 * It can be loaded/called through CAsyncFileManager for instance
307 * ***********************************************/
309 _DefaultPos.setDefaultValue(NLMISC::CVector::Null);
310 _DefaultScale.setDefaultValue(NLMISC::CVector(1, 1, 1));
311 _DefaultRotQuat.setDefaultValue(CQuat::Identity);
313 for (sint k = 0; k < 2; ++k)
315 _HeightMapScale[k].set(1, 1);
316 _HeightMapSpeed[k].set(0, 0);
317 _HeightMapTouch[k] = true;
318 _UsesSceneWaterEnvMap[k] = false;
320 _ColorMapMatColumn0.set(1, 0);
321 _ColorMapMatColumn1.set(0, 1);
322 _ColorMapMatPos.set(0, 0);
323 _EnvMapMeanColorComputed = false;
326 //============================================
327 CRGBA CWaterShape::computeEnvMapMeanColor()
329 // TMP :
330 // just used for water rendering in multiple parts with parallel projection
331 // -> drawn as an uniform polygon with envmap mean coloe
332 if (!_EnvMapMeanColorComputed)
334 _EnvMapMeanColor = NLMISC::CRGBA(0, 0, 255);
335 if (_EnvMap[0])
337 _EnvMap[0]->generate();
338 _EnvMap[0]->convertToType(CBitmap::RGBA);
339 uint32 r = 0;
340 uint32 g = 0;
341 uint32 b = 0;
342 uint32 a = 0;
343 uint numPixs = _EnvMap[0]->getHeight() * _EnvMap[0]->getWidth();
344 const CRGBA *src = (const CRGBA *) (&_EnvMap[0]->getPixels(0)[0]);
345 const CRGBA *last = src + numPixs;
346 while (src != last)
348 r += src->R;
349 g += src->G;
350 b += src->B;
351 a += src->A;
352 ++ src;
354 if (numPixs != 0)
356 _EnvMapMeanColor = NLMISC::CRGBA((uint8) (r / numPixs),
357 (uint8) (g / numPixs),
358 (uint8) (b / numPixs),
359 (uint8) (a / numPixs));
361 _EnvMap[0]->release();
363 _EnvMapMeanColorComputed = true;
365 return _EnvMapMeanColor;
368 //============================================
369 CWaterShape::~CWaterShape()
371 /* ***********************************************
372 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
373 * It can be loaded/called through CAsyncFileManager for instance
374 * ***********************************************/
376 if (
377 (_EnvMap[0] && dynamic_cast<CTextureBlend *>((ITexture *) _EnvMap[0]))
378 || (_EnvMap[1] && dynamic_cast<CTextureBlend *>((ITexture *) _EnvMap[1]))
381 GetWaterPoolManager().unRegisterWaterShape(this);
385 //============================================
386 void CWaterShape::initVertexProgram()
388 static bool created = false;
389 if (!created)
391 // waves
392 /*_VertexProgramBump1 = BuildWaterVP(false, true, false);
393 _VertexProgramBump2 = BuildWaterVP(false, true, true);
395 _VertexProgramBump1Diffuse = BuildWaterVP(true, true, false);
396 _VertexProgramBump2Diffuse = BuildWaterVP(true, true, true);
398 _VertexProgramNoBump = BuildWaterVP(false, false, false);
399 _VertexProgramNoBumpDiffuse = BuildWaterVP(true, false, false);*/
400 // no waves
401 _VertexProgramNoWave = new CVertexProgramWaterVPNoWave(false);
402 _VertexProgramNoWaveDiffuse = new CVertexProgramWaterVPNoWave(true);
403 created = true;
407 //============================================
408 CTransformShape *CWaterShape::createInstance(CScene &scene)
410 CWaterModel *wm = NLMISC::safe_cast<CWaterModel *>(scene.createModel(WaterModelClassId) );
411 wm->Shape = this;
412 // set default pos & scale
413 wm->ITransformable::setPos( _DefaultPos.getDefaultValue() );
414 wm->ITransformable::setScale( _DefaultScale.getDefaultValue() );
415 wm->ITransformable::setRotQuat( _DefaultRotQuat.getDefaultValue() );
417 wm->init();
418 if (scene.getWaterCallback())
420 CWaterShape *ws = NLMISC::safe_cast<CWaterShape *>((IShape *) wm->Shape);
421 scene.getWaterCallback()->waterSurfaceAdded(getShape(), wm->getMatrix(), ws->isSplashEnabled(), ws->getUseSceneWaterEnvMap(0) || ws->getUseSceneWaterEnvMap(1));
423 return wm;
426 //============================================
427 float CWaterShape::getNumTriangles (float distance)
429 // TODO
430 return 0;
433 //============================================
434 void CWaterShape::flushTextures (IDriver &driver, uint selectedTexture)
436 // Test if bump maps are supported by driver before to flush them.
437 // TEMP : can't flush texture for water, because the upload format depends on the shader
438 // Only the driver can determine it.
439 // BumpMaps may be uploaded with unsigned or signed format
442 if (
443 (driver.supportTextureShaders() && driver.supportTextureAddrMode(CMaterial::OffsetTexture))
444 || driver.supportEMBM()
447 for (uint k = 0; k < 2; ++k)
449 if (_BumpMap[k] != NULL)
450 driver.setupTexture(*_BumpMap[k]);
451 if (_EnvMap[k] != NULL)
452 driver.setupTexture(*_EnvMap[k]);
455 if (_ColorMap != NULL)
456 driver.setupTexture(*_ColorMap);
460 //============================================
461 void CWaterShape::setScreenGridSize(uint32 x, uint32 y)
463 nlassert(x > 0 && y > 0);
464 _XScreenGridSize = x;
465 _YScreenGridSize = y;
466 _GridSizeTouched = true;
469 //============================================
470 void CWaterShape::setGridBorderSize(uint32 x, uint32 y)
472 _XGridBorder = x;
473 _YGridBorder = y;
474 _GridSizeTouched = true;
477 //============================================
478 void CWaterShape::setShape(const NLMISC::CPolygon2D &poly)
480 nlassert(poly.Vertices.size() != 0); // empty poly not allowed
481 _Poly = poly;
482 computeBBox();
485 //============================================
486 void CWaterShape::computeBBox()
488 nlassert(_Poly.Vertices.size() != 0);
489 NLMISC::CVector2f min, max;
490 min = max = _Poly.Vertices[0];
491 for (uint k = 1; k < _Poly.Vertices.size(); ++k)
493 min.minof(min, _Poly.Vertices[k]);
494 max.maxof(max, _Poly.Vertices[k]);
496 _BBox.setMinMax(CVector(min.x, min.y, 0), CVector(max.x, max.y, 0));
497 /* nlinfo("center x = %f, y = %f, z = %f", _BBox.getCenter().x, _BBox.getCenter().y, _BBox.getCenter().z);
498 nlinfo("halsize x = %f, y = %f, z = %f", _BBox.getHalfSize().x, _BBox.getHalfSize().y, _BBox.getHalfSize().z); */
501 //============================================
502 void CWaterShape::setHeightMap(uint k, ITexture *hm)
504 nlassert(k < 2);
505 if (!_BumpMap[k])
507 _BumpMap[k] = new CTextureBump;
509 static_cast<CTextureBump *>( (ITexture *) _BumpMap[k])->forceNormalize(true);
510 static_cast<CTextureBump *>( (ITexture *) _BumpMap[k])->setHeightMap(hm);
511 _HeightMapTouch[k] = true; // must recompute normalization factor
514 //============================================
515 ITexture *CWaterShape::getHeightMap(uint k)
517 nlassert(k < 2);
518 return ((CTextureBump *) (ITexture *) _BumpMap[k] )->getHeightMap();
521 //============================================
522 const ITexture *CWaterShape::getHeightMap(uint k) const
524 nlassert(k < 2);
525 return ((CTextureBump *) (ITexture *) _BumpMap[k] )->getHeightMap();
528 //============================================
529 void CWaterShape::serial(NLMISC::IStream &f)
531 /* ***********************************************
532 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
533 * It can be loaded/called through CAsyncFileManager for instance
534 * ***********************************************/
536 // version 4 : added scene water env map
537 // version 3 : added '_Splashenabled' flag
538 sint ver = f.serialVersion(4);
539 // serial 'shape'
540 f.serial(_Poly);
541 // serial heightMap identifier
542 f.serial(_WaterPoolID);
543 //serial maps
544 ITexture *map = NULL;
545 if (f.isReading())
547 f.serialPolyPtr(map); _EnvMap[0] = map;
548 f.serialPolyPtr(map); _EnvMap[1] = map;
549 f.serialPolyPtr(map); _BumpMap[0] = map;
550 f.serialPolyPtr(map); _BumpMap[1] = map;
551 f.serialPolyPtr(map); _ColorMap = map;
552 computeBBox();
554 else
556 map = _EnvMap[0]; f.serialPolyPtr(map);
557 map = _EnvMap[1]; f.serialPolyPtr(map);
558 map = _BumpMap[0]; f.serialPolyPtr(map);
559 map = _BumpMap[1]; f.serialPolyPtr(map);
560 map = _ColorMap; f.serialPolyPtr(map);
563 f.serial(_HeightMapScale[0], _HeightMapScale[1],
564 _HeightMapSpeed[0], _HeightMapSpeed[1]);
566 f.serial(_ColorMapMatColumn0, _ColorMapMatColumn1, _ColorMapMatPos);
568 // serial default tracks
569 f.serial(_DefaultPos);
570 f.serial(_DefaultScale);
571 f.serial(_DefaultRotQuat);
573 f.serial(_TransitionRatio);
575 f.serial(_WaveHeightFactor);
577 if (ver >= 1)
578 f.serial (_ComputeLightmap);
580 if (ver >= 2)
581 f.serial (_DistMax);
583 if (ver >= 3)
584 f.serial(_SplashEnabled);
586 if (ver >= 4)
588 f.serial(_UsesSceneWaterEnvMap[0], _UsesSceneWaterEnvMap[1]);
591 // tmp
593 if (f.isReading())
595 _UsesSceneWaterEnvMap[0] = true;
596 _UsesSceneWaterEnvMap[1] = true;
601 //============================================
602 bool CWaterShape::clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix)
604 for (uint k = 0; k < pyramid.size(); ++k)
606 if (! _BBox.clipBack(pyramid[k] * worldMatrix)) return false;
608 return true;
611 //============================================
612 void CWaterShape::setHeightMapScale(uint k, const NLMISC::CVector2f &scale)
614 nlassert(k < 2);
615 _HeightMapScale[k] = scale;
618 //============================================
619 NLMISC::CVector2f CWaterShape::getHeightMapScale(uint k) const
621 nlassert(k < 2);
622 return _HeightMapScale[k];
625 //============================================
626 void CWaterShape::setHeightMapSpeed(uint k, const NLMISC::CVector2f &speed)
628 nlassert(k < 2);
629 _HeightMapSpeed[k] = speed;
632 //============================================
633 NLMISC::CVector2f CWaterShape::getHeightMapSpeed(uint k) const
635 nlassert(k < 2);
636 return _HeightMapSpeed[k];
639 //============================================
640 void CWaterShape::setColorMapMat(const NLMISC::CVector2f &column0, const NLMISC::CVector2f &column1, const NLMISC::CVector2f &pos)
642 _ColorMapMatColumn0 = column0;
643 _ColorMapMatColumn1 = column1;
644 _ColorMapMatPos = pos;
647 //============================================
648 void CWaterShape::getColorMapMat(NLMISC::CVector2f &column0, NLMISC::CVector2f &column1, NLMISC::CVector2f &pos)
650 column0 = _ColorMapMatColumn0;
651 column1 = _ColorMapMatColumn1;
652 pos = _ColorMapMatPos;
655 //============================================
656 void CWaterShape::envMapUpdate()
658 // if the color map is a blend texture, we MUST be registered to the water pool manager, so that, the
659 // setBlend message will be routed to this texture.
660 if (
661 (_EnvMap[0] && dynamic_cast<CTextureBlend *>((ITexture *) _EnvMap[0]))
662 || (_EnvMap[1] && dynamic_cast<CTextureBlend *>((ITexture *) _EnvMap[1]))
665 if (!GetWaterPoolManager().isWaterShapeObserver(this))
667 GetWaterPoolManager().registerWaterShape(this);
670 else
672 if (GetWaterPoolManager().isWaterShapeObserver(this))
674 GetWaterPoolManager().unRegisterWaterShape(this);
679 //============================================
680 void CWaterShape::setColorMap(ITexture *map)
682 _ColorMap = map;
683 //colorMapUpdate();
686 //============================================
687 void CWaterShape::setEnvMap(uint index, ITexture *envMap)
689 nlassert(index < 2);
690 _EnvMap[index] = envMap;
693 //============================================
694 void CWaterShape::getShapeInWorldSpace(NLMISC::CPolygon &poly) const
696 poly.Vertices.resize(_Poly.Vertices.size());
697 // compute the matrix of the object in world space, by using the default tracks
698 NLMISC::CMatrix objMat;
699 objMat.identity();
700 objMat.translate(_DefaultPos.getDefaultValue());
701 objMat.rotate(_DefaultRotQuat.getDefaultValue());
702 objMat.scale(_DefaultScale.getDefaultValue());
704 for (uint k = 0; k < _Poly.Vertices.size(); ++k)
706 poly.Vertices[k] = objMat * NLMISC::CVector(_Poly.Vertices[k].x, _Poly.Vertices[k].y, 0);
711 //============================================
712 void CWaterShape::getShapeInWorldSpace(NLMISC::CPolygon &poly, const NLMISC::CMatrix &objMat) const
714 poly.Vertices.resize(_Poly.Vertices.size());
715 for (uint k = 0; k < _Poly.Vertices.size(); ++k)
717 poly.Vertices[k] = objMat * NLMISC::CVector(_Poly.Vertices[k].x, _Poly.Vertices[k].y, 0);
722 //============================================
723 void CWaterShape::updateHeightMapNormalizationFactors()
725 for (uint k = 0; k < 2; ++k)
727 if (_HeightMapTouch[k])
729 if (_BumpMap[k] != NULL)
731 _BumpMap[k]->generate();
732 _HeightMapNormalizationFactor[k] = NLMISC::safe_cast<CTextureBump *>((ITexture *)_BumpMap[k])->getNormalizationFactor();
733 if (_BumpMap[k]->getReleasable())
735 _BumpMap[k]->release();
738 else
740 _HeightMapNormalizationFactor[k] = 1.f;
742 _HeightMapTouch[k] = false;
749 //======================================================//
750 // WaveMakerShape //
751 //======================================================//
754 //============================================
755 CWaveMakerShape::CWaveMakerShape() : _Period(1),
756 _Radius(3),
757 _PoolID(0),
758 _Intensity(1),
759 _ImpulsionMode(true)
763 //============================================
764 CWaveMakerShape::~CWaveMakerShape()
768 //============================================
769 void CWaveMakerShape::serial(NLMISC::IStream &f)
771 f.serialVersion(0);
772 f.serial(_Period, _Radius, _Intensity, _PoolID, _ImpulsionMode);
775 //============================================
776 CTransformShape *CWaveMakerShape::createInstance(CScene &scene)
778 CWaveMakerModel *wmm = NLMISC::safe_cast<CWaveMakerModel *>(scene.createModel(WaveMakerModelClassId) );
779 wmm->Shape = this;
780 // set default pos & scale
781 wmm->ITransformable::setPos( _DefaultPos.getDefaultValue() );
782 return wmm;
785 //============================================
786 bool CWaveMakerShape::clip(const std::vector<CPlane> &pyramid, const CMatrix &worldMatrix)
788 // we just test if not too far
789 const CWaterHeightMap &whm = GetWaterPoolManager().getPoolByID(_PoolID);
790 const float maxDist = 0.5f * whm.getUnitSize() * whm.getSize();
791 const NLMISC::CVector pos = worldMatrix.getPos();
792 for (std::vector<NLMISC::CPlane>::const_iterator it = pyramid.begin(); it != pyramid.end(); ++it)
794 if ((*it) * pos > maxDist) return false;
796 return true;
800 //============================================
801 void CWaveMakerShape::getAABBox(NLMISC::CAABBox &bbox) const
803 // its just a point
804 bbox.setCenter(NLMISC::CVector::Null);
805 bbox.setHalfSize(NLMISC::CVector::Null);
808 } // NL3D