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