00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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;
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;
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
00192 dVector Pos=ObState->Transform.gettranslate();
00193
00194
00195 dMatrix rotation = ObState->Transform;
00196 rotation.remove_scale();
00197 dVector zero(0,0,0);
00198 rotation.settranslate(zero);
00199
00200
00201 ObState->Transform*=rotation.inverse();
00202
00203
00204
00205
00206 Ob->Prim->ApplyTransform(true);
00207
00208
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
00224
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
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
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
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
00304 dVector Pos=ObState->Transform.gettranslate();
00305
00306
00307 dMatrix rotation = ObState->Transform;
00308 rotation.remove_scale();
00309 dVector zero(0,0,0);
00310 rotation.settranslate(zero);
00311
00312
00313 ObState->Transform*=rotation.inverse();
00314 ObState->Transform.settranslate(zero);
00315
00316
00317
00318
00319 Ob->Prim->ApplyTransform(false);
00320
00321 ObState->Transform=rotation;
00322 ObState->Transform.settranslate(Pos);
00323
00324
00325
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
00340
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
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
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);
00559 dJointSetHinge2Param(j,dParamFMax2,100);
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);
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;
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;
00793 case HingeJoint : dJointSetHingeParam(i->second->Joint,p,Value); break;
00794 case SliderJoint : dJointSetSliderParam(i->second->Joint,p,Value); break;
00795 case ContactJoint : break;
00796 case UniversalJoint : dJointSetUniversalParam(i->second->Joint,p,Value); break;
00797 case Hinge2Joint : dJointSetHinge2Param(i->second->Joint,p,Value); break;
00798 case FixedJoint : break;
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
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