RigsofRods
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Water.cpp
Go to the documentation of this file.
1 /*
2  This source file is part of Rigs of Rods
3  Copyright 2005-2012 Pierre-Michel Ricordel
4  Copyright 2007-2012 Thomas Fischer
5  Copyright 2013-2020 Petr Ohlidal
6 
7  For more information, see http://www.rigsofrods.org/
8 
9  Rigs of Rods is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License version 3, as
11  published by the Free Software Foundation.
12 
13  Rigs of Rods is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "Water.h"
23 
24 #include "Actor.h"
25 #include "AppContext.h"
26 #include "CameraManager.h"
27 #include "GfxScene.h"
28 #include "PlatformUtils.h" // PathCombine
29 #include "Terrain.h"
30 
31 #include <Ogre.h>
32 
33 using namespace Ogre;
34 using namespace RoR;
35 
36 static const int WAVEREZ = 100;
37 
38 Water::Water(Ogre::Vector3 terrn_size) :
39  m_map_size(terrn_size)
40 {
41  //Ugh.. Why so ugly and hard to read
44 
45  if (m_map_size.x < 1500 && m_map_size.z < 1500)
47 
48  char line[1024] = {};
49  std::string filepath = PathCombine(RoR::App::sys_config_dir->getStr(), "wavefield.cfg");
50  FILE* fd = fopen(filepath.c_str(), "r");
51  if (fd)
52  {
53  while (!feof(fd))
54  {
55  int res = fscanf(fd, " %[^\n\r]", line);
56  if (line[0] == ';')
57  continue;
58  float wl, amp, mx, dir;
59  res = sscanf(line, "%f, %f, %f, %f", &wl, &amp, &mx, &dir);
60  if (res < 4)
61  continue;
62 
63  WaveTrain wavetrain;
64  wavetrain.wavelength = wl;
65  wavetrain.amplitude = amp;
66  wavetrain.maxheight = mx;
67  wavetrain.direction = dir / 57.0;
68  wavetrain.dir_sin = sin(wavetrain.direction);
69  wavetrain.dir_cos = cos(wavetrain.direction);
70 
71  m_wavetrain_defs.push_back(wavetrain);
72  }
73  fclose(fd);
74  }
75  for (size_t i = 0; i < m_wavetrain_defs.size(); i++)
76  {
77  m_wavetrain_defs[i].wavespeed = 1.25 * sqrt(m_wavetrain_defs[i].wavelength);
78  m_max_ampl += m_wavetrain_defs[i].maxheight;
79  }
80 
81  this->PrepareWater();
82 }
83 
85 {
86  if (m_refract_cam != nullptr)
87  {
88  App::GetGfxScene()->GetSceneManager()->destroyCamera(m_refract_cam);
89  m_refract_cam = nullptr;
90  }
91 
92  if (m_reflect_cam != nullptr)
93  {
94  App::GetGfxScene()->GetSceneManager()->destroyCamera(m_reflect_cam);
95  m_reflect_cam = nullptr;
96  }
97 
98  if (m_waterplane_entity != nullptr)
99  {
100  App::GetGfxScene()->GetSceneManager()->destroyEntity("plane");
101  m_waterplane_entity = nullptr;
102  }
103 
104  if (m_waterplane_node != nullptr)
105  {
106  App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->removeAndDestroyChild("WaterPlane");
107  m_waterplane_node = nullptr;
108  }
109 
110  if (m_bottomplane_node != nullptr)
111  {
112  App::GetGfxScene()->GetSceneManager()->destroyEntity("bplane");
113  App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->removeAndDestroyChild("BottomWaterPlane");
114  m_bottomplane_node = nullptr;
115  }
116 
118 
120  {
121  m_refract_rtt_target->removeAllListeners();
122  m_refract_rtt_target->removeAllViewports();
123  m_refract_rtt_target = nullptr;
124  }
125 
126 #if 0 // Doesn't cut it with Ogre 1.11
127  if (!m_refract_rtt_texture.isNull())
128  {
129  m_refract_rtt_texture->unload();
130  Ogre::TextureManager::getSingleton().remove(m_refract_rtt_texture->getHandle());
131  m_refract_rtt_texture.reset();
132  }
133 #endif
134 
136  {
137  m_reflect_rtt_target->removeAllListeners();
138  m_reflect_rtt_target->removeAllViewports();
139  m_reflect_rtt_target = nullptr;
140  }
141 
142 #if 0 // Doesn't cut it with Ogre 1.11
143  if (!m_reflect_rtt_texture.isNull())
144  {
145  m_reflect_rtt_texture->unload();
146  Ogre::TextureManager::getSingleton().remove(m_reflect_rtt_texture->getHandle());
147  m_reflect_rtt_texture.reset();
148  }
149 #endif
150 
152  {
154  m_waterplane_vert_buf_local = nullptr;
155  }
156 
157  Ogre::MeshManager::getSingleton().remove("ReflectPlane");
158  Ogre::MeshManager::getSingleton().remove("BottomPlane");
159  Ogre::MeshManager::getSingleton().remove("WaterPlane");
160 }
161 
163 {
164  m_water_plane.normal = Vector3::UNIT_Y;
165  m_water_plane.d = 0;
166 
167  const auto type = App::gfx_water_mode->getEnum<GfxWaterMode>();
168  const bool full_gfx = type == GfxWaterMode::FULL_HQ || type == GfxWaterMode::FULL_FAST;
169 
170  if (full_gfx || type == GfxWaterMode::REFLECT)
171  {
172  // Check prerequisites first
173  const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
174  if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM)))
175  {
176  OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Your card does not support vertex and fragment programs, so cannot "
177  "run Water effects. Sorry!",
178  "Water effects");
179  }
180  else
181  {
182  if (!GpuProgramManager::getSingleton().isSyntaxSupported("arbfp1") &&
183  !GpuProgramManager::getSingleton().isSyntaxSupported("ps_2_0") &&
184  !GpuProgramManager::getSingleton().isSyntaxSupported("ps_1_4")
185  )
186  {
187  OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Your card does not support advanced fragment programs, "
188  "so cannot run Water effects. Sorry!",
189  "Water effects");
190  }
191  }
192  // Ok
193  // Define a floor plane mesh
194  m_reflect_plane.normal = Vector3::UNIT_Y;
195  m_reflect_plane.d = - 0.15;
196  m_refract_plane.normal = -Vector3::UNIT_Y;
197  m_refract_plane.d = 0.15;
198 
199  if (full_gfx)
200  {
201  TexturePtr m_refract_rtt_targetPtr = Ogre::TextureManager::getSingleton ().getByName ("Refraction");
202  m_refract_rtt_texture = m_refract_rtt_targetPtr;
203  m_refract_rtt_target = m_refract_rtt_targetPtr->getBuffer()->getRenderTarget();
204  {
205  m_refract_cam = App::GetGfxScene()->GetSceneManager()->createCamera("RefractCam");
206  m_refract_cam->setNearClipDistance(App::GetCameraManager()->GetCamera()->getNearClipDistance());
207  m_refract_cam->setFarClipDistance(App::GetCameraManager()->GetCamera()->getFarClipDistance());
208  m_refract_cam->setAspectRatio(
209  (Real)RoR::App::GetAppContext()->GetRenderWindow()->getViewport(0)->getActualWidth() /
210  (Real)RoR::App::GetAppContext()->GetRenderWindow()->getViewport(0)->getActualHeight());
211 
213  m_refract_rtt_viewport->setClearEveryFrame(true);
214  m_refract_rtt_viewport->setBackgroundColour(App::GetGfxScene()->GetSceneManager()->getFogColour());
215 
216  MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction");
217  mat->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName("Refraction");
218 
219  mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefractioninverted");
220  mat->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName("Refraction");
221 
222  m_refract_rtt_viewport->setOverlaysEnabled(false);
223 
225 
226  //optimisation
227  m_refract_rtt_target->setAutoUpdated(false);
228 
229  // Also clip
230  m_refract_cam->enableCustomNearClipPlane(m_refract_plane);
231  }
232  }
233 
234  TexturePtr m_reflect_rtt_targetPtr = Ogre::TextureManager::getSingleton ().getByName ("Reflection");
235  m_reflect_rtt_texture = m_reflect_rtt_targetPtr;
236  m_reflect_rtt_target = m_reflect_rtt_targetPtr->getBuffer()->getRenderTarget();
237  {
238  m_reflect_cam = App::GetGfxScene()->GetSceneManager()->createCamera("ReflectCam");
239  m_reflect_cam->setNearClipDistance(App::GetCameraManager()->GetCamera()->getNearClipDistance());
240  m_reflect_cam->setFarClipDistance(App::GetCameraManager()->GetCamera()->getFarClipDistance());
241  m_reflect_cam->setAspectRatio(
242  (Real)RoR::App::GetAppContext()->GetRenderWindow()->getViewport(0)->getActualWidth() /
243  (Real)RoR::App::GetAppContext()->GetRenderWindow()->getViewport(0)->getActualHeight());
244 
246  m_reflect_rtt_viewport->setClearEveryFrame(true);
247  m_reflect_rtt_viewport->setBackgroundColour(App::GetGfxScene()->GetSceneManager()->getFogColour());
248 
249  MaterialPtr mat;
250  if (full_gfx)
251  {
252  mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction");
253  mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection");
254 
255  mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefractioninverted");
256  mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection");
257  }
258  else
259  {
260  mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflection");
261  mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection");
262  }
263 
264  m_reflect_rtt_viewport->setOverlaysEnabled(false);
265 
267 
268  //optimisation
269  m_reflect_rtt_target->setAutoUpdated(false);
270 
271  // set up linked reflection
272  m_reflect_cam->enableReflection(m_water_plane);
273  // Also clip
274  m_reflect_cam->enableCustomNearClipPlane(m_reflect_plane);
275  }
276 
277  m_waterplane_mesh = MeshManager::getSingleton().createPlane("ReflectPlane",
278  ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
280  m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, WAVEREZ, WAVEREZ, true, 1, 50, 50, Vector3::UNIT_Z, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
281 
282  m_waterplane_entity = App::GetGfxScene()->GetSceneManager()->createEntity("plane", "ReflectPlane");
283  if (full_gfx)
284  m_waterplane_entity->setMaterialName("Examples/FresnelReflectionRefraction");
285  else
286  m_waterplane_entity->setMaterialName("Examples/FresnelReflection");
287  }
288  else
289  {
290  m_waterplane_mesh = MeshManager::getSingleton().createPlane("WaterPlane",
291  ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
293  m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, WAVEREZ, WAVEREZ, true, 1, 50, 50, Vector3::UNIT_Z, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
294  m_waterplane_entity = App::GetGfxScene()->GetSceneManager()->createEntity("plane", "WaterPlane");
295  m_waterplane_entity->setMaterialName("tracks/basicwater");
296  }
297 
298  m_waterplane_entity->setCastShadows(false);
301  //position
302  m_waterplane_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode("WaterPlane");
303  m_waterplane_node->attachObject(m_waterplane_entity);
305 
306  //bottom
307  m_bottom_plane.normal = Vector3::UNIT_Y;
308  m_bottom_plane.d = -m_bottom_height; //30m below waterline
309  MeshManager::getSingleton().createPlane("BottomPlane",
310  ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
312  m_map_size.x * m_waterplane_mesh_scale, m_map_size.z * m_waterplane_mesh_scale, 1, 1, true, 1, 1, 1, Vector3::UNIT_Z);
313  Entity* pE = App::GetGfxScene()->GetSceneManager()->createEntity("bplane", "BottomPlane");
314  pE->setMaterialName("tracks/seabottom");
315  pE->setCastShadows(false);
316 
317  //position
318  m_bottomplane_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode("BottomWaterPlane");
319  m_bottomplane_node->attachObject(pE);
320  m_bottomplane_node->setPosition(Vector3((m_map_size.x * m_waterplane_mesh_scale) / 2, 0, (m_map_size.z * m_waterplane_mesh_scale) / 2));
321 
322  //setup for waves
323  m_waterplane_vert_buf = m_waterplane_mesh->sharedVertexData->vertexBufferBinding->getBuffer(0);
324 
325  if (m_waterplane_vert_buf->getSizeInBytes() == (WAVEREZ + 1) * (WAVEREZ + 1) * 32)
326  {
327  m_waterplane_vert_buf_local = (float*)malloc(m_waterplane_vert_buf->getSizeInBytes());
329  }
330  else
332 }
333 
334 void Water::SetWaterVisible(bool value)
335 {
336  m_water_visible = value;
338  m_waterplane_entity->setVisible(value);
339  if (m_waterplane_node)
340  m_waterplane_node->setVisible(value);
341  if (m_bottomplane_node)
342  m_bottomplane_node->setVisible(value);
343 }
344 
345 void Water::SetReflectionPlaneHeight(float centerheight)
346 {
347  const auto type = App::gfx_water_mode->getEnum<GfxWaterMode>();
348  if (type == GfxWaterMode::FULL_HQ || type == GfxWaterMode::FULL_FAST || type == GfxWaterMode::REFLECT)
349  {
350  this->UpdateReflectionPlane(centerheight);
351  }
352 }
353 
354 void Water::ShowWave(Vector3 refpos)
355 {
357  return;
358 
359  float xScaled = m_map_size.x * m_waterplane_mesh_scale;
360  float zScaled = m_map_size.z * m_waterplane_mesh_scale;
361 
362  for (int pz = 0; pz < WAVEREZ + 1; pz++)
363  {
364  for (int px = 0; px < WAVEREZ + 1; px++)
365  {
366  m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 1] = CalcWavesHeight(refpos + Vector3(xScaled * 0.5 - (float)px * xScaled / WAVEREZ, 0, (float)pz * zScaled / WAVEREZ - zScaled * 0.5)) - m_water_height;
367  }
368  }
369 
370  //normals
371  for (int pz = 0; pz < WAVEREZ + 1; pz++)
372  {
373  for (int px = 0; px < WAVEREZ + 1; px++)
374  {
375  int left = std::max(0, px - 1);
376  int right = std::min(px + 1, WAVEREZ);
377  int up = std::max(0, pz - 1);
378  int down = std::min(pz + 1, WAVEREZ);
379 
380  Vector3 normal = (Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + left) * 8)) - Vector3(m_waterplane_vert_buf_local + ((pz * (WAVEREZ + 1) + right) * 8))).crossProduct(Vector3(m_waterplane_vert_buf_local + ((up * (WAVEREZ + 1) + px) * 8)) - Vector3(m_waterplane_vert_buf_local + ((down * (WAVEREZ + 1) + px) * 8)));
381  normal.normalise();
382 
383  m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 3] = normal.x;
384  m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 4] = normal.y;
385  m_waterplane_vert_buf_local[(pz * (WAVEREZ + 1) + px) * 8 + 5] = normal.z;
386  }
387  }
388 
389  m_waterplane_vert_buf->writeData(0, (WAVEREZ + 1) * (WAVEREZ + 1) * 32, m_waterplane_vert_buf_local, true);
390 }
391 
393 {
394  return (App::GetCameraManager()->GetCameraNode()->getPosition().y < CalcWavesHeight(App::GetCameraManager()->GetCameraNode()->getPosition()));
395 }
396 
398 {
399  if (!m_water_visible)
400  return;
401 
402  const Ogre::Vector3 camera_pos = (m_cam_forced) ? m_cam_forced_position : App::GetCameraManager()->GetCameraNode()->getPosition();
403  const Ogre::Quaternion camera_rot = (m_cam_forced) ? m_cam_forced_orientation : App::GetCameraManager()->GetCameraNode()->getOrientation();
404  const Ogre::Radian camera_fov = (m_cam_forced) ? m_cam_forced_fovy : App::GetCameraManager()->GetCamera()->getFOVy();
405 
406  if (m_waterplane_node)
407  {
408  const Vector3 water_cam_pos(camera_pos.x, m_water_height, camera_pos.z);
409  Vector3 sightPos(water_cam_pos);
410  // Direction points down -Z by default (adapted from Ogre::Camera)
411  Ogre::Vector3 cameraDir = camera_rot * -Ogre::Vector3::UNIT_Z;
412 
413  Ray lineOfSight(camera_pos, cameraDir);
414  Plane waterPlane(Vector3::UNIT_Y, Vector3::UNIT_Y * m_water_height);
415 
416  std::pair<bool, Real> intersection = lineOfSight.intersects(waterPlane);
417 
418  if (intersection.first && intersection.second > 0.0f)
419  sightPos = lineOfSight.getPoint(intersection.second);
420 
421  Real offset = std::min(water_cam_pos.distance(sightPos), std::min(m_map_size.x, m_map_size.z) * 0.5f);
422 
423  Vector3 waterPos = water_cam_pos + (sightPos - water_cam_pos).normalisedCopy() * offset;
424  Vector3 bottomPos = Vector3(waterPos.x, m_bottom_height, waterPos.z);
425 
426  if (waterPos.distance(m_waterplane_node->getPosition()) > 200.0f || m_waterplane_force_update_pos)
427  {
428  m_waterplane_node->setPosition(Vector3(waterPos.x, m_water_height, waterPos.z));
429  m_bottomplane_node->setPosition(bottomPos);
430  }
431  if (RoR::App::gfx_water_waves->getBool() && RoR::App::mp_state->getEnum<MpState>() == RoR::MpState::DISABLED)
432  this->ShowWave(m_waterplane_node->getPosition());
433  }
434 
435  m_frame_counter++;
436  if (App::gfx_water_mode->getEnum<GfxWaterMode>() == GfxWaterMode::FULL_FAST)
437  {
439  {
440  m_reflect_cam->setOrientation(camera_rot);
441  m_reflect_cam->setPosition(camera_pos);
442  m_reflect_cam->setFOVy(camera_fov);
443  m_reflect_rtt_target->update();
444  }
446  {
447  m_refract_cam->setOrientation(camera_rot);
448  m_refract_cam->setPosition(camera_pos);
449  m_refract_cam->setFOVy(camera_fov);
450  m_refract_rtt_target->update();
451  }
452  }
453  else if (App::gfx_water_mode->getEnum<GfxWaterMode>() == GfxWaterMode::FULL_HQ)
454  {
455  m_reflect_cam->setOrientation(camera_rot);
456  m_reflect_cam->setPosition(camera_pos);
457  m_reflect_cam->setFOVy(camera_fov);
458  m_reflect_rtt_target->update();
459 
460  m_refract_cam->setOrientation(camera_rot);
461  m_refract_cam->setPosition(camera_pos);
462  m_refract_cam->setFOVy(camera_fov);
463  m_refract_rtt_target->update();
464  }
465  else if (App::gfx_water_mode->getEnum<GfxWaterMode>() == GfxWaterMode::REFLECT)
466  {
467  m_reflect_cam->setOrientation(camera_rot);
468  m_reflect_cam->setPosition(camera_pos);
469  m_reflect_cam->setFOVy(camera_fov);
470  m_reflect_rtt_target->update();
471  }
472 
474 }
475 
477 {
479  m_refract_rtt_target->removeListener(&m_refract_listener);
481  m_reflect_rtt_target->removeListener(&m_reflect_listener);
482 }
483 
485 {
486  return m_water_height;
487 };
488 
490 {
491  m_water_height = value;
493 }
494 
495 void Water::SetWavesHeight(float value)
496 {
497  m_waves_height = value;
498 }
499 
501 {
502  m_bottom_height = value;
503 }
504 
505 float Water::CalcWavesHeight(Vector3 pos)
506 {
507  // no waves?
508  if (!RoR::App::gfx_water_waves->getBool() || RoR::App::mp_state->getEnum<MpState>() == RoR::MpState::CONNECTED)
509  {
510  // constant height, sea is flat as pancake
511  return m_water_height;
512  }
513 
514  // uh, some upper limit?!
515  if (pos.y > m_water_height + m_max_ampl)
516  return m_water_height;
517 
518  float waveheight = GetWaveHeight(pos);
519  // we will store the result in this variable, init it with the default height
520  float result = m_water_height;
521  // now walk through all the wave trains. One 'train' is one sin/cos set that will generate once wave. All the trains together will sum up, so that they generate a 'rough' sea
522  for (size_t i = 0; i < m_wavetrain_defs.size(); i++)
523  {
524  // calculate the amplitude that this wave will have. wavetrains[i].amplitude is read from the config
525  // upper limit: prevent too big waves by setting an upper limit
526  float amp = std::min(m_wavetrain_defs[i].amplitude * waveheight, m_wavetrain_defs[i].maxheight);
527  // now the main thing:
528  // calculate the sinus with the values of the config file and add it to the result
529  result += amp * sin(Math::TWO_PI * ((m_sim_time_counter * m_wavetrain_defs[i].wavespeed + m_wavetrain_defs[i].dir_sin * pos.x + m_wavetrain_defs[i].dir_cos * pos.z) / m_wavetrain_defs[i].wavelength));
530  }
531  // return the summed up waves
532  return result;
533 }
534 
535 bool Water::IsUnderWater(Vector3 pos)
536 {
537  float waterheight = m_water_height;
538 
539  if (RoR::App::gfx_water_waves->getBool() && RoR::App::mp_state->getEnum<MpState>() == RoR::MpState::DISABLED)
540  {
541  float waveheight = GetWaveHeight(pos);
542 
543  if (pos.y > m_water_height + m_max_ampl * waveheight || pos.y > m_water_height + m_max_ampl)
544  return false;
545 
546  waterheight = CalcWavesHeight(pos);
547  }
548 
549  return pos.y < waterheight;
550 }
551 
552 Vector3 Water::CalcWavesVelocity(Vector3 pos)
553 {
554  if (!RoR::App::gfx_water_waves->getBool() || RoR::App::mp_state->getEnum<MpState>() == RoR::MpState::CONNECTED)
555  return Vector3::ZERO;
556 
557  float waveheight = GetWaveHeight(pos);
558 
559  if (pos.y > m_water_height + m_max_ampl)
560  return Vector3::ZERO;
561 
562  Vector3 result(Vector3::ZERO);
563 
564  const float time_sec = (float)(App::GetAppContext()->GetOgreRoot()->getTimer()->getMilliseconds() * 0.001);
565 
566  for (size_t i = 0; i < m_wavetrain_defs.size(); i++)
567  {
568  float amp = std::min(m_wavetrain_defs[i].amplitude * waveheight, m_wavetrain_defs[i].maxheight);
569  float speed = Math::TWO_PI * amp / (m_wavetrain_defs[i].wavelength / m_wavetrain_defs[i].wavespeed);
570  float coeff = Math::TWO_PI * (time_sec * m_wavetrain_defs[i].wavespeed + m_wavetrain_defs[i].dir_sin * pos.x + m_wavetrain_defs[i].dir_cos * pos.z) / m_wavetrain_defs[i].wavelength;
571  result.y += speed * cos(coeff);
572  result += Vector3(m_wavetrain_defs[i].dir_sin, 0, m_wavetrain_defs[i].dir_cos) * speed * sin(coeff);
573  }
574 
575  return result;
576 }
577 
579 {
580  if (this->IsCameraUnderWater())
581  {
582  m_water_plane.d = -h;
583  if (m_reflect_cam)
584  {
585  m_reflect_cam->disableReflection();
586  m_reflect_cam->disableCustomNearClipPlane();
587  }
588  }
589  else
590  {
591  m_reflect_plane.normal = Vector3::UNIT_Y;
592  m_refract_plane.normal = -Vector3::UNIT_Y;
593  m_reflect_plane.d = -h + 0.15;
594  m_refract_plane.d = h + 0.15;
595  m_water_plane.d = -h;
596  if (m_reflect_cam)
597  {
598  m_reflect_cam->enableReflection(m_water_plane);
599  m_reflect_cam->enableCustomNearClipPlane(m_reflect_plane);
600  }
601  }
602 
603  if (m_refract_cam)
604  {
605  m_refract_cam->enableCustomNearClipPlane(m_refract_plane);
606  }
607 }
608 
609 void Water::FrameStepWater(float dt)
610 {
611  // Update even if game paused to account for camera movement (important for reflections).
612  // --------------------------------------------------------------------------------------
613  this->UpdateWater();
614  m_sim_time_counter += dt;
615 }
616 
617 void Water::SetForcedCameraTransform(Ogre::Radian fovy, Ogre::Vector3 pos, Ogre::Quaternion rot)
618 {
619  m_cam_forced = true;
620  m_cam_forced_fovy = fovy;
621  m_cam_forced_position = pos;
623 }
624 
626 {
627  m_cam_forced = false;
628  m_cam_forced_fovy = 0;
629  m_cam_forced_position = Ogre::Vector3::ZERO;
630  m_cam_forced_orientation = Ogre::Quaternion::IDENTITY;
631 }
632 
633 float Water::GetWaveHeight(Vector3 pos)
634 {
635  // calculate how high the waves should be at this point
636  // (mapsize.x * m_waterplane_mesh_scale) / 2 = terrain width / 2
637  // (mapsize.z * m_waterplane_mesh_scale) / 2 = terrain height / 2
638  // calculate distance to the center of the terrain and divide by 3.000.000
639  float waveheight = (pos - Vector3((m_map_size.x * m_waterplane_mesh_scale) * 0.5, m_water_height, (m_map_size.z * m_waterplane_mesh_scale) * 0.5)).squaredLength() / 3000000.0;
640  waveheight += m_waves_height;
641 
642  return waveheight;
643 }
644 
645 
646 // ------------------------- The listeners -------------------------
647 
648 
649 void Water::RefractionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
650 {
651  this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(false);
652  this->waterplane_entity->setVisible(false);
653  App::GetGfxScene()->SetParticlesVisible(false); // Hide water spray
654 }
655 
656 void Water::RefractionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
657 {
658  this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(true);
659  this->waterplane_entity->setVisible(true);
660  App::GetGfxScene()->SetParticlesVisible(true); // Restore water spray
661 }
662 
663 void Water::ReflectionListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
664 {
665  this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(false);
666  this->waterplane_entity->setVisible(false);
667 }
668 
669 void Water::ReflectionListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
670 {
671  this->scene_mgr->getRenderQueue()->getQueueGroup(RENDER_QUEUE_MAIN)->setShadowsEnabled(true);
672  this->waterplane_entity->setVisible(true);
673 }
RoR::Water::WaveTrain::direction
float direction
Definition: Water.h:72
RoR::Water::WaveTrain::dir_cos
float dir_cos
Definition: Water.h:74
RoR::Water::m_reflect_listener
ReflectionListener m_reflect_listener
Definition: Water.h:122
RoR::Water::RefractionListener::scene_mgr
Ogre::SceneManager * scene_mgr
Definition: Water.h:95
RoR::Water::IsCameraUnderWater
bool IsCameraUnderWater()
Definition: Water.cpp:392
RoR::Water::m_waterplane_entity
Ogre::Entity * m_waterplane_entity
Definition: Water.h:115
y
float y
Definition: (ValueTypes) quaternion.h:6
RoR::Water::IsUnderWater
bool IsUnderWater(Ogre::Vector3 pos) override
Definition: Water.cpp:535
RoR::Water::m_bottomplane_node
Ogre::SceneNode * m_bottomplane_node
Definition: Water.h:132
RoR::MpState::CONNECTED
@ CONNECTED
RoR::Water::m_reflect_rtt_target
Ogre::RenderTexture * m_reflect_rtt_target
Definition: Water.h:127
RoR::Water::m_waterplane_node
Ogre::SceneNode * m_waterplane_node
Definition: Water.h:116
RoR::App::GetCameraManager
CameraManager * GetCameraManager()
Definition: Application.cpp:291
RoR::Water::m_waterplane_vert_buf
Ogre::HardwareVertexBufferSharedPtr m_waterplane_vert_buf
Definition: Water.h:117
RoR::Water::SetWavesHeight
void SetWavesHeight(float value) override
Definition: Water.cpp:495
RoR::Water::CalcWavesVelocity
Ogre::Vector3 CalcWavesVelocity(Ogre::Vector3 pos) override
Definition: Water.cpp:552
RoR::Water::m_waterplane_vert_buf_local
float * m_waterplane_vert_buf_local
Definition: Water.h:118
RoR::GfxWaterMode
GfxWaterMode
Definition: Application.h:394
RoR::Water::SetReflectionPlaneHeight
void SetReflectionPlaneHeight(float centerheight) override
Definition: Water.cpp:345
RoR::App::GetAppContext
AppContext * GetAppContext()
Definition: Application.cpp:282
RoR::Water::m_reflect_cam
Ogre::Camera * m_reflect_cam
Definition: Water.h:124
RoR::Water::~Water
~Water()
Definition: Water.cpp:84
RoR::GfxScene::SetParticlesVisible
void SetParticlesVisible(bool visible)
Definition: GfxScene.cpp:268
RoR::Water::ClearForcedCameraTransform
void ClearForcedCameraTransform() override
Definition: Water.cpp:625
CameraManager.h
RoR::Water::m_water_visible
bool m_water_visible
Definition: Water.h:104
AppContext.h
System integration layer; inspired by OgreBites::ApplicationContext.
RoR::Water::m_reflect_rtt_texture
Ogre::TexturePtr m_reflect_rtt_texture
Definition: Water.h:129
RoR::Water::m_max_ampl
float m_max_ampl
Definition: Water.h:108
RoR::Water::WaveTrain
Definition: Water.h:66
RoR::Water::m_frame_counter
int m_frame_counter
Definition: Water.h:110
RoR::Water::RefractionListener::waterplane_entity
Ogre::Entity * waterplane_entity
Definition: Water.h:96
RoR::CameraManager::GetCameraNode
Ogre::SceneNode * GetCameraNode()
Definition: CameraManager.h:63
RoR::Water::GetWaveHeight
float GetWaveHeight(Ogre::Vector3 pos)
Definition: Water.cpp:633
RoR::Water::m_bottom_plane
Ogre::Plane m_bottom_plane
Definition: Water.h:133
RoR::GfxWaterMode::FULL_HQ
@ FULL_HQ
Reflection + refraction (quality optimized)
RoR::Water::ReflectionListener::waterplane_entity
Ogre::Entity * waterplane_entity
Definition: Water.h:85
Actor.h
RoR::GfxScene::GetSceneManager
Ogre::SceneManager * GetSceneManager()
Definition: GfxScene.h:83
RoR::Water::m_water_height
float m_water_height
Definition: Water.h:105
RoR::Water::m_reflect_rtt_viewport
Ogre::Viewport * m_reflect_rtt_viewport
Definition: Water.h:131
RoR::Water::CalcWavesHeight
float CalcWavesHeight(Ogre::Vector3 pos) override
Definition: Water.cpp:505
RoR::Water::PrepareWater
void PrepareWater()
Definition: Water.cpp:162
RoR::App::mp_state
CVar * mp_state
Definition: Application.cpp:115
RoR::Water::m_reflect_plane
Ogre::Plane m_reflect_plane
Definition: Water.h:120
RoR::Water::WaveTrain::wavelength
float wavelength
Definition: Water.h:70
RoR::CameraManager::GetCamera
Ogre::Camera * GetCamera()
Definition: CameraManager.h:64
RoR::Water::FrameStepWater
void FrameStepWater(float dt) override
Definition: Water.cpp:609
RoR::Water::UpdateReflectionPlane
void UpdateReflectionPlane(float h) override
Definition: Water.cpp:578
RoR::Water::WaveTrain::dir_sin
float dir_sin
Definition: Water.h:73
RoR::Water::SetForcedCameraTransform
void SetForcedCameraTransform(Ogre::Radian fovy, Ogre::Vector3 pos, Ogre::Quaternion rot) override
Definition: Water.cpp:617
RoR::Water::RefractionListener::preRenderTargetUpdate
void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override
Definition: Water.cpp:649
RoR::Water::RefractionListener::postRenderTargetUpdate
void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override
Definition: Water.cpp:656
RoR::PathCombine
std::string PathCombine(std::string a, std::string b)
Definition: PlatformUtils.h:48
RoR::Water::ShowWave
void ShowWave(Ogre::Vector3 refpos)
Definition: Water.cpp:354
RoR::Water::GetStaticWaterHeight
float GetStaticWaterHeight() override
Returns static water level configured in 'terrn2'.
Definition: Water.cpp:484
RoR::GfxWaterMode::FULL_FAST
@ FULL_FAST
Reflection + refraction (speed optimized)
RoR::Water::SetStaticWaterHeight
void SetStaticWaterHeight(float value) override
Definition: Water.cpp:489
RoR::Water::m_wavetrain_defs
std::vector< WaveTrain > m_wavetrain_defs
Definition: Water.h:134
RoR::Water::WaterPrepareShutdown
void WaterPrepareShutdown() override
Definition: Water.cpp:476
GfxScene.h
PlatformUtils.h
Platform-specific utilities. We use narrow UTF-8 encoded strings as paths. Inspired by http://utf8eve...
RoR::Water::WaveTrain::amplitude
float amplitude
Definition: Water.h:68
RoR::Water::m_refract_cam
Ogre::Camera * m_refract_cam
Definition: Water.h:125
RoR::CVar::getEnum
T getEnum() const
Definition: CVar.h:99
RoR::Water::m_water_plane
Ogre::Plane m_water_plane
Definition: Water.h:113
RoR::Water::m_refract_rtt_texture
Ogre::TexturePtr m_refract_rtt_texture
Definition: Water.h:128
RoR::App::gfx_water_mode
CVar * gfx_water_mode
Definition: Application.cpp:236
RoR::Water::m_cam_forced_fovy
Ogre::Radian m_cam_forced_fovy
Definition: Water.h:138
RoR::App::sys_config_dir
CVar * sys_config_dir
Definition: Application.cpp:164
RoR::Water::m_waterplane_force_update_pos
bool m_waterplane_force_update_pos
Definition: Water.h:119
RoR::Water::m_refract_plane
Ogre::Plane m_refract_plane
Definition: Water.h:121
RoR::App::gfx_water_waves
CVar * gfx_water_waves
Definition: Application.cpp:238
RoR::Water::ReflectionListener::postRenderTargetUpdate
void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override
Definition: Water.cpp:669
RoR::Water::WaveTrain::maxheight
float maxheight
Definition: Water.h:69
RoR::Water::ReflectionListener::preRenderTargetUpdate
void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override
Definition: Water.cpp:663
RoR::MpState::DISABLED
@ DISABLED
Not connected for whatever reason.
RoR::Water::m_map_size
Ogre::Vector3 m_map_size
Definition: Water.h:112
RoR::AppContext::GetOgreRoot
Ogre::Root * GetOgreRoot()
Definition: AppContext.h:65
Terrain.h
RoR::Water::m_waves_height
float m_waves_height
Definition: Water.h:106
RoR::Water::m_cam_forced
bool m_cam_forced
Definition: Water.h:137
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::Water::UpdateWater
void UpdateWater() override
Definition: Water.cpp:397
RoR::Water::m_waterplane_mesh
Ogre::MeshPtr m_waterplane_mesh
Definition: Water.h:114
RoR::Water::m_cam_forced_orientation
Ogre::Quaternion m_cam_forced_orientation
Definition: Water.h:140
RoR::Water::SetWaterBottomHeight
void SetWaterBottomHeight(float value) override
Definition: Water.cpp:500
RoR::Water::m_refract_rtt_viewport
Ogre::Viewport * m_refract_rtt_viewport
Definition: Water.h:130
RoR::GfxWaterMode::REFLECT
@ REFLECT
Reflection.
RoR::Water::SetWaterVisible
void SetWaterVisible(bool value) override
Definition: Water.cpp:334
RoR::Water::ReflectionListener::scene_mgr
Ogre::SceneManager * scene_mgr
Definition: Water.h:84
RoR::Water::m_refract_rtt_target
Ogre::RenderTexture * m_refract_rtt_target
Definition: Water.h:126
RoR
Definition: AppContext.h:36
RoR::Water::m_waterplane_mesh_scale
float m_waterplane_mesh_scale
Definition: Water.h:109
RoR::Water::m_sim_time_counter
float m_sim_time_counter
Elapsed simulation time in seconds.
Definition: Water.h:111
RoR::Water::m_bottom_height
float m_bottom_height
Definition: Water.h:107
Water.h
RoR::App::GetGfxScene
GfxScene * GetGfxScene()
Definition: Application.cpp:292
RoR::Water::m_refract_listener
RefractionListener m_refract_listener
Definition: Water.h:123
WAVEREZ
static const int WAVEREZ
Definition: Water.cpp:36
RoR::Water::m_cam_forced_position
Ogre::Vector3 m_cam_forced_position
Definition: Water.h:139