namespace moof {
+// Timestep Example Source Code
+// Copyright (c) Glenn Fiedler 2004
+// http://www.gaffer.org/articles
+
+struct State
+{
+ float x;
+ float v;
+};
+
+struct Derivative
+{
+ float dx;
+ float dv;
+};
+
+State interpolate(const State &previous, const State ¤t, float alpha)
+{
+ State state;
+ state.x = current.x*alpha + previous.x*(1-alpha);
+ state.v = current.v*alpha + previous.v*(1-alpha);
+ return state;
+}
+
+float acceleration(const State &state, float t)
+{
+ const float k = 10;
+ const float b = 1;
+ return - k*state.x - b*state.v;
+}
+
+Derivative evaluate(const State &initial, float t)
+{
+ Derivative output;
+ output.dx = initial.v;
+ output.dv = acceleration(initial, t);
+ return output;
+}
+
+Derivative evaluate(const State &initial, float t, float dt, const Derivative &d)
+{
+ State state;
+ state.x = initial.x + d.dx*dt;
+ state.v = initial.v + d.dv*dt;
+ Derivative output;
+ output.dx = state.v;
+ output.dv = acceleration(state, t+dt);
+ return output;
+}
+
+void integrate(State &state, float t, float dt)
+{
+ Derivative a = evaluate(state, t);
+ Derivative b = evaluate(state, t, dt*0.5f, a);
+ Derivative c = evaluate(state, t, dt*0.5f, b);
+ Derivative d = evaluate(state, t, dt, c);
+
+ const float dxdt = 1.0f/6.0f * (a.dx + 2.0f*(b.dx + c.dx) + d.dx);
+ const float dvdt = 1.0f/6.0f * (a.dv + 2.0f*(b.dv + c.dv) + d.dv);
+
+ state.x = state.x + dxdt*dt;
+ state.v = state.v + dvdt*dt;
+}
+
+
class root_view : public view
{
void update(scalar t, scalar dt)
* function will return the exit code used to stop the loop.
*/
+ scalar nextUpdate;
+ scalar totalTime;
+
+ void U(timer& T, scalar t)
+ {
+ const int MAX_FRAMESKIP = 15;
+
+ log_info("update");
+
+ int i = 0;
+ while (nextUpdate < t && ++i < MAX_FRAMESKIP)
+ {
+ totalTime += timestep_; // 3. update state
+ view_.update(totalTime, timestep_);
+
+ //previous = current;
+ //integrate(current, totalTime, timestep);
+
+ nextUpdate += timestep_;
+ }
+ }
+
+ void D(timer& T, scalar t)
+ {
+ const scalar inverseTimestep = SCALAR(1.0) / timestep_;
+
+ log_info("draw");
+
+ scalar alpha = (t + timestep_ - nextUpdate) * inverseTimestep;
+ //scalar alpha = (nextUpdate - t) * inverseTimestep;
+ if (alpha < SCALAR(0.0)) log_error("UH OH!!!!! It's NEGATIVE", alpha);
+ if (alpha > SCALAR(1.0)) log_error("UH OH!!!!! It's POSITIVE", alpha);
+ log_info("alpha:", alpha);
+
+ view_.draw(alpha);
+ video_->swap(); // 4. draw state
+ }
+
+ timer utimer, dtimer;
+
void run()
{
ASSERT(video_ && "running without video set");
+ utimer.init(boost::bind(&impl::U, this, _1, _2), timestep_, timer::repeat);
+ dtimer.init(boost::bind(&impl::D, this, _1, _2), framerate_, timer::repeat);
+
+ totalTime = 0.0f;
+ nextUpdate = timer::ticks();
+
+
scalar totalTime = 0.0;
scalar ticks = timer::ticks();
fps_ = 0;
int frameCount = 0;
- const scalar timestep = timestep_;
+ const scalar timestep = SCALAR(0.01);//timestep_;
const scalar framerate = framerate_;
const int MAX_FRAMESKIP = 15;
timer::fire_expired_timers(); // 1. fire timers
dispatch_events(); // 2. dispatch events
- if (!is_running_) break;
-
- int i = 0;
- while (nextUpdate < timer::ticks() && i < MAX_FRAMESKIP)
- {
- totalTime += timestep; // 3. update state
- view_.update(totalTime, timestep);
-
- nextUpdate += timestep;
- ++i;
-
- if (!is_running_) break;
- }
-
- if (nextDraw < (ticks = timer::ticks()))
- {
- view_.draw(
- (ticks + timestep - nextUpdate) * inverseTimestep);
- video_->swap(); // 4. draw state
-
- nextDraw += framerate;
- ++frameCount;
-
- if (nextSecond < timer::ticks())
- {
- fps_ = frameCount;
- frameCount = 0;
+ //if (!is_running_) break;
+
+ //int i = 0;
+ //while (nextUpdate < timer::ticks() && i < MAX_FRAMESKIP)
+ //{
+ //totalTime += timestep; // 3. update state
+ //view_.update(totalTime, timestep);
+
+ ////previous = current;
+ ////integrate(current, totalTime, timestep);
+
+ //nextUpdate += timestep;
+ //++i;
+
+ //if (!is_running_) break;
+ //}
+
+ ////const float newTime = timer::ticks();
+ ////float deltaTime = newTime - currentTime;
+ ////currentTime = newTime;
+
+ ////if (deltaTime>0.25f)
+ ////deltaTime = 0.25f;
+
+ ////accumulator += deltaTime;
+
+ ////while (accumulator>=dt)
+ ////{
+ ////accumulator -= dt;
+ ////previous = current;
+ ////integrate(current, t, dt);
+ ////t += dt;
+ ////}
+
+ ////if (nextDraw < (ticks = timer::ticks()))
+ ////{
+ //ticks = timer::ticks();
+ //scalar diff = ticks - nextDraw;
+ ////log_info("difference:", diff);
+ //scalar alpha = (ticks + timestep - nextUpdate) * inverseTimestep;
+ ////scalar alpha = (nextUpdate - ticks) * inverseTimestep;
+ ////float alpha = accumulator/dt;
+ //if (alpha < SCALAR(0.0)) log_error("UH OH!!!!! It's NEGATIVE", alpha);
+ //if (alpha > SCALAR(1.0)) log_error("UH OH!!!!! It's POSITIVE", alpha);
+ //log_info("alpha:", alpha);
+
+ //view_.draw(alpha);
+
+ //// TEMP
+ ////State state = interpolate(previous, current, alpha);
+ ////glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ////glBegin(GL_POINTS);
+ ////glColor3f(1,1,1);
+ ////glVertex3f(state.x, 0, 0);
+ ////glEnd();
+
+
+
+ //video_->swap(); // 4. draw state
+
+ //nextDraw += framerate;
+ //++frameCount;
+
+ //if (nextSecond < ticks)//timer::ticks())
+ //{
+ //fps_ = frameCount;
+ //frameCount = 0;
+
+ //if (show_fps_) log_info << fps_ << " fps" << std::endl;
+
+ //nextSecond += SCALAR(1.0);
+ //}
+ ////}
- if (show_fps_) log_info << fps_ << " fps" << std::endl;
+ if (!is_running_) break;
- nextSecond += SCALAR(1.0);
- }
- }
+ //ticks = timer::ticks(); // 5. yield timeslice
+ //scalar next = std::min(nextUpdate, nextDraw);
+ //next = std::min(next, timer::next_event());
+ //if (ticks < next) timer::sleep(next, timer::absolute);
- if (!is_running_) break;
+ timer::sleep(timer::next_event(), timer::absolute);
- ticks = timer::ticks(); // 5. yield timeslice
- if (ticks < nextUpdate && ticks < nextDraw) timer::sleep(0.0);
+ // Animation is choppy... the sound timer makes the draw occur
+ // late. It's not usually enough to make the FPS drop, but it
+ // certainly is noticeably choppy. Maybe update and draw
+ // should both be scheduled like timers. That should reduce
+ // the number of times either update or draw occur late. It
+ // doesn't really matter if update is late, but it's ugly if
+ // draw is late.
}
}