RigsofRods
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
GfxScene.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 "GfxScene.h"
23 
24 #include "AppContext.h"
25 #include "Actor.h"
26 #include "ActorManager.h"
27 #include "ApproxMath.h"
28 #include "Console.h"
29 #include "DustPool.h"
30 #include "HydraxWater.h"
31 #include "GameContext.h"
32 #include "GUIManager.h"
33 #include "GUIUtils.h"
34 #include "GUI_DirectionArrow.h"
35 #include "OverlayWrapper.h"
36 #include "SkyManager.h"
37 #include "SkyXManager.h"
38 #include "TerrainGeometryManager.h"
39 #include "Terrain.h"
40 #include "TerrainObjectManager.h"
41 #include "Utils.h"
42 
43 #include "imgui_internal.h"
44 
45 #include <Ogre.h>
46 
47 using namespace Ogre;
48 using namespace RoR;
49 
50 void GfxScene::CreateDustPools()
51 {
52  ROR_ASSERT(m_dustpools.size() == 0);
53  m_dustpools["dust"] = new DustPool(m_scene_manager, "tracks/Dust", 20);
54  m_dustpools["clump"] = new DustPool(m_scene_manager, "tracks/Clump", 20);
55  m_dustpools["sparks"] = new DustPool(m_scene_manager, "tracks/Sparks", 10);
56  m_dustpools["drip"] = new DustPool(m_scene_manager, "tracks/Drip", 50);
57  m_dustpools["splash"] = new DustPool(m_scene_manager, "tracks/Splash", 20);
58  m_dustpools["ripple"] = new DustPool(m_scene_manager, "tracks/Ripple", 20);
59 }
60 
61 void GfxScene::ClearScene()
62 {
63  // Delete dustpools
64  for (auto itor : m_dustpools)
65  {
66  itor.second->Discard(m_scene_manager);
67  delete itor.second;
68  }
69  m_dustpools.clear();
70 
71  // Delete game elements
72  m_all_gfx_actors.clear();
73  m_all_gfx_characters.clear();
74 
75  // Wipe scene manager
76  m_scene_manager->clearScene();
77  m_gfx_freebeams_grouping_node = nullptr;
78 
79  // Recover from the wipe
82  m_gfx_freebeams_grouping_node = m_scene_manager->getRootSceneNode()->createChildSceneNode("FreeBeam Visuals");
83 }
84 
85 void GfxScene::Init()
86 {
87  ROR_ASSERT(!m_scene_manager);
88  m_scene_manager = App::GetAppContext()->GetOgreRoot()->createSceneManager();
89  m_gfx_freebeams_grouping_node = m_scene_manager->getRootSceneNode()->createChildSceneNode("FreeBeam Visuals");
90 
91  m_skidmark_conf.LoadDefaultSkidmarkDefs();
92 }
93 
94 void GfxScene::UpdateScene(float dt)
95 {
96  // NOTE: The `dt` parameter here is simulation time (0 when paused), not real time!
97  // ================================================================================
98 
99  // Actors - start threaded tasks
100  for (GfxActor* gfx_actor: m_live_gfx_actors)
101  {
102  gfx_actor->UpdateFlexbodies(); // Push flexbody tasks to threadpool
103  gfx_actor->UpdateWheelVisuals(); // Push flexwheel tasks to threadpool
104  }
105 
106  // Var
107  GfxActor* player_gfx_actor = nullptr;
108  if (m_simbuf.simbuf_player_actor != nullptr)
109  {
110  player_gfx_actor = m_simbuf.simbuf_player_actor->GetGfxActor();
111  }
112 
113  // FOV
114  if (m_simbuf.simbuf_camera_behavior != CameraManager::CAMERA_BEHAVIOR_STATIC)
115  {
116  float fov = (m_simbuf.simbuf_camera_behavior == CameraManager::CAMERA_BEHAVIOR_VEHICLE_CINECAM)
118  RoR::App::GetCameraManager()->GetCamera()->setFOVy(Ogre::Degree(fov));
119  }
120 
121  // Particles
122  if (App::gfx_particles_mode->getInt() == 1)
123  {
124  // Generate particles as needed
125  for (GfxActor* gfx_actor: m_all_gfx_actors)
126  {
127  float dt_actor = (!gfx_actor->GetSimDataBuffer().simbuf_physics_paused) ? dt : 0.f;
128  gfx_actor->UpdateParticles(dt_actor);
129  }
130 
131  // Update particle movement
132  for (auto itor : m_dustpools)
133  {
134  itor.second->update();
135  }
136  }
137 
138  // Realtime reflections on player vehicle
139  // IMPORTANT: Toggles visibility of all meshes -> must be done before any other visibility control is evaluated (i.e. aero propellers)
140  if (player_gfx_actor != nullptr)
141  {
142  // Safe to be called here, only modifies OGRE objects, doesn't read any physics state.
143  m_envmap.UpdateEnvMap(player_gfx_actor->GetSimDataBuffer().simbuf_pos, player_gfx_actor);
144  }
145 
146  // Terrain - animated meshes and paged geometry
148 
149  // Terrain - lightmap; TODO: ported as-is from Terrain::update(), is it needed? ~ only_a_ptr, 05/2018
150  App::GetGameContext()->GetTerrain()->getGeometryManager()->UpdateMainLightPosition(); // TODO: Is this necessary? I'm leaving it here just in case ~ only_a_ptr, 04/2017
151 
152  // Terrain - water
154  if (water)
155  {
156  if (player_gfx_actor != nullptr)
157  {
158  water->SetReflectionPlaneHeight(water->CalcWavesHeight(player_gfx_actor->GetSimDataBuffer().simbuf_pos));
159  }
160  else
161  {
163  }
164  water->FrameStepWater(dt);
165  }
166 
167  // Terrain - sky
168 #ifdef USE_CAELUM
169  SkyManager* sky = App::GetGameContext()->GetTerrain()->getSkyManager();
170  if (sky != nullptr)
171  {
172  sky->DetectSkyUpdate();
173  }
174 #endif
175 
177  if (skyx_man != nullptr)
178  {
179  skyx_man->update(dt); // Light update
180  }
181 
182  // GUI - race
183  if (m_simbuf.simbuf_race_in_progress != m_simbuf.simbuf_race_in_progress_prev)
184  {
185  if (m_simbuf.simbuf_race_in_progress) // Started
186  {
188  }
189  else // Ended
190  {
192  }
193  }
194  if (m_simbuf.simbuf_race_in_progress)
195  {
197  }
198 
199  // GUI - vehicle pressure
200  if (m_simbuf.simbuf_player_actor)
201  {
202  App::GetOverlayWrapper()->UpdatePressureOverlay(m_simbuf.simbuf_player_actor->GetGfxActor());
203  }
204 
205  // HUD - network labels (always update)
206  for (GfxActor* gfx_actor: m_all_gfx_actors)
207  {
208  gfx_actor->UpdateNetLabels(dt);
209  }
210 
211  // Player avatars
212  for (GfxCharacter* a: m_all_gfx_characters)
213  {
214  a->UpdateCharacterInScene();
215  }
216 
217  // Actors - update misc visuals
218  for (GfxActor* gfx_actor: m_all_gfx_actors)
219  {
220  float dt_actor = (!gfx_actor->GetSimDataBuffer().simbuf_physics_paused) ? dt : 0.f;
221  if (gfx_actor->IsActorLive())
222  {
223  gfx_actor->UpdateRods();
224  gfx_actor->UpdateCabMesh();
225  gfx_actor->UpdateWingMeshes();
226  gfx_actor->UpdateAirbrakes();
227  gfx_actor->UpdateCParticles();
228  gfx_actor->UpdateExhausts();
229  gfx_actor->UpdateAeroEngines();
230  gfx_actor->UpdatePropAnimations(dt_actor);
231  gfx_actor->UpdateRenderdashRTT();
232  }
233  // Beacon flares must always be updated
234  gfx_actor->UpdateProps(dt_actor, (gfx_actor == player_gfx_actor));
235  // Blinkers (turn signals) must always be updated
236  gfx_actor->UpdateFlares(dt_actor, (gfx_actor == player_gfx_actor));
237  }
238  if (player_gfx_actor != nullptr)
239  {
240  float dt_actor = (!player_gfx_actor->GetSimDataBuffer().simbuf_physics_paused) ? dt : 0.f;
241  player_gfx_actor->UpdateVideoCameras(dt_actor);
242 
243  // The old-style render-to-texture dashboard (based on OGRE overlays)
244  if (m_simbuf.simbuf_player_actor->ar_driveable == TRUCK && m_simbuf.simbuf_player_actor->ar_engine != nullptr)
245  {
247  }
248  else if (m_simbuf.simbuf_player_actor->ar_driveable == AIRPLANE)
249  {
250  RoR::App::GetOverlayWrapper()->UpdateAerialHUD(player_gfx_actor);
251  }
252  }
253 
254  App::GetGuiManager()->DrawSimGuiBuffered(player_gfx_actor);
255 
257 
258  this->UpdateFreeBeamGfx(dt);
259 
260  // Actors - finalize threaded tasks
261  for (GfxActor* gfx_actor: m_live_gfx_actors)
262  {
263  gfx_actor->FinishWheelUpdates();
264  gfx_actor->FinishFlexbodyTasks();
265  }
266 }
267 
268 void GfxScene::SetParticlesVisible(bool visible)
269 {
270  for (auto itor : m_dustpools)
271  {
272  itor.second->setVisible(visible);
273  }
274 }
275 
276 DustPool* GfxScene::GetDustPool(const char* name)
277 {
278  auto found = m_dustpools.find(name);
279  if (found != m_dustpools.end())
280  {
281  return found->second;
282  }
283  else
284  {
285  return nullptr;
286  }
287 }
288 
289 void GfxScene::RegisterGfxActor(RoR::GfxActor* gfx_actor)
290 {
291  m_all_gfx_actors.push_back(gfx_actor);
292 }
293 
294 void GfxScene::BufferSimulationData()
295 {
296  m_simbuf.simbuf_player_actor = App::GetGameContext()->GetPlayerActor();
297  m_simbuf.simbuf_character_pos = App::GetGameContext()->GetPlayerCharacter()->getPosition();
298  m_simbuf.simbuf_sim_paused = App::GetGameContext()->GetActorManager()->IsSimulationPaused();
299  m_simbuf.simbuf_sim_speed = App::GetGameContext()->GetActorManager()->GetSimulationSpeed();
300  m_simbuf.simbuf_camera_behavior = App::GetCameraManager()->GetCurrentBehavior();
301 
302  // Race system
303  m_simbuf.simbuf_race_time = App::GetGameContext()->GetRaceSystem().GetRaceTime();
304  m_simbuf.simbuf_race_best_time = App::GetGameContext()->GetRaceSystem().GetRaceBestTime();
305  m_simbuf.simbuf_race_time_diff = App::GetGameContext()->GetRaceSystem().GetRaceTimeDiff();
306  m_simbuf.simbuf_race_in_progress_prev = m_simbuf.simbuf_race_in_progress;
307  m_simbuf.simbuf_race_in_progress = App::GetGameContext()->GetRaceSystem().IsRaceInProgress();
308  m_simbuf.simbuf_dir_arrow_target = App::GetGameContext()->GetRaceSystem().GetDirArrowTarget();
309  m_simbuf.simbuf_dir_arrow_text = App::GetGameContext()->GetRaceSystem().GetDirArrowText();
310  m_simbuf.simbuf_dir_arrow_visible = App::GetGameContext()->GetRaceSystem().IsDirArrowVisible();
311 
312  m_live_gfx_actors.clear();
313  for (GfxActor* a: m_all_gfx_actors)
314  {
315  if (a->IsActorLive() || !a->IsActorInitialized())
316  {
317  a->UpdateSimDataBuffer();
318  m_live_gfx_actors.push_back(a);
319  a->InitializeActor();
320  }
321  }
322 
323  for (GfxCharacter* a: m_all_gfx_characters)
324  {
325  a->BufferSimulationData();
326  }
327 }
328 
329 void GfxScene::RemoveGfxActor(RoR::GfxActor* remove_me)
330 {
331  auto itor = std::remove(m_all_gfx_actors.begin(), m_all_gfx_actors.end(), remove_me);
332  if (itor != m_all_gfx_actors.end())
333  {
334  m_all_gfx_actors.erase(itor, m_all_gfx_actors.end());
335  }
336 }
337 
338 void GfxScene::ForceUpdateSingleGfxActor(RoR::GfxActor* gfx_actor)
339 {
340  // Do the work `UpdateScene()` would, but for a single actor.
341  // Needed for i.e. terrain editor mode.
342  // ------------------------------------------------------
343 
344  // Start threaded stuff
345  gfx_actor->UpdateFlexbodies(); // Push flexbody tasks to threadpool
346  gfx_actor->UpdateWheelVisuals(); // Push flexwheel tasks to threadpool
347 
348  // Do sync stuff
349  gfx_actor->UpdateRods();
350  gfx_actor->UpdateCabMesh();
351  gfx_actor->UpdateWingMeshes();
352  gfx_actor->UpdateAirbrakes();
353 
354  // Finish threaded stuff
355  gfx_actor->FinishWheelUpdates();
356  gfx_actor->FinishFlexbodyTasks();
357 }
358 
359 void GfxScene::RegisterGfxCharacter(RoR::GfxCharacter* gfx_character)
360 {
361  m_all_gfx_characters.push_back(gfx_character);
362 }
363 
364 void GfxScene::RemoveGfxCharacter(RoR::GfxCharacter* remove_me)
365 {
366  auto itor = std::remove(m_all_gfx_characters.begin(), m_all_gfx_characters.end(), remove_me);
367  if (itor != m_all_gfx_characters.end())
368  {
369  m_all_gfx_characters.erase(itor, m_all_gfx_characters.end());
370  }
371 }
372 
373 void GfxScene::DrawNetLabel(Ogre::Vector3 scene_pos, float cam_dist, std::string const& nick, int colornum)
374 {
375 #if USE_SOCKETW
376 
377  // this ensures that the nickname is always in a readable size
378  float font_size = std::max(0.6, cam_dist / 40.0);
379  std::string caption;
380  if (cam_dist > 1000) // 1000 ... vlen
381  {
382  caption =
383  nick + " (" + TOSTRING((float)(ceil(cam_dist / 100) / 10.0) ) + " km)";
384  }
385  else if (cam_dist > 20) // 20 ... vlen ... 1000
386  {
387  caption =
388  nick + " (" + TOSTRING((int)cam_dist) + " m)";
389  }
390  else // 0 ... vlen ... 20
391  {
392  caption = nick;
393  }
394 
395  // draw with DearIMGUI
396 
397  ImVec2 screen_size = ImGui::GetIO().DisplaySize;
398  World2ScreenConverter world2screen(
399  App::GetCameraManager()->GetCamera()->getViewMatrix(true), App::GetCameraManager()->GetCamera()->getProjectionMatrix(), Ogre::Vector2(screen_size.x, screen_size.y));
400 
401  Ogre::Vector3 pos_xyz = world2screen.Convert(scene_pos);
402 
403  // only draw when in front of camera
404  if (pos_xyz.z < 0.f)
405  {
406  // Align position to whole pixels, to minimize jitter.
407  ImVec2 pos((int)pos_xyz.x+0.5, (int)pos_xyz.y+0.5);
408 
409  ImVec2 text_size = ImGui::CalcTextSize(caption.c_str());
411 
412  ImDrawList* drawlist = GetImDummyFullscreenWindow();
413  ImGuiContext* g = ImGui::GetCurrentContext();
414 
415  ImVec2 text_pos(pos.x - ((text_size.x / 2)), pos.y - ((text_size.y / 2)));
416 
417  // Draw background rectangle
418  const float PADDING = 4.f;
419  drawlist->AddRectFilled(
420  text_pos - ImVec2(PADDING, PADDING),
421  text_pos + text_size + ImVec2(PADDING, PADDING),
422  ImColor(theme.semitransparent_window_bg),
423  ImGui::GetStyle().WindowRounding);
424 
425  // draw colored text
426  Ogre::ColourValue color = App::GetNetwork()->GetPlayerColor(colornum);
427  ImVec4 text_color(color.r, color.g, color.b, 1.f);
428  drawlist->AddText(g->Font, g->FontSize, text_pos, ImColor(text_color), caption.c_str());
429  }
430 
431 #endif // USE_SOCKETW
432 }
433 
434 void GfxScene::AdjustParticleSystemTimeFactor(Ogre::ParticleSystem* psys)
435 {
436  float speed_factor = 0.f;
437  if (App::sim_state->getEnum<SimState>() == SimState::RUNNING && !App::GetGameContext()->GetActorManager()->IsSimulationPaused())
438  {
439  speed_factor = m_simbuf.simbuf_sim_speed;
440  }
441 
442  psys->setSpeedFactor(speed_factor);
443 }
444 
445 void GfxScene::AddFreeBeamGfx(FreeBeamGfxRequest* rq)
446 {
447  auto itor = std::find_if(m_gfx_freebeams.begin(), m_gfx_freebeams.end(),
448  [rq](const FreeBeamGfx& obj) { return obj.fbx_id == rq->fbr_id; });
449  if (itor != m_gfx_freebeams.end())
450  {
451  App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_WARNING,
452  fmt::format("FreeBeamGfx with ID %d already exists, ignoring request.",rq->fbr_id));
453  return;
454  }
455 
456  FreeBeamGfx obj;
457  obj.fbx_id = rq->fbr_id;
460  obj.fbx_diameter = rq->fbr_diameter;
461 
462  Ogre::Entity* e = m_scene_manager->createEntity(fmt::format("FreeBeamGfx_{}", rq->fbr_id), rq->fbr_mesh_name);
463  e->setMaterialName(rq->fbr_material_name);
464 
465  obj.fbx_scenenode = m_gfx_freebeams_grouping_node->createChildSceneNode(fmt::format("FreeBeamGfx_{}", rq->fbr_id));
466  obj.fbx_scenenode->setScale(rq->fbr_diameter, -1, rq->fbr_diameter);
467  obj.fbx_scenenode->attachObject(e);
468 
469  m_gfx_freebeams.push_back(obj);
470 }
471 
472 void GfxScene::ModifyFreeBeamGfx(FreeBeamGfxRequest* rq)
473 {
474  auto itor = std::find_if(m_gfx_freebeams.begin(), m_gfx_freebeams.end(),
475  [rq](const FreeBeamGfx& obj) { return obj.fbx_id == rq->fbr_id; });
476  if (itor == m_gfx_freebeams.end())
477  {
478  App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_WARNING,
479  fmt::format("FreeBeamGfx with ID %d not found, ignoring request.", rq->fbr_id));
480  return;
481  }
482 
483  FreeBeamGfx& obj = *itor;
484  this->RemoveFreeBeamGfx(rq->fbr_id);
485  this->AddFreeBeamGfx(rq);
486 }
487 
488 void GfxScene::RemoveFreeBeamGfx(FreeBeamGfxID_t id)
489 {
490  auto itor = std::find_if(m_gfx_freebeams.begin(), m_gfx_freebeams.end(),
491  [id](const FreeBeamGfx& obj) { return obj.fbx_id == id; });
492  if (itor == m_gfx_freebeams.end())
493  {
494  App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_WARNING,
495  fmt::format("FreeBeamGfx with ID %d not found, ignoring request.", id));
496  return;
497  }
498 
499  FreeBeamGfx& obj = *itor;
500  m_scene_manager->destroyEntity((Ogre::Entity*)obj.fbx_scenenode->getAttachedObject(0));
501  m_gfx_freebeams_grouping_node->removeChild(obj.fbx_scenenode);
502  m_gfx_freebeams.erase(itor);
503 }
504 
505 void GfxScene::UpdateFreeBeamGfx(float dt)
506 {
507  for (FreeBeamGfx& freebeam : m_gfx_freebeams)
508  {
509  // Sanity checks - primary freeforce
510  ROR_ASSERT(freebeam.fbx_id != FREEBEAMGFXID_INVALID);
511  ROR_ASSERT(freebeam.fbx_freeforce_primary != FREEFORCEID_INVALID);
512  ActorManager::FreeForceVec_t::iterator itor;
513  const bool exists = App::GetGameContext()->GetActorManager()->FindFreeForce(freebeam.fbx_freeforce_primary, itor);
514  ROR_ASSERT(exists);
515  if (!exists)
516  {
517  continue;
518  }
519  FreeForce& freeforce = *itor;
520 
521  // Sanity checks - base actor
522  ROR_ASSERT(freeforce.ffc_base_actor);
523  ROR_ASSERT(freeforce.ffc_base_actor->ar_state != ActorState::DISPOSED);
524  GfxActor* gfx_actor_base = freeforce.ffc_base_actor->GetGfxActor();
525  ROR_ASSERT(gfx_actor_base);
527  ROR_ASSERT(freeforce.ffc_base_node < freeforce.ffc_base_actor->ar_num_nodes);
528 
529  // Sanity checks - target actor
530  ROR_ASSERT(freeforce.ffc_target_actor);
531  ROR_ASSERT(freeforce.ffc_target_actor->ar_state != ActorState::DISPOSED);
532  GfxActor* gfx_actor_target = freeforce.ffc_target_actor->GetGfxActor();
533  ROR_ASSERT(gfx_actor_target);
536 
537  // Get node positions
538  Ogre::Vector3 basenode_pos = gfx_actor_base->GetSimNodeBuffer()[freeforce.ffc_base_node].AbsPosition;
539  Ogre::Vector3 targetnode_pos = gfx_actor_target->GetSimNodeBuffer()[freeforce.ffc_target_node].AbsPosition;
540 
541  // Do the transforms
542  freebeam.fbx_scenenode->setPosition(basenode_pos.midPoint(targetnode_pos));
543  freebeam.fbx_scenenode->setOrientation(GfxScene::SpecialGetRotationTo(Ogre::Vector3::UNIT_Y, (basenode_pos - targetnode_pos)));
544  freebeam.fbx_scenenode->setScale(freebeam.fbx_diameter, basenode_pos.distance(targetnode_pos), freebeam.fbx_diameter);
545  }
546 }
547 
548 void GfxScene::OnFreeForceRemoved(FreeForceID_t id)
549 {
550  auto itor_secondary = std::find_if(m_gfx_freebeams.begin(), m_gfx_freebeams.end(),
551  [id](const FreeBeamGfx& obj) { return obj.fbx_freeforce_secondary == id; });
552  if (itor_secondary != m_gfx_freebeams.end())
553  {
554  // Just clear the freeforce ID
555  itor_secondary->fbx_freeforce_secondary = FREEFORCEID_INVALID;
556  }
557  else
558  {
559  auto itor_primary = std::find_if(m_gfx_freebeams.begin(), m_gfx_freebeams.end(),
560  [id](const FreeBeamGfx& obj) { return obj.fbx_freeforce_primary == id; });
561  if (itor_primary != m_gfx_freebeams.end())
562  {
563  // Remove the whole freebeam
564  this->RemoveFreeBeamGfx(itor_primary->fbx_id);
565  }
566  }
567 }
568 
569 void GfxScene::OnFreeForceBroken(FreeForceID_t id)
570 {
571  auto itor = std::find_if(m_gfx_freebeams.begin(), m_gfx_freebeams.end(),
572  [id](const FreeBeamGfx& obj) { return obj.fbx_freeforce_primary == id || obj.fbx_freeforce_secondary == id; });
573  if (itor != m_gfx_freebeams.end())
574  {
575  // Remove the whole freebeam if either freeforce broke
576  this->RemoveFreeBeamGfx(itor->fbx_id);
577  }
578 }
579 
580 Ogre::Quaternion RoR::GfxScene::SpecialGetRotationTo(const Ogre::Vector3& src, const Ogre::Vector3& dest)
581 {
582  // Based on Stan Melax's article in Game Programming Gems
583  Ogre::Quaternion q;
584  // Copy, since cannot modify local
585  Ogre::Vector3 v0 = src;
586  Ogre::Vector3 v1 = dest;
587  v0.normalise();
588  v1.normalise();
589 
590  // NB if the crossProduct approaches zero, we get unstable because ANY axis will do
591  // when v0 == -v1
592  Ogre::Real d = v0.dotProduct(v1);
593  // If dot == 1, vectors are the same
594  if (d >= 1.0f)
595  {
596  return Ogre::Quaternion::IDENTITY;
597  }
598  if (d < (1e-6f - 1.0f))
599  {
600  // Generate an axis
601  Ogre::Vector3 axis = Ogre::Vector3::UNIT_X.crossProduct(src);
602  if (axis.isZeroLength()) // pick another if colinear
603  axis = Ogre::Vector3::UNIT_Y.crossProduct(src);
604  axis.normalise();
605  q.FromAngleAxis(Ogre::Radian(Ogre::Math::PI), axis);
606  }
607  else
608  {
609  Ogre::Real s = fast_sqrt((1 + d) * 2);
610  if (s == 0)
611  return Ogre::Quaternion::IDENTITY;
612 
613  Ogre::Vector3 c = v0.crossProduct(v1);
614  Ogre::Real invs = 1 / s;
615 
616  q.x = c.x * invs;
617  q.y = c.y * invs;
618  q.z = c.z * invs;
619  q.w = s * 0.5;
620  }
621  return q;
622 }
ROR_ASSERT
#define ROR_ASSERT(_EXPR)
Definition: Application.h:40
GameContext.h
Game state manager and message-queue provider.
RoR::IWater::GetStaticWaterHeight
virtual float GetStaticWaterHeight()=0
Returns static water level configured in 'terrn2'.
RoR::App::GetNetwork
Network * GetNetwork()
Definition: Application.cpp:300
RoR::ActorManager::GetSimulationSpeed
float GetSimulationSpeed() const
Definition: ActorManager.h:93
RoR::IWater::CalcWavesHeight
virtual float CalcWavesHeight(Ogre::Vector3 pos)=0
RoR::GfxActor::UpdateAirbrakes
void UpdateAirbrakes()
Definition: GfxActor.cpp:1967
SkyXManager.h
RoR::IWater::SetReflectionPlaneHeight
virtual void SetReflectionPlaneHeight(float)
Definition: IWater.h:53
RoR::App::gfx_fov_internal
CVar * gfx_fov_internal
Definition: Application.cpp:252
OverlayWrapper.h
RoR::FreeForce::ffc_target_node
NodeNum_t ffc_target_node
Definition: SimData.h:766
RoR::FreeBeamGfxRequest::fbr_mesh_name
std::string fbr_mesh_name
Definition: GfxData.h:293
RoR::GUI::DirectionArrow::CreateArrow
void CreateArrow()
Must be called again after OGRE scenemanager is cleared.
Definition: GUI_DirectionArrow.cpp:50
RoR::TRUCK
@ TRUCK
its a truck (or other land vehicle)
Definition: SimData.h:85
RoR::DustPool
Definition: DustPool.h:33
RoR::GUIManager::GuiTheme
Definition: GUIManager.h:79
RoR::App::GetCameraManager
CameraManager * GetCameraManager()
Definition: Application.cpp:291
RoR::App::GetGuiManager
GUIManager * GetGuiManager()
Definition: Application.cpp:285
RoR::FreeBeamGfxID_t
int FreeBeamGfxID_t
Index into GfxScene::m_gfx_freebeams, use RoR::FREEBEAMGFXID_INVALID as empty value.
Definition: ForwardDeclarations.h:93
RoR::IWater::FrameStepWater
virtual void FrameStepWater(float dt)=0
RoR::GfxActor::GetSimNodeBuffer
NodeSB * GetSimNodeBuffer()
Definition: GfxActor.h:129
RoR::Actor::ar_num_nodes
int ar_num_nodes
Definition: Actor.h:317
SkyManager.h
RoR::App::GetAppContext
AppContext * GetAppContext()
Definition: Application.cpp:282
RoR::NODENUM_INVALID
static const NodeNum_t NODENUM_INVALID
Definition: ForwardDeclarations.h:55
RoR::GfxActor::UpdateRods
void UpdateRods()
Definition: GfxActor.cpp:1647
format
Truck file format(technical spec)
GUIUtils.h
RoR::Terrain::getObjectManager
TerrainObjectManager * getObjectManager()
Definition: Terrain.h:79
RoR::FreeBeamGfx::fbx_freeforce_primary
FreeForceID_t fbx_freeforce_primary
Required.
Definition: GfxData.h:274
RoR::Terrain::getSkyManager
SkyManager * getSkyManager()
Definition: Terrain.cpp:515
RoR::RaceSystem::GetDirArrowText
std::string const & GetDirArrowText() const
Definition: RaceSystem.h:49
TerrainGeometryManager.h
RoR::FreeBeamGfxRequest::fbr_material_name
std::string fbr_material_name
Definition: GfxData.h:294
RoR::GameContext::GetPlayerCharacter
Character * GetPlayerCharacter()
Definition: GameContext.cpp:897
RoR::App::gfx_particles_mode
CVar * gfx_particles_mode
Definition: Application.cpp:239
RoR::IWater
< TODO: Mixed gfx+physics (waves) - must be separated ~ only_a_ptr, 02/2018
Definition: IWater.h:32
RoR::FREEBEAMGFXID_INVALID
static const FreeBeamGfxID_t FREEBEAMGFXID_INVALID
Definition: ForwardDeclarations.h:94
RoR::App::GetOverlayWrapper
OverlayWrapper * GetOverlayWrapper()
Definition: Application.cpp:284
RoR::OverlayWrapper::UpdateAerialHUD
void UpdateAerialHUD(RoR::GfxActor *ga)
Definition: OverlayWrapper.cpp:760
RoR::OverlayWrapper::UpdateRacingGui
void UpdateRacingGui(RoR::GfxScene *gs)
Definition: OverlayWrapper.cpp:982
AppContext.h
System integration layer; inspired by OgreBites::ApplicationContext.
Console.h
RoR::Console::putMessage
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition: Console.cpp:103
GUI_DirectionArrow.h
Race direction arrow and text info (using OGRE Overlay)
RoR::GfxActor::UpdateCabMesh
void UpdateCabMesh()
Definition: GfxActor.cpp:1907
RoR::FreeBeamGfxRequest
Used by MSG_EDI_[ADD/MODIFY]_FREEBEAMGFX_REQUESTED; tailored for use with AngelScript thru GameScript...
Definition: GfxData.h:284
RoR::GfxActor::FinishFlexbodyTasks
void FinishFlexbodyTasks()
Definition: GfxActor.cpp:3186
RoR::FreeForce::ffc_target_actor
ActorPtr ffc_target_actor
Definition: SimData.h:765
RoR::Actor::GetGfxActor
GfxActor * GetGfxActor()
Definition: Actor.h:281
RoR::RaceSystem::IsDirArrowVisible
bool IsDirArrowVisible() const
Definition: RaceSystem.h:50
RoR::App::sim_state
CVar * sim_state
Definition: Application.cpp:96
Utils.h
RoR::RaceSystem::GetRaceTime
float GetRaceTime() const
Definition: RaceSystem.cpp:59
RoR::GUIManager::GuiTheme::semitransparent_window_bg
ImVec4 semitransparent_window_bg
Definition: GUIManager.h:92
TerrainObjectManager.h
RoR::World2ScreenConverter::Convert
Ogre::Vector3 Convert(Ogre::Vector3 world_pos)
Definition: Utils.h:90
RoR::GUIManager::DirectionArrow
GUI::DirectionArrow DirectionArrow
Definition: GUIManager.h:136
RoR::FreeForce::ffc_base_node
NodeNum_t ffc_base_node
Definition: SimData.h:761
RoR::FreeBeamGfxRequest::fbr_diameter
double fbr_diameter
meters
Definition: GfxData.h:295
GUIManager.h
ActorManager.h
Actor.h
RoR::FreeBeamGfx
Visuals of a 'freebeam' (a pair of HALFBEAM_ freeforces)
Definition: GfxData.h:270
RoR::GameContext::GetRaceSystem
RaceSystem & GetRaceSystem()
Definition: GameContext.h:169
RoR::RaceSystem::GetRaceTimeDiff
float GetRaceTimeDiff() const
Definition: RaceSystem.h:42
RoR::OverlayWrapper::UpdatePressureOverlay
void UpdatePressureOverlay(RoR::GfxActor *ga)
Definition: OverlayWrapper.cpp:665
RoR::GfxActor::FinishWheelUpdates
void FinishWheelUpdates()
Definition: GfxActor.cpp:1933
RoR::GetImDummyFullscreenWindow
ImDrawList * GetImDummyFullscreenWindow(const std::string &name="RoR_TransparentFullscreenWindow")
Definition: GUIUtils.cpp:358
RoR::OverlayWrapper::UpdateLandVehicleHUD
void UpdateLandVehicleHUD(RoR::GfxActor *ga)
Definition: OverlayWrapper.cpp:680
RoR::CameraManager::GetCurrentBehavior
CameraBehaviors GetCurrentBehavior() const
Definition: CameraManager.h:62
RoR::GUIManager::GetTheme
GuiTheme & GetTheme()
Definition: GUIManager.h:168
TOSTRING
#define TOSTRING(x)
Definition: Application.h:56
RoR::FREEFORCEID_INVALID
static const FreeForceID_t FREEFORCEID_INVALID
Definition: ForwardDeclarations.h:68
RoR::CameraManager::GetCamera
Ogre::Camera * GetCamera()
Definition: CameraManager.h:64
RoR::FreeBeamGfx::fbx_scenenode
Ogre::SceneNode * fbx_scenenode
Definition: GfxData.h:278
RoR::GameContext::GetSceneMouse
SceneMouse & GetSceneMouse()
Definition: GameContext.h:171
RoR::CameraManager::ReCreateCameraNode
void ReCreateCameraNode()
Needed since we call Ogre::SceneManager::ClearScene() after end of sim. session.
Definition: CameraManager.cpp:142
RoR::World2ScreenConverter
< Keeps data close for faster access.
Definition: Utils.h:82
RoR::GfxCharacter
Definition: Character.h:98
RoR::Terrain::getGeometryManager
TerrainGeometryManager * getGeometryManager()
Definition: Terrain.h:78
RoR::GUIManager::DrawSimGuiBuffered
void DrawSimGuiBuffered(GfxActor *player_gfx_actor)
Reads data from simbuffer.
Definition: GUIManager.cpp:187
RoR::FreeForceID_t
int FreeForceID_t
Unique sequentially generated ID of FreeForce; use ActorManager::GetFreeForceNextId().
Definition: ForwardDeclarations.h:67
RoR::TerrainGeometryManager::UpdateMainLightPosition
void UpdateMainLightPosition()
Definition: TerrainGeometryManager.cpp:407
RoR::FreeBeamGfx::fbx_diameter
float fbx_diameter
meters
Definition: GfxData.h:279
RoR::SceneMouse::UpdateVisuals
void UpdateVisuals()
Definition: SceneMouse.cpp:212
GfxScene.h
RoR::GfxScene::SpecialGetRotationTo
static Ogre::Quaternion SpecialGetRotationTo(const Ogre::Vector3 &src, const Ogre::Vector3 &dest)
Definition: GfxScene.cpp:580
RoR::FreeBeamGfxRequest::fbr_freeforce_primary
int64_t fbr_freeforce_primary
Required.
Definition: GfxData.h:290
RoR::App::GetConsole
Console * GetConsole()
Definition: Application.cpp:286
RoR::FreeForce::ffc_base_actor
ActorPtr ffc_base_actor
Definition: SimData.h:760
RoR::App::GetGameContext
GameContext * GetGameContext()
Definition: Application.cpp:296
RoR::GfxActor::UpdateVideoCameras
void UpdateVideoCameras(float dt)
Definition: GfxActor.cpp:470
RoR::Character::getPosition
Ogre::Vector3 getPosition()
Definition: Character.cpp:92
RoR::AIRPLANE
@ AIRPLANE
its an airplane
Definition: SimData.h:86
RoR::RaceSystem::GetDirArrowTarget
Ogre::Vector3 GetDirArrowTarget()
Definition: RaceSystem.h:48
RoR::FreeForce
Global force affecting particular (base) node of particular (base) actor; added ad-hoc by scripts.
Definition: SimData.h:754
RoR::ActorSB::simbuf_pos
Ogre::Vector3 simbuf_pos
Definition: SimBuffers.h:123
ApproxMath.h
RoR::RaceSystem::GetRaceBestTime
float GetRaceBestTime() const
Definition: RaceSystem.h:45
DustPool.h
RoR::ActorSB::simbuf_physics_paused
bool simbuf_physics_paused
Definition: SimBuffers.h:116
RoR::Network::GetPlayerColor
Ogre::ColourValue GetPlayerColor(int color_num)
Definition: Network.cpp:94
RoR::NodeSB::AbsPosition
Ogre::Vector3 AbsPosition
Definition: SimBuffers.h:69
RoR::SkyXManager::update
bool update(float dt)
Definition: SkyXManager.cpp:77
RoR::FreeBeamGfxRequest::fbr_id
int64_t fbr_id
ID of the freebeam gfx, use GfxScene::GetFreeBeamGfxNextId()
Definition: GfxData.h:288
RoR::TerrainObjectManager::UpdateTerrainObjects
bool UpdateTerrainObjects(float dt)
Definition: TerrainObjectManager.cpp:1096
RoR::Terrain::getSkyXManager
SkyXManager * getSkyXManager()
Definition: Terrain.h:82
RoR::GfxActor::UpdateWingMeshes
void UpdateWingMeshes()
Definition: GfxActor.cpp:3359
RoR::App::gfx_fov_external
CVar * gfx_fov_external
Definition: Application.cpp:250
RoR::AppContext::GetOgreRoot
Ogre::Root * GetOgreRoot()
Definition: AppContext.h:65
Terrain.h
RoR::GfxActor
Definition: GfxActor.h:52
RoR::FreeBeamGfx::fbx_freeforce_secondary
FreeForceID_t fbx_freeforce_secondary
Not required for fixed-end beams.
Definition: GfxData.h:275
RoR::CVar::getFloat
float getFloat() const
Definition: CVar.h:96
Ogre
Definition: ExtinguishableFireAffector.cpp:35
RoR::OverlayWrapper::HideRacingOverlay
void HideRacingOverlay()
Definition: OverlayWrapper.cpp:977
RoR::ActorManager::FindFreeForce
bool FindFreeForce(FreeForceID_t id, FreeForceVec_t::iterator &out_itor)
Definition: ActorManager.cpp:1761
fast_sqrt
float fast_sqrt(const float x)
Definition: ApproxMath.h:135
RoR::RaceSystem::IsRaceInProgress
bool IsRaceInProgress() const
Definition: RaceSystem.h:36
RoR::ActorManager::IsSimulationPaused
bool IsSimulationPaused() const
Definition: ActorManager.h:94
RoR::Actor::ar_state
ActorState ar_state
Definition: Actor.h:488
RoR::GfxActor::UpdateFlexbodies
void UpdateFlexbodies()
Definition: GfxActor.cpp:3147
RoR::GfxActor::UpdateWheelVisuals
void UpdateWheelVisuals()
Definition: GfxActor.cpp:1915
RoR::GameContext::GetPlayerActor
const ActorPtr & GetPlayerActor()
Definition: GameContext.h:134
RoR::OverlayWrapper::ShowRacingOverlay
void ShowRacingOverlay()
Definition: OverlayWrapper.cpp:972
RoR::GfxActor::GetSimDataBuffer
ActorSB & GetSimDataBuffer()
Definition: GfxActor.h:128
RoR
Definition: AppContext.h:36
RoR::GameContext::GetActorManager
ActorManager * GetActorManager()
Definition: GameContext.h:127
RoR::Terrain::getWater
IWater * getWater()
Definition: Terrain.h:86
HydraxWater.h
RoR::SkyXManager
Definition: SkyXManager.h:32
RoR::FreeBeamGfxRequest::fbr_freeforce_secondary
int64_t fbr_freeforce_secondary
Not required for fixed-end beams.
Definition: GfxData.h:291
RoR::FreeBeamGfx::fbx_id
FreeBeamGfxID_t fbx_id
ID of the freebeam gfx, use GfxScene::GetFreeBeamGfxNextId()
Definition: GfxData.h:272
RoR::GameContext::GetTerrain
const TerrainPtr & GetTerrain()
Definition: GameContext.h:117