Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

c:/home/kevn/src/animaniac/ani/Dynamics/Particle.h

Go to the documentation of this file.
00001 
00003 //
00004 //                         -=     Particle     =-
00005 //
00006 // Definition: "particle, just position no rotation, 2nd order derivatives"
00007 //
00009 //
00010 //    $RCSfile: Particle.h,v $
00011 //    $Date: 2002/06/10 03:08:00 $
00012 //    $Revision: 1.9 $
00013 //    Copyright (C) 1998, 1999, 2000  Kevin Meinert, kevin@vrsource.org
00014 //
00015 //    This library is free software; you can redistribute it and/or
00016 //    modify it under the terms of the GNU Library General Public
00017 //    License as published by the Free Software Foundation; either
00018 //    version 2 of the License, or (at your option) any later version.
00019 //
00020 //    This library is distributed in the hope that it will be useful,
00021 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00023 //    Library General Public License for more details.
00024 //
00025 //    You should have received a copy of the GNU Library General Public
00026 //    License along with this library; if not, write to the Free
00027 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 //
00030 #ifndef PARTICLE_INCLUDED_H
00031 #define PARTICLE_INCLUDED_H
00032 
00033 #include <gmtl/Vec.h>
00034 
00035 #include "ani/Dynamics/Memory.h"
00036 
00037 // Rigid body references:
00038 //  - Thick, very detailed.
00039 //    http://www.cs.cmu.edu/~baraff/sigcourse/
00040 //  - Easy to understand, most is implemented from it.
00041 //    http://www.cs.unc.edu/~ehmann/RigidTutorial/
00042 
00043 
00044 // ani namespace.
00045 namespace ani
00046 {
00047    //: Particle, for use in a particle system.
00048    //  particle is able to do newtonian physics through application of force.
00049    //  - Dynamic attributes (affected by force) include position, and velocity
00050    //  - Static attributes (which are not affected by force) include mass, and color.
00051    //
00052    // Use Particle objects in conjunction with DynamicSystem, Operator, and ODEsolvers.
00053    //
00054    // Notes on "phase space"
00055    // The motion of a newtonian particle is governed by the familiar f = ma, or, as we will write it here 
00056    // x'' = a = f/m.  This equation differs from a canonical ODE because it involves a second time derivative, making
00057    // it a _second_order_ equation.  To handle a second order ODE, we convert it to a first order one by introducing
00058    // extra variables.  Here we create a variable mVelocity to represent velocity, giving us a pair of coupled first
00059    // order ODE's: v' = f/m, and x' = v.  This position/velocity product space is called _phase_space_.
00060    class Particle : public ani::Memory
00061    {
00062    public:
00063       Particle() : ani::Memory(),
00064                mPosition( 0.0f, 0.0f, 0.0f ),
00065                mLinearMomentum( 0.0f, 0.0f, 0.0f ),
00066                mForceAccumulator( 0.0f, 0.0f, 0.0f ),
00067                mMass( 1.0f ), mInvMass( 1.0f ), mVolume( 1.0f, 1.0f, 1.0f ),
00068                mDragCoef(1.0f)//, mColor
00069       {
00070       }
00071 
00072       Particle( const Particle& p )
00073       {
00074          this->copy( p );
00075       }      
00076 
00077       virtual ~Particle()
00078       {
00079       }
00080 
00081    // operations/operators:
00082    public:
00083 
00084       Particle& operator=( const Particle& p )
00085       {
00086          this->copy( p );
00087          return *this;
00088       }   
00089 
00090       // this = p
00091       // copies all attributes.
00092       inline virtual void copy( const Particle& p )
00093       {
00094          mPosition = p.mPosition;           
00095          mLinearMomentum = p.mLinearMomentum;  
00096          mForceAccumulator = p.mForceAccumulator;  
00097          mMass = p.mMass;
00098          mInvMass = p.mInvMass; 
00099          mVolume = p.mVolume;         
00100          mDragCoef = p.mDragCoef;
00101       }
00102 
00103       //: computeDerivative
00104       //
00105       // The behavior of the system is described by an "Ordinary
00106       // Differential Equation" (ODE) of the form
00107       // x' = f( x, t )
00108       // where f is a known function, x is the state of the system
00109       // and x' is the time derivitive of x.
00110       //
00111       // Here, f = computeDerivative, x' = this, and x = currentState;
00112       // This function computes change due to the force accumulator
00113       // The x' returned assumes time=1, so for example using Euler's 
00114       // method to solve the next step, you will have to scale 
00115       // x' by the amount of time since this func was last called.
00116       // 
00117       //
00118       // this = the time derivitive of "currentState"
00119       inline virtual void computeDerivative( const Particle& currentState, const float& currentTime )
00120       {
00121          // change in position/rotation over time (first order)
00122             // x' = v = P(t)/M
00123             mPosition = currentState.linearVelocity();
00124 
00125          // change in momentum over time (second order)
00126             // P'(t) = F(t)
00127             mLinearMomentum = currentState.mForceAccumulator;
00128       }
00129 
00130       virtual void normalize()
00131       {
00132       }
00133 
00134       // scale by time.
00135       // this = a * h
00136       inline virtual void multiplyPhase( const Particle& a, float h )
00137       {
00138          mPosition = a.mPosition * h;
00139          mLinearMomentum = a.mLinearMomentum * h;
00140       }
00141 
00142       // scale by time.
00143       // this *= h
00144       inline virtual void multiplyPhase( float h )
00145       {
00146          mPosition *= h;
00147          mLinearMomentum *= h;
00148       }
00149 
00150       // phase space addition operator
00151       // this = a + b
00152       inline virtual void addPhase( const Particle& a, const Particle& b )
00153       {
00154          mPosition = a.mPosition + b.mPosition;
00155          mLinearMomentum = a.mLinearMomentum + b.mLinearMomentum;
00156       }
00157 
00158       // phase space addition operator
00159       // this += a
00160       inline virtual void addPhase( const Particle& a ) //
00161       {
00162          mPosition += a.mPosition;
00163          mLinearMomentum += a.mLinearMomentum;
00164       }
00165 
00166    // state setting/accumulation
00167    public:   
00168       void setPosition( const gmtl::Vec3f& position) { mPosition = position; }
00169       void setVelocity( const gmtl::Vec3f& velocity ) { mLinearMomentum = velocity * mMass; }
00170 
00171       //: Apply a force to the particle
00172       //  Each call to applyForce adds a force vector and torque to the particle.
00173       //  call update() to finally apply the accumulated forces which were added with this function.
00174       //  NOTE: the force applied, should be with respect to 1.0 unit of time.
00175       void applyForce( const gmtl::Vec3f& force ) 
00176       { 
00177          mForceAccumulator += force; 
00178       }
00179       
00180       inline virtual void zeroForce()
00181       {
00182          mForceAccumulator.set( 0.0f, 0.0f, 0.0f );
00183       }
00184 
00185       //: set the mass
00186       //  units are metric kilograms
00187       void setMass( const float& kilograms )
00188       {
00189          mMass = kilograms;
00190          
00191          // precompute the inverse mass
00192          mInvMass = 1.0f / kilograms;  
00193       }
00194       
00195       void setVolume( gmtl::Vec3f vol )
00196       {
00197          mVolume = vol;
00198       }
00199       
00200    // aliases (getters)
00201    public:
00202    // "phase space" (see note above)
00203       inline const gmtl::Vec3f&       position() const { return mPosition; }
00204       
00205       //: Calculate v(t)
00206       inline gmtl::Vec3f linearVelocity() const
00207       {
00208          return mLinearMomentum * mInvMass;
00209       }
00210       
00211       inline gmtl::Vec3f linearMomentum() const
00212       {
00213          return mLinearMomentum;
00214       }
00215        
00216    // other things needed by ODE to compute changes in the "phase space"
00217       inline const gmtl::Vec3f& accumulatedForce() const { return mForceAccumulator; }
00218       inline const float&       mass() const { return mMass; }
00219       inline const gmtl::Vec3f& volume() const { return mVolume; }
00220 
00221    public:
00222    //:: "phase space" (see note above)
00223       // state variables:
00224       gmtl::Vec3f mPosition;           // meters        - x(t)
00225       gmtl::Vec3f mLinearMomentum;     // linear momentum P(t)
00226                                        // mLinearMomentum = mMass * mVelocity
00227 
00228       // derived quantities (aux variables)
00229       //gmtl::Vec3f mVelocity;         // v(t) (meters/second)
00230       
00231    //:: other things needed by ODE to compute changes in the "phase space"
00232 
00233       // accumulation buffers:
00234       gmtl::Vec3f mForceAccumulator;  // newtons - F(t)
00235       
00236       // constant (set) quantities
00237       float       mMass, mInvMass;    // kilograms
00238       gmtl::Vec3f mVolume;            // 3D volume (a box)
00239 
00240    // other attribs for the particle.
00241       float       mDragCoef;          // just a coef from 0 (no drag) to 1 (drag)
00242    };
00243 
00244 }; // ani namespace
00245 
00246 #endif

Generated on Wed Jun 12 01:54:01 2002 for Animaniac by doxygen1.2.15