X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fmoof%2Fview.cc;fp=src%2Fmoof%2Fview.cc;h=ab0058b5b115954262d0c105d3cba85791484a2d;hp=5c10378022032afc7e3aceaaedee110893392808;hb=e9a16d767785b1a903a4466ff26265a5f7dae9e5;hpb=6f1b787a10d8ab1a3117a4b8c004dd2d90599608 diff --git a/src/moof/view.cc b/src/moof/view.cc index 5c10378..ab0058b 100644 --- a/src/moof/view.cc +++ b/src/moof/view.cc @@ -30,6 +30,71 @@ 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) @@ -93,10 +158,57 @@ public: * 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(); @@ -107,7 +219,7 @@ public: 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; @@ -119,44 +231,97 @@ public: 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. } }