00001 /* 00002 Sheep - A Rigid Body Dynamics Engine 00003 Copyright (C) 2001-2004 Francois Beaune 00004 Contact: http://toxicengine.sourceforge.net/ 00005 00006 This file is part of Sheep. 00007 00008 Sheep is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 Sheep is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with Sheep; if not, write to the Free Software 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 */ 00022 00023 #include "rigidbody.h" 00024 00025 using namespace sheep; 00026 00027 #define STATEVECTOR RigidBody::StateVector 00028 00029 STATEVECTOR RigidBody::StateVectorDE::GetDerivativeAt(const STATEVECTOR &x, Real t) const { 00030 // Rotation matrix associated to the body's orientation. 00031 Matrix3 R = Matrix3::Rotation(x.m_q.Normalized()); // world space 00032 00033 assert(feq(R.Determinant(), 1)); 00034 00035 // Inertia tensor in world space. 00036 Matrix3 I = R * m_parent->m_inertia * R.Transpose(); // world space 00037 00038 // Angular velocity. 00039 Vector3 omega = I.Inverse() * x.m_L; // world space 00040 00041 STATEVECTOR d; 00042 00043 // Derivative of the location of the center of mass. 00044 d.m_x = 1.0 / m_parent->m_mass * x.m_P; // world space 00045 00046 // Derivative of the orientation. 00047 d.m_q = 0.5 * Quaternion(0, omega) * x.m_q; // world space 00048 00049 // Derivative of the linear momentum. 00050 d.m_P = m_parent->m_total_force; // world space 00051 00052 // Derivative of the angular momentum. 00053 d.m_L = m_parent->m_total_torque; // world space 00054 00055 return d; 00056 } 00057 00058 #undef STATEVECTOR 00059 00060 RigidBody::RigidBody(Real mass, const Matrix3 &inertia) { 00061 const Real EPSILON = 1e-6; 00062 00063 assert(mass > EPSILON); 00064 assert(fnz(inertia.Determinant())); 00065 00066 m_mass = mass; 00067 m_inertia = inertia; 00068 00069 // Define the initial state of the body. 00070 m_state.m_x = 0; 00071 m_state.m_q = Quaternion::Identity(); 00072 m_state.m_P = 0; 00073 m_state.m_L = 0; 00074 00075 // The state differential equation needs to access the body 00076 // to which it is attached. 00077 m_state_de = new StateVectorDE(this); 00078 00079 m_is_frozen = false; 00080 00081 m_total_force = 0; 00082 m_total_torque = 0; 00083 } 00084 00085 RigidBody::~RigidBody() { 00086 delete m_state_de; 00087 } 00088 00089 void RigidBody::EvolveOneStep(const StateDESolver &solver, Real t, Real h) { 00090 const Real EPSILON = 1e-6; 00091 00092 assert(h > EPSILON); 00093 00094 m_state = solver.Integrate(*m_state_de, m_state, t, h); 00095 00096 //!\todo Calculate the system energy. 00097 00098 // Numerical integration can result in a non-normalized quaternion 00099 // for the orientation, so we ensure that this quaternion has unit 00100 // length before continuing. 00101 m_state.m_q = m_state.m_q.Normalized(); 00102 }
1.3.6