00001 // Filename: angularEulerIntegrator.cxx 00002 // Created by: charles (09Aug00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "angularEulerIntegrator.h" 00020 #include "forceNode.h" 00021 #include "physicalNode.h" 00022 #include "config_physics.h" 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function : AngularEulerIntegrator 00026 // Access : Public 00027 // Description : constructor 00028 //////////////////////////////////////////////////////////////////// 00029 AngularEulerIntegrator:: 00030 AngularEulerIntegrator(void) { 00031 } 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Function : AngularEulerIntegrator 00035 // Access : Public 00036 // Description : destructor 00037 //////////////////////////////////////////////////////////////////// 00038 AngularEulerIntegrator:: 00039 ~AngularEulerIntegrator(void) { 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function : Integrate 00044 // Access : Public 00045 // Description : Integrate a step of motion (based on dt) by 00046 // applying every force in force_vec to every object 00047 // in obj_vec. 00048 //////////////////////////////////////////////////////////////////// 00049 void AngularEulerIntegrator:: 00050 child_integrate(Physical *physical, 00051 pvector< PT(AngularForce) >& forces, 00052 float dt) { 00053 // perform the precomputation. Note that the vector returned by 00054 // get_precomputed_matrices() has the matrices loaded in order of force 00055 // type: first global, then local. If you're using this as a guide to write 00056 // another integrator, be sure to process your forces global, then local. 00057 // otherwise your transforms will be VERY bad. No good. 00058 precompute_angular_matrices(physical, forces); 00059 const pvector< LMatrix4f > &matrices = get_precomputed_angular_matrices(); 00060 00061 // Loop through each object in the set. This processing occurs in O(pf) time, 00062 // where p is the number of physical objects and f is the number of 00063 // forces. Unfortunately, no precomputation of forces can occur, as 00064 // each force is possibly contingent on such things as the position and 00065 // velocity of each physicsobject in the set. Accordingly, we have 00066 // to grunt our way through each one. wrt caching of the xform matrix 00067 // should help. 00068 pvector< PT(PhysicsObject) >::const_iterator current_object_iter; 00069 current_object_iter = physical->get_object_vector().begin(); 00070 00071 for (; current_object_iter != physical->get_object_vector().end(); 00072 current_object_iter++) { 00073 00074 PhysicsObject *current_object = *current_object_iter; 00075 00076 // bail out if this object doesn't exist or doesn't want to be 00077 // processed. 00078 if (current_object == (PhysicsObject *) NULL) 00079 continue; 00080 00081 if (current_object->get_active() == false) 00082 continue; 00083 00084 LVector3f accum_vec(0, 0, 0); 00085 00086 // set up the traversal stuff. 00087 ForceNode *force_node; 00088 pvector< PT(AngularForce) >::const_iterator f_cur; 00089 00090 LVector3f f; 00091 00092 // global forces 00093 f_cur = forces.begin(); 00094 int index = 0; 00095 for (; f_cur != forces.end(); f_cur++) { 00096 AngularForce *cur_force = *f_cur; 00097 00098 // make sure the force is turned on. 00099 if (cur_force->get_active() == false) 00100 continue; 00101 00102 force_node = cur_force->get_force_node(); 00103 00104 // now we go from force space to our object's space. 00105 f = cur_force->get_vector(current_object) * matrices[index++]; 00106 00107 // tally it into the accum vector, applying the inertial tensor. 00108 accum_vec += f; 00109 } 00110 00111 // local forces 00112 f_cur = physical->get_angular_forces().begin(); 00113 for (; f_cur != physical->get_angular_forces().end(); f_cur++) { 00114 AngularForce *cur_force = *f_cur; 00115 00116 // make sure the force is turned on. 00117 if (cur_force->get_active() == false) 00118 continue; 00119 00120 force_node = cur_force->get_force_node(); 00121 00122 // go from force space to object space 00123 f = cur_force->get_vector(current_object) * matrices[index++]; 00124 00125 // tally it into the accum vectors 00126 accum_vec += f; 00127 } 00128 00129 // apply the accumulated torque vector to the object's inertial tensor. 00130 // this matrix represents how much force the object 'wants' applied to it 00131 // in any direction, among other things. 00132 accum_vec = accum_vec * current_object->get_inertial_tensor(); 00133 00134 // derive this into the angular velocity vector. 00135 LVector3f rot_vec = current_object->get_rotation(); 00136 rot_vec += accum_vec * dt; 00137 00138 // here's the trick. we've been accumulating these forces as vectors 00139 // and treating them as vectors, but now we're going to treat them as pure 00140 // imaginary quaternions where r = 0. This vector NOW represents the 00141 // imaginary vector formed by (i, j, k). 00142 00143 LVector3f normalized_rot_vec = rot_vec; 00144 float len = rot_vec.length(); 00145 00146 normalized_rot_vec *= 1.0f / len; 00147 LRotationf rot_quat = LRotationf(normalized_rot_vec, len); 00148 00149 LOrientationf old_orientation = current_object->get_orientation(); 00150 LOrientationf new_orientation = old_orientation * rot_quat; 00151 new_orientation.normalize(); 00152 00153 // and write the results back. 00154 current_object->set_orientation(new_orientation); 00155 current_object->set_rotation(rot_vec); 00156 } 00157 }