+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <algorithm>
-#include <cstdlib> // exit, srand
-#include <ctime> // time
-#include <string>
-
-#include <SDL/SDL.h>
-#include "fastevents.h"
-
-#include "event.hh"
-#include "log.hh"
-#include "math.hh"
-#include "modal_dialog.hh"
-#include "settings.hh"
-#include "timer.hh"
-#include "video.hh"
-#include "view.hh"
-
-
-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)
- {
- if (children().size() == 0) stop();
- }
-};
-
-static root_view gRootView;
-
-
-class view::impl
-{
-public:
-
- impl(view* view, moof::settings& settings, moof::video& video) :
- view_(*view),
- settings_(&settings),
- video_(&video),
- parent_(&gRootView)
- {
- init();
-
- unsigned randomSeed;
- if (settings.get("rngseed", randomSeed)) srand(randomSeed);
- else srand(time(0));
-
- scalar timestep = 80.0;
- settings.get("timestep", timestep);
- timestep_ = 1.0 / timestep;
-
- scalar framerate = 40.0;
- settings.get("framerate", framerate);
- framerate_ = 1.0 / framerate;
-
- show_fps_ = false;
- settings.get("showfps", show_fps_);
- }
-
- impl(view* view) :
- view_(*view),
- settings_(0),
- video_(0),
- parent_(&gRootView)
- {
- init();
- }
-
- void init()
- {
- timestep_ = SCALAR(0.01);
- framerate_ = SCALAR(0.02);
- show_fps_ = false;
- }
-
-
- /**
- * The main loop. This just calls dispatch_events(), update(), and
- * draw() over and over again. The timing of the update and draw are
- * decoupled. The actual frame rate is also calculated here. This
- * 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();
-
- //scalar nextUpdate = ticks;
- //scalar nextDraw = ticks;
- //scalar nextSecond = ticks + SCALAR(1.0);
-
- fps_ = 0;
- //int frameCount = 0;
-
- //const scalar timestep = SCALAR(0.01);//timestep_;
- //const scalar framerate = framerate_;
-
- //const int MAX_FRAMESKIP = 15;
- //const scalar inverseTimestep = SCALAR(1.0) / timestep;
-
- is_running_ = true;
- for (;;)
- {
- //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);
-
- ////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 (!is_running_) break;
-
- //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);
-
- //timer::sleep(timer::next_event(), timer::absolute);
-
- // 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.
- }
- }
-
- void stop()
- {
- is_running_ = false;
- }
-
-
- void dispatch_events()
- {
- event event;
-
- while (FE_PollEvent(&event) == 1)
- {
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE &&
- (SDL_GetModState() & KMOD_CTRL) )
- {
- // emergency escape
- log_warning("escape forced");
- exit(1);
- }
- break;
-
- case SDL_VIDEORESIZE:
- video_->resize(event.resize.w, event.resize.h);
- break;
- }
-
- view_.handle_event(event);
- }
- }
-
- bool handle_event(const event& event)
- {
- std::list<view_ptr>::iterator it;
- for (it = children_.begin(); it != children_.end(); ++it)
- {
- if ((*it)->handle_event(event)) return true;
- }
-
- return false;
- }
-
- void update(scalar t, scalar dt)
- {
- std::list<view_ptr>::iterator it;
- for (it = children_.begin(); it != children_.end(); ++it)
- {
- (*it)->update(t, dt);
- }
- }
-
- void draw(scalar alpha)
- {
- std::list<view_ptr>::iterator it;
- for (it = children_.begin(); it != children_.end(); ++it)
- {
- (*it)->draw(alpha);
- }
- }
-
-
- void add_child(view_ptr child)
- {
- ASSERT(child && "adding null view");
- ASSERT(child.get() != &view_ && "adding view to itself");
-
- child->impl_->parent_->remove_child(child);
- children_.push_back(child);
-
- child->impl_->parent_ = &view_;
- child->impl_->percolate_objects();
-
- child->did_add_to_view();
- }
-
- void percolate_objects()
- {
- bool recurseAgain = false;
-
- if (parent_->impl_->video_ && parent_->impl_->video_ != video_)
- {
- video_ = parent_->impl_->video_;
- recurseAgain = true;
- }
-
- if (parent_->impl_->settings_ &&
- parent_->impl_->settings_ != settings_)
- {
- settings_ = parent_->impl_->settings_;
- recurseAgain = true;
- }
-
- if (recurseAgain)
- {
- std::list<view_ptr>::iterator it;
- for (it = children_.begin(); it != children_.end(); ++it)
- {
- (*it)->impl_->percolate_objects();
- }
- }
- }
-
- view_ptr remove_child(view* child)
- {
- ASSERT(child && "cannot remove null child");
-
- std::list<view_ptr>::iterator it;
- for (it = children_.begin(); it != children_.end(); ++it)
- {
- if ((*it).get() == child)
- {
- view_ptr found = *it;
- found->will_remove_from_view();
- children_.erase(it);
-
- found->impl_->parent_ = &gRootView;
-
- return found;
- }
- }
-
- return view_ptr();
- }
-
- void clear()
- {
- children_.clear();
- }
-
-
- bool is_running_;
- view& view_;
-
- moof::settings* settings_;
- moof::video* video_;
-
- view* parent_;
- std::list<view_ptr> children_;
-
- scalar timestep_;
- scalar framerate_;
-
- int fps_;
- bool show_fps_;
-};
-
-
-view::view(moof::settings& settings, moof::video& video) :
- // pass through
- impl_(new view::impl(this, settings, video)) {}
-
-view::view() :
- impl_(new view::impl(this)) {}
-
-
-void view::update(scalar t, scalar dt)
-{
- // pass through
- impl_->update(t, dt);
-}
-
-void view::draw(scalar alpha) const
-{
- // pass through
- impl_->draw(alpha);
-}
-
-bool view::handle_event(const event& event)
-{
- // pass through
- return impl_->handle_event(event);
-}
-
-
-void view::add_child(view_ptr view)
-{
- // pass through
- impl_->add_child(view);
-}
-
-view_ptr view::remove_child(view* view)
-{
- // pass through
- return impl_->remove_child(view);
-}
-
-view_ptr view::remove_child(view_ptr view)
-{
- // pass through
- return impl_->remove_child(view.get());
-}
-
-void view::clear()
-{
- // pass through
- impl_->clear();
-}
-
-
-view& view::parent() const
-{
- return *(impl_->parent_);
-}
-
-const std::list<view_ptr>& view::children() const
-{
- return impl_->children_;
-}
-
-
-moof::settings& view::settings() const
-{
- ASSERT(impl_->settings_ && "accessing null reference");
- // pass through
- return *(impl_->settings_);
-}
-
-video& view::video() const
-{
- ASSERT(impl_->video_ && "accessing null reference");
- // pass through
- return *(impl_->video_);
-}
-
-
-void view::run()
-{
- // pass through
- return impl_->run();
-}
-
-void view::stop()
-{
- // pass through
- return impl_->stop();
-}
-
-bool view::is_running() const
-{
- // pass through
- return impl_->is_running_;
-}
-
-
-} // namespace moof
-