From dc8f29206201fcc977443ce9c6138c2f3129c1c8 Mon Sep 17 00:00:00 2001 From: sanine Date: Wed, 22 Mar 2023 23:06:26 -0500 Subject: re-implement bouncing ball --- src/ode/CMakeLists.txt | 1 + src/ode/bind | 15 ++++ src/ode/body.c | 11 +-- src/ode/joint.c | 84 +++++++++++++--------- src/ode/mass.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ode/ode_bindings.h | 42 ++++++++++- src/ode/setup.c | 4 ++ src/ode/world.c | 4 +- src/options/options.c | 6 -- src/util/util.c | 8 +++ src/util/util.h | 2 + 11 files changed, 323 insertions(+), 46 deletions(-) create mode 100644 src/ode/bind create mode 100644 src/ode/mass.c diff --git a/src/ode/CMakeLists.txt b/src/ode/CMakeLists.txt index f11573f..1538d1d 100644 --- a/src/ode/CMakeLists.txt +++ b/src/ode/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(honey PUBLIC ${CMAKE_CURRENT_LIST_DIR}/body.c ${CMAKE_CURRENT_LIST_DIR}/joint.c ${CMAKE_CURRENT_LIST_DIR}/geom.c + ${CMAKE_CURRENT_LIST_DIR}/mass.c ) diff --git a/src/ode/bind b/src/ode/bind new file mode 100644 index 0000000..1c28b65 --- /dev/null +++ b/src/ode/bind @@ -0,0 +1,15 @@ +void dMassSetZero (dMass *m); +void dMassSetParameters (dMass *m, dReal themass, dReal cgx, dReal cgy, dReal cgz, dReal I11, dReal I22, dReal I33, dReal I12, dReal I13, dReal I23); +void dMassSetSphere (dMass *m, dReal density, dReal radius); +void dMassSetSphereTotal (dMass *m, dReal total_mass, dReal radius); +void dMassSetCapsule (dMass *m, dReal density, int direction, dReal radius, dReal length); +void dMassSetCapsuleTotal (dMass *m, dReal total_mass, int direction, dReal radius, dReal length); +void dMassSetCylinder (dMass *m, dReal density, int direction, dReal radius, dReal length); +void dMassSetCylinderTotal (dMass *m, dReal total_mass, int direction, dReal radius, dReal length); +void dMassSetBox (dMass *m, dReal density, dReal lx, dReal ly, dReal lz); +void dMassSetBoxTotal (dMass *m, dReal total_mass, dReal lx, dReal ly, dReal lz); +void dMassSetTrimesh (dMass *m, dReal density, dGeomID g) +void dMassAdjust (dMass *m, dReal newmass); +void dMassTranslate (dMass *m, dReal x, dReal y, dReal z); +void dMassRotate (dMass *m, const dMatrix3 R); +void dMassAdd (dMass *ma, const dMass *mb); diff --git a/src/ode/body.c b/src/ode/body.c index f543b34..1284bb0 100644 --- a/src/ode/body.c +++ b/src/ode/body.c @@ -19,9 +19,11 @@ void ode_push_body(lua_State *L, dBodyID bb) { struct body_t *b = lua_newuserdata(L, sizeof(struct body_t)); b->id = bb; - b->data.L = L; - b->data.callback_ref = LUA_NOREF; - dBodySetData(b->id, &(b->data)); + if (bb != 0) { + b->data.L = L; + b->data.callback_ref = LUA_NOREF; + dBodySetData(b->id, &(b->data)); + } luaL_getmetatable(L, ode_body_tname); lua_setmetatable(L, -2); } @@ -140,7 +142,8 @@ int dBodyGetQuaternion_bind(lua_State *L) lua_pushnumber(L, bind_result[0]); lua_pushnumber(L, bind_result[1]); lua_pushnumber(L, bind_result[2]); - return 3; + lua_pushnumber(L, bind_result[3]); + return 4; } diff --git a/src/ode/joint.c b/src/ode/joint.c index 6fa79b4..7ff4c22 100644 --- a/src/ode/joint.c +++ b/src/ode/joint.c @@ -56,7 +56,7 @@ static int get_field(lua_State *L, int tbl, const char *key, int type) { lua_getfield(L, tbl, key); int actual_type = lua_type(L, -1); - if (actual_type != type) { + if (actual_type != type && actual_type != LUA_TNIL) { luaL_error(L, "field \"%s\" must have type %s but is %s instead", key, lua_typename(L, type), lua_typename(L, actual_type) @@ -67,49 +67,49 @@ static int get_field(lua_State *L, int tbl, const char *key, int type) static int parse_surface_params(lua_State *L, struct dSurfaceParameters *surface, int tbl) { get_field(L, tbl, "mode", LUA_TNUMBER); - surface->mode = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->mode = lua_tointeger(L, -1); get_field(L, tbl, "mu", LUA_TNUMBER); - surface->mu = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->mu = lua_tointeger(L, -1); get_field(L, tbl, "mu2", LUA_TNUMBER); - surface->mu2 = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->mu2 = lua_tointeger(L, -1); get_field(L, tbl, "rho", LUA_TNUMBER); - surface->rho = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->rho = lua_tointeger(L, -1); get_field(L, tbl, "rho2", LUA_TNUMBER); - surface->rho2 = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->rho2 = lua_tointeger(L, -1); get_field(L, tbl, "rhoN", LUA_TNUMBER); - surface->rhoN = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->rhoN = lua_tointeger(L, -1); get_field(L, tbl, "bounce", LUA_TNUMBER); - surface->bounce = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->bounce = lua_tointeger(L, -1); get_field(L, tbl, "bounce_vel", LUA_TNUMBER); - surface->bounce_vel = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->bounce_vel = lua_tointeger(L, -1); get_field(L, tbl, "soft_erp", LUA_TNUMBER); - surface->soft_erp = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->soft_erp = lua_tointeger(L, -1); get_field(L, tbl, "soft_cfm", LUA_TNUMBER); - surface->soft_cfm = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->soft_cfm = lua_tointeger(L, -1); get_field(L, tbl, "motion1", LUA_TNUMBER); - surface->motion1 = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->motion1 = lua_tointeger(L, -1); get_field(L, tbl, "motion2", LUA_TNUMBER); - surface->motion2 = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->motion2 = lua_tointeger(L, -1); get_field(L, tbl, "motionN", LUA_TNUMBER); - surface->motionN = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->motionN = lua_tointeger(L, -1); get_field(L, tbl, "slip1", LUA_TNUMBER); - surface->slip1 = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->slip1 = lua_tointeger(L, -1); get_field(L, tbl, "slip2", LUA_TNUMBER); - surface->slip2 = lua_tointeger(L, -1); + if (!lua_isnil(L, -1)) surface->slip2 = lua_tointeger(L, -1); lua_pop(L, 15); } @@ -121,30 +121,50 @@ static int parse_contact_tbl(lua_State *L, dContact *contact, int tbl) parse_surface_params(L, &(contact->surface), surface_tbl); lua_pop(L, 1); - get_field(L, tbl, "geom", LUA_TUSERDATA); - dContactGeom *g = lua_touserdata(L, -1); - contact->geom = *g; - lua_pop(L, 1); + //get_field(L, tbl, "geom", LUA_TUSERDATA); + //dContactGeom *g = lua_touserdata(L, -1); + //contact->geom = *g; + //lua_pop(L, 1); get_field(L, tbl, "fdir1", LUA_TTABLE); - int fdir_tbl = lua_gettop(L); - lua_rawgeti(L, fdir_tbl, 1); - contact->fdir1[0] = lua_tonumber(L, -1); - lua_rawgeti(L, fdir_tbl, 1); - contact->fdir1[1] = lua_tonumber(L, -1); - lua_rawgeti(L, fdir_tbl, 1); - contact->fdir1[2] = lua_tonumber(L, -1); - lua_pop(L, 4); + if (!lua_isnil(L, -1)) { + int fdir_tbl = lua_gettop(L); + lua_rawgeti(L, fdir_tbl, 1); + contact->fdir1[0] = lua_tonumber(L, -1); + lua_rawgeti(L, fdir_tbl, 1); + contact->fdir1[1] = lua_tonumber(L, -1); + lua_rawgeti(L, fdir_tbl, 1); + contact->fdir1[2] = lua_tonumber(L, -1); + lua_pop(L, 3); + } + lua_pop(L, 1); +} + + +int CreateContact_bind(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + dContact *contact = lua_newuserdata(L, sizeof(dContact)); + parse_contact_tbl(L, contact, 1); + return 1; } + +int ContactSetGeom_bind(lua_State *L) +{ + dContact *contact = lua_touserdata(L, 1); + dContactGeom *geom = lua_touserdata(L, 2); + contact->geom = *geom; + return 0; +} + + int dJointCreateContact_bind(lua_State *L) { dWorldID *w = luaL_checkudata(L, 1, ode_world_tname); dJointGroupID *g = luaL_checkudata(L, 2, ode_jointgroup_tname); - luaL_checktype(L, 3, LUA_TTABLE); - dContact contact; - parse_contact_tbl(L, &contact, 3); - dJointID bind_result = dJointCreateContact(*w, *g, &contact); + dContact *contact = lua_touserdata(L, 3); + dJointID bind_result = dJointCreateContact(*w, *g, contact); ode_push_joint(L, bind_result); return 1; } diff --git a/src/ode/mass.c b/src/ode/mass.c new file mode 100644 index 0000000..fb90d65 --- /dev/null +++ b/src/ode/mass.c @@ -0,0 +1,192 @@ +#include +#include +#include +#include "ode_bindings.h" + + +int MassCreate_bind(lua_State *L) +{ + dMass *m = lua_newuserdata(L, sizeof(dMass)); + luaL_getmetatable(L, ode_mass_tname); + lua_setmetatable(L, -2); + return 1; +} + + +int dMassSetZero_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dMassSetZero(m); + return 0; +} + + +int dMassSetParameters_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal themass = luaL_checknumber(L, 2); + dReal cgx = luaL_checknumber(L, 3); + dReal cgy = luaL_checknumber(L, 4); + dReal cgz = luaL_checknumber(L, 5); + dReal I11 = luaL_checknumber(L, 6); + dReal I22 = luaL_checknumber(L, 7); + dReal I33 = luaL_checknumber(L, 8); + dReal I12 = luaL_checknumber(L, 9); + dReal I13 = luaL_checknumber(L, 10); + dReal I23 = luaL_checknumber(L, 11); + dMassSetParameters(m, themass, cgx, cgy, cgz, I11, I22, I33, I12, I13, I23); + return 0; +} + + +int dMassSetSphere_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal density = luaL_checknumber(L, 2); + dReal radius = luaL_checknumber(L, 3); + dMassSetSphere(m, density, radius); + return 0; +} + + +int dMassSetSphereTotal_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal total_mass = luaL_checknumber(L, 2); + dReal radius = luaL_checknumber(L, 3); + dMassSetSphereTotal(m, total_mass, radius); + return 0; +} + + +int dMassSetCapsule_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal density = luaL_checknumber(L, 2); + int direction = luaL_checkinteger(L, 3); + dReal radius = luaL_checknumber(L, 4); + dReal length = luaL_checknumber(L, 5); + dMassSetCapsule(m, density, direction, radius, length); + return 0; +} + + +int dMassSetCapsuleTotal_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal total_mass = luaL_checknumber(L, 2); + int direction = luaL_checkinteger(L, 3); + dReal radius = luaL_checknumber(L, 4); + dReal length = luaL_checknumber(L, 5); + dMassSetCapsuleTotal(m, total_mass, direction, radius, length); + return 0; +} + + +int dMassSetCylinder_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal density = luaL_checknumber(L, 2); + int direction = luaL_checkinteger(L, 3); + dReal radius = luaL_checknumber(L, 4); + dReal length = luaL_checknumber(L, 5); + dMassSetCylinder(m, density, direction, radius, length); + return 0; +} + + +int dMassSetCylinderTotal_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal total_mass = luaL_checknumber(L, 2); + int direction = luaL_checkinteger(L, 3); + dReal radius = luaL_checknumber(L, 4); + dReal length = luaL_checknumber(L, 5); + dMassSetCylinderTotal(m, total_mass, direction, radius, length); + return 0; +} + + +int dMassSetBox_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal density = luaL_checknumber(L, 2); + dReal lx = luaL_checknumber(L, 3); + dReal ly = luaL_checknumber(L, 4); + dReal lz = luaL_checknumber(L, 5); + dMassSetBox(m, density, lx, ly, lz); + return 0; +} + + +int dMassSetBoxTotal_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal total_mass = luaL_checknumber(L, 2); + dReal lx = luaL_checknumber(L, 3); + dReal ly = luaL_checknumber(L, 4); + dReal lz = luaL_checknumber(L, 5); + dMassSetBoxTotal(m, total_mass, lx, ly, lz); + return 0; +} + + +int dMassSetTrimesh_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal density = luaL_checknumber(L, 2); + dGeomID g = luaL_checkudata(L, 3, ode_geom_tname); + dMassSetTrimesh(m, density, g); + return 0; +} + + +int dMassAdjust_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal newmass = luaL_checknumber(L, 2); + dMassAdjust(m, newmass); + return 0; +} + + +int dMassTranslate_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dReal x = luaL_checknumber(L, 2); + dReal y = luaL_checknumber(L, 3); + dReal z = luaL_checknumber(L, 4); + dMassTranslate(m, x, y, z); + return 0; +} + + +int dMassRotate_bind(lua_State *L) +{ + dMass * m = luaL_checkudata(L, 1, ode_mass_tname); + dMatrix3 R; + R[0] = luaL_checknumber(L, 2); + R[1] = luaL_checknumber(L, 3); + R[2] = luaL_checknumber(L, 4); + + R[4] = luaL_checknumber(L, 5); + R[5] = luaL_checknumber(L, 6); + R[6] = luaL_checknumber(L, 7); + + R[8] = luaL_checknumber(L, 8); + R[9] = luaL_checknumber(L, 9); + R[10] = luaL_checknumber(L, 10); + dMassRotate(m, R); + return 0; +} + + +int dMassAdd_bind(lua_State *L) +{ + dMass * ma = luaL_checkudata(L, 1, ode_mass_tname); + const dMass * mb = luaL_checkudata(L, 2, ode_mass_tname); + dMassAdd(ma, mb); + return 0; +} + + diff --git a/src/ode/ode_bindings.h b/src/ode/ode_bindings.h index 62c7bd9..3305b2a 100644 --- a/src/ode/ode_bindings.h +++ b/src/ode/ode_bindings.h @@ -412,12 +412,50 @@ void ode_push_space(lua_State *L, dSpaceID s); X("CreateHeightfield", dCreateHeightfield_bind) \ X("GeomHeightfieldSetHeightfieldData", dGeomHeightfieldSetHeightfieldData_bind) \ X("GeomHeightfieldGetHeightfieldData", dGeomHeightfieldGetHeightfieldData_bind) \ - - + X("CreateContact", CreateContact_bind) \ + X("ContactSetGeom", ContactSetGeom_bind) \ + /* mass */ \ + X("MassCreate", MassCreate_bind) \ + X("MassSetZero", dMassSetZero_bind) \ + X("MassSetParameters", dMassSetParameters_bind) \ + X("MassSetSphere", dMassSetSphere_bind) \ + X("MassSetSphereTotal", dMassSetSphereTotal_bind) \ + X("MassSetCapsule", dMassSetCapsule_bind) \ + X("MassSetCapsuleTotal", dMassSetCapsuleTotal_bind) \ + X("MassSetCylinder", dMassSetCylinder_bind) \ + X("MassSetCylinderTotal", dMassSetCylinderTotal_bind) \ + X("MassSetBox", dMassSetBox_bind) \ + X("MassSetBoxTotal", dMassSetBoxTotal_bind) \ + X("MassSetTrimesh", dMassSetTrimesh_bind) \ + X("MassAdjust", dMassAdjust_bind) \ + X("MassTranslate", dMassTranslate_bind) \ + X("MassRotate", dMassRotate_bind) \ + X("MassAdd", dMassAdd_bind) \ #define X(name, func) int func(lua_State *L); ODE_FUNCTIONS #undef X + + +#define ODE_ENUMS \ + /* contact modes */ \ + X("ContactMu2", dContactMu2) \ + X("ContactFDir1", dContactFDir1) \ + X("ContactBounce", dContactBounce) \ + X("ContactSoftERP", dContactSoftERP) \ + X("ContactSoftCFM", dContactSoftCFM) \ + X("ContactMotion1", dContactMotion1) \ + X("ContactMotion2", dContactMotion2) \ + X("ContactMotionN", dContactMotionN) \ + X("ContactSlip1", dContactSlip1) \ + X("ContactSlip2", dContactSlip2) \ + X("ContactRolling", dContactRolling) \ + X("ContactApprox1_1", dContactApprox1_1) \ + X("ContactApprox1_2", dContactApprox1_2) \ + X("ContactApprox1_N", dContactApprox1_N) \ + X("ContactApprox1", dContactApprox1) \ + + #endif diff --git a/src/ode/setup.c b/src/ode/setup.c index 91e452c..2b5b1e3 100644 --- a/src/ode/setup.c +++ b/src/ode/setup.c @@ -28,6 +28,10 @@ void setup_ode(lua_State *L, int honey_tbl) #define X(name, func) H_FUNC(name, func), ODE_FUNCTIONS #undef X + #define X(name, value) H_INT(name, value), + ODE_ENUMS + #undef X + H_NUM("Infinity", dInfinity), H_END }; create_table(L, ode); diff --git a/src/ode/world.c b/src/ode/world.c index 69b5a92..a38eb30 100644 --- a/src/ode/world.c +++ b/src/ode/world.c @@ -15,7 +15,7 @@ void ode_push_world(lua_State *L, dWorldID w) int dWorldCreate_bind(lua_State *L) { - dWorldID w = lua_newuserdata(L, sizeof(dWorldID)); + dWorldID w = dWorldCreate(); ode_push_world(L, w); return 1; } @@ -206,7 +206,7 @@ int dWorldStep_bind(lua_State *L) int dWorldQuickStep_bind(lua_State *L) { dWorldID *w = luaL_checkudata(L, 1, ode_world_tname); - dReal stepsize = luaL_checkinteger(L, 2); + dReal stepsize = luaL_checknumber(L, 2); dWorldQuickStep(*w, stepsize); return 0; } diff --git a/src/options/options.c b/src/options/options.c index 7ac35c7..cf2ae49 100644 --- a/src/options/options.c +++ b/src/options/options.c @@ -37,12 +37,6 @@ void print_help(char *program_name) enum outcomes_t parse_options(struct honey_options *options, int argc, char **argv) { - /* check if we even need to parse at all */ - if (argc == 1) { - print_help(argv[0]); - return EXIT_SUCCESS; - } - /* default values */ options->script_file = "main.lua"; diff --git a/src/util/util.c b/src/util/util.c index 564ffd4..0e71f22 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -16,6 +16,14 @@ void create_table(lua_State *L, struct honey_tbl_t *tbl) lua_pushcfunction(L, pair->value.function); lua_setfield(L, t, pair->key); } + else if (pair->type == LUA_TSTRING) { + lua_pushstring(L, pair->value.string); + lua_setfield(L, t, pair->key); + } + else if (pair->type == LUA_TNUMBER) { + lua_pushnumber(L, pair->value.number); + lua_setfield(L, t, pair->key); + } else { /* bad type, ignore */ } diff --git a/src/util/util.h b/src/util/util.h index 293397c..c73ba54 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -9,6 +9,7 @@ struct honey_tbl_t { int type; union { lua_Integer integer; + lua_Number number; lua_CFunction function; const char *string; } value; @@ -18,6 +19,7 @@ struct honey_tbl_t { #define H_ENUM(v) { .key=#v, .type=LUA_TNUMBER, .value.integer=v } #define H_FUNC(k, v) { .key=k, .type=LUA_TFUNCTION, .value.function=v } #define H_STR(k, v) { .key=k, .type=LUA_TSTRING, .value.string=v } +#define H_NUM(k, v) { .key=k, .type=LUA_TNUMBER, .value.number=v } #define H_END { .key=NULL, .type=LUA_TNIL, .value.integer=0 } -- cgit v1.2.1