// Filename: angularEulerIntegrator.cxx // Created by: charles (09Aug00) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved // // All use of this software is subject to the terms of the Panda 3d // Software license. You should have received a copy of this license // along with this source code; you will also find a current copy of // the license at http://etc.cmu.edu/panda3d/docs/license/ . // // To contact the maintainers of this program write to // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// #include "angularEulerIntegrator.h" #include "forceNode.h" #include "physicalNode.h" #include "config_physics.h" //////////////////////////////////////////////////////////////////// // Function : AngularEulerIntegrator // Access : Public // Description : constructor //////////////////////////////////////////////////////////////////// AngularEulerIntegrator:: AngularEulerIntegrator() { } //////////////////////////////////////////////////////////////////// // Function : AngularEulerIntegrator // Access : Public // Description : destructor //////////////////////////////////////////////////////////////////// AngularEulerIntegrator:: ~AngularEulerIntegrator() { } //////////////////////////////////////////////////////////////////// // Function : Integrate // Access : Public // Description : Integrate a step of motion (based on dt) by // applying every force in force_vec to every object // in obj_vec. //////////////////////////////////////////////////////////////////// void AngularEulerIntegrator:: child_integrate(Physical *physical, AngularForceVector& forces, float dt) { // perform the precomputation. Note that the vector returned by // get_precomputed_matrices() has the matrices loaded in order of force // type: first global, then local. If you're using this as a guide to write // another integrator, be sure to process your forces global, then local. // otherwise your transforms will be VERY bad. No good. precompute_angular_matrices(physical, forces); const pvector< LMatrix4f > &matrices = get_precomputed_angular_matrices(); assert(matrices.size() == (forces.size() + physical->get_angular_forces().size())); // Loop through each object in the set. This processing occurs in O(pf) time, // where p is the number of physical objects and f is the number of // forces. Unfortunately, no precomputation of forces can occur, as // each force is possibly contingent on such things as the position and // velocity of each physicsobject in the set. Accordingly, we have // to grunt our way through each one. wrt caching of the xform matrix // should help. PhysicsObject::Vector::const_iterator current_object_iter; current_object_iter = physical->get_object_vector().begin(); for (; current_object_iter != physical->get_object_vector().end(); ++current_object_iter) { PhysicsObject *current_object = *current_object_iter; // bail out if this object doesn't exist or doesn't want to be // processed. if (current_object == (PhysicsObject *) NULL) { continue; } if (current_object->get_active() == false) { continue; } LRotationf accum_quat(0, 0, 0, 0); // set up the traversal stuff. //////////////////////ForceNode *force_node; AngularForceVector::const_iterator f_cur; LRotationf f; // global forces f_cur = forces.begin(); unsigned int index = 0; for (; f_cur != forces.end(); ++f_cur) { AngularForce *cur_force = *f_cur; // make sure the force is turned on. if (cur_force->get_active() == false) { continue; } /////////////////force_node = cur_force->get_force_node(); // now we go from force space to our object's space. assert(index >= 0 && index < matrices.size()); //f = matrices[index++] * cur_force->get_quat(current_object); f = cur_force->get_quat(current_object); // tally it into the accumulation quaternion accum_quat += f; } // local forces f_cur = physical->get_angular_forces().begin(); for (; f_cur != physical->get_angular_forces().end(); ++f_cur) { AngularForce *cur_force = *f_cur; // make sure the force is turned on. if (cur_force->get_active() == false) { continue; } ///////////////force_node = cur_force->get_force_node(); // go from force space to object space //assert(index >= 0 && index < matrices.size()); //f = matrices[index++] * cur_force->get_quat(current_object); f = cur_force->get_quat(current_object); // tally it into the accumulation quaternion accum_quat += f; } //assert(index == matrices.size()); // apply the accumulated torque vector to the object's inertial tensor. // this matrix represents how much force the object 'wants' applied to it // in any direction, among other things. accum_quat = current_object->get_inertial_tensor() * accum_quat; // derive this into the angular velocity vector. LRotationf rot_quat = current_object->get_rotation(); #if 0 rot_quat += accum_quat * dt; if (rot_quat.normalize()) { LOrientationf old_orientation = current_object->get_orientation(); LOrientationf new_orientation = old_orientation * rot_quat; new_orientation.normalize(); // and write the results back. current_object->set_orientation(new_orientation); current_object->set_rotation(rot_quat); } #else //accum_quat*=viscosityDamper; LOrientationf orientation = current_object->get_orientation(); //accum_quat.normalize(); // x = x + v * t + 0.5 * a * t * t orientation = orientation * ((rot_quat * dt) * (accum_quat * (0.5 * dt * dt))); // v = v + a * t rot_quat = rot_quat + (accum_quat * dt); //if (rot_quat.normalize()) { //if (orientation.normalize() && rot_quat.normalize()) { // and write the results back. current_object->set_orientation(orientation); current_object->set_rotation(rot_quat); //} #endif } } //////////////////////////////////////////////////////////////////// // Function : output // Access : Public // Description : Write a string representation of this instance to // . //////////////////////////////////////////////////////////////////// void AngularEulerIntegrator:: output(ostream &out) const { #ifndef NDEBUG //[ out<<"AngularEulerIntegrator (id "<. //////////////////////////////////////////////////////////////////// void AngularEulerIntegrator:: write(ostream &out, unsigned int indent) const { #ifndef NDEBUG //[ out.width(indent); out<<""; out<<"AngularEulerIntegrator:\n"; AngularIntegrator::write(out, indent+2); #endif //] NDEBUG }