00001 #include "lugre_prefix.h"
00002 #include "lugre_luabind.h"
00003
00004 extern "C" {
00005 #include "lua.h"
00006 #include "lauxlib.h"
00007 #include "lualib.h"
00008 }
00009
00010 #include "lugre_ode.h"
00011
00012
00013
00014 using namespace Lugre;
00015
00016
00017 #ifdef ENABLE_ODE
00018
00019 using namespace ODE;
00020
00021 void nearCallback(void *data, dGeomID o0, dGeomID o1)
00022 {
00023 cOdeWorld *p = reinterpret_cast<cOdeWorld*>(data);
00024 p->HandleCollisionBetween(o0,o1);
00025 }
00026
00027 cOdeWorld::cOdeWorld (float secondsByStep) : mfSecondsByStep(secondsByStep) {
00028 moWorld = dWorldCreate();
00029 moSpace = dHashSpaceCreate(0);
00030 moContactgroup = dJointGroupCreate(0);
00031
00032
00033 SetGravity(0,0,-9.81f);
00034 }
00035
00036 cOdeWorld::~cOdeWorld (){
00037
00038 while(!mlObject.empty()){
00039 delete(mlObject.front());
00040 }
00041
00042 KillDeadObjects();
00043
00044 dSpaceDestroy(moSpace);
00045 dWorldDestroy(moWorld);
00046 dCloseODE();
00047 }
00048
00049 void cOdeWorld::SetAutoDisableFlag (bool enabled){
00050 dWorldSetAutoDisableFlag(moWorld,enabled);
00051 }
00052
00053 bool cOdeWorld::IsAutoDisableFlagEnabeled(){
00054 return dWorldGetAutoDisableFlag(moWorld);
00055 }
00056
00057 void cOdeWorld::Step() {
00058 double dt = mTimer.elapsed();
00059
00060 if(dt > mfSecondsByStep){
00061
00062 int steps = int(dt / mfSecondsByStep);
00063
00064 for(int i = 0; i < steps; ++i){
00065
00066 dSpaceCollide(moSpace,this,&nearCallback);
00067
00068 dWorldQuickStep(moWorld, mfSecondsByStep);
00069
00070 dJointGroupEmpty(moContactgroup);
00071 }
00072
00073 mTimer.restart();
00074 }
00075 KillDeadObjects();
00076 }
00077
00078 void cOdeWorld::SetGravity (const dReal x, const dReal y, const dReal z){
00079 dWorldSetGravity(moWorld,x,y,z);
00080 }
00081
00082 void cOdeWorld::KillDeadObjects (){
00083 while(mlDeadObject.size() > 0){
00084 cOdeObject *p = *(mlDeadObject.begin());
00085 mlObject.remove(p);
00086 mlDeadObject.pop_front();
00087 delete p;
00088 }
00089 }
00090
00091 void cOdeWorld::HandleCollisionBetween (dGeomID o0, dGeomID o1){
00092
00093
00094
00095 static const int MAX_CONTACTS = 10;
00096 dContact contact[MAX_CONTACTS];
00097
00098 for (int i = 0; i < MAX_CONTACTS; i++)
00099 {
00100 contact[i].surface.mode = dContactBounce | dContactSoftCFM;
00101 contact[i].surface.mu = dInfinity;
00102 contact[i].surface.mu2 = 0;
00103 contact[i].surface.bounce = 0.8;
00104 contact[i].surface.bounce_vel = 0.1;
00105 contact[i].surface.soft_cfm = 0.01;
00106 }
00107 if (int numc = dCollide(o0, o1, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)))
00108 {
00109
00110 dBodyID b1 = dGeomGetBody(o0);
00111 dBodyID b2 = dGeomGetBody(o1);
00112
00113
00114 for (int i = 0; i < numc; i++)
00115 {
00116
00117
00118
00119 dJointID c = dJointCreateContact(moWorld, moContactgroup, contact + i);
00120 dJointAttach(c, b1, b2);
00121 }
00122 }
00123 }
00124
00125
00126
00127
00128 void cOdeObject::SetAutoDisableFlag (bool enabled){
00129 dBodySetAutoDisableFlag(moBody,enabled);
00130 }
00131
00132 bool cOdeObject::IsAutoDisableFlagEnabeled(){
00133 return dBodyGetAutoDisableFlag(moBody);
00134 }
00135
00136 cOdeObject::cOdeObject (cOdeWorld* world, const dReal x, const dReal y, const dReal z) : moBody(0), moGeom(0), mpWorld(world) {
00137 moBody = dBodyCreate(world->moWorld);
00138 dBodySetPosition(moBody,x,y,z);
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 }
00165
00166 void cOdeObject::GetRelPosVel(const ODE::dReal lx, const ODE::dReal ly, const ODE::dReal lz,
00167 ODE::dReal &vx, ODE::dReal &vy, ODE::dReal &vz){
00168
00169 dVector3 local;
00170 dBodyGetRelPointVel(moBody,lx,ly,lz,local);
00171 vx = local[0];
00172 vy = local[1];
00173 vz = local[2];
00174
00175 }
00176
00177 void cOdeObject::SetTorque(const ODE::dReal x, const ODE::dReal y, const ODE::dReal z){dBodySetTorque(moBody,x,y,z);}
00178 void cOdeObject::GetTorque(ODE::dReal &x, ODE::dReal &y, ODE::dReal &z){const dReal* p = dBodyGetTorque(moBody); x = p[0]; y = p[1]; z = p[2];}
00179 void cOdeObject::SetForce(const ODE::dReal x, const ODE::dReal y, const ODE::dReal z){dBodySetForce(moBody,x,y,z);}
00180 void cOdeObject::GetForce(ODE::dReal &x, ODE::dReal &y, ODE::dReal &z){const dReal* p = dBodyGetForce(moBody); x = p[0]; y = p[1]; z = p[2];}
00181
00182 void cOdeObject::DeleteShape () {
00183 if(moGeom){
00184 dMassSetZero(&mMass);
00185 dGeomDestroy(moGeom);
00186 moGeom = 0;
00187 }
00188 }
00189
00190 void cOdeObject::SetShapeSphere (const dReal radius, const dReal mass){
00191 DeleteShape();
00192 moGeom = dCreateSphere(mpWorld->moSpace, radius);
00193 dMassSetSphereTotal(&mMass, mass, radius);
00194 dBodySetMass(moBody, &mMass);
00195 dGeomSetBody(moGeom, moBody);
00196 }
00197
00198 void cOdeObject::SetShapeBox (const dReal mass, const dReal lx, const dReal ly, const dReal lz){
00199 DeleteShape();
00200 moGeom = dCreateBox(mpWorld->moSpace, lx, ly, lz);
00201 dMassSetBoxTotal(&mMass, mass, lx, ly, lz);
00202 dBodySetMass(moBody, &mMass);
00203 dGeomSetBody(moGeom, moBody);
00204 }
00205
00206 cOdeObject::~cOdeObject (){
00207 DeleteShape();
00208 dBodyDestroy(moBody);
00209
00210
00211 mpWorld->mlDeadObject.push_back(this);
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 }
00222
00223 void cOdeObject::SetPosition (const dReal x, const dReal y, const dReal z){ dBodySetPosition(moBody,x,y,z); }
00224 void cOdeObject::SetRotation (const dReal x, const dReal y, const dReal z, const dReal w){ dQuaternion q; q[0] = x; q[1] = y; q[2] = z; q[3] = w; dBodySetQuaternion(moBody,q); }
00225 void cOdeObject::SetLinearVelocity (const dReal x, const dReal y, const dReal z){ dBodySetLinearVel(moBody,x,y,z); }
00226 void cOdeObject::SetAngularVelocity (const dReal x, const dReal y, const dReal z){ dBodySetAngularVel(moBody,x,y,z); }
00227
00228 void cOdeObject::GetPosition (dReal &x, dReal &y, dReal &z){ const dReal* p = dBodyGetPosition(moBody); x = p[0]; y = p[1]; z = p[2]; }
00229 void cOdeObject::GetRotation (dReal &x, dReal &y, dReal &z, dReal &w){ const dReal* p = dBodyGetRotation(moBody); x = p[0]; y = p[1]; z = p[2]; w = p[3]; }
00230 void cOdeObject::GetLinearVelocity (dReal &x, dReal &y, dReal &z){ const dReal* p = dBodyGetLinearVel(moBody); x = p[0]; y = p[1]; z = p[2]; }
00231 void cOdeObject::GetAngularVelocity (dReal &x, dReal &y, dReal &z){ const dReal* p = dBodyGetAngularVel(moBody); x = p[0]; y = p[1]; z = p[2]; }
00232
00233
00234 void cOdeObject::GetAABB (dReal* aabb){
00235 dGeomGetAABB(moGeom, aabb);
00236 }
00237
00238 void cOdeObject::AddForce (const dReal fx, const dReal fy, const dReal fz){
00239 dBodyAddForce(moBody,fx,fy,fz);
00240 }
00241
00242 void cOdeObject::AddRelForce (const dReal fx, const dReal fy, const dReal fz){
00243 dBodyAddRelForce(moBody,fx,fy,fz);
00244 }
00245
00246 void cOdeObject::AddForceAtPos (
00247 const dReal fx, const dReal fy, const dReal fz,
00248 const dReal x, const dReal y, const dReal z){
00249
00250 dBodyAddForceAtPos(moBody,fx,fy,fz,x,y,z);
00251 }
00252
00253 void cOdeObject::AddForceAtRelPos (
00254 const dReal fx, const dReal fy, const dReal fz,
00255 const dReal x, const dReal y, const dReal z){
00256
00257 dBodyAddForceAtRelPos(moBody,fx,fy,fz,x,y,z);
00258 }
00259
00260 void cOdeObject::AddRelForceAtPos (
00261 const dReal fx, const dReal fy, const dReal fz,
00262 const dReal x, const dReal y, const dReal z){
00263
00264 dBodyAddRelForceAtPos(moBody,fx,fy,fz,x,y,z);
00265 }
00266
00267 void cOdeObject::AddRelForceAtRelPos (
00268 const dReal fx, const dReal fy, const dReal fz,
00269 const dReal x, const dReal y, const dReal z){
00270
00271 dBodyAddRelForceAtRelPos(moBody,fx,fy,fz,x,y,z);
00272 }
00273
00274 void cOdeObject::SetEnabled (const bool enabled){
00275 if(enabled)dBodyEnable(moBody);
00276 else dBodyDisable(moBody);
00277 }
00278
00279 bool cOdeObject::IsEnabled (){
00280 return dBodyIsEnabled(moBody);
00281 }
00282
00283
00284
00285
00286
00287 class cOdeObject_L : public cLuaBind<cOdeObject> { public:
00289 virtual void RegisterMethods (lua_State *L) { PROFILE
00290
00291 #define REGISTER_METHOD(methodname) mlMethod.push_back(make_luaL_reg(#methodname,&cOdeObject_L::methodname));
00292
00293 REGISTER_METHOD(Destroy);
00294
00295 REGISTER_METHOD(GetPosition);
00296 REGISTER_METHOD(SetPosition);
00297 REGISTER_METHOD(GetRotation);
00298 REGISTER_METHOD(SetRotation);
00299
00300 REGISTER_METHOD(DeleteShape);
00301 REGISTER_METHOD(SetShapeSphere);
00302 REGISTER_METHOD(SetShapeBox);
00303 REGISTER_METHOD(GetAABB);
00304
00305 REGISTER_METHOD(AddForce);
00306 REGISTER_METHOD(AddRelForce);
00307 REGISTER_METHOD(AddForceAtPos);
00308 REGISTER_METHOD(AddForceAtRelPos);
00309 REGISTER_METHOD(AddRelForceAtPos);
00310 REGISTER_METHOD(AddRelForceAtRelPos);
00311
00312 REGISTER_METHOD(SetEnabled);
00313 REGISTER_METHOD(IsEnabled);
00314
00315 REGISTER_METHOD(SetAutoDisableFlag);
00316 REGISTER_METHOD(IsAutoDisableFlagEnabeled);
00317
00318 #undef REGISTER_METHOD
00319 }
00320
00322 static int Destroy (lua_State *L) { PROFILE
00323 delete checkudata_alive(L);
00324 return 0;
00325 }
00326
00328 static int DeleteShape (lua_State *L) { PROFILE
00329 checkudata_alive(L)->DeleteShape();
00330 return 0;
00331 }
00332
00334 static int GetAABB (lua_State *L) { PROFILE
00335 cOdeObject *p = checkudata_alive(L);
00336 dReal aabb[6];
00337 p->GetAABB(aabb);
00338 for(int i = 0; i < 6; ++i)lua_pushnumber(L,aabb[i]);
00339 return 6;
00340 }
00341
00343 static int SetAutoDisableFlag (lua_State *L) { PROFILE
00344 checkudata_alive(L)->SetAutoDisableFlag(lua_isboolean(L,2) ? lua_toboolean(L,2) : luaL_checkint(L,2));
00345 return 0;
00346 }
00347
00349 static int IsAutoDisableFlagEnabeled (lua_State *L) { PROFILE
00350 lua_pushboolean(L,checkudata_alive(L)->IsAutoDisableFlagEnabeled());
00351 return 1;
00352 }
00353
00355 static int SetEnabled (lua_State *L) { PROFILE
00356 checkudata_alive(L)->SetEnabled(lua_isboolean(L,2) ? lua_toboolean(L,2) : luaL_checkint(L,2));
00357 return 0;
00358 }
00359
00361 static int IsEnabled (lua_State *L) { PROFILE
00362 lua_pushboolean(L,checkudata_alive(L)->IsEnabled());
00363 return 1;
00364 }
00365
00367 static int SetShapeSphere (lua_State *L) { PROFILE
00368 checkudata_alive(L)->SetShapeSphere(
00369 luaL_checknumber(L, 2),
00370 luaL_checknumber(L, 3));
00371 return 0;
00372 }
00373
00375 static int SetShapeBox (lua_State *L) { PROFILE
00376 checkudata_alive(L)->SetShapeBox(
00377 luaL_checknumber(L, 2),
00378 luaL_checknumber(L, 3),
00379 luaL_checknumber(L, 4),
00380 luaL_checknumber(L, 5));
00381 return 0;
00382 }
00383
00385 static int GetPosition (lua_State *L) { PROFILE
00386 cOdeObject *p = checkudata_alive(L);
00387 dReal x,y,z;
00388 p->GetPosition(x,y,z);
00389 lua_pushnumber(L,x);
00390 lua_pushnumber(L,y);
00391 lua_pushnumber(L,z);
00392 return 3;
00393 }
00394
00396 static int SetPosition (lua_State *L) { PROFILE
00397 checkudata_alive(L)->SetPosition(
00398 luaL_checknumber(L, 2),
00399 luaL_checknumber(L, 3),
00400 luaL_checknumber(L, 4));
00401 return 0;
00402 }
00403
00405 static int GetAngularVelocity (lua_State *L) { PROFILE
00406 cOdeObject *p = checkudata_alive(L);
00407 dReal x,y,z;
00408 p->GetAngularVelocity(x,y,z);
00409 lua_pushnumber(L,x);
00410 lua_pushnumber(L,y);
00411 lua_pushnumber(L,z);
00412 return 3;
00413 }
00414
00416 static int SetAngularVelocity (lua_State *L) { PROFILE
00417 checkudata_alive(L)->SetAngularVelocity(
00418 luaL_checknumber(L, 2),
00419 luaL_checknumber(L, 3),
00420 luaL_checknumber(L, 4));
00421 return 0;
00422 }
00423
00425 static int GetLinearVelocity (lua_State *L) { PROFILE
00426 cOdeObject *p = checkudata_alive(L);
00427 dReal x,y,z;
00428 p->GetLinearVelocity(x,y,z);
00429 lua_pushnumber(L,x);
00430 lua_pushnumber(L,y);
00431 lua_pushnumber(L,z);
00432 return 3;
00433 }
00434
00436 static int SetLinearVelocity (lua_State *L) { PROFILE
00437 checkudata_alive(L)->SetLinearVelocity(
00438 luaL_checknumber(L, 2),
00439 luaL_checknumber(L, 3),
00440 luaL_checknumber(L, 4));
00441 return 0;
00442 }
00443
00445 static int GetRotation (lua_State *L) { PROFILE
00446 cOdeObject *p = checkudata_alive(L);
00447 dReal x,y,z,w;
00448 p->GetRotation(x,y,z,w);
00449 lua_pushnumber(L,x);
00450 lua_pushnumber(L,y);
00451 lua_pushnumber(L,z);
00452 lua_pushnumber(L,w);
00453 return 4;
00454 }
00455
00457 static int SetRotation (lua_State *L) { PROFILE
00458 checkudata_alive(L)->SetRotation(
00459 luaL_checknumber(L, 2),
00460 luaL_checknumber(L, 3),
00461 luaL_checknumber(L, 4),
00462 luaL_checknumber(L, 5));
00463 return 0;
00464 }
00465
00467 static int AddForce (lua_State *L){
00468 checkudata_alive(L)->AddForce(
00469 luaL_checknumber(L, 2),
00470 luaL_checknumber(L, 3),
00471 luaL_checknumber(L, 4));
00472 return 0;
00473 }
00475 static int AddRelForce (lua_State *L){
00476 checkudata_alive(L)->AddRelForce(
00477 luaL_checknumber(L, 2),
00478 luaL_checknumber(L, 3),
00479 luaL_checknumber(L, 4));
00480 return 0;
00481 }
00483 static int AddForceAtPos (lua_State *L){
00484 checkudata_alive(L)->AddForceAtPos(
00485 luaL_checknumber(L, 2),
00486 luaL_checknumber(L, 3),
00487 luaL_checknumber(L, 4),
00488
00489 luaL_checknumber(L, 5),
00490 luaL_checknumber(L, 6),
00491 luaL_checknumber(L, 7));
00492 return 0;
00493 }
00495 static int AddForceAtRelPos (lua_State *L){
00496 checkudata_alive(L)->AddForceAtRelPos(
00497 luaL_checknumber(L, 2),
00498 luaL_checknumber(L, 3),
00499 luaL_checknumber(L, 4),
00500
00501 luaL_checknumber(L, 5),
00502 luaL_checknumber(L, 6),
00503 luaL_checknumber(L, 7));
00504 return 0;
00505 }
00507 static int AddRelForceAtPos (lua_State *L){
00508 checkudata_alive(L)->AddRelForceAtPos(
00509 luaL_checknumber(L, 2),
00510 luaL_checknumber(L, 3),
00511 luaL_checknumber(L, 4),
00512
00513 luaL_checknumber(L, 5),
00514 luaL_checknumber(L, 6),
00515 luaL_checknumber(L, 7));
00516 return 0;
00517 }
00519 static int AddRelForceAtRelPos (lua_State *L){
00520 checkudata_alive(L)->AddRelForceAtRelPos(
00521 luaL_checknumber(L, 2),
00522 luaL_checknumber(L, 3),
00523 luaL_checknumber(L, 4),
00524
00525 luaL_checknumber(L, 5),
00526 luaL_checknumber(L, 6),
00527 luaL_checknumber(L, 7));
00528 return 0;
00529 }
00530
00531 virtual const char* GetLuaTypeName () { return "lugre.odeObject"; }
00532 };
00533
00534
00535
00536 class cOdeWorld_L : public cLuaBind<cOdeWorld> { public:
00538 virtual void RegisterMethods (lua_State *L) { PROFILE
00539
00540 lua_register(L,"CreateOdeWorld", &cOdeWorld_L::CreateOdeWorld);
00541
00542 #define REGISTER_METHOD(methodname) mlMethod.push_back(make_luaL_reg(#methodname,&cOdeWorld_L::methodname));
00543
00544 REGISTER_METHOD(Destroy);
00545
00546 REGISTER_METHOD(Step);
00547 REGISTER_METHOD(SetGravity);
00548 REGISTER_METHOD(CreateObject);
00549
00550 REGISTER_METHOD(SetAutoDisableFlag);
00551 REGISTER_METHOD(IsAutoDisableFlagEnabeled);
00552
00553 #undef REGISTER_METHOD
00554 }
00555
00557
00559 static int CreateOdeWorld (lua_State *L) { PROFILE
00560 cOdeWorld* target = new cOdeWorld(luaL_checknumber(L, 1));
00561 return CreateUData(L,target);
00562 }
00563
00565 static int Destroy (lua_State *L) { PROFILE
00566 delete checkudata_alive(L);
00567 return 0;
00568 }
00569
00571 static int SetAutoDisableFlag (lua_State *L) { PROFILE
00572 checkudata_alive(L)->SetAutoDisableFlag(lua_isboolean(L,2) ? lua_toboolean(L,2) : luaL_checkint(L,2));
00573 return 0;
00574 }
00575
00577 static int IsAutoDisableFlagEnabeled (lua_State *L) { PROFILE
00578 lua_pushboolean(L,checkudata_alive(L)->IsAutoDisableFlagEnabeled());
00579 return 1;
00580 }
00581
00583 static int Step (lua_State *L) { PROFILE
00584 checkudata_alive(L)->Step();
00585 return 0;
00586 }
00587
00589 static int CreateObject (lua_State *L) { PROFILE
00590 return cOdeObject_L::CreateUData(L,
00591 new cOdeObject(
00592 checkudata_alive(L),
00593 luaL_checknumber(L, 2),
00594 luaL_checknumber(L, 3),
00595 luaL_checknumber(L, 4)));
00596 }
00597
00599 static int SetGravity (lua_State *L) { PROFILE
00600 checkudata_alive(L)->SetGravity(
00601 luaL_checknumber(L, 2),
00602 luaL_checknumber(L, 3),
00603 luaL_checknumber(L, 4));
00604 return 0;
00605 }
00606
00607 virtual const char* GetLuaTypeName () { return "lugre.odeWorld"; }
00608 };
00609
00610 #endif
00611
00612
00613
00614 void OdeLuaRegister(lua_State* L){
00615 #ifdef ENABLE_ODE
00616 cLuaBind<cOdeWorld>::GetSingletonPtr(new cOdeWorld_L())->LuaRegister(L);
00617 cLuaBind<cOdeObject>::GetSingletonPtr(new cOdeObject_L())->LuaRegister(L);
00618 #endif
00619 }