00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "physics/rigid_body.hpp"
00035
00036 namespace gsgl
00037 {
00038
00039 using namespace data;
00040 using namespace math;
00041
00042
00043 namespace physics
00044 {
00045
00046 rigid_body_state & rigid_body_state::operator= (const rigid_body_state & s)
00047 {
00048 parent_body = s.parent_body;
00049 x = s.x;
00050 q = s.q;
00051 p = s.p;
00052 L = s.L;
00053 return *this;
00054 }
00055
00056
00057 rigid_body_state rigid_body_state::operator+ (const rigid_body_state & s) const
00058 {
00059 rigid_body_state result;
00060
00061 result.parent_body = parent_body;
00062 result.x = x + s.x;
00063 result.q = q + s.q;
00064 result.p = p + s.p;
00065 result.L = L + s.L;
00066
00067 return result;
00068 }
00069
00070
00071 rigid_body_state rigid_body_state::operator* (const double & n) const
00072 {
00073 rigid_body_state result;
00074
00075 result.parent_body = parent_body;
00076 result.x = x * static_cast<gsgl::real_t>(n);
00077 result.q = q * static_cast<gsgl::real_t>(n);
00078 result.p = p * static_cast<gsgl::real_t>(n);
00079 result.L = L * static_cast<gsgl::real_t>(n);
00080
00081 return result;
00082 }
00083
00084
00085 rigid_body_state rigid_body_state::derivative(const double & t) const
00086 {
00087 rigid_body_state result;
00088 result.parent_body = parent_body;
00089
00090 parent_body->calculate_force_and_torque(t, parent_body->force, parent_body->torque);
00091 result.x = parent_body->mass_inverse * p;
00092
00093 vector w = parent_body->j_inverse * L;
00094 result.q = (quaternion(w.get_w(), w.get_x(), w.get_y(), w.get_z()) * q) * 0.5f;
00095
00096 result.p = parent_body->force;
00097 result.L = parent_body->torque;
00098
00099 return result;
00100 }
00101
00102
00103
00104
00105
00106 rigid_body::rigid_body(const config_record & obj_config)
00107 : physics_frame(obj_config),
00108 center_of_mass(vector::ZERO), mass(1), mass_inverse(1),
00109 jbody(transform::IDENTITY), jbody_inverse(transform::IDENTITY)
00110 {
00111 motion_solver = new runge_kutta_solver<rigid_body_state>();
00112
00113
00114 cur_state.parent_body = this;
00115 }
00116
00117
00118 rigid_body::~rigid_body()
00119 {
00120 }
00121
00122
00123 void rigid_body::init(gsgl::scenegraph::context *c)
00124 {
00125
00126 jbody = calculate_inertia_tensor(center_of_mass);
00127 jbody_inverse = jbody.inverse();
00128 mass_inverse = 1.0f / mass;
00129
00130
00131 get_translation() = get_translation() + center_of_mass;
00132
00133
00134 for (simple_array<node *>::iterator i = get_children().iter(); i.is_valid(); ++i)
00135 {
00136 (*i)->get_translation() = (*i)->get_translation() - center_of_mass;
00137 }
00138
00139
00140 cur_state.x = get_translation();
00141 cur_state.p = get_linear_velocity() * mass;
00142 cur_state.q = get_orientation();
00143
00144 R = get_orientation();
00145 cur_state.L = (R * jbody_inverse * R.transpose()).inverse() * get_angular_velocity();
00146
00147 compute_derived_quantities();
00148 }
00149
00150
00151 void rigid_body::update(gsgl::scenegraph::context *c)
00152 {
00153
00154 cur_state = motion_solver->next(cur_state, c->cur_time, c->delta_time);
00155 compute_derived_quantities();
00156
00157
00158 get_translation() = cur_state.x;
00159 get_orientation() = R;
00160 get_linear_velocity() = v;
00161 get_angular_velocity() = w;
00162 }
00163
00164
00165 void rigid_body::compute_derived_quantities()
00166 {
00167 cur_state.q.normalize();
00168 R = cur_state.q;
00169 j_inverse = R * jbody_inverse * R.transpose();
00170 v = mass_inverse * cur_state.p;
00171 w = j_inverse * cur_state.L;
00172 }
00173
00174
00175 }
00176
00177 }