Physics.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2005 Dave Griffiths
00002 //
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 #include <ode/ode.h>
00018 #include "Physics.h"
00019 #include "State.h"
00020 #include "Primitive.h"
00021 
00022 using namespace Fluxus;
00023 
00024 Physics::Object::Object()
00025 {
00026     Prim=NULL;
00027 }
00028 
00029 Physics::Object::~Object()
00030 {
00031     if (Type==ACTIVE) dBodyDestroy(Body);
00032     dGeomDestroy(Bound);
00033     Prim->SetPhysicalHint(false);
00034 }
00035 
00036 Physics::JointObject::JointObject()
00037 {
00038 }
00039 
00040 Physics::JointObject::~JointObject()
00041 {
00042     dJointDestroy(Joint);
00043 }
00044         
00046 
00047 Physics::Physics(Renderer *r) :
00048 m_Renderer(r),
00049 m_MaxObjectCount(1000),
00050 m_GroundCreated(false),
00051 m_NextJointID(1),
00052 m_Collisions(false),
00053 m_Slip1(0.9),
00054 m_Slip2(0.9),
00055 m_SoftErp(0.25),
00056 m_SoftCfm(0.15)
00057 {
00058     m_World = dWorldCreate();
00059     m_Space = dHashSpaceCreate(0);
00060     m_ContactGroup = dJointGroupCreate(0);
00061     dWorldSetGravity(m_World,0,-5,0);
00062 }
00063 
00064 Physics::~Physics()
00065 {
00066 }
00067     
00068 void Physics::Tick()
00069 {
00070     m_CollisionRecord.clear();
00071 
00072     dSpaceCollide(m_Space,this,&NearCallback);
00073     dWorldQuickStep(m_World,0.05);
00074     
00075     // remove all contact joints
00076     dJointGroupEmpty(m_ContactGroup);
00077 
00078     UpdatePrimitives();
00079 }
00080 
00081 void Physics::DrawLocator(dVector3 pos)
00082 {
00083     float scale=0.5;
00084     glBegin(GL_LINES);          
00085     glVertex3f(pos[0]-scale,pos[1],pos[2]);
00086     glVertex3f(pos[0]+scale,pos[1],pos[2]);
00087     glVertex3f(pos[0],pos[1]-scale,pos[2]);
00088     glVertex3f(pos[0],pos[1]+scale,pos[2]);
00089     glVertex3f(pos[0],pos[1],pos[2]-scale);
00090     glVertex3f(pos[0],pos[1],pos[2]+scale);
00091     glEnd();
00092 }
00093 
00094 void Physics::DrawAxis(dVector3 pos, dVector3 dir)
00095 {
00096     glBegin(GL_LINES);          
00097     glVertex3f(pos[0],pos[1],pos[2]);
00098     glVertex3f(pos[0]+dir[0],pos[1]+dir[1],pos[2]+dir[2]);
00099     glEnd();
00100 }
00101 
00102 void Physics::Render()
00103 {
00104     glDisable(GL_LIGHTING);
00105     glDisable(GL_DEPTH_TEST);
00106     
00107     for (map<int,JointObject*>::iterator i=m_JointMap.begin(); i!=m_JointMap.end(); i++)
00108     {
00109         switch (i->second->Type)
00110         {
00111             case BallJoint      : 
00112             { 
00113                 dVector3 pos;
00114                 dJointGetBallAnchor(i->second->Joint, pos);
00115                 glColor3f(1,0,0);
00116                 DrawLocator(pos);
00117             }
00118             break;
00119             case HingeJoint     : 
00120             {
00121                 dVector3 pos;
00122                 dJointGetHingeAnchor(i->second->Joint, pos);
00123                 glColor3f(1,0,0);
00124                 DrawLocator(pos);
00125                 dJointGetHingeAnchor2(i->second->Joint, pos);
00126                 DrawLocator(pos);
00127                 dVector3 axis;
00128                 dJointGetHingeAxis(i->second->Joint, axis);
00129                 glColor3f(0,1,0);
00130                 DrawAxis(pos,axis);
00131             }
00132             break;  
00133             case SliderJoint :   break;
00134             case ContactJoint   : break;    // no set param required
00135             case UniversalJoint : break;    
00136             case Hinge2Joint   : 
00137             {
00138                 dVector3 pos;
00139                 dJointGetHinge2Anchor(i->second->Joint, pos);
00140                 glColor3f(1,0,0);
00141                 DrawLocator(pos);
00142                 dJointGetHinge2Anchor2(i->second->Joint, pos);
00143                 DrawLocator(pos);
00144                 dVector3 axis;
00145                 dJointGetHinge2Axis1(i->second->Joint, axis);
00146                 glColor3f(0,1,0);
00147                 DrawAxis(pos,axis);
00148                 dJointGetHinge2Axis2(i->second->Joint, axis);
00149                 DrawAxis(pos,axis);
00150             }
00151             break;
00152             case FixedJoint     : break;    // no set param required
00153             case AMotorJoint    : break;
00154         }   
00155     }   
00156     glEnable(GL_LIGHTING);
00157     glEnable(GL_DEPTH_TEST);
00158 }
00159 
00160 void Physics::SetGravity(const dVector &g)
00161 {
00162     dWorldSetGravity(m_World,g.x,g.y,g.z);
00163 }
00164 
00165 void Physics::GroundPlane(dVector ori, float off)
00166 {
00167     m_Ground = dCreatePlane(m_Space,ori.x,ori.y,ori.z,off);
00168     m_GroundCreated=true;
00169 }
00170 
00171 void Physics::MakeActive(int ID, float Mass, BoundingType Bound)
00172 {   
00173     if (m_ObjectMap.find(ID)!=m_ObjectMap.end())
00174     {
00175         Trace::Stream<<"Physics::AddToGroup : Object ["<<ID<<"] already registered"<<endl;
00176         return;
00177     }
00178     
00179     Object *Ob = new Object;
00180     Ob->Type = ACTIVE;
00181     Ob->Prim = m_Renderer->GetPrimitive(ID);    
00182     
00183     if (!Ob->Prim) return;
00184     Ob->Prim->SetPhysicalHint(true);
00185     
00186     dMass m;
00187     Ob->Body = dBodyCreate(m_World);
00188     
00189     State *ObState=Ob->Prim->GetState();
00190     
00191     // get position
00192     dVector Pos=ObState->Transform.gettranslate();
00193     
00194     // extract the rotation from the state
00195     dMatrix rotation = ObState->Transform;
00196     rotation.remove_scale();
00197     dVector zero(0,0,0);
00198     rotation.settranslate(zero);
00199     
00200     // remove the rotation 
00201     ObState->Transform*=rotation.inverse();
00202         
00203     // need to apply transform to object here, so we are left with an identity in the
00204     // state transform for the object, and the bounding volume will be correct.
00205     // can't undo this. 
00206     Ob->Prim->ApplyTransform(true);     
00207     
00208     // get the bounding box from the fluxus object
00209     switch (Bound)
00210     {
00211         case BOX:
00212         {
00213             dBoundingBox Box=Ob->Prim->GetBoundingBox();
00214             dVector BoxSize=Box.max-Box.min;
00215             dMassSetBox(&m,1,BoxSize.x,BoxSize.y,BoxSize.z);
00216             dMassAdjust(&m,Mass);
00217             dBodySetMass(Ob->Body,&m);
00218             Ob->Bound = dCreateBox (m_Space,BoxSize.x,BoxSize.y,BoxSize.z);
00219         } break;
00220         case SPHERE:
00221         {
00222             dBoundingBox Box=Ob->Prim->GetBoundingBox();
00223             // Take the distance across the box in x divided by 2 to be the
00224             // radius. This works with a sphere well enough...
00225             float Radius=(Box.max.x-Box.min.x)/2;
00226             dMassSetSphere(&m,1,Radius);
00227             dMassAdjust(&m,Mass);
00228             dBodySetMass(Ob->Body,&m);
00229             Ob->Bound = dCreateSphere (m_Space,Radius); 
00230         } break;
00231         case CYLINDER:
00232         {
00233             dBoundingBox Box=Ob->Prim->GetBoundingBox();
00234             float Radius=(Box.max.x-Box.min.x)/2;
00235             float Height=Box.max.y-Box.min.y;
00236             dMassSetCappedCylinder(&m,1,2,Radius,Height);
00237             dMassAdjust(&m,Mass);
00238             dBodySetMass(Ob->Body,&m);
00239             Ob->Bound = dCreateCCylinder(m_Space,Radius,Height);    
00240         }
00241     }
00242     
00243     // set rotation into ode body
00244     dMatrix4 rot;
00245     rot[0]=rotation.m[0][0];
00246     rot[1]=rotation.m[1][0];
00247     rot[2]=rotation.m[2][0];
00248     rot[3]=rotation.m[3][0];
00249     
00250     rot[4]=rotation.m[0][1];
00251     rot[5]=rotation.m[1][1];
00252     rot[6]=rotation.m[2][1];
00253     rot[7]=rotation.m[3][1];
00254     
00255     rot[8]=rotation.m[0][2];
00256     rot[9]=rotation.m[1][2];
00257     rot[10]=rotation.m[2][2];
00258     rot[11]=rotation.m[3][2];
00259 
00260     rot[12]=rotation.m[0][3];
00261     rot[13]=rotation.m[1][3];
00262     rot[14]=rotation.m[2][3];
00263     rot[15]=rotation.m[3][3];
00264     
00265     dBodySetRotation(Ob->Body,rot);
00266     
00267     // set position into ode body
00268     dBodySetPosition(Ob->Body,Pos.x,Pos.y,Pos.z);
00269 
00270     dGeomSetBody (Ob->Bound,Ob->Body);
00271     
00272     dBodySetAutoDisableFlag(Ob->Body, 1);   
00273         
00274     m_ObjectMap[ID]=Ob;
00275     m_History.push_back(ID);
00276     
00277     // remove oldest object if neccesary
00278     if ((int)m_ObjectMap.size()>m_MaxObjectCount)
00279     {
00280         Free(*m_History.begin());
00281         m_Renderer->RemovePrimitive(*m_History.begin());
00282         m_History.pop_front();
00283     }
00284 }
00285 
00286 void Physics::MakePassive(int ID, float Mass, BoundingType Bound)
00287 {   
00288     if (m_ObjectMap.find(ID)!=m_ObjectMap.end())
00289     {
00290         Trace::Stream<<"Physics::AddToGroup : Object ["<<ID<<"] already registered"<<endl;
00291         return;
00292     }
00293     
00294     Object *Ob = new Object;
00295     Ob->Type = PASSIVE;
00296     Ob->Prim = m_Renderer->GetPrimitive(ID);    
00297     
00298     if (!Ob->Prim) return;
00299     Ob->Prim->SetPhysicalHint(true);
00300     
00301     State *ObState=Ob->Prim->GetState();
00302     
00303     // get position
00304     dVector Pos=ObState->Transform.gettranslate();
00305     
00306     // extract the rotation from the state
00307     dMatrix rotation = ObState->Transform;
00308     rotation.remove_scale();
00309     dVector zero(0,0,0);
00310     rotation.settranslate(zero);
00311     
00312     // remove the rotation 
00313     ObState->Transform*=rotation.inverse();
00314     ObState->Transform.settranslate(zero);
00315     
00316     // need to apply transform to object here, so we are left with an identity in the
00317     // state transform for the object, and the bounding volume will be correct etc.
00318     // can't undo this. 
00319     Ob->Prim->ApplyTransform(false);  
00320     
00321     ObState->Transform=rotation;
00322     ObState->Transform.settranslate(Pos);
00323     
00324     // this tells ode to attach joints to the static environment if they are attached
00325     // to this joint
00326     Ob->Body = 0;
00327     
00328     switch (Bound)
00329     {
00330         case BOX:
00331         {
00332             dBoundingBox Box=Ob->Prim->GetBoundingBox();
00333             dVector BoxSize=Box.max-Box.min;
00334             Ob->Bound = dCreateBox(m_Space,BoxSize.x,BoxSize.y,BoxSize.z);
00335         } break;
00336         case SPHERE:
00337         {
00338             dBoundingBox Box=Ob->Prim->GetBoundingBox();
00339             // Take the distance across the box in x divided by 2 to be the
00340             // radius. This works with a sphere well enough...
00341             float Radius=(Box.max.x-Box.min.x)/2;
00342             Ob->Bound = dCreateSphere(m_Space,Radius);  
00343         } break;
00344         case CYLINDER:
00345         {
00346             dBoundingBox Box=Ob->Prim->GetBoundingBox();
00347             float Radius=(Box.max.x-Box.min.x)/2;
00348             float Height=Box.max.y-Box.min.y;
00349             Ob->Bound = dCreateCCylinder(m_Space,Radius,Height);    
00350         }
00351     }
00352     
00353     // set rotation into ode body
00354     dMatrix4 rot;
00355     rot[0]=rotation.m[0][0];
00356     rot[1]=rotation.m[1][0];
00357     rot[2]=rotation.m[2][0];
00358     rot[3]=rotation.m[3][0];
00359     
00360     rot[4]=rotation.m[0][1];
00361     rot[5]=rotation.m[1][1];
00362     rot[6]=rotation.m[2][1];
00363     rot[7]=rotation.m[3][1];
00364     
00365     rot[8]=rotation.m[0][2];
00366     rot[9]=rotation.m[1][2];
00367     rot[10]=rotation.m[2][2];
00368     rot[11]=rotation.m[3][2];
00369 
00370     rot[12]=rotation.m[0][3];
00371     rot[13]=rotation.m[1][3];
00372     rot[14]=rotation.m[2][3];
00373     rot[15]=rotation.m[3][3];
00374     
00375     dGeomSetPosition(Ob->Bound,Pos.x,Pos.y,Pos.z);
00376     dGeomSetRotation(Ob->Bound,rot);
00377 
00378     
00379     m_ObjectMap[ID]=Ob;
00380 }
00381 
00382 void Physics::SetMass(int ID, float mass)
00383 {
00384     map<int,Object*>::iterator i = m_ObjectMap.find(ID);
00385     if (i==m_ObjectMap.end())
00386     {
00387         Trace::Stream<<"Physics::SetMass : Object ["<<ID<<"] doesn't exist"<<endl;
00388         return;
00389     }
00390     
00391     if (i->second->Type!=ACTIVE)
00392     {
00393         Trace::Stream<<"Physics::SetMass : Object ["<<ID<<"] isn't active"<<endl;
00394         return;
00395     }
00396     
00397     dMass m;
00398     dBodyGetMass(i->second->Body,&m);
00399     dMassAdjust(&m,mass);
00400     dBodySetMass(i->second->Body,&m);
00401 }
00402 
00403 void Physics::Free(int ID)
00404 {
00405     map<int,Object*>::iterator i = m_ObjectMap.find(ID);
00406     if (i==m_ObjectMap.end())
00407     {
00408         Trace::Stream<<"Physics::Free : Object ["<<ID<<"] doesn't exist"<<endl;
00409         return;
00410     }
00411 
00412     delete i->second;   
00413     m_ObjectMap.erase(i);
00414 }
00415 
00416 void Physics::Clear()
00417 {
00418     for(map<int,Object*>::iterator i=m_ObjectMap.begin(); i!=m_ObjectMap.end(); ++i)
00419     {
00420         delete i->second;   
00421     }
00422     m_ObjectMap.clear();
00423     
00424     for(map<int,JointObject*>::iterator i=m_JointMap.begin(); i!=m_JointMap.end(); ++i)
00425     {
00426         delete i->second;   
00427     }
00428     m_JointMap.clear();
00429     
00430     m_History.clear();
00431     if (m_GroundCreated) 
00432     {
00433         dGeomDestroy(m_Ground);
00434         m_GroundCreated=false;
00435     }
00436     
00437     m_NextJointID=0;
00438 }
00439 
00440 void Physics::UpdatePrimitives()
00441 {
00442     // for every object
00443     for(map<int,Object*>::iterator i=m_ObjectMap.begin(); i!=m_ObjectMap.end(); ++i)
00444     {
00445         if (i->second->Type==ACTIVE)
00446         {
00447             float Pos[3]={dBodyGetPosition(i->second->Body)[0],
00448                           dBodyGetPosition(i->second->Body)[1],
00449                           dBodyGetPosition(i->second->Body)[2]};
00450                     
00451             dMatrix Rot(dBodyGetRotation(i->second->Body)[0], dBodyGetRotation(i->second->Body)[1], dBodyGetRotation(i->second->Body)[2],
00452                            dBodyGetRotation(i->second->Body)[3], dBodyGetRotation(i->second->Body)[4], dBodyGetRotation(i->second->Body)[5],
00453                            dBodyGetRotation(i->second->Body)[6], dBodyGetRotation(i->second->Body)[7], dBodyGetRotation(i->second->Body)[8],
00454                            dBodyGetRotation(i->second->Body)[9], dBodyGetRotation(i->second->Body)[10], dBodyGetRotation(i->second->Body)[11], 0,0,0,1);
00455                     
00456             dVector PosVec(Pos[0],Pos[1],Pos[2]);   
00457                 
00458             i->second->Prim->GetState()->Transform=Rot;
00459             i->second->Prim->GetState()->Transform.settranslate(PosVec);
00460         }
00461     }
00462 }
00463 
00464 void Physics::Kick(int ID, dVector v)
00465 {
00466     map<int,Object*>::iterator i = m_ObjectMap.find(ID);
00467     if (i==m_ObjectMap.end())
00468     {
00469         Trace::Stream<<"Physics::Kick : Object ["<<ID<<"] doesn't exist"<<endl;
00470         return;
00471     }
00472     
00473     if (i->second->Type==ACTIVE)
00474     {
00475         const dReal *cv = dBodyGetLinearVel(i->second->Body);
00476         dBodySetLinearVel(i->second->Body,cv[0]+v.x,cv[1]+v.y,cv[2]+v.z);
00477     }
00478 }
00479 
00480 void Physics::Twist(int ID, dVector v)
00481 {
00482     map<int,Object*>::iterator i = m_ObjectMap.find(ID);
00483     if (i==m_ObjectMap.end())
00484     {
00485         Trace::Stream<<"Physics::Twist : Object ["<<ID<<"] doesn't exist"<<endl;
00486         return;
00487     }
00488     
00489     if (i->second->Type==ACTIVE)
00490     {
00491         const dReal *cv = dBodyGetAngularVel(i->second->Body);
00492         dBodySetAngularVel(i->second->Body,cv[0]+v.x,cv[1]+v.y,cv[2]+v.z);
00493     }
00494 }
00495 
00496 void Physics::NearCallback(void *data, dGeomID o1, dGeomID o2)
00497 {
00498     ((Physics*)data)->NearCallback_i(o1,o2);
00499 }
00500 
00501 void Physics::NearCallback_i(dGeomID o1, dGeomID o2)
00502 {
00503     if (m_Collisions)
00504     {
00505         const int N = 10;
00506         dContact contact[N];
00507 
00508         int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));
00509         if (n > 0)
00510         {
00511             for (int i=0; i<n; i++)
00512             {
00513                 contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1;
00514                 contact[i].surface.mu = dInfinity;
00515                 contact[i].surface.slip1 = m_Slip1;
00516                 contact[i].surface.slip2 = m_Slip2;
00517                 contact[i].surface.soft_erp = m_SoftErp;
00518                 contact[i].surface.soft_cfm = m_SoftCfm;
00519                 dJointID c = dJointCreateContact(m_World,m_ContactGroup,&contact[i]);
00520                 dBodyID geom1 = dGeomGetBody(contact[i].geom.g1);
00521                 dBodyID geom2 = dGeomGetBody(contact[i].geom.g2);
00522                 dJointAttach(c,geom1,geom2);
00523                 m_CollisionRecord.insert(geom1);
00524                 m_CollisionRecord.insert(geom2);
00525             }
00526         }
00527     }
00528 }
00529 
00530 int Physics::CreateJointHinge2(int Ob1, int Ob2, dVector Anchor, dVector Hinge[2])
00531 {
00532     map<int,Object*>::iterator i1 = m_ObjectMap.find(Ob1);
00533     map<int,Object*>::iterator i2 = m_ObjectMap.find(Ob2);
00534     
00535     if (i1==m_ObjectMap.end())
00536     {
00537         Trace::Stream<<"Physics::CreateJointHinge2 : Object ["<<Ob1<<"] doesn't exist"<<endl;
00538         return 0;
00539     }
00540     
00541     if (i2==m_ObjectMap.end())
00542     {
00543         Trace::Stream<<"Physics::CreateJointHinge2 : Object ["<<Ob2<<"] doesn't exist"<<endl;
00544         return 0;
00545     }
00546     
00547     if (i1->second->Body==0 || i2->second->Body==0)
00548     {
00549         Trace::Stream<<"Physics::CreateJointHinge2 : cant connect passive objects"<<endl;
00550         return 0;
00551     }
00552 
00553     dJointID j = dJointCreateHinge2(m_World,0);
00554     dJointAttach(j,i1->second->Body,i2->second->Body);
00555     dJointSetHinge2Anchor(j,Anchor.x,Anchor.y,Anchor.z);
00556     dJointSetHinge2Axis1(j,Hinge[0].x, Hinge[0].y, Hinge[0].z);
00557     dJointSetHinge2Axis2(j,Hinge[1].x, Hinge[1].y, Hinge[1].z);
00558     dJointSetHinge2Param(j,dParamFMax,100); // unlock the joint by default
00559     dJointSetHinge2Param(j,dParamFMax2,100); // unlock the joint by default
00560     
00561     JointObject *NewJoint = new JointObject;
00562     NewJoint->Joint=j;
00563     NewJoint->Type=Hinge2Joint;
00564     m_JointMap[m_NextJointID]=NewJoint;
00565     m_NextJointID++;
00566     return m_NextJointID-1;
00567 }
00568 
00569 int Physics::CreateJointHinge(int Ob1, int Ob2, dVector Anchor, dVector Hinge)
00570 {
00571     map<int,Object*>::iterator i1 = m_ObjectMap.find(Ob1);
00572     map<int,Object*>::iterator i2 = m_ObjectMap.find(Ob2);
00573     
00574     if (i1==m_ObjectMap.end())
00575     {
00576         Trace::Stream<<"Physics::CreateJointHinge : Object ["<<Ob1<<"] doesn't exist"<<endl;
00577         return 0;
00578     }
00579     
00580     if (i2==m_ObjectMap.end())
00581     {
00582         Trace::Stream<<"Physics::CreateJointHinge : Object ["<<Ob2<<"] doesn't exist"<<endl;
00583         return 0;
00584     }
00585     
00586     if (i1->second->Body==0 || i2->second->Body==0)
00587     {
00588         Trace::Stream<<"Physics::CreateJointHinge : cant connect passive objects"<<endl;
00589         return 0;
00590     }
00591     
00592     dJointID j = dJointCreateHinge(m_World,0);
00593     dJointAttach (j,i1->second->Body,i2->second->Body);
00594     dJointSetHingeAnchor(j,Anchor.x,Anchor.y,Anchor.z);
00595     dJointSetHingeAxis(j,Hinge.x, Hinge.y, Hinge.z);
00596     dJointSetHingeParam(j,dParamFMax,100); // unlock the joint by default
00597     
00598     JointObject *NewJoint = new JointObject;
00599     NewJoint->Joint=j;
00600     NewJoint->Type=HingeJoint;
00601     m_JointMap[m_NextJointID]=NewJoint;
00602     m_NextJointID++;
00603     return m_NextJointID-1;
00604 }
00605 
00606 int Physics::CreateJointFixed(int Ob)
00607 {
00608     map<int,Object*>::iterator i = m_ObjectMap.find(Ob);
00609     
00610     if (i==m_ObjectMap.end())
00611     {
00612         Trace::Stream<<"Physics::CreateJointFixed : Object ["<<Ob<<"] doesn't exist"<<endl;
00613         return 0;
00614     }
00615     
00616     if (i->second->Body==0)
00617     {
00618         Trace::Stream<<"Physics::CreateJointFixed : can't connect passive objects"<<endl;
00619         return 0;
00620     }
00621 
00622     dJointID j = dJointCreateFixed(m_World,0);
00623     dJointAttach (j,0,i->second->Body);
00624     dJointSetFixed(j);
00625     
00626     JointObject *NewJoint = new JointObject;
00627     NewJoint->Joint=j;
00628     NewJoint->Type=FixedJoint;
00629     m_JointMap[m_NextJointID]=NewJoint;
00630     m_NextJointID++;
00631     return m_NextJointID-1;
00632 }
00633 
00634 int Physics::CreateJointSlider(int Ob1, int Ob2, dVector Hinge)
00635 {
00636     map<int,Object*>::iterator i1 = m_ObjectMap.find(Ob1);
00637     map<int,Object*>::iterator i2 = m_ObjectMap.find(Ob2);
00638     
00639     if (i1==m_ObjectMap.end())
00640     {
00641         Trace::Stream<<"Physics::CreateJointSlider : Object ["<<Ob1<<"] doesn't exist"<<endl;
00642         return 0;
00643     }
00644     
00645     if (i2==m_ObjectMap.end())
00646     {
00647         Trace::Stream<<"Physics::CreateJointSlider : Object ["<<Ob2<<"] doesn't exist"<<endl;
00648         return 0;
00649     }
00650 
00651     if (i1->second->Body==0 || i2->second->Body==0)
00652     {
00653         Trace::Stream<<"Physics::CreateJointSlider : cant connect passive objects"<<endl;
00654         return 0;
00655     }
00656     
00657     dJointID j = dJointCreateSlider(m_World,0);
00658     dJointAttach (j,i1->second->Body,i2->second->Body);
00659     dJointSetSliderAxis(j,Hinge.x, Hinge.y, Hinge.z);
00660     
00661     JointObject *NewJoint = new JointObject;
00662     NewJoint->Joint=j;
00663     NewJoint->Type=SliderJoint;
00664     m_JointMap[m_NextJointID]=NewJoint;
00665     m_NextJointID++;
00666     return m_NextJointID-1;
00667 }
00668 
00669 int Physics::CreateJointAMotor(int Ob1, int Ob2, dVector Axis)
00670 {
00671     map<int,Object*>::iterator i1 = m_ObjectMap.find(Ob1);
00672     map<int,Object*>::iterator i2 = m_ObjectMap.find(Ob2);
00673     
00674     if (i1==m_ObjectMap.end())
00675     {
00676         Trace::Stream<<"Physics::CreateJointAMotor : Object ["<<Ob1<<"] doesn't exist"<<endl;
00677         return 0;
00678     }
00679     
00680     if (i2==m_ObjectMap.end())
00681     {
00682         Trace::Stream<<"Physics::CreateJointAMotor : Object ["<<Ob2<<"] doesn't exist"<<endl;
00683         return 0;
00684     }
00685 
00686     if (i1->second->Body==0 || i2->second->Body==0)
00687     {
00688         Trace::Stream<<"Physics::CreateJointAMotor : cant connect passive objects"<<endl;
00689         return 0;
00690     }
00691 
00692     dJointID j = dJointCreateAMotor (m_World,0);
00693     dJointAttach(j,i1->second->Body,i2->second->Body);
00694 
00695     dJointSetAMotorMode(j,dAMotorUser);
00696     dJointSetAMotorNumAxes(j,1);
00697     dJointSetAMotorAxis(j, 0, 1, Axis.x, Axis.y, Axis.z);
00698               
00699     JointObject *NewJoint = new JointObject;
00700     NewJoint->Joint=j;
00701     NewJoint->Type=AMotorJoint;
00702     m_JointMap[m_NextJointID]=NewJoint;
00703     m_NextJointID++;
00704     return m_NextJointID-1;
00705 }
00706 
00707 int Physics::CreateJointBall(int Ob1, int Ob2, dVector Anchor)
00708 {
00709     map<int,Object*>::iterator i1 = m_ObjectMap.find(Ob1);
00710     map<int,Object*>::iterator i2 = m_ObjectMap.find(Ob2);
00711     
00712     if (i1==m_ObjectMap.end())
00713     {
00714         Trace::Stream<<"Physics::CreateJointBall : Object ["<<Ob1<<"] doesn't exist"<<endl;
00715         return 0;
00716     }
00717     
00718     if (i2==m_ObjectMap.end())
00719     {
00720         Trace::Stream<<"Physics::CreateJointBall : Object ["<<Ob2<<"] doesn't exist"<<endl;
00721         return 0;
00722     }
00723 
00724     if (i1->second->Body==0 || i2->second->Body==0)
00725     {
00726         Trace::Stream<<"Physics::CreateJointBall : cant connect passive objects"<<endl;
00727         return 0;
00728     }
00729 
00730     dJointID j = dJointCreateHinge2 (m_World,0);
00731     dJointAttach (j,i1->second->Body,i2->second->Body);
00732     dJointSetBallAnchor (j,Anchor.x,Anchor.y,Anchor.z);
00733 
00734     JointObject *NewJoint = new JointObject;
00735     NewJoint->Joint=j;
00736     NewJoint->Type=BallJoint;
00737     m_JointMap[m_NextJointID]=NewJoint;
00738     m_NextJointID++;
00739     return m_NextJointID-1;
00740 }
00741 
00742 void Physics::SetJointAngle(int ID, float vel, float angle)
00743 {
00744     map<int,JointObject*>::iterator i = m_JointMap.find(ID);
00745     if (i==m_JointMap.end())
00746     {
00747         Trace::Stream<<"Physics::SetJointAngle : Joint ["<<ID<<"] doesn't exist"<<endl;
00748         return;
00749     }
00750     
00751     if (i->second->Type==HingeJoint)
00752     {
00753         float cur=dJointGetHingeAngle(i->second->Joint);
00754         float diff=fabs(cur-angle);
00755         vel*=diff; // add some damping
00756         if (cur<angle) dJointSetHingeParam(i->second->Joint,dParamVel,vel);
00757         else dJointSetHingeParam(i->second->Joint,dParamVel,-vel);
00758     }
00759 }
00760 
00761 void Physics::SetJointParam(int ID, const string &Param, float Value)
00762 { 
00763     map<int,JointObject*>::iterator i = m_JointMap.find(ID);
00764     if (i==m_JointMap.end())
00765     {
00766         Trace::Stream<<"Physics::SetJointParam : Joint ["<<ID<<"] doesn't exist"<<endl;
00767         return;
00768     }
00769 
00770     int p=-1;
00771     if (Param=="LoStop")             p=dParamLoStop;
00772     else if (Param=="HiStop")        p=dParamHiStop;                   
00773     else if (Param=="Vel")           p=dParamVel;              
00774     else if (Param=="FMax")          p=dParamFMax;            
00775     else if (Param=="FudgeFactor")   p=dParamFudgeFactor;        
00776     else if (Param=="Bounce")        p=dParamBounce;           
00777     else if (Param=="CFM")           p=dParamCFM;              
00778     else if (Param=="StopERP")       p=dParamStopERP;            
00779     else if (Param=="StopCFM")       p=dParamStopCFM;
00780     else if (Param=="SuspensionERP") p=dParamSuspensionERP; 
00781     else if (Param=="SuspensionCFM") p=dParamSuspensionCFM;
00782     else if (Param=="Vel2")          p=dParamVel2;
00783     else if (Param=="FMax2")         p=dParamFMax2; 
00784     else 
00785     {
00786         Trace::Stream<<"unknown parameter "<<Param<<endl;
00787         return;
00788     }
00789     
00790     switch (i->second->Type)
00791     {
00792         case BallJoint      : break; // no set param required   
00793         case HingeJoint     : dJointSetHingeParam(i->second->Joint,p,Value); break; 
00794         case SliderJoint    : dJointSetSliderParam(i->second->Joint,p,Value); break;    
00795         case ContactJoint   : break;    // no set param required
00796         case UniversalJoint : dJointSetUniversalParam(i->second->Joint,p,Value); break; 
00797         case Hinge2Joint    : dJointSetHinge2Param(i->second->Joint,p,Value); break;    
00798         case FixedJoint     : break;    // no set param required
00799         case AMotorJoint    : dJointSetAMotorParam(i->second->Joint,p,Value); break;
00800         default : Trace::Stream<<"unknown joint type "<<i->second->Type<<endl; return; break;   
00801     }   
00802 }
00803 
00804 bool Physics::HasCollided(int Ob)
00805 {
00806     map<int,Object*>::iterator i = m_ObjectMap.find(Ob);
00807     if (i==m_ObjectMap.end())
00808     {
00809         Trace::Stream<<"Physics::HasCollided : Object ["<<Ob<<"] doesn't exist"<<endl;
00810         return false;
00811     }
00812     
00813     // only active objects have bodies to get
00814     if (i->second->Type==ACTIVE && m_CollisionRecord.find(i->second->Body)!=m_CollisionRecord.end())
00815     {
00816         return true;
00817     }
00818     
00819     return false;
00820 }
00821 

Generated on Tue Sep 4 23:22:18 2007 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1