open_toontown_panda3d/panda/src/physics/physicsManager.cxx

341 lines
11 KiB
C++

// Filename: physicsManager.cxx
// Created by: charles (14Jun00)
//
////////////////////////////////////////////////////////////////////
//
// 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 "physicsManager.h"
#include "actorNode.h"
#include <algorithm>
#include "pvector.h"
ConfigVariableInt PhysicsManager::_random_seed
("physics_manager_random_seed", 139);
////////////////////////////////////////////////////////////////////
// Function : PhysicsManager
// Access : Public
// Description : Default Constructor. NOTE: EulerIntegrator is
// the standard default.
////////////////////////////////////////////////////////////////////
PhysicsManager::
PhysicsManager() {
_linear_integrator.clear();
_angular_integrator.clear();
_viscosity=0.0;
}
////////////////////////////////////////////////////////////////////
// Function : ~PhysicsManager
// Access : Public
// Description : Simple Destructor
////////////////////////////////////////////////////////////////////
PhysicsManager::
~PhysicsManager() {
PhysicalsVector::iterator pi;
for (pi = _physicals.begin(); pi != _physicals.end(); ++pi) {
nassertv((*pi)->_physics_manager == this);
(*pi)->_physics_manager = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function : InitRandomSeed
// Access : Public
// Description : One-time config function, sets up the random seed
// used by the physics and particle systems.
// For synchronizing across distributed computers
////////////////////////////////////////////////////////////////////
void PhysicsManager::
init_random_seed() {
// Use the random seed specified by the physics_manager_random_seed
// Config Variable
srand(_random_seed);
}
////////////////////////////////////////////////////////////////////
// Function : remove_linear_force
// Access : Public
// Description : takes a linear force out of the physics list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_linear_force(LinearForce *f) {
nassertv(f);
LinearForceVector::iterator found;
PT(LinearForce) ptbf = f;
found = find(_linear_forces.begin(), _linear_forces.end(), ptbf);
if (found == _linear_forces.end()) {
return;
}
_linear_forces.erase(found);
}
////////////////////////////////////////////////////////////////////
// Function : remove_angular_force
// Access : Public
// Description : takes an angular force out of the physics list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_angular_force(AngularForce *f) {
nassertv(f);
AngularForceVector::iterator found;
PT(BaseForce) ptbf = f;
found = find(_angular_forces.begin(), _angular_forces.end(), ptbf);
if (found == _angular_forces.end()) {
return;
}
_angular_forces.erase(found);
}
////////////////////////////////////////////////////////////////////
// Function : remove_physical
// Access : Public
// Description : takes a physical out of the object list
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_physical(Physical *p) {
nassertv(p);
pvector< Physical * >::iterator found;
found = find(_physicals.begin(), _physicals.end(), p);
if (found == _physicals.end()) {
return;
}
nassertv(p->_physics_manager == this);
p->_physics_manager = (PhysicsManager *) NULL;
_physicals.erase(found);
}
////////////////////////////////////////////////////////////////////
// Function : remove_physical_node
// Access : Public
// Description : Removes a physicalnode from the manager
////////////////////////////////////////////////////////////////////
void PhysicsManager::
remove_physical_node(PhysicalNode *p) {
nassertv(p);
for (int i = 0; i < p->get_num_physicals(); ++i) {
remove_physical(p->get_physical(i));
}
}
////////////////////////////////////////////////////////////////////
// Function : DoPhysics
// Access : Public
// Description : This is the main high-level API call. Performs
// integration on every attached Physical.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
do_physics(PN_stdfloat dt) {
// now, run through each physics object in the set.
PhysicalsVector::iterator p_cur = _physicals.begin();
for (; p_cur != _physicals.end(); ++p_cur) {
Physical *physical = *p_cur;
nassertv(physical);
// do linear
//if (_linear_integrator.is_null() == false) {
if (_linear_integrator) {
_linear_integrator->integrate(physical, _linear_forces, dt);
}
// do angular
//if (_angular_integrator.is_null() == false) {
if (_angular_integrator) {
_angular_integrator->integrate(physical, _angular_forces, dt);
}
// if it's an actor node, tell it to update itself.
PhysicalNode *pn = physical->get_physical_node();
if (pn && pn->is_of_type(ActorNode::get_class_type())) {
ActorNode *an = (ActorNode *) pn;
an->update_transform();
}
}
}
////////////////////////////////////////////////////////////////////
// Function : DoPhysics
// Access : Public
// Description : This is the main high-level API call. Performs
// integration on a single physical. Make sure its
// associated forces are active.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
do_physics(PN_stdfloat dt, Physical *physical) {
nassertv(physical);
// do linear
//if (_linear_integrator.is_null() == false) {
if (_linear_integrator) {
_linear_integrator->integrate(physical, _linear_forces, dt);
}
// do angular
//if (_angular_integrator.is_null() == false) {
if (_angular_integrator) {
_angular_integrator->integrate(physical, _angular_forces, dt);
}
// if it's an actor node, tell it to update itself.
PhysicalNode *pn = physical->get_physical_node();
if (pn && pn->is_of_type(ActorNode::get_class_type())) {
ActorNode *an = (ActorNode *) pn;
an->update_transform();
}
}
////////////////////////////////////////////////////////////////////
// Function : output
// Access : Public
// Description : Write a string representation of this instance to
// <out>.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
output(ostream &out) const {
#ifndef NDEBUG //[
out<<""<<"PhysicsManager";
#endif //] NDEBUG
}
////////////////////////////////////////////////////////////////////
// Function : write_physicals
// Access : Public
// Description : Write a string representation of this instance to
// <out>.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
write_physicals(ostream &out, unsigned int indent) const {
#ifndef NDEBUG //[
if (indent>10) {
return;
}
out.width(indent);
out<<""<<"_physicals ("<<_physicals.size()<<" physicals)\n";
//out<<ios::width(indent)<<" "<<"[physicals \n";
for (pvector< Physical * >::const_iterator i=_physicals.begin();
i != _physicals.end();
++i) {
(*i)->write(out, indent+2);
}
#endif //] NDEBUG
}
////////////////////////////////////////////////////////////////////
// Function : write_forces
// Access : Public
// Description : Write a string representation of this instance to
// <out>.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
write_linear_forces(ostream &out, unsigned int indent) const {
#ifndef NDEBUG //[
out.width(indent);
out<<""<<"_linear_forces ("<<_linear_forces.size()<<" forces)\n";
for (LinearForceVector::const_iterator i=_linear_forces.begin();
i != _linear_forces.end();
++i) {
(*i)->write(out, indent+2);
}
#endif //] NDEBUG
}
////////////////////////////////////////////////////////////////////
// Function : write_angular_forces
// Access : Public
// Description : Write a string representation of this instance to
// <out>.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
write_angular_forces(ostream &out, unsigned int indent) const {
#ifndef NDEBUG //[
out.width(indent);
out<<""<<"_angular_forces ("<<_angular_forces.size()<<" forces)\n";
for (AngularForceVector::const_iterator i=_angular_forces.begin();
i != _angular_forces.end();
++i) {
(*i)->write(out, indent+2);
}
#endif //] NDEBUG
}
////////////////////////////////////////////////////////////////////
// Function : write
// Access : Public
// Description : Write a string representation of this instance to
// <out>.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
write(ostream &out, unsigned int indent) const {
#ifndef NDEBUG //[
out.width(indent); out<<""<<"PhysicsManager:\n";
if (indent>20) {
// ...indent limit is arbitrary, it limits recursion.
out.width(indent+2); out<<""<<"...\n";
return;
}
write_physicals(out, indent+2);
write_linear_forces(out, indent+2);
write_angular_forces(out, indent+2);
out.width(indent+2); out<<""<<"_linear_integrator:\n";
if (_linear_integrator) {
_linear_integrator->write(out, indent+4);
} else {
out.width(indent+4); out<<""<<"null\n";
}
out.width(indent+2); out<<""<<"_angular_integrator:\n";
if (_angular_integrator) {
_angular_integrator->write(out, indent+4);
} else {
out.width(indent+4); out<<""<<"null\n";
}
#endif //] NDEBUG
}
////////////////////////////////////////////////////////////////////
// Function : write
// Access : Public
// Description : Write a string representation of this instance to
// <out>.
////////////////////////////////////////////////////////////////////
void PhysicsManager::
debug_output(ostream &out, unsigned int indent) const {
#ifndef NDEBUG //[
out.width(indent); out<<""<<"PhysicsManager li"<<(_linear_integrator?1:0)<<" ai"<<(_angular_integrator?1:0)<<"\n";
out<<" _physicals "<<_physicals.size()<<"\n";
//_physicals._phys_body.write(out, indent+2);
out.width(indent+2);
out<<""<<"_linear_forces ("<<_linear_forces.size()<<" forces)\n";
LinearForceVector::const_iterator li;
for (li=_linear_forces.begin();
li != _linear_forces.end();
++li) {
(*li)->write(out, indent+2);
}
out.width(indent+2);
out<<""<<" _angular_forces "<<_angular_forces.size()<<"\n";
AngularForceVector::const_iterator ai;
for (ai=_angular_forces.begin();
ai != _angular_forces.end();
++ai) {
(*ai)->write(out, indent+2);
}
#endif //] NDEBUG
}