Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
185ff8f0cThis file is pinned to the selected release. Download the original to open it in your design tool.
#include "LuaPhysicsSetup.h"
#include "../CommonInterfaces/CommonMultiBodyBase.h"
#include "../Importers/ImportURDFDemo/BulletURDFImporter.h"
#include "../Importers/ImportURDFDemo/MyMultiBodyCreator.h"
#include "../Importers/ImportURDFDemo/URDF2Bullet.h"
struct LuaPhysicsSetup : public CommonMultiBodyBase
{
LuaPhysicsSetup(GUIHelperInterface* helper);
virtual ~LuaPhysicsSetup();
virtual void initPhysics();
virtual void exitPhysics();
virtual void stepSimulation(float deltaTime)
{
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
CommonMultiBodyBase::stepSimulation(deltaTime);
}
};
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include <iostream>
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
const char* sLuaFileName = "init_physics.lua";
static int upaxis = 1;
//const char* sLuaFileName = "init_urdf.lua";
//static int upaxis = 2;
static const float scaling = 0.35f;
static LuaPhysicsSetup* sLuaDemo = 0;
static btVector4 colors[4] =
{
btVector4(1, 0, 0, 1),
btVector4(0, 1, 0, 1),
btVector4(0, 1, 1, 1),
btVector4(1, 1, 0, 1),
};
LuaPhysicsSetup::LuaPhysicsSetup(GUIHelperInterface* helper)
: CommonMultiBodyBase(helper)
{
sLuaDemo = this;
}
LuaPhysicsSetup::~LuaPhysicsSetup()
{
sLuaDemo = 0;
}
//todo: allow to create solver, broadphase, multiple worlds etc.
static int gCreateDefaultDynamicsWorld(lua_State* L)
{
sLuaDemo->createEmptyDynamicsWorld();
btVector3 grav(0, 0, 0);
grav[upaxis] = -10;
sLuaDemo->m_dynamicsWorld->setGravity(grav);
sLuaDemo->m_guiHelper->createPhysicsDebugDrawer(sLuaDemo->m_dynamicsWorld);
lua_pushlightuserdata(L, sLuaDemo->m_dynamicsWorld);
return 1;
}
static int gDeleteDynamicsWorld(lua_State* L)
{
return 0;
}
ATTRIBUTE_ALIGNED16(struct)
CustomRigidBodyData
{
int m_graphicsInstanceIndex;
};
static int gCreateCubeShape(lua_State* L)
{
int argc = lua_gettop(L);
if (argc == 4)
{
btVector3 halfExtents(1, 1, 1);
if (!lua_isuserdata(L, 1))
{
std::cerr << "error: first argument to createCubeShape should be world";
return 0;
}
//expect userdata = sLuaDemo->m_dynamicsWorld
halfExtents = btVector3(lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4));
btCollisionShape* colShape = new btBoxShape(halfExtents);
lua_pushlightuserdata(L, colShape);
return 1;
}
else
{
std::cerr << "Error: invalid number of arguments to createCubeShape, expected 4 (world,halfExtentsX,halfExtentsY,halfExtentsX) but got " << argc;
}
return 0;
}
static int gCreateSphereShape(lua_State* L)
{
int argc = lua_gettop(L);
if (argc == 2)
{
btVector3 halfExtents(1, 1, 1);
if (!lua_isuserdata(L, 1))
{
std::cerr << "error: first argument to createSphereShape should be world";
return 0;
}
//expect userdata = sLuaDemo->m_dynamicsWorld
btScalar radius = lua_tonumber(L, 2);
btCollisionShape* colShape = new btSphereShape(radius);
lua_pushlightuserdata(L, colShape);
return 1;
}
else
{
std::cerr << "Error: invalid number of arguments to createSphereShape, expected 2 (world,radius) but got " << argc;
}
return 0;
}
int luaL_returnlen(lua_State* L, int index)
{
lua_len(L, index);
int len = lua_tointeger(L, -1);
lua_pop(L, 1);
return len;
}
btVector3 getLuaVectorArg(lua_State* L, int index)
{
btVector3 pos(0, 0, 0);
int sz = luaL_returnlen(L, index); // get size of table
{
lua_rawgeti(L, index, 1); // push t[i]
pos[0] = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, index, 2); // push t[i]
pos[1] = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, index, 3); // push t[i]
pos[2] = lua_tonumber(L, -1);
lua_pop(L, 1);
}
return pos;
}
btQuaternion getLuaQuaternionArg(lua_State* L, int index)
{
btQuaternion orn(0, 0, 0, 1);
int sz = luaL_returnlen(L, index); // get size of table
{
lua_rawgeti(L, index, 1); // push t[i]
orn[0] = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, index, 2); // push t[i]
orn[1] = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, index, 3); // push t[i]
orn[2] = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_rawgeti(L, index, 4); // push t[i]
orn[3] = lua_tonumber(L, -1);
lua_pop(L, 1);
}
return orn;
}
static int gLoadMultiBodyFromUrdf(lua_State* L)
{
int argc = lua_gettop(L);
if (argc == 4)
{
if (!lua_isuserdata(L, 1))
{
std::cerr << "error: first argument to b3CreateRigidbody should be world";
return 0;
}
luaL_checktype(L, 3, LUA_TTABLE);
btVector3 pos = getLuaVectorArg(L, 3);
btQuaternion orn = getLuaQuaternionArg(L, 4);
btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*)lua_touserdata(L, 1);
if (world != sLuaDemo->m_dynamicsWorld)
{
std::cerr << "error: first argument expected to be a world";
return 0;
}
const char* fileName = lua_tostring(L, 2);
#if 1
BulletURDFImporter u2b(sLuaDemo->m_guiHelper, 0);
bool loadOk = u2b.loadURDF(fileName);
if (loadOk)
{
b3Printf("loaded %s OK!", fileName);
btTransform tr;
tr.setIdentity();
tr.setOrigin(pos);
tr.setRotation(orn);
int rootLinkIndex = u2b.getRootLinkIndex();
// printf("urdf root link index = %d\n",rootLinkIndex);
MyMultiBodyCreator creation(sLuaDemo->m_guiHelper);
bool m_useMultiBody = true;
ConvertURDF2Bullet(u2b, creation, tr, sLuaDemo->m_dynamicsWorld, m_useMultiBody, u2b.getPathPrefix());
btMultiBody* mb = creation.getBulletMultiBody();
if (mb)
{
lua_pushlightuserdata(L, mb);
return 1;
}
}
else
{
b3Printf("can't find %s", fileName);
}
#endif
}
return 0;
}
static int gCreateRigidBody(lua_State* L)
{
int argc = lua_gettop(L);
if (argc == 5)
{
btTransform startTransform;
startTransform.setIdentity();
if (!lua_isuserdata(L, 1))
{
std::cerr << "error: first argument to b3CreateRigidbody should be world";
return 0;
}
btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*)lua_touserdata(L, 1);
if (world != sLuaDemo->m_dynamicsWorld)
{
std::cerr << "error: first argument expected to be a world";
return 0;
}
if (!lua_isuserdata(L, 2))
{
std::cerr << "error: second argument to b3CreateRigidbody should be collision shape";
return 0;
}
btScalar mass = lua_tonumber(L, 3);
luaL_checktype(L, 4, LUA_TTABLE);
btVector3 pos = getLuaVectorArg(L, 4);
btQuaternion orn = getLuaQuaternionArg(L, 5);
btCollisionShape* colShape = (btCollisionShape*)lua_touserdata(L, 2);
//expect userdata = sLuaDemo->m_dynamicsWorld
btVector3 inertia(0, 0, 0);
if (mass)
{
colShape->calculateLocalInertia(mass, inertia);
}
btRigidBody* body = new btRigidBody(mass, 0, colShape, inertia);
body->getWorldTransform().setOrigin(pos);
body->getWorldTransform().setRotation(orn);
world->addRigidBody(body);
lua_pushlightuserdata(L, body);
return 1;
}
else
{
std::cerr << "Error: invalid number of arguments to createRigidBody, expected 5 (world,shape,mass,pos,orn) but got " << argc;
}
return 0;
}
static int gSetBodyPosition(lua_State* L)
{
int argc = lua_gettop(L);
if (argc == 3)
{
if (!lua_isuserdata(L, 1))
{
std::cerr << "error: first argument needs to be a world";
return 0;
}
if (!lua_isuserdata(L, 2))
{
std::cerr << "error: second argument needs to be a body";
return 0;
}
btRigidBody* body = (btRigidBody*)lua_touserdata(L, 2);
btVector3 pos = getLuaVectorArg(L, 3);
btTransform& tr = body->getWorldTransform();
tr.setOrigin(pos);
body->setWorldTransform(tr);
}
else
{
std::cerr << "error: setBodyPosition expects 6 arguments like setBodyPosition(world,body,0,1,0)";
}
return 0;
}
static int gSetBodyOrientation(lua_State* L)
{
int argc = lua_gettop(L);
if (argc == 3)
{
if (!lua_isuserdata(L, 1))
{
std::cerr << "error: first argument needs to be a world";
return 0;
}
if (!lua_isuserdata(L, 2))
{
std::cerr << "error: second argument needs to be a body";
return 0;
}
btRigidBody* body = (btRigidBody*)lua_touserdata(L, 2);
btQuaternion orn = getLuaQuaternionArg(L, 3);
btTransform& tr = body->getWorldTransform();
tr.setRotation(orn);
body->setWorldTransform(tr);
}
else
{
std::cerr << "error: setBodyOrientation expects 3 arguments like setBodyOrientation(world,body,orn)";
}
return 0;
}
//b3CreateConvexShape(world, points)
//b3CreateHingeConstraint(world,bodyA,bodyB,...)
static void report_errors(lua_State* L, int status)
{
if (status != 0)
{
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
void LuaPhysicsSetup::initPhysics()
{
m_guiHelper->setUpAxis(upaxis);
const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
int numPrefixes = sizeof(prefix) / sizeof(const char*);
char relativeFileName[1024];
FILE* f = 0;
int result = 0;
for (int i = 0; !f && i < numPrefixes; i++)
{
sprintf(relativeFileName, "%s%s", prefix[i], sLuaFileName);
f = fopen(relativeFileName, "rb");
}
if (f)
{
fclose(f);
lua_State* L = luaL_newstate();
luaopen_io(L); // provides io.*
luaopen_base(L);
luaopen_table(L);
luaopen_string(L);
luaopen_math(L);
//luaopen_package(L);
luaL_openlibs(L);
// make my_function() available to Lua programs
lua_register(L, "createDefaultDynamicsWorld", gCreateDefaultDynamicsWorld);
lua_register(L, "deleteDynamicsWorld", gDeleteDynamicsWorld);
lua_register(L, "createCubeShape", gCreateCubeShape);
lua_register(L, "createSphereShape", gCreateSphereShape);
lua_register(L, "loadMultiBodyFromUrdf", gLoadMultiBodyFromUrdf);
lua_register(L, "createRigidBody", gCreateRigidBody);
lua_register(L, "setBodyPosition", gSetBodyPosition);
lua_register(L, "setBodyOrientation", gSetBodyOrientation);
int s = luaL_loadfile(L, relativeFileName);
if (s == 0)
{
// execute Lua program
s = lua_pcall(L, 0, LUA_MULTRET, 0);
}
report_errors(L, s);
lua_close(L);
}
else
{
b3Error("Cannot find Lua file%s\n", sLuaFileName);
}
}
void LuaPhysicsSetup::exitPhysics()
{
CommonMultiBodyBase::exitPhysics();
}
class CommonExampleInterface* LuaDemoCreateFunc(struct CommonExampleOptions& options)
{
return new LuaPhysicsSetup(options.m_guiHelper);
}