starting to move to a generic state structure
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Mon, 2 Nov 2009 19:02:33 +0000 (12:02 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Mon, 2 Nov 2009 19:02:33 +0000 (12:02 -0700)
src/Character.cc
src/Character.hh
src/Moof/OpenGL.hh
src/Moof/RK4.hh

index accad6512ecc4e0ffc185a528bbc495b13a423f6..ffecfd5b8c5db2c2c82c3e4cc478c00d718f3fed 100644 (file)
 #include "Log.hh"
 
        
+struct SpringForce
+{
+       explicit SpringForce(Mf::Vector2 x) :
+               location(x) {}
+
+       const Mf::Vector2& operator () (const Mf::LinearState<2>& state)
+       {
+               Mf::Vector2 x = state.position - location;
+               Mf::Scalar mag = x.length();
+               Mf::Scalar d = 50.0;
+
+               // spring:
+               //current.force += -15.0 * x - 1.5 * current.velocity;
+               force = -20.0 * (mag - d) * (x / mag) - 2.0 * state.velocity;
+
+               return force;
+       }
+
+private:
+
+       Mf::Vector2 force;
+       Mf::Vector2 location;
+};
+
+struct WindResistenceForce
+{
+       const Mf::Vector2& operator () (const Mf::LinearState<2>& state)
+       {
+               force = -2.0 * state.velocity;
+               return force;
+       }
+
+private:
+
+       Mf::Vector2 force;
+};
+
+
 Character::Character(const std::string& name) :
        tilemap_(name),
        animation_(name)
 {
+       current.init();
+
        current.mass = 1.0;
        current.inverseMass = 1.0 / current.mass;
 
        // gravity
-       current.force = Mf::Vector2(0.0, -120.0);
+       current.force = Mf::Vector2(0.0, 000.0);
+       current.forces.push_back(SpringForce(Mf::Vector2(500.0, 200.0)));
+       current.forces.push_back(WindResistenceForce());
+       current.forces.push_back(Mf::LinearState<2>::GravityForce(-2000.0));
 
        // starting position
        current.position = Mf::Vector2(64.0, 64.0);
@@ -55,21 +98,25 @@ void Character::update(Mf::Scalar t, Mf::Scalar dt)
 {
        previous = current;
 
-       Mf::Vector2 x = current.position - Mf::Vector2(500.0, 200.0);
-       Mf::Scalar mag = x.length();
-       Mf::Scalar d = 50.0;
-
-       // gravity:
-       current.force = Mf::Vector2(0.0, -2000.0);
-       // spring:
-       //current.force += -15.0 * x - 1.5 * current.velocity;
-       current.force += -20.0 * (mag - d) * (x / mag) - 2.0 * current.velocity;
-       // internal:
-       current.force += userForce;
-       current.recalculate();
+       //Mf::Vector2 x = current.position - Mf::Vector2(500.0, 200.0);
+       //Mf::Scalar mag = x.length();
+       //Mf::Scalar d = 50.0;
+
+       //// gravity:
+       //current.force = Mf::Vector2(0.0, -2000.0);
+       //// spring:
+       ////current.force += -15.0 * x - 1.5 * current.velocity;
+       //current.force += -20.0 * (mag - d) * (x / mag) - 2.0 * current.velocity;
+       //// internal:
+       //current.force += userForce;
+       //current.recalculate();
        //std::cout << "force: " << current.momentum << std::endl;
 
-       Mf::euler<State,Derivative>(current, t, dt);
+       //Mf::euler<State,Derivative>(current, t, dt);
+
+       //current.force = Mf::Vector2(0.0, -2000.0);
+       current.force = userForce;
+       current.integrate(t, dt);
 
        animation_.update(t, dt);
 }
@@ -77,7 +124,7 @@ void Character::update(Mf::Scalar t, Mf::Scalar dt)
 
 void Character::draw(Mf::Scalar alpha) const
 {
-       State state = cml::lerp(previous, current, alpha);
+       Mf::Vector2 position = cml::lerp(previous.position, current.position, alpha);
 
        //glColor3f(1.0f, 1.0f, 1.0f);
        tilemap_.bind();
@@ -95,13 +142,13 @@ void Character::draw(Mf::Scalar alpha) const
 
        glBegin(GL_TRIANGLE_FAN);
                glTexCoord2f(coords[0], coords[1]);
-               glVertex3(state.position[0]-s, state.position[1]-s, z);
+               glVertex3(position[0]-s, position[1]-s, z);
                glTexCoord2f(coords[2], coords[3]);
-               glVertex3(state.position[0]+s, state.position[1]-s, z);
+               glVertex3(position[0]+s, position[1]-s, z);
                glTexCoord2f(coords[4], coords[5]);
-               glVertex3(state.position[0]+s, state.position[1]+s, z);
+               glVertex3(position[0]+s, position[1]+s, z);
                glTexCoord2f(coords[6], coords[7]);
-               glVertex3(state.position[0]-s, state.position[1]+s, z);
+               glVertex3(position[0]-s, position[1]+s, z);
        glEnd();
 
        //glColor3f(0.0f, 0.0f, 0.0f);
index 087bf494c819743eafc099fcca9f7c9635fc300a..090e7cb97a1d308e124735f01190f21751e785e0 100644 (file)
@@ -50,6 +50,7 @@ typedef boost::shared_ptr<Character> CharacterP;
 
 struct Character : public Mf::Entity
 {
+       /*
        struct Derivative
        {
                Mf::Vector2 velocity;
@@ -134,9 +135,10 @@ struct Character : public Mf::Entity
                        return newState;
                }
        };
+*/
 
-       State                   previous;
-       State                   current;
+       Mf::State2              previous;
+       Mf::State2              current;
 
 
 private:
index c16d701d9afc391aa17da399e14cbf16efa70592..e74f6010b584b7ab646b2d0b3391bd1ea9dd8cdb 100644 (file)
@@ -40,7 +40,7 @@
 
 typedef GLdouble       GLscalar;
 #define GL_SCALAR      GL_DOUBLE
-#define SCALAR(D)      D
+#define SCALAR(D)      (D)
 
 inline void glGetScalarv(GLenum a, GLscalar* b)
 { glGetDoublev(a, b); }
@@ -96,7 +96,7 @@ inline void glTexCoord4v(const GLscalar* a)
 
 typedef GLfloat                GLscalar;
 #define GL_SCALAR      GL_FLOAT
-#define SCALAR(F)      F##f
+#define SCALAR(F)      (F##f)
 
 inline void glGetScalarv(GLenum a, GLscalar* b)
 { glGetFloatv(a, b); }
index 806127ecc977c1388b2dcef37f838f2658f86f77..453cf1ef4e1d00766bcb4b27383784a4082917e6 100644 (file)
 #ifndef _MOOF_RK4_HH_
 #define _MOOF_RK4_HH_
 
+#include <vector>
+
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
 #include <Moof/Math.hh>
 
 
 namespace Mf {
 
+
 // Generic implementations of a few simple integrators.  To use, you need one
 // type representing the state and another containing the derivatives of the
 // primary state variables.  The state class must implement these methods:
 //
 // void getDerivative(Derivative_Type& derivative, Scalar absoluteTime);
-// void applyDerivative(const Derivative_Type& derivative, Scalar deltaTime);
+// void step(const Derivative_Type& derivative, Scalar deltaTime);
 //
 // Additionally, the derivative class must overload a few operators:
 //
@@ -55,11 +61,10 @@ inline D evaluate(const S& state, Scalar t)
 }
 
 template<typename S, typename D>
-inline D evaluate(const S& state,  Scalar t, Scalar dt, const D& derivative)
+inline D evaluate(S state,  Scalar t, Scalar dt, const D& derivative)
 {
-       S temp = state;
-       temp.applyDerivative(derivative, dt);
-       return evaluate<S,D>(temp, t + dt);
+       state.step(derivative, dt);
+       return evaluate<S,D>(state, t + dt);
 }
 
 
@@ -68,30 +73,224 @@ inline void euler(S& state, Scalar t, Scalar dt)
 {
        D a = evaluate<S,D>(state, t);
 
-       state.applyDerivative(a, dt);
+       state.step(a, dt);
 }
 
 template<typename S, typename D>
 inline void rk2(S& state, Scalar t, Scalar dt)
 {
        D a = evaluate<S,D>(state, t);
-       D b = evaluate<S,D>(state, t, dt * 0.5, a);
+       D b = evaluate<S,D>(state, t, dt * SCALAR(0.5), a);
 
-       state.applyDerivative(b, dt);
+       state.step(b, dt);
 }
 
 template<typename S, typename D>
 inline void rk4(S& state, Scalar t, Scalar dt)
 {
        D a = evaluate<S,D>(state, t);
-       D b = evaluate<S,D>(state, t, dt * 0.5, a);
-       D c = evaluate<S,D>(state, t, dt * 0.5, b);
+       D b = evaluate<S,D>(state, t, dt * SCALAR(0.5), a);
+       D c = evaluate<S,D>(state, t, dt * SCALAR(0.5), b);
        D d = evaluate<S,D>(state, t, dt, c);
 
-       state.applyDerivative((a + (b + c) * 2.0 + d) * (1.0/6.0), dt);
+       state.step((a + (b + c) * SCALAR(2.0) + d) * SCALAR(1.0/6.0), dt);
 }
 
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+template <int D = 3>
+struct LinearState
+{
+       typedef cml::vector< Scalar, cml::fixed<D> >                            Vector;
+       typedef boost::function<const Vector& (const LinearState&)>     ForceFunction;
+
+       // primary
+       
+       Vector          position;
+       Vector          momentum;
+
+       // secondary
+
+       Vector          velocity;
+
+       // user
+       //
+       Vector          force;
+       std::vector<ForceFunction> forces;
+
+       // constant
+       
+       Scalar          mass;
+       Scalar          inverseMass;
+
+
+       void recalculateLinear()
+       {
+               velocity = momentum * inverseMass;
+       }
+
+
+       struct GravityForce
+       {
+               explicit GravityForce(Scalar a = -9.8)
+               {
+                       force.zero();
+                       acceleration = a;
+               }
+
+               const Vector& operator () (const LinearState& state)
+               {
+                       force[1] = state.mass * acceleration;
+                       return force;
+               }
+
+       private:
+
+               Vector force;
+               Scalar acceleration;
+       };
+
+
+       void init()
+       {
+               position.zero();
+               momentum.zero();
+
+               velocity.zero();
+
+               force.zero();
+               forces.clear();
+
+               mass = SCALAR(1.0);
+               inverseMass = 1.0 / mass;
+       }
+
+
+       struct Derivative
+       {
+               Vector  velocity;
+               Vector  force;
+
+               Derivative operator*(Scalar dt) const
+               {
+                       Derivative derivative;
+                       derivative.velocity = dt * velocity;
+                       derivative.force = dt * force;
+                       return derivative;
+               }
+
+               Derivative operator+(const Derivative& other) const
+               {
+                       Derivative derivative;
+                       derivative.velocity = velocity + other.velocity;
+                       derivative.force = force + other.force;
+                       return derivative;
+               }
+       };
+
+
+       Vector getForce() const
+       {
+               Vector f(force);
+
+               for (size_t i = 0; i < forces.size(); ++i)
+               {
+                       f += forces[i](*this);
+               }
+
+               return f;
+       }
+
+       void getDerivative(Derivative& derivative, Scalar t) const
+       {
+               derivative.velocity = velocity;
+               derivative.force = getForce();
+       }
+
+       void step(const Derivative& derivative, Scalar dt)
+       {
+               position += dt * derivative.velocity;
+               momentum += dt * derivative.force;
+               recalculateLinear();
+       }
+};
+
+
+struct RotationalState2
+{
+       // primary
+
+       Scalar          orientation;
+       Scalar          angularMomentum;
+
+       // secondary
+
+       Scalar          angularVelocity;
+
+       // constant
+
+       Scalar          inertia;
+       Scalar          inverseInertia;
+
+
+       void recalculateRotational()
+       {
+               angularVelocity = angularMomentum * inertia;
+       }
+
+
+       struct Derivative
+       {
+               Scalar  angularVelocity;
+               Scalar  torque;
+       };
+
+       void step(const Derivative& derivative, Scalar dt)
+       {
+               orientation += dt * derivative.angularVelocity;
+               angularMomentum += dt * derivative.torque;
+               recalculateRotational();
+       }
+};
+
+struct RotationalState3
+{
+       // primary
+
+       Quaternion      orientation;
+       Vector3         angularMomentum;
+
+       // secondary
+
+       Quaternion      spin;
+       Vector3         angularVelocity;
+
+       // constant
+
+       Scalar          inertia;
+       Scalar          inverseInertia;
+};
+
+
+struct State2 : public LinearState<2>, public RotationalState2
+{
+       void recalculate()
+       {
+               recalculateLinear();
+               recalculateRotational();
+       }
+
+       void integrate(Scalar t, Scalar dt)
+       {
+               rk4<LinearState<2>,LinearState<2>::Derivative>(*this, t, dt);
+       }
+};
+
+struct State3 : public LinearState<3>, public RotationalState3 {};
+
+
 } // namespace Mf
 
 #endif // _MOOF_RK4_HH_
This page took 0.031953 seconds and 4 git commands to generate.