Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/ogreode/OgreOdeStepper.cpp @ 1923

Last change on this file since 1923 was 1923, checked in by rgrieder, 16 years ago

Cleaned up the heavy mess with header file includes in OgreOde. It should now compile a lot faster.

  • 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.