Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

physics/ODECollisionDetector.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2002 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: ODECollisionDetector.cpp 1066 2004-02-27 19:55:32Z jungd $
00019  
00020 ****************************************************************************/
00021 
00022 #include <physics/ODECollisionDetector>
00023 
00024 #include <physics/ODECollidableBody>
00025 
00026 using physics::ODECollisionDetector;
00027 
00028 using base::Vector3;
00029 using physics::CollisionState;
00030 using physics::CollidableBody;
00031 using physics::ODECollidableBody;
00032 
00033 //!!!debug
00034 #include <physics/SolidConnectedCollidableBody>
00035 using physics::SolidConnectedCollidableBody;
00036 
00037 
00038 
00039 ODECollisionDetector::ODECollisionDetector()
00040 {
00041 }
00042 
00043 
00044 ODECollisionDetector::~ODECollisionDetector()
00045 {
00046 }
00047 
00048 
00049 ref<CollidableBody> ODECollisionDetector::createCollidableBody(ref<Shape> shape)
00050 {
00051   return ref<CollidableBody>(NewNamedObj("ODECollidableBody") ODECollidableBody(shape));
00052 }
00053 
00054 
00055 ODECollisionDetector::ODECollisionState::ODECollisionState(ref<const CollidableBody> collidable1, ref<const CollidableBody> collidable2)
00056   : CollisionState(collidable1, collidable2)
00057 {
00058 }
00059 
00060 
00061 ODECollisionDetector::ODECollisionState::~ODECollisionState()
00062 {
00063 }
00064 
00065 
00066 
00067 
00068 ref<CollisionState> ODECollisionDetector::newCollisionState(ref<const CollidableBody> collidable1, ref<const CollidableBody> collidable2) const
00069 {
00070   if (&(*collidable1) > &(*collidable2))
00071     base::swap(collidable1,collidable2);
00072 
00073   return ref<ODECollisionState>(NewNamedObj("ODECollisionState") ODECollisionState(collidable1, collidable2) );
00074 }
00075 
00076 
00077 
00078 void ODECollisionDetector::collide(ref<const Collidable> collidable1, ref<const Collidable> collidable2)
00079 {
00080   if (!isCollisionEnabled()) return;
00081 
00082   Assertm( &(*collidable1) != &(*collidable2), "collidable1 is not collidable2");
00083   
00084   if (!instanceof(*collidable1, const ODECollidableBody) || !instanceof(*collidable2, const ODECollidableBody))
00085     throw new std::runtime_error(Exception("can only collide() Collidables of type CollidableBody (specifically ODECollidableBody"));
00086 
00087   ref<const ODECollidableBody> collidableBody1(narrow_ref<const ODECollidableBody>(collidable1));
00088   ref<const ODECollidableBody> collidableBody2(narrow_ref<const ODECollidableBody>(collidable2));
00089   
00090   if (&(*collidableBody1) > &(*collidableBody2))
00091     base::swap(collidableBody1,collidableBody2);
00092 
00093   // Get the CollisionState for the pair of CollidableBodys
00094   ref<CollisionState> cstate(getCollisionState(collidableBody1,collidableBody2));
00095 
00096 
00097   //
00098   // Do a pair-wise collision check
00099   
00100   dGeomID geomID1 = collidableBody1->getGeomID();
00101   dGeomID geomID2 = collidableBody2->getGeomID();
00102   Assert( !dGeomIsSpace(geomID1) );
00103   Assert( !dGeomIsSpace(geomID2) );
00104 
00105   // call ODE dCollide 
00106   dContactGeom contacts[4]; //!!! probably needs to be greater (perhaps object dependent, so that boxes only use 4 etc.)
00107   Int numContacts = dCollide(geomID1, geomID2, 4, contacts, sizeof(dContactGeom));
00108   bool collided = (numContacts != 0);
00109 
00110 
00111   if (collided) {
00112 //!!!
00113 //String name1( instanceof(*collidable1, const SolidConnectedCollidableBody)? (narrow_ref<const SolidConnectedCollidableBody>(collidable1))->getSolid()->getName():"unknown");
00114 //String name2( instanceof(*collidable2, const SolidConnectedCollidableBody)? (narrow_ref<const SolidConnectedCollidableBody>(collidable2))->getSolid()->getName():"unknown");
00115 //if ((name1 == "TitanII link 3") && (name2 == "ground")) {
00116 //Debugcln(Tmp,"collision between:" << name1 << "(geomID:" << (void*)geomID1  
00117 //                            << ") and " << name2 << "(geomID:" << (void*)geomID2 << ")");
00118 //}
00119 
00120     // construct contacts 
00121     cstate->contacts.clear();
00122     for (Int c=0; c<numContacts; c++) {
00123       dContactGeom* odeContact(&contacts[c]);
00124       // transform global contact point into local coords  of each Solid
00125       Point3 gcpos(odeContact->pos[0], odeContact->pos[1], odeContact->pos[2]); // global coord. frame
00126       Point3 cpos1( inverse(collidableBody1->getConfiguration()) * gcpos );
00127       Point3 cpos2( inverse(collidableBody2->getConfiguration()) * gcpos );
00128       
00129       //!!!
00130 //      Quat4 orientation1( collidableBody1->getOrientation() );
00131 //      Quat4 orientation2( collidableBody2->getOrientation() );
00132 //      Point3 position1( collidableBody1->getPosition() );
00133 //      Point3 position2( collidableBody2->getPosition() );
00134       
00135 //      Point3 cpos1( inverse(orientation1).rotate(gcpos-position1) );
00136 //      Point3 cpos2( inverse(orientation2).rotate(gcpos-position2) );
00137 
00138       // transform normal into Solid1 frame
00139       Vector3 gnormal( odeContact->normal[0], odeContact->normal[1], odeContact->normal[2] );
00140       Orient  inverseRot( collidableBody1->getOrientation() ); inverseRot.invert();
00141       Vector3 normal1 = inverseRot.rotate(gnormal);
00142       
00143 //      Vector3 normal1( inverse(orientation1).rotate(gnormal));
00144 
00145       CollisionState::Contact contact(cpos1, cpos2, normal1, Real(odeContact->depth) );
00146       cstate->contacts.push_back(contact);
00147     }
00148 
00149     notifyListeners(collidable1, collidable2);
00150     
00151   } 
00152     
00153 }
00154 

Generated on Thu Jul 29 15:56:25 2004 for OpenSim by doxygen 1.3.6