Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics_new/src/ogreode/OgreOdeStepper.cpp @ 2119

Last change on this file since 2119 was 2119, checked in by rgrieder, 15 years ago

Merged physics branch into physics_new branch.

  • Property svn:eol-style set to native
File size: 11.4 KB
Line 
1#include "OgreOdePrecompiledHeaders.h"
2#include "OgreOdeStepper.h"
3
4#include <OgreRoot.h>
5
6#include "OgreOdeGeometry.h"
7#include "OgreOdeBody.h"
8#include "OgreOdeSpace.h"
9
10using namespace OgreOde;
11using namespace Ogre;
12
13//------------------------------------------------------------------------------------------------
14const Ogre::Real cEpsilon = std::numeric_limits<Real>::epsilon();
15//------------------------------------------------------------------------------------------------
16StepHandler::StepHandler(World *world, 
17                 StepModeType stepModeType,
18                 const Ogre::Real step_size, 
19                 const Ogre::Real max_interval, 
20                 const Ogre::Real time_scale) :
21    _world  (world),
22    _paused (false),
23    _auto_pre (false),
24    _auto_post (false), 
25    _listener (0),
26    _root  (0),
27    _step_size (step_size),
28    _total_time (Ogre::Real(0.0)),
29    _max_interval (max_interval),
30    _time_scale (time_scale)
31{
32    switch (stepModeType)
33    {
34        case BasicStep:
35            _current_stepper = new BasicStepMode(world);
36            break;
37        case QuickStep:
38            _current_stepper = new QuickStepMode(world);
39            break;
40        case FastStep:
41            _current_stepper = new FastStepMode(world);
42            break;
43        case StepModeTypeCount:
44        default:
45            assert(0);
46    }
47    assert((step_size > 0)&&("Step size must be greater than zero"));
48    assert((max_interval > 0)&&("max interval must be greater than zero"));
49}
50//------------------------------------------------------------------------------------------------
51void StepHandler::pause(bool pause)
52{
53        _paused = pause;
54}
55//------------------------------------------------------------------------------------------------
56void StepHandler::setStepListener(StepListener* listener)
57{
58        _listener = listener;
59}
60//------------------------------------------------------------------------------------------------
61bool StepHandler::isPaused()
62{
63        return _paused;
64}
65//------------------------------------------------------------------------------------------------
66void StepHandler::setAutomatic(StepHandler::AutoMode mode, Root* root)
67{
68        if ((_root)&&((_auto_pre)||(_auto_post))) 
69        _root->removeFrameListener(this);
70
71        _auto_pre = (mode == AutoMode_PreFrame)?true:false;
72        _auto_post = (mode == AutoMode_PostFrame)?true:false;
73
74        if ((root)&&((_auto_pre)||(_auto_post)))
75        {
76                _root = root;
77                _root->addFrameListener(this);
78        }
79}
80//------------------------------------------------------------------------------------------------
81bool StepHandler::frameStarted(const FrameEvent& evt)
82{
83        if (_auto_pre)
84        {
85                if (step (evt.timeSinceLastFrame)) 
86                        _world->synchronise();
87        }
88        return true;
89}
90//------------------------------------------------------------------------------------------------
91bool StepHandler::frameEnded(const FrameEvent& evt)
92{
93        if (_auto_post)
94        {
95                if (step (evt.timeSinceLastFrame))
96                        _world->synchronise();
97        }
98        return true;
99}
100//------------------------------------------------------------------------------------------------
101StepHandler::~StepHandler()
102{
103        setAutomatic(AutoMode_NotAutomatic);
104}
105//------------------------------------------------------------------------------------------------
106bool StepHandler::basicStep(const Ogre::Real time)
107{
108    if (_listener && !_listener->preStep(time))
109        return false;
110
111    _world->getDefaultSpace()->collide();
112
113    if (_listener && !_listener->middleStep(time))
114        return false;
115
116    _current_stepper->step(time);
117
118
119        _world->clearContacts();
120
121    if (_listener && !_listener->postStep(time))
122        return false;
123
124        return true;
125}
126//------------------------------------------------------------------------------------------------
127bool StepHandler::isRunning(const Ogre::Real time)
128{
129    if (!_paused)
130    {
131       return true;
132    }
133    return false;
134}
135//------------------------------------------------------------------------------------------------
136bool StepHandler::prepareSteppingTime(const Ogre::Real time)
137{
138    // make sure time is not too high (alt-tab, debug)
139        if (_max_interval - time < cEpsilon
140                )
141        {
142                _total_time += _max_interval * _time_scale;
143        }
144        else
145        {
146                _total_time += time * _time_scale;
147        }
148        return (_total_time - cEpsilon > 0);
149}
150//------------------------------------------------------------------------------------------------
151bool StepHandler::step(const Ogre::Real time)
152{
153        if (isRunning(time) && prepareSteppingTime(time))
154        { 
155                if (basicStep(_total_time))
156                {
157                        _world->updateDrawState ();
158            _total_time = Ogre::Real(0);
159                }
160                return true;
161        }
162        return false;
163}
164//------------------------------------------------------------------------------------------------
165ExactVariableStepHandler::ExactVariableStepHandler(World *world, 
166                                                   StepModeType stepModeType,
167                                                   const Ogre::Real step_size, 
168                                                   const Ogre::Real max_interval, 
169                                                   const Ogre::Real time_scale):
170    StepHandler(world, stepModeType, step_size,  max_interval, time_scale)
171{
172}
173//------------------------------------------------------------------------------------------------
174bool ExactVariableStepHandler::step(const Ogre::Real time)
175{
176    if (isRunning(time) && prepareSteppingTime(time))
177    {
178        // Steps in fixed time slices first...
179        bool did_run = false;
180
181        while (_total_time - _step_size > cEpsilon)
182        {
183            if (StepHandler::basicStep(_step_size))
184            {
185                did_run = true;
186                _total_time -= _step_size;
187            }
188            else 
189            {
190                break;
191            }
192        } 
193
194        // Then do a little clean-up step
195        if (_total_time > cEpsilon)
196        {
197            if (StepHandler::basicStep(_total_time))
198            {
199                did_run = true;
200                _total_time = Ogre::Real(0);
201            }
202        }
203
204        if (did_run)
205        {
206            _world->updateDrawState ();
207        }
208        return did_run;
209    }
210    return false;
211}
212//------------------------------------------------------------------------------------------------
213ExactVariableStepHandler::~ExactVariableStepHandler()
214{
215}
216//------------------------------------------------------------------------------------------------
217ForwardFixedStepHandler::ForwardFixedStepHandler(World *world, 
218    StepModeType stepModeType,
219    const Ogre::Real step_size, 
220    const Ogre::Real max_interval, 
221    const Ogre::Real time_scale):
222    StepHandler(world, stepModeType, step_size, max_interval, time_scale)
223{
224}
225//------------------------------------------------------------------------------------------------
226bool ForwardFixedStepHandler::step(const Ogre::Real time)
227{
228        if (isRunning(time) && prepareSteppingTime(time))
229        {
230                // Slightly different type of ODE stepper, always makes sure
231                // the ODE world is at least level with real-time, and possibly
232                // up to one step ahead, seems to make things a bit smoother (?)
233                bool did_run = false;
234
235        while (_total_time  > cEpsilon)
236        {
237            if (StepHandler::basicStep(_step_size))
238            {
239                did_run = true;
240                _total_time -= _step_size;
241            }
242            else 
243            {
244                break;
245            }
246        } 
247
248
249                if (did_run)
250                        _world->updateDrawState ();
251
252                return did_run;
253        }
254        return false;
255}
256//------------------------------------------------------------------------------------------------
257ForwardFixedStepHandler::~ForwardFixedStepHandler()
258{
259}
260//------------------------------------------------------------------------------------------------
261ForwardFixedInterpolatedStepHandler::ForwardFixedInterpolatedStepHandler(World *world, 
262    StepModeType stepModeType,
263    const Ogre::Real step_size, 
264    const Ogre::Real frame_rate, 
265    const Ogre::Real max_interval, 
266    const Ogre::Real time_scale):
267        StepHandler(world, stepModeType, step_size, max_interval, time_scale),
268        _dbl_step_size(step_size * 2),
269        _inv_step_size(1.0 / frame_rate),
270        _frame_rate (frame_rate)
271{
272    if (frame_rate == Ogre::Real(0))
273    {
274        _fixed_frame_rate = false;
275        _next_frame_step_count = 1;
276    }
277    else
278    {
279        _fixed_frame_rate = true;
280        _next_frame_step_count = (unsigned int)(_frame_rate / (_step_size * _time_scale));
281        if (_next_frame_step_count == 0)
282            _next_frame_step_count = 1;
283    }
284    // compute here the frame_rate adapted to step_size
285    _next_total_time = _next_frame_step_count * _step_size;
286    _inv_next_total_time = 1 / _next_total_time;
287
288        // Need at least _previous and _current position
289        if (_world->getHistorySize() < 2)
290                _world->setHistorySize (2);
291}
292//------------------------------------------------------------------------------------------------
293bool ForwardFixedInterpolatedStepHandler::step(const Ogre::Real time)
294{
295    if (isRunning(time))
296        {       
297                bool did_run = false;
298
299        // if some time did elapse
300        bool should_run = prepareSteppingTime(time);
301        // if fixed frame rate.
302        // make sure we're waiting until next fixed frame rate stepping.
303        if (_fixed_frame_rate && _total_time - _next_total_time < cEpsilon)
304            should_run = false;
305
306        if (should_run)
307        {
308#ifdef _one_step_forward
309            // normal steps, without storing results in history
310            while (_total_time - _step_size > cEpsilon)
311            {
312                if (StepHandler::basicStep(_step_size))
313                {
314                    did_run = true;
315                    _total_time -= _step_size;
316                }
317                else 
318                {
319                    break;
320                }
321            }
322            if (did_run)
323            {
324                // last Special Single Step is specific as we save last state prior stepping.
325                _world->updatePreviousState ();
326                // compute next Frame physic state
327                StepHandler::basicStep(_step_size);
328                _world->updateCurrentState (); 
329            }
330
331#else// _OLD
332
333            // last Special Step is specific as we save last state prior stepping.
334            _world->updatePreviousState ();
335
336            // normal steps, without storing results in history
337            unsigned int next_frame_step_count = _next_frame_step_count;
338            while (next_frame_step_count--)
339            {
340                if (StepHandler::basicStep(_step_size))
341                {
342                    did_run = true;
343                }
344                else 
345                {
346                    break;
347                }
348            }
349
350            if (did_run)
351                _world->updateCurrentState (); 
352
353            _total_time = std::max(_total_time - _next_total_time, Ogre::Real(0.0));
354
355#endif// _OLD
356               
357        }
358            // even if no new physic step happened
359        // interpolation may changed its value if time changed...       
360
361            // interpolate between previousState and currentState;
362        // currentState*interpolationTime + previousState * (1.0f - interpolationTime)
363        // interpolate
364            _world->interpolateDrawState(
365            Ogre::Real(1.0) -  (_next_total_time - _total_time) * _inv_next_total_time
366            //(_total_time - _next_total_time) * _inv_next_total_time
367            );
368                return true;
369        }
370        return false;
371}
372//------------------------------------------------------------------------------------------------
373ForwardFixedInterpolatedStepHandler::~ForwardFixedInterpolatedStepHandler()
374{
375}
376
Note: See TracBrowser for help on using the repository browser.