Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
WaterManager.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19  * Water settings (speed, height) and texture management
20  */
21 
22 #include "precompiled.h"
23 
24 #include "graphics/Terrain.h"
26 
27 #include "lib/bits.h"
28 #include "lib/timer.h"
29 #include "lib/tex/tex.h"
31 
32 #include "maths/MathUtil.h"
33 #include "maths/Vector2D.h"
34 
35 #include "ps/Game.h"
36 #include "ps/World.h"
37 
38 #include "renderer/WaterManager.h"
39 #include "renderer/Renderer.h"
40 
44 
45 
46 ///////////////////////////////////////////////////////////////////////////////////////////////
47 // WaterManager implementation
48 
49 
50 ///////////////////////////////////////////////////////////////////
51 // Construction/Destruction
53 {
54  // water
55  m_RenderWater = false; // disabled until textures are successfully loaded
56  m_WaterHeight = 5.0f;
57  m_WaterColor = CColor(0.3f, 0.35f, 0.7f, 1.0f);
58  m_WaterFullDepth = 5.0f;
59  m_WaterMaxAlpha = 1.0f;
60  m_WaterAlphaOffset = -0.05f;
61  m_SWaterTrans = 0;
62  m_TWaterTrans = 0;
63  m_SWaterSpeed = 0.0015f;
64  m_TWaterSpeed = 0.0015f;
72  m_WaterTexTimer = 0.0;
73  m_Shininess = 150.0f;
74  m_SpecularStrength = 0.6f;
75  m_Waviness = 8.0f;
76  m_ReflectionTint = CColor(0.28f, 0.3f, 0.59f, 1.0f);
78  m_WaterTint = CColor(0.28f, 0.3f, 0.59f, 1.0f);
79  m_Murkiness = 0.45f;
80  m_RepeatPeriod = 16.0f;
81  m_WaveX = NULL;
82  m_WaveZ = NULL;
83  m_DistanceToShore = NULL;
84  m_FoamFactor = NULL;
85 
86  m_WaterNormal = false;
87  m_WaterRealDepth = false;
88  m_WaterFoam = false;
89  m_WaterCoastalWaves = false;
90  m_WaterRefraction = false;
91  m_WaterReflection = false;
92  m_WaterShadows = false;
93 
94  m_NeedsReloading = false;
95  m_NeedInfoUpdate = true;
96 
97  m_VBWaves = NULL;
98  m_VBWavesIndices = NULL;
99 
100  m_depthTT = 0;
101  m_waveTT = 0;
102 
103  m_MapSize = 0;
104 
105  m_updatei0 = 0;
106  m_updatej0 = 0;
107  m_updatei1 = 0;
108  m_updatej1 = 0;
109 }
110 
112 {
113  // Cleanup if the caller messed up
115  delete[] m_WaveX;
116  delete[] m_WaveZ;
117  delete[] m_DistanceToShore;
118  delete[] m_FoamFactor;
119 
120  glDeleteTextures(1, &m_depthTT);
121  glDeleteTextures(1, &m_waveTT);
122 
125 
126 }
127 
128 
129 ///////////////////////////////////////////////////////////////////
130 // Progressive load of water textures
132 {
133  // TODO: this doesn't need to be progressive-loading any more
134  // (since texture loading is async now)
135 
136  // TODO: add a member variable and setter for this. (can't make this
137  // a parameter because this function is called via delay-load code)
138  static const wchar_t* const water_type = L"default";
139 
140  wchar_t pathname[PATH_MAX];
141 
142  // Load diffuse grayscale images (for non-fancy water)
143  for (size_t i = 0; i < ARRAY_SIZE(m_WaterTexture); ++i)
144  {
145  swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/diffuse%02d.dds", water_type, (int)i+1);
146  CTextureProperties textureProps(pathname);
147  textureProps.SetWrap(GL_REPEAT);
148 
149  CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
150  texture->Prefetch();
151  m_WaterTexture[i] = texture;
152  }
153 
154  // Load normalmaps (for fancy water)
155  for (size_t i = 0; i < ARRAY_SIZE(m_NormalMap); ++i)
156  {
157  swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/normal%02d.dds", water_type, (int)i+1);
158  CTextureProperties textureProps(pathname);
159  textureProps.SetWrap(GL_REPEAT);
160  textureProps.SetMaxAnisotropy(4);
161 
162  CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
163  texture->Prefetch();
164  m_NormalMap[i] = texture;
165  }
166  // Load foam (for fancy water)
167  {
168  CTextureProperties textureProps("art/textures/terrain/types/water/foam.png");
169  textureProps.SetWrap(GL_REPEAT);
170 
171  CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
172  texture->Prefetch();
173  m_Foam = texture;
174  }
175  // Load waves (for fancy water)
176  {
177  CTextureProperties textureProps("art/textures/terrain/types/water/shore_wave.png");
178  textureProps.SetWrap(GL_REPEAT);
179 
180  CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
181  texture->Prefetch();
182  m_Wave = texture;
183  }
184  // Set the size to the largest power of 2 that is <= to the window height, so
185  // the reflection/refraction images will fit within the window
186  // (alternative: use FBO's, which can have arbitrary size - but do we need
187  // the reflection/refraction textures to be that large?)
188  int size = (int)round_up_to_pow2((unsigned)g_Renderer.GetHeight());
189  if(size > g_Renderer.GetHeight()) size /= 2;
192 
193  // Create reflection texture
194  glGenTextures(1, &m_ReflectionTexture);
195  glBindTexture(GL_TEXTURE_2D, m_ReflectionTexture);
196  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB,
197  (GLsizei)m_ReflectionTextureSize, (GLsizei)m_ReflectionTextureSize,
198  0, GL_RGB, GL_UNSIGNED_BYTE, 0);
199  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
200  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
201  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
202  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
203 
204  // Create refraction texture
205  glGenTextures(1, &m_RefractionTexture);
206  glBindTexture(GL_TEXTURE_2D, m_RefractionTexture);
207  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB,
208  (GLsizei)m_RefractionTextureSize, (GLsizei)m_RefractionTextureSize,
209  0, GL_RGB, GL_UNSIGNED_BYTE, 0);
210  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
211  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
212  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
213  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
214 
215  // Enable rendering, now that we've succeeded this far
216  m_RenderWater = true;
217 
218  return 0;
219 }
220 
221 
222 ///////////////////////////////////////////////////////////////////
223 // Unload water textures
225 {
226  for(size_t i = 0; i < ARRAY_SIZE(m_WaterTexture); i++)
227  {
228  m_WaterTexture[i].reset();
229  }
230 
231 
232  for(size_t i = 0; i < ARRAY_SIZE(m_NormalMap); i++)
233  {
234  m_NormalMap[i].reset();
235  }
236 }
237 
238 ///////////////////////////////////////////////////////////////////
239 // Create information about the terrain and wave vertices.
241 {
242  if (m_VBWaves)
243  {
245  m_VBWaves = NULL;
246  }
247  if (m_VBWavesIndices)
248  {
250  m_VBWavesIndices = NULL;
251  }
252 
253  CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
254 
255  CmpPtr<ICmpWaterManager> cmpWaterManager(*simulation, SYSTEM_ENTITY);
256  if (!cmpWaterManager)
257  return; // REALLY shouldn't happen and will most likely crash.
258 
259  // Using this to get some more optimization on circular maps
260  CmpPtr<ICmpRangeManager> cmpRangeManager(*simulation, SYSTEM_ENTITY);
261  if (!cmpRangeManager)
262  return;
263  bool circular = cmpRangeManager->GetLosCircular();
264  float mSize = m_MapSize*m_MapSize;
265  float halfSize = (m_MapSize/2.0);
266 
267  // Warning: this won't work with multiple water planes
268  m_WaterHeight = cmpWaterManager->GetExactWaterLevel(0,0);
269 
270  // Get the square we want to work on.
271  i32 Xstart = clamp(m_updatei0, 0, (i32)m_MapSize-1);
272  i32 Xend = clamp(m_updatei1, 0, (i32)m_MapSize-1);
273  i32 Zstart = clamp(m_updatej0, 0, (i32)m_MapSize-1);
274  i32 Zend = clamp(m_updatej1, 0, (i32)m_MapSize-1);
275 
276  if (m_WaveX == NULL)
277  {
278  m_WaveX = new float[m_MapSize*m_MapSize];
279  m_WaveZ = new float[m_MapSize*m_MapSize];
280  m_DistanceToShore = new float[m_MapSize*m_MapSize];
281  m_FoamFactor = new float[m_MapSize*m_MapSize];
282  }
283 
284  u16* heightmap = terrain->GetHeightMap();
285 
286  // some temporary stuff for wave intensity
287  // not really used too much right now.
288  //u8* waveForceHQ = new u8[mapSize*mapSize];
289 
290  // used to cache terrain normals since otherwise we'd recalculate them a lot (I'm blurring the "normal" map).
291  // this might be updated to actually cache in the terrain manager but that's not for now.
292  CVector3D* normals = new CVector3D[m_MapSize*m_MapSize];
293 
294 
295  // taken out of the bottom loop, blurs the normal map
296  // To remove if below is reactivated
297  ssize_t blurZstart = Zstart-4 < 0 ? 0 : Zstart - 4;
298  ssize_t blurZend = Zend+4 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : Zend + 4;
299  ssize_t blurXstart = Xstart-4 < 0 ? 0 : Xstart - 4;
300  ssize_t blurXend = Xend+4 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : Xend + 4;
301  for (ssize_t j = blurZstart; j < blurZend; ++j)
302  {
303  for (ssize_t i = blurXstart; i < blurXend; ++i)
304  {
305  normals[j*m_MapSize + i] = terrain->CalcExactNormal(((float)i)*4.0f,((float)j)*4.0f);
306  }
307  }
308  // TODO: reactivate?
309  /*
310  // calculate wave force (not really used right now)
311  // and puts into "normals" the terrain normal at that point
312  // so as to avoid recalculating terrain normals too often.
313  for (ssize_t i = 0; i < mapSize; ++i)
314  {
315  for (ssize_t j = 0; j < mapSize; ++j)
316  {
317  normals[j*mapSize + i] = terrain->CalcExactNormal(((float)i)*4.0f,((float)j)*4.0f);
318  if (circular && (i-halfSize)*(i-halfSize)+(j-halfSize)*(j-halfSize) > mSize)
319  {
320  waveForceHQ[j*mapSize + i] = 255;
321  continue;
322  }
323  u8 color = 0;
324  for (int v = 0; v <= 18; v += 3){
325  if (j-v >= 0 && i-v >= 0 && heightmap[(j-v)*mapSize + i-v] > waterHeightInu16)
326  {
327  if (color == 0)
328  color = 5;
329  else
330  color++;
331  }
332  }
333  waveForceHQ[j*mapSize + i] = 255 - color * 40;
334  }
335  }
336  */
337  // this creates information for waves and stores it in float arrays. PatchRData then puts it in the vertex info for speed.
338  for (ssize_t j = Zstart; j < Zend; ++j)
339  {
340  for (ssize_t i = Xstart; i < Xend; ++i)
341  {
342  if (circular && (i-halfSize)*(i-halfSize)+(j-halfSize)*(j-halfSize) > mSize)
343  {
344  m_WaveX[j*m_MapSize + i] = 0.0f;
345  m_WaveZ[j*m_MapSize + i] = 0.0f;
346  m_DistanceToShore[j*m_MapSize + i] = 100;
347  m_FoamFactor[j*m_MapSize + i] = 0.0f;
348  continue;
349  }
350  float depth = m_WaterHeight - heightmap[j*m_MapSize + i]*HEIGHT_SCALE;
351  int distanceToShore = 10000;
352 
353  // calculation of the distance to the shore.
354  // TODO: this is fairly dumb, though it returns a good result
355  // Could be sped up a fair bit.
356  if (depth >= 0)
357  {
358  // check in the square around.
359  for (int yy = -5; yy <= 5; ++yy)
360  {
361  for (int xx = -5; xx <= 5; ++xx)
362  {
363  if (i+xx >= 0 && i + xx < (long)m_MapSize)
364  if (j + yy >= 0 && j + yy < (long)m_MapSize)
365  {
366  float hereDepth = m_WaterHeight - heightmap[(j+yy)*m_MapSize + (i+xx)]*HEIGHT_SCALE;
367  if (hereDepth < 0 && xx*xx + yy*yy < distanceToShore)
368  distanceToShore = xx*xx + yy*yy;
369  }
370  }
371  }
372  // refine the calculation if we're close enough
373  if (distanceToShore < 9)
374  {
375  for (float yy = -2.5f; yy <= 2.5f; ++yy)
376  {
377  for (float xx = -2.5f; xx <= 2.5f; ++xx)
378  {
379  float hereDepth = m_WaterHeight - terrain->GetExactGroundLevel( (i+xx)*4, (j+yy)*4 );
380  if (hereDepth < 0 && xx*xx + yy*yy < distanceToShore)
381  distanceToShore = xx*xx + yy*yy;
382  }
383  }
384  }
385  }
386  else
387  {
388  for (int yy = -2; yy <= 2; ++yy)
389  {
390  for (int xx = -2; xx <= 2; ++xx)
391  {
392  float hereDepth = m_WaterHeight - terrain->GetVertexGroundLevel(i+xx, j+yy);
393  if (hereDepth > 0)
394  distanceToShore = 0;
395  }
396  }
397 
398  }
399  // speedup with default values for land squares
400  if (distanceToShore == 10000)
401  {
402  m_WaveX[j*m_MapSize + i] = 0.0f;
403  m_WaveZ[j*m_MapSize + i] = 0.0f;
404  m_DistanceToShore[j*m_MapSize + i] = 100;
405  m_FoamFactor[j*m_MapSize + i] = 0.0f;
406  continue;
407  }
408  // We'll compute the normals and the "water raise", to know about foam
409  // Normals are a pretty good calculation but it's slow since we normalize so much.
410  CVector3D normal;
411  int waterRaise = 0;
412  for (int yy = -4; yy <= 4; yy += 2)
413  {
414  for (int xx = -4; xx <= 4; xx += 2) // every 2 tile is good enough.
415  {
416  if (j+yy < (long)m_MapSize && i+xx < (long)m_MapSize && i+xx >= 0 && j+yy >= 0)
417  normal += normals[(j+yy)*m_MapSize + (i+xx)];
418  if (terrain->GetVertexGroundLevel(i+xx,j+yy) < heightmap[j*m_MapSize + i]*HEIGHT_SCALE)
419  waterRaise += heightmap[j*m_MapSize + i]*HEIGHT_SCALE - terrain->GetVertexGroundLevel(i+xx,j+yy);
420  }
421  }
422  // normalizes the terrain info to avoid foam moving at too different speeds.
423  normal *= 0.012345679f;
424  normal[1] = 0.1f;
425  normal = normal.Normalized();
426 
427  m_WaveX[j*m_MapSize + i] = normal[0];
428  m_WaveZ[j*m_MapSize + i] = normal[2];
429  // distance is /5.0 to be a [0,1] value.
430 
431  m_DistanceToShore[j*m_MapSize + i] = sqrtf(distanceToShore)/5.0f; // TODO: this can probably be cached as I'm integer here.
432 
433  // computing the amount of foam I want
434 
435  depth = clamp(depth,0.0f,10.0f);
436  float foamAmount = (waterRaise/255.0f) * (1.0f - depth/10.0f) /** (waveForceHQ[j*m_MapSize+i]/255.0f)*/ * (m_Waviness/8.0f);
437  foamAmount += clamp(m_Waviness/2.0f - distanceToShore,0.0f,m_Waviness/2.0f)/(m_Waviness/2.0f) * clamp(m_Waviness/9.0f,0.3f,1.0f);
438  foamAmount = foamAmount > 1.0f ? 1.0f: foamAmount;
439 
440  m_FoamFactor[j*m_MapSize + i] = foamAmount;
441  }
442  }
443 
444  delete[] normals;
445  //delete[] waveForceHQ;
446 
447  // TODO: The rest should be cleaned up
448 
449  // okay let's create the waves squares. i'll divide the map in arbitrary squares
450  // For each of these squares, check if waves are needed.
451  // If yes, look for the best positionning (in order to have a nice blending with the shore)
452  // Then clean-up: remove squares that are too close to each other
453 
454  std::vector<CVector2D> waveSquares;
455 
456  int size = 8; // I think this is the size of the squares.
457  for (size_t j = 0; j < m_MapSize/size; ++j)
458  {
459  for (size_t i = 0; i < m_MapSize/size; ++i)
460  {
461  int landTexel = 0;
462  int waterTexel = 0;
463  CVector3D avnormal (0.0f,0.0f,0.0f);
464  CVector2D landPosition(0.0f,0.0f);
465  CVector2D waterPosition(0.0f,0.0f);
466  for (int yy = 0; yy < size; ++yy)
467  {
468  for (int xx = 0; xx < size; ++xx)
469  {
470  if (terrain->GetVertexGroundLevel(i*size+xx,j*size+yy) > m_WaterHeight)
471  {
472  landTexel++;
473  landPosition += CVector2D(i*size+xx,j*size+yy);
474  }
475  else
476  {
477  waterPosition += CVector2D(i*size+xx,j*size+yy);
478  waterTexel++;
479  avnormal += terrain->CalcExactNormal( (i*size+xx)*4.0f,(j*size+yy)*4.0f);
480  }
481  }
482  }
483  if (landTexel < size/2)
484  continue;
485 
486  landPosition /= landTexel;
487  waterPosition /= waterTexel;
488 
489  avnormal[1] = 1.0f;
490  avnormal.Normalize();
491  avnormal[1] = 0.0f;
492 
493  // this should help ensure that the shore is pretty flat.
494  if (avnormal.Length() <= 0.2f)
495  continue;
496 
497  // To get the best position for squares, I start at the mean "ocean" position
498  // And step by step go to the mean "land" position. I keep the position where I change from water to land.
499  // If this never happens, the square is scrapped.
500  if (terrain->GetExactGroundLevel(waterPosition.X*4.0f,waterPosition.Y*4.0f) > m_WaterHeight)
501  continue;
502 
503  CVector2D squarePos(-1,-1);
504  for (u8 i = 0; i < 40; i++)
505  {
506  squarePos = landPosition * (i/40.0f) + waterPosition * (1.0f-(i/40.0f));
507  if (terrain->GetExactGroundLevel(squarePos.X*4.0f,squarePos.Y*4.0f) > m_WaterHeight)
508  break;
509  }
510  if (squarePos.X == -1)
511  continue;
512 
513  u8 enter = 1;
514  // okaaaaaay. Got a square. Check for proximity.
515  for (unsigned long i = 0; i < waveSquares.size(); i++)
516  {
517  if ( CVector2D(waveSquares[i]-squarePos).LengthSquared() < 80) {
518  enter = 0;
519  break;
520  }
521  }
522  if (enter == 1)
523  waveSquares.push_back(squarePos);
524  }
525  }
526 
527  // Actually create the waves' meshes.
528  std::vector<SWavesVertex> waves_vertex_data;
529  std::vector<GLushort> waves_indices;
530 
531  // loop through each square point. Look in the square around it, calculate the normal
532  // create the square.
533  for (unsigned long i = 0; i < waveSquares.size(); i++)
534  {
535  CVector2D pos(waveSquares[i]);
536 
537  CVector3D avgnorm(0.0f,0.0f,0.0f);
538  for (int yy = -size/2; yy < size/2; ++yy)
539  {
540  for (int xx = -size/2; xx < size/2; ++xx)
541  {
542  avgnorm += terrain->CalcExactNormal((pos.X+xx)*4.0f,(pos.Y+yy)*4.0f);
543  }
544  }
545  avgnorm[1] = 0.1f;
546  // okay crank out a square.
547  // we have the direction of the square. We'll get the perpendicular vector too
548  CVector2D perp(-avgnorm[2],avgnorm[0]);
549  perp = perp.Normalized();
550  avgnorm = avgnorm.Normalized();
551 
552  SWavesVertex vertex[4];
553  vertex[0].m_Position = CVector3D(pos.X + perp.X*(size/2.2f) - avgnorm[0]*1.0f, 0.0f,pos.Y + perp.Y*(size/2.2f) - avgnorm[2]*1.0f);
554  vertex[0].m_Position *= 4.0f;
555  vertex[0].m_Position.Y = m_WaterHeight + 1.0f;
556  vertex[0].m_UV[1] = 1;
557  vertex[0].m_UV[0] = 0;
558 
559  vertex[1].m_Position = CVector3D(pos.X - perp.X*(size/2.2f) - avgnorm[0]*1.0f, 0.0f,pos.Y - perp.Y*(size/2.2f) - avgnorm[2]*1.0f);
560  vertex[1].m_Position *= 4.0f;
561  vertex[1].m_Position.Y = m_WaterHeight + 1.0f;
562  vertex[1].m_UV[1] = 1;
563  vertex[1].m_UV[0] = 1;
564 
565  vertex[3].m_Position = CVector3D(pos.X + perp.X*(size/2.2f) + avgnorm[0]*(size/1.5f), 0.0f,pos.Y + perp.Y*(size/2.2f) + avgnorm[2]*(size/1.5f));
566  vertex[3].m_Position *= 4.0f;
567  vertex[3].m_Position.Y = m_WaterHeight + 1.0f;
568  vertex[3].m_UV[1] = 0;
569  vertex[3].m_UV[0] = 0;
570 
571  vertex[2].m_Position = CVector3D(pos.X - perp.X*(size/2.2f) + avgnorm[0]*(size/1.5f), 0.0f,pos.Y - perp.Y*(size/2.2f) + avgnorm[2]*(size/1.5f));
572  vertex[2].m_Position *= 4.0f;
573  vertex[2].m_Position.Y = m_WaterHeight + 1.0f;
574  vertex[2].m_UV[1] = 0;
575  vertex[2].m_UV[0] = 1;
576 
577  waves_indices.push_back(waves_vertex_data.size());
578  waves_vertex_data.push_back(vertex[0]);
579  waves_indices.push_back(waves_vertex_data.size());
580  waves_vertex_data.push_back(vertex[1]);
581  waves_indices.push_back(waves_vertex_data.size());
582  waves_vertex_data.push_back(vertex[2]);
583  waves_indices.push_back(waves_vertex_data.size());
584  waves_vertex_data.push_back(vertex[3]);
585  }
586 
587  // no vertex buffers if no data generated
588  if (waves_indices.empty())
589  return;
590 
591  // waves
592  // allocate vertex buffer
593  m_VBWaves = g_VBMan.Allocate(sizeof(SWavesVertex), waves_vertex_data.size(), GL_STATIC_DRAW, GL_ARRAY_BUFFER);
594  m_VBWaves->m_Owner->UpdateChunkVertices(m_VBWaves, &waves_vertex_data[0]);
595 
596  // Construct indices buffer
597  m_VBWavesIndices = g_VBMan.Allocate(sizeof(GLushort), waves_indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
599 }
600 
601 ////////////////////////////////////////////////////////////////////////
602 // This will always recalculate for now
603 void WaterManager::SetMapSize(size_t size)
604 {
605  // TODO: Im' blindly trusting the user here.
606  m_MapSize = size;
607  m_NeedInfoUpdate = true;
608  m_updatei0 = 0;
609  m_updatei1 = size;
610  m_updatej0 = 0;
611  m_updatej1 = size;
612 
617 }
618 
619 ////////////////////////////////////////////////////////////////////////
620 // This will set the bools properly
622 {
623  if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERNORMAL) != m_WaterNormal) {
625  m_NeedsReloading = true;
626  }
629  m_NeedsReloading = true;
630  }
631  if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERFOAM) != m_WaterFoam) {
633  m_NeedsReloading = true;
634  m_NeedInfoUpdate = true;
635  }
638  m_NeedsReloading = true;
639  m_NeedInfoUpdate = true;
640  }
643  m_NeedsReloading = true;
644  }
647  m_NeedsReloading = true;
648  }
649  if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERSHADOW) != m_WaterShadows) {
651  m_NeedsReloading = true;
652  }
653 }
654 
656 {
657  if (!g_Renderer.GetCapabilities().m_FragmentShader)
658  return false;
659  if (!m_RenderWater)
660  return false;
661  return true;
662 }
CTexturePtr m_WaterTexture[60]
Definition: WaterManager.h:52
#define u8
Definition: types.h:39
bool m_NeedInfoUpdate
Definition: WaterManager.h:88
float m_RepeatPeriod
Definition: WaterManager.h:117
float m_Shininess
Definition: WaterManager.h:118
float m_WaterMaxAlpha
Definition: WaterManager.h:92
float X
Definition: Vector2D.h:157
float LengthSquared() const
Definition: Vector2D.h:107
float m_SWaterTrans
Definition: WaterManager.h:98
GLuint m_depthTT
Definition: WaterManager.h:64
Definition: Overlay.h:34
#define i32
Definition: types.h:36
bool m_WaterRealDepth
Definition: WaterManager.h:79
size_t m_RefractionTextureSize
Definition: WaterManager.h:108
CVertexBufferManager g_VBMan
Represents the filename and GL parameters of a texture, for passing to CTextureManager::CreateTexture...
CVertexBuffer::VBChunk * m_VBWaves
Definition: WaterManager.h:127
float m_Waviness
Definition: WaterManager.h:120
bool m_WaterShadows
Definition: WaterManager.h:84
bool m_WaterNormal
Definition: WaterManager.h:78
size_t m_ReflectionTextureSize
Definition: WaterManager.h:107
CTexturePtr m_NormalMap[60]
Definition: WaterManager.h:53
float GetExactGroundLevel(float x, float z) const
Definition: Terrain.cpp:353
void Normalize()
Definition: Vector3D.cpp:77
GLuint m_RefractionTexture
Definition: WaterManager.h:106
int m_WaterCurrentTex
Definition: WaterManager.h:73
float m_TWaterScrollCounter
Definition: WaterManager.h:101
int swprintf_s(wchar_t *buf, size_t max_chars, const wchar_t *fmt,...) WPRINTF_ARGS(3)
float m_TWaterTrans
Definition: WaterManager.h:99
float m_WaterHeight
Definition: WaterManager.h:91
virtual bool GetLosCircular()=0
Returns whether the LOS is restricted to a circular map.
float m_TWaterSpeed
Definition: WaterManager.h:97
bool m_WaterFoam
Definition: WaterManager.h:80
float * m_WaveX
Definition: WaterManager.h:56
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton &#39;system&#39; components.
Definition: Entity.h:44
#define ARRAY_SIZE(name)
Public API for simulation system.
Definition: Simulation2.h:46
#define g_Renderer
Definition: Renderer.h:61
CTexturePtr m_Foam
Definition: WaterManager.h:54
void SetMapSize(size_t size)
Updates the map size.
float * m_FoamFactor
Definition: WaterManager.h:59
CTerrain * GetTerrain()
Get the pointer to the terrain object.
Definition: World.h:88
float m_WaterAlphaOffset
Definition: WaterManager.h:94
bool m_NeedsReloading
Definition: WaterManager.h:86
float m_Murkiness
Definition: WaterManager.h:121
T round_up_to_pow2(T x)
round up to next larger power of two.
Definition: bits.h:244
void UpdateQuality()
Updates the settings to the one from the renderer, and sets m_NeedsReloading.
CVertexBuffer::VBChunk * Allocate(size_t vertexSize, size_t numVertices, GLenum usage, GLenum target)
Try to allocate a vertex buffer of the given size and type.
bool m_RenderWater
Definition: WaterManager.h:75
const float HEIGHT_SCALE
metres per u16 height unit
Definition: Terrain.h:46
GLuint m_waveTT
Definition: WaterManager.h:65
CVector2D Normalized() const
Definition: Vector2D.h:124
float Length() const
Definition: Vector3D.cpp:72
CColor m_WaterTint
Definition: WaterManager.h:116
float Y
Definition: Vector3D.h:31
int LoadWaterTextures()
LoadWaterTextures: Load water textures from within the progressive load framework.
float m_SWaterScrollCounter
Definition: WaterManager.h:100
bool m_WaterRefraction
Definition: WaterManager.h:82
virtual float GetExactWaterLevel(float x, float z)=0
Get the current water level at the given point.
CGame * g_Game
Globally accessible pointer to the CGame object.
Definition: Game.cpp:56
void UpdateChunkVertices(VBChunk *chunk, void *data)
Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer...
void UnloadWaterTextures()
UnloadWaterTextures: Free any loaded water textures and reset the internal state so that another call...
#define PATH_MAX
Definition: wposix_types.h:101
float m_SpecularStrength
Definition: WaterManager.h:119
A simplified syntax for accessing entity components.
Definition: CmpPtr.h:55
float Y
Definition: Vector2D.h:157
intptr_t ssize_t
Definition: wposix_types.h:82
#define u16
Definition: types.h:40
void CreateSuperfancyInfo(CSimulation2 *simulation)
CreateSuperfancyInfo: creates textures and wave vertices for superfancy water.
void Release(CVertexBuffer::VBChunk *chunk)
Returns the given chunk to its owning buffer.
void SetMaxAnisotropy(float aniso)
Set maximum anisotropy value.
bool WillRenderFancyWater()
Returns true if fancy water shaders will be used (i.e.
float * m_WaveZ
Definition: WaterManager.h:57
float m_ReflectionTintStrength
Definition: WaterManager.h:123
GLuint m_ReflectionTexture
Definition: WaterManager.h:105
CVertexBuffer * m_Owner
Owning (parent) vertex buffer.
Definition: VertexBuffer.h:50
float GetVertexGroundLevel(ssize_t i, ssize_t j) const
Definition: Terrain.cpp:308
CVertexBuffer::VBChunk * m_VBWavesIndices
Definition: WaterManager.h:128
CTexturePtr m_Wave
Definition: WaterManager.h:55
bool m_WaterReflection
Definition: WaterManager.h:83
CColor m_WaterColor
Definition: WaterManager.h:74
float m_SWaterSpeed
Definition: WaterManager.h:96
CWorld * GetWorld()
Get the pointer to the game world object.
Definition: Game.h:120
double m_WaterTexTimer
Definition: WaterManager.h:102
#define SAFE_ARRAY_DELETE(p)
delete memory ensuing from new[] and set the pointer to zero (thus making double-frees safe / a no-op...
u16 * GetHeightMap() const
Definition: Terrain.h:103
float m_WaterFullDepth
Definition: WaterManager.h:93
float * m_DistanceToShore
Definition: WaterManager.h:58
void SetWrap(GLint wrap)
Set wrapping mode (typically GL_REPEAT, GL_CLAMP_TO_EDGE, etc).
CVector3D Normalized() const
Definition: Vector3D.cpp:86
T clamp(T value, T min, T max)
Definition: MathUtil.h:32
size_t m_MapSize
Definition: WaterManager.h:61
CVector3D CalcExactNormal(float x, float z) const
Definition: Terrain.cpp:235
CVector3D m_Position
Definition: WaterManager.h:35
bool m_WaterCoastalWaves
Definition: WaterManager.h:81
shared_ptr< CTexture > CTexturePtr
Definition: Texture.h:22
CColor m_ReflectionTint
Definition: WaterManager.h:122