LuaPhysicsSetup.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #include "LuaPhysicsSetup.h"
  2. #include "../CommonInterfaces/CommonMultiBodyBase.h"
  3. #include "../Importers/ImportURDFDemo/BulletURDFImporter.h"
  4. #include "../Importers/ImportURDFDemo/MyMultiBodyCreator.h"
  5. #include "../Importers/ImportURDFDemo/URDF2Bullet.h"
  6. struct LuaPhysicsSetup : public CommonMultiBodyBase
  7. {
  8. LuaPhysicsSetup(GUIHelperInterface* helper);
  9. virtual ~LuaPhysicsSetup();
  10. virtual void initPhysics();
  11. virtual void exitPhysics();
  12. virtual void stepSimulation(float deltaTime)
  13. {
  14. m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
  15. CommonMultiBodyBase::stepSimulation(deltaTime);
  16. }
  17. };
  18. #include "btBulletDynamicsCommon.h"
  19. #include "LinearMath/btVector3.h"
  20. #include <iostream>
  21. extern "C"
  22. {
  23. #include "lua.h"
  24. #include "lualib.h"
  25. #include "lauxlib.h"
  26. }
  27. const char* sLuaFileName = "init_physics.lua";
  28. static int upaxis = 1;
  29. //const char* sLuaFileName = "init_urdf.lua";
  30. //static int upaxis = 2;
  31. static const float scaling = 0.35f;
  32. static LuaPhysicsSetup* sLuaDemo = 0;
  33. static btVector4 colors[4] =
  34. {
  35. btVector4(1, 0, 0, 1),
  36. btVector4(0, 1, 0, 1),
  37. btVector4(0, 1, 1, 1),
  38. btVector4(1, 1, 0, 1),
  39. };
  40. LuaPhysicsSetup::LuaPhysicsSetup(GUIHelperInterface* helper)
  41. : CommonMultiBodyBase(helper)
  42. {
  43. sLuaDemo = this;
  44. }
  45. LuaPhysicsSetup::~LuaPhysicsSetup()
  46. {
  47. sLuaDemo = 0;
  48. }
  49. //todo: allow to create solver, broadphase, multiple worlds etc.
  50. static int gCreateDefaultDynamicsWorld(lua_State* L)
  51. {
  52. sLuaDemo->createEmptyDynamicsWorld();
  53. btVector3 grav(0, 0, 0);
  54. grav[upaxis] = -10;
  55. sLuaDemo->m_dynamicsWorld->setGravity(grav);
  56. sLuaDemo->m_guiHelper->createPhysicsDebugDrawer(sLuaDemo->m_dynamicsWorld);
  57. lua_pushlightuserdata(L, sLuaDemo->m_dynamicsWorld);
  58. return 1;
  59. }
  60. static int gDeleteDynamicsWorld(lua_State* L)
  61. {
  62. return 0;
  63. }
  64. ATTRIBUTE_ALIGNED16(struct)
  65. CustomRigidBodyData
  66. {
  67. int m_graphicsInstanceIndex;
  68. };
  69. static int gCreateCubeShape(lua_State* L)
  70. {
  71. int argc = lua_gettop(L);
  72. if (argc == 4)
  73. {
  74. btVector3 halfExtents(1, 1, 1);
  75. if (!lua_isuserdata(L, 1))
  76. {
  77. std::cerr << "error: first argument to createCubeShape should be world";
  78. return 0;
  79. }
  80. //expect userdata = sLuaDemo->m_dynamicsWorld
  81. halfExtents = btVector3(lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4));
  82. btCollisionShape* colShape = new btBoxShape(halfExtents);
  83. lua_pushlightuserdata(L, colShape);
  84. return 1;
  85. }
  86. else
  87. {
  88. std::cerr << "Error: invalid number of arguments to createCubeShape, expected 4 (world,halfExtentsX,halfExtentsY,halfExtentsX) but got " << argc;
  89. }
  90. return 0;
  91. }
  92. static int gCreateSphereShape(lua_State* L)
  93. {
  94. int argc = lua_gettop(L);
  95. if (argc == 2)
  96. {
  97. btVector3 halfExtents(1, 1, 1);
  98. if (!lua_isuserdata(L, 1))
  99. {
  100. std::cerr << "error: first argument to createSphereShape should be world";
  101. return 0;
  102. }
  103. //expect userdata = sLuaDemo->m_dynamicsWorld
  104. btScalar radius = lua_tonumber(L, 2);
  105. btCollisionShape* colShape = new btSphereShape(radius);
  106. lua_pushlightuserdata(L, colShape);
  107. return 1;
  108. }
  109. else
  110. {
  111. std::cerr << "Error: invalid number of arguments to createSphereShape, expected 2 (world,radius) but got " << argc;
  112. }
  113. return 0;
  114. }
  115. int luaL_returnlen(lua_State* L, int index)
  116. {
  117. lua_len(L, index);
  118. int len = lua_tointeger(L, -1);
  119. lua_pop(L, 1);
  120. return len;
  121. }
  122. btVector3 getLuaVectorArg(lua_State* L, int index)
  123. {
  124. btVector3 pos(0, 0, 0);
  125. int sz = luaL_returnlen(L, index); // get size of table
  126. {
  127. lua_rawgeti(L, index, 1); // push t[i]
  128. pos[0] = lua_tonumber(L, -1);
  129. lua_pop(L, 1);
  130. lua_rawgeti(L, index, 2); // push t[i]
  131. pos[1] = lua_tonumber(L, -1);
  132. lua_pop(L, 1);
  133. lua_rawgeti(L, index, 3); // push t[i]
  134. pos[2] = lua_tonumber(L, -1);
  135. lua_pop(L, 1);
  136. }
  137. return pos;
  138. }
  139. btQuaternion getLuaQuaternionArg(lua_State* L, int index)
  140. {
  141. btQuaternion orn(0, 0, 0, 1);
  142. int sz = luaL_returnlen(L, index); // get size of table
  143. {
  144. lua_rawgeti(L, index, 1); // push t[i]
  145. orn[0] = lua_tonumber(L, -1);
  146. lua_pop(L, 1);
  147. lua_rawgeti(L, index, 2); // push t[i]
  148. orn[1] = lua_tonumber(L, -1);
  149. lua_pop(L, 1);
  150. lua_rawgeti(L, index, 3); // push t[i]
  151. orn[2] = lua_tonumber(L, -1);
  152. lua_pop(L, 1);
  153. lua_rawgeti(L, index, 4); // push t[i]
  154. orn[3] = lua_tonumber(L, -1);
  155. lua_pop(L, 1);
  156. }
  157. return orn;
  158. }
  159. static int gLoadMultiBodyFromUrdf(lua_State* L)
  160. {
  161. int argc = lua_gettop(L);
  162. if (argc == 4)
  163. {
  164. if (!lua_isuserdata(L, 1))
  165. {
  166. std::cerr << "error: first argument to b3CreateRigidbody should be world";
  167. return 0;
  168. }
  169. luaL_checktype(L, 3, LUA_TTABLE);
  170. btVector3 pos = getLuaVectorArg(L, 3);
  171. btQuaternion orn = getLuaQuaternionArg(L, 4);
  172. btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*)lua_touserdata(L, 1);
  173. if (world != sLuaDemo->m_dynamicsWorld)
  174. {
  175. std::cerr << "error: first argument expected to be a world";
  176. return 0;
  177. }
  178. const char* fileName = lua_tostring(L, 2);
  179. #if 1
  180. BulletURDFImporter u2b(sLuaDemo->m_guiHelper, 0);
  181. bool loadOk = u2b.loadURDF(fileName);
  182. if (loadOk)
  183. {
  184. b3Printf("loaded %s OK!", fileName);
  185. btTransform tr;
  186. tr.setIdentity();
  187. tr.setOrigin(pos);
  188. tr.setRotation(orn);
  189. int rootLinkIndex = u2b.getRootLinkIndex();
  190. // printf("urdf root link index = %d\n",rootLinkIndex);
  191. MyMultiBodyCreator creation(sLuaDemo->m_guiHelper);
  192. bool m_useMultiBody = true;
  193. ConvertURDF2Bullet(u2b, creation, tr, sLuaDemo->m_dynamicsWorld, m_useMultiBody, u2b.getPathPrefix());
  194. btMultiBody* mb = creation.getBulletMultiBody();
  195. if (mb)
  196. {
  197. lua_pushlightuserdata(L, mb);
  198. return 1;
  199. }
  200. }
  201. else
  202. {
  203. b3Printf("can't find %s", fileName);
  204. }
  205. #endif
  206. }
  207. return 0;
  208. }
  209. static int gCreateRigidBody(lua_State* L)
  210. {
  211. int argc = lua_gettop(L);
  212. if (argc == 5)
  213. {
  214. btTransform startTransform;
  215. startTransform.setIdentity();
  216. if (!lua_isuserdata(L, 1))
  217. {
  218. std::cerr << "error: first argument to b3CreateRigidbody should be world";
  219. return 0;
  220. }
  221. btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*)lua_touserdata(L, 1);
  222. if (world != sLuaDemo->m_dynamicsWorld)
  223. {
  224. std::cerr << "error: first argument expected to be a world";
  225. return 0;
  226. }
  227. if (!lua_isuserdata(L, 2))
  228. {
  229. std::cerr << "error: second argument to b3CreateRigidbody should be collision shape";
  230. return 0;
  231. }
  232. btScalar mass = lua_tonumber(L, 3);
  233. luaL_checktype(L, 4, LUA_TTABLE);
  234. btVector3 pos = getLuaVectorArg(L, 4);
  235. btQuaternion orn = getLuaQuaternionArg(L, 5);
  236. btCollisionShape* colShape = (btCollisionShape*)lua_touserdata(L, 2);
  237. //expect userdata = sLuaDemo->m_dynamicsWorld
  238. btVector3 inertia(0, 0, 0);
  239. if (mass)
  240. {
  241. colShape->calculateLocalInertia(mass, inertia);
  242. }
  243. btRigidBody* body = new btRigidBody(mass, 0, colShape, inertia);
  244. body->getWorldTransform().setOrigin(pos);
  245. body->getWorldTransform().setRotation(orn);
  246. world->addRigidBody(body);
  247. lua_pushlightuserdata(L, body);
  248. return 1;
  249. }
  250. else
  251. {
  252. std::cerr << "Error: invalid number of arguments to createRigidBody, expected 5 (world,shape,mass,pos,orn) but got " << argc;
  253. }
  254. return 0;
  255. }
  256. static int gSetBodyPosition(lua_State* L)
  257. {
  258. int argc = lua_gettop(L);
  259. if (argc == 3)
  260. {
  261. if (!lua_isuserdata(L, 1))
  262. {
  263. std::cerr << "error: first argument needs to be a world";
  264. return 0;
  265. }
  266. if (!lua_isuserdata(L, 2))
  267. {
  268. std::cerr << "error: second argument needs to be a body";
  269. return 0;
  270. }
  271. btRigidBody* body = (btRigidBody*)lua_touserdata(L, 2);
  272. btVector3 pos = getLuaVectorArg(L, 3);
  273. btTransform& tr = body->getWorldTransform();
  274. tr.setOrigin(pos);
  275. body->setWorldTransform(tr);
  276. }
  277. else
  278. {
  279. std::cerr << "error: setBodyPosition expects 6 arguments like setBodyPosition(world,body,0,1,0)";
  280. }
  281. return 0;
  282. }
  283. static int gSetBodyOrientation(lua_State* L)
  284. {
  285. int argc = lua_gettop(L);
  286. if (argc == 3)
  287. {
  288. if (!lua_isuserdata(L, 1))
  289. {
  290. std::cerr << "error: first argument needs to be a world";
  291. return 0;
  292. }
  293. if (!lua_isuserdata(L, 2))
  294. {
  295. std::cerr << "error: second argument needs to be a body";
  296. return 0;
  297. }
  298. btRigidBody* body = (btRigidBody*)lua_touserdata(L, 2);
  299. btQuaternion orn = getLuaQuaternionArg(L, 3);
  300. btTransform& tr = body->getWorldTransform();
  301. tr.setRotation(orn);
  302. body->setWorldTransform(tr);
  303. }
  304. else
  305. {
  306. std::cerr << "error: setBodyOrientation expects 3 arguments like setBodyOrientation(world,body,orn)";
  307. }
  308. return 0;
  309. }
  310. //b3CreateConvexShape(world, points)
  311. //b3CreateHingeConstraint(world,bodyA,bodyB,...)
  312. static void report_errors(lua_State* L, int status)
  313. {
  314. if (status != 0)
  315. {
  316. std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
  317. lua_pop(L, 1); // remove error message
  318. }
  319. }
  320. void LuaPhysicsSetup::initPhysics()
  321. {
  322. m_guiHelper->setUpAxis(upaxis);
  323. const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
  324. int numPrefixes = sizeof(prefix) / sizeof(const char*);
  325. char relativeFileName[1024];
  326. FILE* f = 0;
  327. int result = 0;
  328. for (int i = 0; !f && i < numPrefixes; i++)
  329. {
  330. sprintf(relativeFileName, "%s%s", prefix[i], sLuaFileName);
  331. f = fopen(relativeFileName, "rb");
  332. }
  333. if (f)
  334. {
  335. fclose(f);
  336. lua_State* L = luaL_newstate();
  337. luaopen_io(L); // provides io.*
  338. luaopen_base(L);
  339. luaopen_table(L);
  340. luaopen_string(L);
  341. luaopen_math(L);
  342. //luaopen_package(L);
  343. luaL_openlibs(L);
  344. // make my_function() available to Lua programs
  345. lua_register(L, "createDefaultDynamicsWorld", gCreateDefaultDynamicsWorld);
  346. lua_register(L, "deleteDynamicsWorld", gDeleteDynamicsWorld);
  347. lua_register(L, "createCubeShape", gCreateCubeShape);
  348. lua_register(L, "createSphereShape", gCreateSphereShape);
  349. lua_register(L, "loadMultiBodyFromUrdf", gLoadMultiBodyFromUrdf);
  350. lua_register(L, "createRigidBody", gCreateRigidBody);
  351. lua_register(L, "setBodyPosition", gSetBodyPosition);
  352. lua_register(L, "setBodyOrientation", gSetBodyOrientation);
  353. int s = luaL_loadfile(L, relativeFileName);
  354. if (s == 0)
  355. {
  356. // execute Lua program
  357. s = lua_pcall(L, 0, LUA_MULTRET, 0);
  358. }
  359. report_errors(L, s);
  360. lua_close(L);
  361. }
  362. else
  363. {
  364. b3Error("Cannot find Lua file%s\n", sLuaFileName);
  365. }
  366. }
  367. void LuaPhysicsSetup::exitPhysics()
  368. {
  369. CommonMultiBodyBase::exitPhysics();
  370. }
  371. class CommonExampleInterface* LuaDemoCreateFunc(struct CommonExampleOptions& options)
  372. {
  373. return new LuaPhysicsSetup(options.m_guiHelper);
  374. }