// Filename: angularEulerIntegrator.cxx // Created by: charles (09Aug00) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// #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, PN_stdfloat dt) { // 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; } LRotation accum_quat(0, 0, 0, 0); // set up the traversal stuff. AngularForceVector::const_iterator f_cur; LRotation 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; } // tally it into the accumulation quaternion f = cur_force->get_quat(current_object); accum_quat += f; } LOrientation orientation = current_object->get_orientation(); // 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; } f = cur_force->get_quat(current_object); // tally it into the accumulation quaternion // i.e. orientation * f * orientation.conjugate() accum_quat += orientation.xform(f); } // 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. LRotation rot_quat = current_object->get_rotation(); #if 0 rot_quat += accum_quat * dt; if (rot_quat.normalize()) { LOrientation old_orientation = current_object->get_orientation(); LOrientation 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; //LOrientation 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 }