Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 m_rpm_percent = 0;
311 m_throtle = 0;
312 m_propwash = 0;
313 m_is_failed = false;
314 m_ignition = false;
315 m_reverse = false;
316}
317
319{
320 if (!m_reversable)
321 return;
322 m_throtle = 0;
324}
325
327{
328 m_reverse = val;
329}
330
332{
333 if (m_timer - m_last_flip < 0.3)
334 return;
336 if (m_ignition && !m_is_failed)
337 {
338 m_warmup = true;
341 }
342 else
343 {
345 }
346
348}
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:330
int ar_num_aeroengines
Definition Actor.h:389
ActorSB & GetSimDataBuffer()
Definition GfxActor.h:128
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
void AdjustParticleSystemTimeFactor(Ogre::ParticleSystem *psys)
Definition GfxScene.cpp:435
Ogre::SceneManager * GetSceneManager()
Definition GfxScene.h:83
float m_reflen
Definition TurboJet.h:122
float m_warmup_time
Definition TurboJet.h:127
float m_timer
Definition TurboJet.h:125
void updateForces(float dt, int doUpdate)
Definition TurboJet.cpp:227
void setReverse(bool val)
Definition TurboJet.cpp:326
Ogre::Vector3 m_axis
Definition TurboJet.h:108
bool tjet_afterburnable
Definition TurboJet.h:104
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:105
void setRPM(float _rpm)
Definition TurboJet.cpp:303
float m_radius
Definition TurboJet.h:121
void toggleReverse()
Definition TurboJet.cpp:318
float m_throtle
Definition TurboJet.h:124
void setVisible(bool visible) override
Definition TurboJet.cpp:148
float m_warmup_start
Definition TurboJet.h:126
bool m_afterburner_active
Definition TurboJet.h:109
ActorPtr m_actor
Definition TurboJet.h:134
float m_rpm_percent
in percent!
Definition TurboJet.h:123
NodeNum_t m_node_ref
Definition TurboJet.h:137
bool m_ignition
Definition TurboJet.h:111
float m_exhaust_velocity
in m/s
Definition TurboJet.h:117
void setThrottle(float val)
Definition TurboJet.cpp:286
void updateVisuals(RoR::GfxActor *gfx_actor) override
Definition TurboJet.cpp:142
bool m_is_failed
Definition TurboJet.h:110
bool m_reversable
Definition TurboJet.h:112
virtual ~Turbojet() override
Definition TurboJet.cpp:114
NodeNum_t m_node_back
Definition TurboJet.h:135
float m_last_flip
Definition TurboJet.h:118
float m_propwash
Definition TurboJet.h:120
void flipStart()
Definition TurboJet.cpp:331
float getThrottle()
Definition TurboJet.cpp:298
float m_max_dry_thrust
in kN
Definition TurboJet.h:119
NodeNum_t m_node_front
Definition TurboJet.h:136
float m_afterburn_thrust
in kN
Definition TurboJet.h:115
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:166
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