Rigs of Rods 2026.01
Soft-body Physics Simulation
Loading...
Searching...
No Matches
TurboJet.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 2017-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 "TurboJet.h"
23
24#include <Ogre.h>
25
26#include "Application.h"
27#include "Actor.h"
28#include "SimData.h"
29#include "GfxActor.h"
30#include "GfxScene.h"
31#include "SoundScriptManager.h"
32
33using namespace Ogre;
34using namespace RoR;
35
36Turbojet::Turbojet(ActorPtr actor, NodeNum_t tnodefront, NodeNum_t tnodeback, NodeNum_t tnoderef, RigDef::Turbojet & def)
37{
38 m_actor = actor;
39#ifdef USE_OPENAL
40 switch (actor->ar_num_aeroengines)
41 {
51 }
52#endif
53 m_node_back = tnodeback;
54 m_node_front = tnodefront;
55 m_node_ref = tnoderef;
56 tjet_afterburnable = (def.wet_thrust > 0.f);
57 m_reversable = def.is_reversable != 0;
61 m_timer = 0;
62 m_warmup_time = 15.0;
63 m_last_flip = 0;
64 m_radius = def.back_diameter / 2.f;
65 m_area = 2 * 3.14159 * m_radius * 0.6 * m_radius * 0.6;
68 m_reflen = m_axis.length();
70 reset();
71}
72
73void TurbojetVisual::SetupVisuals(RigDef::Turbojet & def, int num, std::string const& propname, Ogre::Entity* nozzle, Ogre::Entity* afterburner_flame)
74{
75 m_radius = def.back_diameter / 2.0;
76 m_number = num;
77
78 m_nozzle_entity = nozzle;
79 m_nozzle_scenenode = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode();
82
83 if (afterburner_flame != nullptr)
84 {
85 m_flame_entity = afterburner_flame;
86 m_flame_scenenode = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode();
87 m_flame_scenenode->attachObject(m_flame_entity);
88 m_flame_scenenode->setScale(1.0, def.back_diameter, def.back_diameter);
89 m_flame_scenenode->setVisible(false);
90 }
91
92 //smoke visual
93 m_smoke_scenenode = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode();
94 m_smoke_particle = App::GetGfxScene()->GetSceneManager()->createParticleSystem("SmokeParticle-"+propname, "tracks/TurbopropSmoke");
96 {
97 m_smoke_particle->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap
99 m_smoke_particle->setCastShadows(false);
100 }
101
102}
103
105{
106 ROR_ASSERT(front != NODENUM_INVALID);
108
109 m_node_front = front;
110 m_node_back = back;
111 m_node_ref = ref;
112}
113
123
125{
126 if (m_flame_entity != nullptr)
127 {
128 m_flame_entity->setVisible(false);
129 }
130
131 if (m_nozzle_entity != nullptr)
132 {
133 m_nozzle_entity->setVisible(false);
134 }
135
136 if (m_smoke_particle != nullptr)
137 {
138 m_smoke_particle->removeAllEmitters();
139 }
140}
141
143{
144 if (this->tjet_visual.IsVisible())
145 this->tjet_visual.UpdateVisuals(gfx_actor);
146}
147
148void Turbojet::setVisible(bool visible)
149{
150 this->tjet_visual.SetVisible(visible);
151}
152
154{
155 RoR::NodeSB* node_buf = gfx_actor->GetSimNodeBuffer();
156 RoR::AeroEngineSB& ae_buf
158
159 //nozzle
160 m_nozzle_scenenode->setPosition(node_buf[m_node_back].AbsPosition);
161 //build a local system
162 Vector3 laxis = node_buf[m_node_front].AbsPosition - node_buf[m_node_back].AbsPosition;
163 laxis.normalise();
164 Vector3 paxis = Plane(laxis, 0).projectVector(node_buf[m_node_ref].AbsPosition - node_buf[m_node_back].AbsPosition);
165 paxis.normalise();
166 Vector3 taxis = laxis.crossProduct(paxis);
167 Quaternion dir = Quaternion(laxis, paxis, taxis);
168 m_nozzle_scenenode->setOrientation(dir);
169 //afterburner
170 if (ae_buf.simbuf_tj_afterburn)
171 {
172 m_flame_scenenode->setVisible(true);
173 float flamelength = (ae_buf.simbuf_tj_ab_thrust / 15.0) * (ae_buf.simbuf_ae_rpmpc / 100.0);
174 flamelength = flamelength * (1.0 + (((Real)rand() / (Real)RAND_MAX) - 0.5) / 10.0);
175 m_flame_scenenode->setScale(flamelength, m_radius * 2.0, m_radius * 2.0);
176 m_flame_scenenode->setPosition(node_buf[m_node_back].AbsPosition + dir * Vector3(-0.2, 0.0, 0.0));
177 m_flame_scenenode->setOrientation(dir);
178 }
179 else
180 m_flame_scenenode->setVisible(false);
181
182 //smoke
183 if (m_smoke_particle &&
185 {
187 m_smoke_scenenode->setPosition(node_buf[m_node_back].AbsPosition);
188 ParticleEmitter* emit = m_smoke_particle->getEmitter(0);
189 emit->setDirection(-laxis);
190 emit->setParticleVelocity(ae_buf.simbuf_tj_exhaust_velo);
191 if (!ae_buf.simbuf_ae_failed)
192 {
193 if (ae_buf.simbuf_ae_ignition)
194 {
195 emit->setEnabled(true);
196 emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.02 + ae_buf.simbuf_ae_throttle * 0.03));
197 emit->setTimeToLive((0.02 + ae_buf.simbuf_ae_throttle * 0.03) / 0.1);
198 }
199 else
200 {
201 emit->setEnabled(false);
202 }
203 }
204 else
205 {
206 emit->setDirection(Vector3(0, 1, 0));
207 emit->setParticleVelocity(7.0);
208 emit->setEnabled(true);
209 emit->setColour(ColourValue(0.0, 0.0, 0.0, 0.1));
210 emit->setTimeToLive(0.1 / 0.1);
211 }
212 }
213}
214
216{
217 m_visible = visible;
218 m_smoke_particle->setVisible(visible);
219 m_nozzle_scenenode->setVisible(visible);
220 if (!visible)
221 {
222 // only hide, regular update will restore visibility if needed.
223 m_flame_scenenode->setVisible(false);
224 }
225}
226
227void Turbojet::updateForces(float dt, int doUpdate)
228{
229 if (doUpdate)
230 {
232 }
233 m_timer += dt;
235 float axlen = m_axis.length();
236 m_axis = m_axis / axlen; //normalize
237 if (fabs(m_reflen - axlen) > 0.1)
238 {
239 m_rpm_percent = 0;
240 m_is_failed = true;
241 }; //check for broken
242
243 float warmupfactor = 1.0;
244 if (m_warmup)
245 {
246 warmupfactor = (m_timer - m_warmup_start) / m_warmup_time;
247 if (warmupfactor >= 1.0)
248 m_warmup = false;
249 }
250
251 //turbine RPM
252 //braking (compression)
253 if (m_rpm_percent < 0)
254 m_rpm_percent = 0;
255 float torque = -m_rpm_percent / 100.0;
256 //powering with limiter
257 if (m_rpm_percent < 100.0 && !m_is_failed && m_ignition)
258 torque += ((0.2 + m_throtle * 0.8) * warmupfactor);
259 //integration
260 m_rpm_percent += (double)dt * torque * 30.0;
261
262 float enginethrust = 0;
263 if (!m_is_failed && m_ignition)
264 {
265 enginethrust = m_max_dry_thrust * m_rpm_percent / 100.0;
268 enginethrust += (m_afterburn_thrust - m_max_dry_thrust);
269 }
270 else
271 m_afterburner_active = false;
272
275 else
277
278 if (m_reverse)
279 m_actor->ar_nodes[m_node_back].Forces -= (enginethrust * 1000.0) * m_axis;
280 else
281 m_actor->ar_nodes[m_node_back].Forces += (enginethrust * 1000.0) * m_axis;
282
283 m_exhaust_velocity = enginethrust * 5.6 / m_area;
284}
285
287{
288 if (val > 1.0)
289 val = 1.0;
290
291 if (val < 0.0)
292 val = 0.0;
293
294 m_throtle = val;
296}
297
299{
300 return m_throtle;
301}
302
303void Turbojet::setRPM(float _rpm)
304{
305 m_rpm_percent = _rpm;
306}
307
309{
310 if (thrust >= 0 && thrust <= m_afterburn_thrust)
311 {
312 m_max_dry_thrust = thrust;
313 }
314}
315
317{
318 if (abThrust >= m_max_dry_thrust)
319 {
320 m_afterburn_thrust = abThrust;
321 }
322}
323
325{
326 m_rpm_percent = 0;
327 m_throtle = 0;
328 m_propwash = 0;
329 m_is_failed = false;
330 m_ignition = false;
331 m_reverse = false;
332}
333
335{
336 if (!m_reversable)
337 return;
338 m_throtle = 0;
340}
341
343{
344 m_reverse = val;
345}
346
348{
349 if (m_timer - m_last_flip < 0.3)
350 return;
352 if (m_ignition && !m_is_failed)
353 {
354 m_warmup = true;
357 }
358 else
359 {
361 }
362
364}
Central state/object manager and communications hub.
#define ROR_ASSERT(_EXPR)
Definition Application.h:40
Manager for all visuals belonging to a single actor.
Core data structures for simulation; Everything affected by by either physics, network or user intera...
#define SOUND_START(_ACTOR_, _TRIG_)
#define SOUND_STOP(_ACTOR_, _TRIG_)
#define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_)
node_t * ar_nodes
Definition Actor.h:365
int ar_num_aeroengines
Definition Actor.h:424
ActorSB & GetSimDataBuffer()
Definition GfxActor.h:125
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:126
void AdjustParticleSystemTimeFactor(Ogre::ParticleSystem *psys, GfxActor *gfx_actor=nullptr)
Definition GfxScene.cpp:435
Ogre::SceneManager * GetSceneManager()
Definition GfxScene.h:83
float m_reflen
Definition TurboJet.h:124
float m_warmup_time
Definition TurboJet.h:129
float m_timer
Definition TurboJet.h:127
void updateForces(float dt, int doUpdate)
Definition TurboJet.cpp:227
void setReverse(bool val)
Definition TurboJet.cpp:342
Ogre::Vector3 m_axis
Definition TurboJet.h:110
bool tjet_afterburnable
Definition TurboJet.h:106
Turbojet(ActorPtr actor, NodeNum_t tnodefront, NodeNum_t tnodeback, NodeNum_t tnoderef, RigDef::Turbojet &def)
Definition TurboJet.cpp:36
TurbojetVisual tjet_visual
Definition TurboJet.h:107
void setRPM(float _rpm)
Definition TurboJet.cpp:303
float m_radius
Definition TurboJet.h:123
void toggleReverse()
Definition TurboJet.cpp:334
float m_throtle
Definition TurboJet.h:126
void setVisible(bool visible) override
Definition TurboJet.cpp:148
float m_warmup_start
Definition TurboJet.h:128
bool m_afterburner_active
Definition TurboJet.h:111
ActorPtr m_actor
Definition TurboJet.h:136
float m_rpm_percent
in percent!
Definition TurboJet.h:125
NodeNum_t m_node_ref
Definition TurboJet.h:139
bool m_ignition
Definition TurboJet.h:113
float m_exhaust_velocity
in m/s
Definition TurboJet.h:119
void setThrottle(float val)
Definition TurboJet.cpp:286
void updateVisuals(RoR::GfxActor *gfx_actor) override
Definition TurboJet.cpp:142
void setMaxDryThrust(float thrust)
Definition TurboJet.cpp:308
bool m_is_failed
Definition TurboJet.h:112
void setAfterburnThrust(float abThrust)
Definition TurboJet.cpp:316
bool m_reversable
Definition TurboJet.h:114
virtual ~Turbojet() override
Definition TurboJet.cpp:114
NodeNum_t m_node_back
Definition TurboJet.h:137
float m_last_flip
Definition TurboJet.h:120
float m_propwash
Definition TurboJet.h:122
void flipStart()
Definition TurboJet.cpp:347
float getThrottle()
Definition TurboJet.cpp:298
float m_max_dry_thrust
in kN
Definition TurboJet.h:121
NodeNum_t m_node_front
Definition TurboJet.h:138
float m_afterburn_thrust
in kN
Definition TurboJet.h:117
Ogre::SceneNode * m_smoke_scenenode
Definition TurboJet.h:41
void SetupVisuals(RigDef::Turbojet &def, int num, std::string const &propname, Ogre::Entity *nozzle, Ogre::Entity *afterburner_flame)
Definition TurboJet.cpp:73
NodeNum_t m_node_front
Definition TurboJet.h:52
void UpdateVisuals(RoR::GfxActor *gfx_actor)
Definition TurboJet.cpp:153
Ogre::Entity * m_flame_entity
Definition TurboJet.h:43
Ogre::Entity * m_nozzle_entity
Definition TurboJet.h:45
bool IsVisible() const
Definition TurboJet.h:38
Ogre::SceneNode * m_flame_scenenode
Definition TurboJet.h:44
void SetNodes(NodeNum_t front, NodeNum_t back, NodeNum_t ref)
Definition TurboJet.cpp:104
Ogre::SceneNode * m_nozzle_scenenode
Definition TurboJet.h:46
NodeNum_t m_node_back
Definition TurboJet.h:51
NodeNum_t m_node_ref
Definition TurboJet.h:53
void SetVisible(bool visible)
Definition TurboJet.cpp:215
Ogre::ParticleSystem * m_smoke_particle
Definition TurboJet.h:42
@ SS_TRIG_AFTERBURNER4
@ SS_TRIG_AEROENGINE7
@ SS_TRIG_AEROENGINE2
@ SS_TRIG_AFTERBURNER2
@ SS_TRIG_AEROENGINE3
@ SS_TRIG_AFTERBURNER5
@ SS_TRIG_AFTERBURNER7
@ SS_TRIG_AEROENGINE1
@ SS_TRIG_AEROENGINE5
@ SS_TRIG_AEROENGINE6
@ SS_TRIG_AFTERBURNER6
@ SS_TRIG_AEROENGINE8
@ SS_TRIG_AFTERBURNER1
@ SS_TRIG_AEROENGINE4
@ SS_TRIG_AFTERBURNER3
@ SS_TRIG_AFTERBURNER8
GfxScene * GetGfxScene()
static const NodeNum_t NODENUM_INVALID
@ DEPTHMAP_DISABLED
uint16_t NodeNum_t
Node position within Actor::ar_nodes; use RoR::NODENUM_INVALID as empty value.
bool simbuf_smoke_enabled
Definition SimBuffers.h:167
std::vector< AeroEngineSB > simbuf_aeroengines
Definition SimBuffers.h:138
float simbuf_tj_ab_thrust
Definition SimBuffers.h:98
bool simbuf_ae_ignition
Turbojet.
Definition SimBuffers.h:100
float simbuf_ae_throttle
Definition SimBuffers.h:95
float simbuf_tj_exhaust_velo
Turbojet afterburner.
Definition SimBuffers.h:99
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69
Ogre::Vector3 Forces
Definition SimData.h:269
Ogre::Vector3 RelPosition
relative to the local physics origin (one origin per actor) (shaky)
Definition SimData.h:266