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
Replay.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
6 For more information, see http://www.rigsofrods.org/
7
8 Rigs of Rods is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 3, as
10 published by the Free Software Foundation.
11
12 Rigs of Rods is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "Replay.h"
22
23#include "Application.h"
24#include "Actor.h"
25#include "ActorManager.h"
26#include "GameContext.h"
27#include "GUIManager.h"
28#include "InputEngine.h"
29#include "Language.h"
30#include "Utils.h"
31
32using namespace Ogre;
33using namespace RoR;
34
35Replay::Replay(ActorPtr actor, int _numFrames)
36{
37 m_actor = actor;
38 numFrames = _numFrames;
39
40 curFrameTime = 0;
41
42 replayTimer = new Timer();
43
44 // DO NOT get memory here, get memory when we use it first time!
45 nodes = 0;
46 beams = 0;
47 times = 0;
48
49 outOfMemory = false;
50
51 const int numNodes = actor->ar_num_nodes;
52 const int numBeams = actor->ar_num_beams;
53 unsigned long bsize = (numNodes * numFrames * sizeof(node_simple_t) + numBeams * numFrames * sizeof(beam_simple_t) + numFrames * sizeof(unsigned long)) / 1024.0f;
54 LOG("replay buffer size: " + TOSTRING(bsize) + " kB");
55
56 writeIndex = 0;
57 firstRun = 1;
58
59 int steps = App::sim_replay_stepping->getInt();
60
61 if (steps <= 0)
62 this->ar_replay_precision = 0.0f;
63 else
64 this->ar_replay_precision = 1.0f / ((float)steps);
65
66 // windowing
67 int width = 300;
68 int height = 60;
69 int x = (MyGUI::RenderManager::getInstance().getViewSize().width - width) / 2;
70 int y = 0;
71}
72
74{
75 if (nodes)
76 {
77 free(nodes);
78 nodes = 0;
79 free(beams);
80 beams = 0;
81 free(times);
82 times = 0;
83 }
84 delete replayTimer;
85}
86
88{
89 if (outOfMemory)
90 return 0;
91 if (!nodes)
92 {
93 // get memory
95 if (!nodes)
96 {
97 outOfMemory = true;
98 return 0;
99 }
101 if (!beams)
102 {
103 free(nodes);
104 nodes = 0;
105 outOfMemory = true;
106 return 0;
107 }
108 times = (unsigned long*)calloc(numFrames, sizeof(unsigned long));
109 if (!times)
110 {
111 free(nodes);
112 nodes = 0;
113 free(beams);
114 beams = 0;
115 outOfMemory = true;
116 return 0;
117 }
118 }
119 void* ptr = 0;
120 times[writeIndex] = replayTimer->getMicroseconds();
121 if (type == 0)
122 {
123 // nodes
124 ptr = (void *)(nodes + (writeIndex * m_actor->ar_num_nodes));
125 }
126 else if (type == 1)
127 {
128 // beams
129 ptr = (void *)(beams + (writeIndex * m_actor->ar_num_beams));
130 }
131 return ptr;
132}
133
135{
136 if (outOfMemory)
137 return;
138 writeIndex++;
139 if (writeIndex == numFrames)
140 {
141 firstRun = 0;
142 writeIndex = 0;
143 }
144}
145
146//we take negative offsets only
147void* Replay::getReadBuffer(int offset, int type, unsigned long& time)
148{
149 if (offset >= 0)
150 offset = -1;
151 if (offset <= -numFrames)
152 offset = -numFrames + 1;
153
154 int delta = writeIndex + offset;
155 if (delta < 0)
156 if (firstRun && type == 0)
157 return (void *)(nodes);
158 else if (firstRun && type == 1)
159 return (void *)(beams);
160 else
161 delta += numFrames;
162
163 // set the time
164 time = times[delta];
165 curFrameTime = time;
166
167 if (outOfMemory)
168 return 0;
169
170 // return buffer pointer
171 if (type == 0)
172 return (void *)(nodes + delta * m_actor->ar_num_nodes);
173 else if (type == 1)
174 return (void *)(beams + delta * m_actor->ar_num_beams);
175 return 0;
176}
177
179{
180 return curFrameTime;
181}
182
184{
187 {
188 // store nodes
189 node_simple_t* nbuff = (node_simple_t *)this->getWriteBuffer(0);
190 if (nbuff)
191 {
192 for (int i = 0; i < m_actor->ar_num_nodes; i++)
193 {
194 nbuff[i].position = m_actor->ar_nodes[i].AbsPosition;
195 nbuff[i].velocity = m_actor->ar_nodes[i].Velocity;
196 }
197 }
198
199 // store beams
200 beam_simple_t* bbuff = (beam_simple_t *)this->getWriteBuffer(1);
201 if (bbuff)
202 {
203 for (int i = 0; i < m_actor->ar_num_beams; i++)
204 {
205 bbuff[i].broken = m_actor->ar_beams[i].bm_broken;
206 bbuff[i].disabled = m_actor->ar_beams[i].bm_disabled;
207 }
208 }
209
210 this->writeDone();
211 m_replay_timer = 0.0f;
212 }
213}
214
216{
218 {
219 unsigned long time = 0;
220
221 node_simple_t* nbuff = (node_simple_t *)this->getReadBuffer(ar_replay_pos, 0, time);
222 if (nbuff)
223 {
224 for (int i = 0; i < m_actor->ar_num_nodes; i++)
225 {
226 m_actor->ar_nodes[i].AbsPosition = nbuff[i].position;
228
229 m_actor->ar_nodes[i].Velocity = nbuff[i].velocity;
230 m_actor->ar_nodes[i].Forces = Vector3::ZERO;
231 }
232
236 }
237
238 beam_simple_t* bbuff = (beam_simple_t *)this->getReadBuffer(ar_replay_pos, 1, time);
239 if (bbuff)
240 {
241 for (int i = 0; i < m_actor->ar_num_beams; i++)
242 {
243 m_actor->ar_beams[i].bm_broken = bbuff[i].broken;
244 m_actor->ar_beams[i].bm_disabled = bbuff[i].disabled;
245 }
246 }
248 }
249}
250
252{
253 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_TOGGLE_REPLAY_MODE))
254 {
257 else
259 }
260
262 {
263 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FORWARD, 0.1f) && this->ar_replay_pos <= 0)
264 {
265 this->ar_replay_pos++;
266 }
267 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_BACKWARD, 0.1f) && this->ar_replay_pos > -this->getNumFrames())
268 {
269 this->ar_replay_pos--;
270 }
271 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FAST_FORWARD, 0.1f) && this->ar_replay_pos + 10 <= 0)
272 {
273 this->ar_replay_pos += 10;
274 }
275 if (App::GetInputEngine()->getEventBoolValueBounce(EV_COMMON_REPLAY_FAST_BACKWARD, 0.1f) && this->ar_replay_pos - 10 > -this->getNumFrames())
276 {
277 this->ar_replay_pos -= 10;
278 }
279
280 if (App::GetInputEngine()->isKeyDown(OIS::KC_LMENU))
281 {
282 if (this->ar_replay_pos <= 0 && this->ar_replay_pos >= -this->getNumFrames())
283 {
284 if (App::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) || App::GetInputEngine()->isKeyDown(OIS::KC_RSHIFT))
285 {
286 this->ar_replay_pos += App::GetInputEngine()->getMouseState().X.rel * 1.5f;
287 }
288 else
289 {
290 this->ar_replay_pos += App::GetInputEngine()->getMouseState().X.rel * 0.05f;
291 }
292 if (this->ar_replay_pos > 0)
293 {
294 this->ar_replay_pos = 0;
295 }
296 if (this->ar_replay_pos < -this->getNumFrames())
297 {
298 this->ar_replay_pos = -this->getNumFrames();
299 }
300 }
301 }
302 }
303}
Central state/object manager and communications hub.
#define TOSTRING(x)
Definition Application.h:57
void LOG(const char *msg)
Legacy alias - formerly a macro.
Game state manager and message-queue provider.
Handles controller inputs from player.
#define PHYSICS_DT
node_t * ar_nodes
Definition Actor.h:330
Ogre::Vector3 ar_origin
Physics state; base position for softbody nodes.
Definition Actor.h:438
ActorState ar_state
Definition Actor.h:518
void updateSlideNodePositions()
incrementally update the position of all SlideNodes
int ar_num_beams
Definition Actor.h:349
int ar_num_nodes
Definition Actor.h:345
void calculateAveragePosition()
Definition Actor.cpp:1166
void UpdateBoundingBoxes()
Definition Actor.cpp:1201
beam_t * ar_beams
Definition Actor.h:348
int getInt() const
Definition CVar.h:97
OIS::MouseState getMouseState()
beam_simple_t * beams
Definition Replay.h:73
int numFrames
Definition Replay.h:65
Ogre::Timer * replayTimer
Definition Replay.h:64
unsigned long curFrameTime
Definition Replay.h:69
void * getWriteBuffer(int type)
Definition Replay.cpp:87
float ar_replay_precision
Definition Replay.h:61
int writeIndex
Definition Replay.h:67
void replayStepActor()
Definition Replay.cpp:215
Replay(ActorPtr b, int nframes)
Definition Replay.cpp:35
int getNumFrames() const
Definition Replay.h:53
unsigned long getLastReadTime()
Definition Replay.cpp:178
int m_replay_pos_prev
Definition Replay.h:63
void writeDone()
Definition Replay.cpp:134
void onPhysicsStep()
Definition Replay.cpp:183
bool outOfMemory
Definition Replay.h:66
unsigned long * times
Definition Replay.h:74
int firstRun
Definition Replay.h:68
void UpdateInputEvents()
Definition Replay.cpp:251
node_simple_t * nodes
Definition Replay.h:72
ActorPtr m_actor
Definition Replay.h:59
float m_replay_timer
Definition Replay.h:60
int ar_replay_pos
Definition Replay.h:62
void * getReadBuffer(int offset, int type, unsigned long &time)
Definition Replay.cpp:147
@ EV_COMMON_REPLAY_BACKWARD
@ EV_COMMON_REPLAY_FORWARD
@ EV_COMMON_REPLAY_FAST_FORWARD
@ EV_COMMON_REPLAY_FAST_BACKWARD
@ EV_COMMON_TOGGLE_REPLAY_MODE
toggle replay mode
@ LOCAL_SIMULATED
simulated (local) actor
InputEngine * GetInputEngine()
CVar * sim_replay_stepping
bool bm_broken
Definition SimData.h:326
bool bm_disabled
Definition SimData.h:325
Ogre::Vector3 position
Definition Replay.h:29
Ogre::Vector3 velocity
Definition Replay.h:30
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition SimData.h:267
Ogre::Vector3 Velocity
Definition SimData.h:268
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