Compare commits

..

22 Commits

Author SHA1 Message Date
bjorn d876de66cb Move Shape:is/setSensor and Shape:is/setEnabled to Collider; 2024-04-06 12:52:51 -07:00
bjorn 1a8d05b8b4 newCollider takes optional Shape as first arg; 2024-04-06 12:51:17 -07:00
bjorn 24708f7114 Shape fixes;
- Collider always has Shape now.  When left off or set to null, it's a
  tiny sphere (representing a point).
- Preserve shape offset when changing shape.
2024-04-06 12:51:17 -07:00
bjorn f82715d402 lovrColliderCreate takes shape;
Jolt requires a shape, also it saves a bit of work.
2024-04-06 12:50:59 -07:00
bjorn 2cc5dc8c85 Add Collider:getShapes for backcompat; 2024-04-06 12:50:35 -07:00
bjorn 17475f7ad2 rm unused shape prototypes; 2024-04-06 12:50:35 -07:00
bjorn aa6b3fb6c8 ODE compatibility; 2024-04-06 12:50:35 -07:00
bjorn f79dec31ff Collider shape is required I think;
Jolt doesn't really support bodies without shapes.
2024-04-06 12:50:35 -07:00
bjorn 6b5244a8e1 Add Collider:get/setShapeOffset; 2024-04-06 12:50:35 -07:00
bjorn 8f40d98074 World queries return collider/shapeindex instead of Shape; 2024-04-06 12:50:35 -07:00
bjorn e842c2b772 Require frozen CompoundShapes to have at least 2 children;
If you create a StaticCompoundShape with 1 child, Jolt creates a
RotatedTranslatedShape.  It would be a pain to have to branch on that,
so let's just require 2 children.
2024-04-06 12:50:35 -07:00
bjorn 48559ccd0f rm Shape setters;
Jolt doesn't support this and requires you to recreate the shape.  Since
the shape -> collider relationship is 1:N, we can't really create a new
shape because we'd have to figure out which colliders/compoundshapes to
assign it to, which isn't feasible.
2024-04-06 12:50:35 -07:00
bjorn 6cf9f8082e CompoundShape fixes; 2024-04-06 12:50:35 -07:00
bjorn 7640be2281 Shapes set their userdata; 2024-04-06 12:50:35 -07:00
bjorn 7474192e78 CompoundShape API; 2024-04-06 12:50:35 -07:00
bjorn 50fbcf1450 Start CompoundShape; 2024-04-06 12:50:35 -07:00
bjorn 5244420828 Colliders can only have 1 shape; rm shape pose; 2024-04-06 12:50:35 -07:00
bjorn 5bf9f874b8 Update Jolt; 2024-04-06 12:50:35 -07:00
bjorn f4d5c0d758 Add assert for body count; 2024-04-06 00:47:31 -07:00
bjorn 38a68dc4e5 TerrainShape image must be square; 2024-04-06 00:12:50 -07:00
bjorn 5e521b7698 Collider:applyLinear/AngularImpulse; 2024-04-05 19:16:39 -07:00
bjorn fb6b402034 Add Collider:is/setContinuous; 2024-04-05 19:05:25 -07:00
5 changed files with 193 additions and 104 deletions

View File

@ -17,6 +17,20 @@ static int l_lovrColliderIsDestroyed(lua_State* L) {
return 1;
}
static int l_lovrColliderIsEnabled(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool enabled = lovrColliderIsEnabled(collider);
lua_pushboolean(L, enabled);
return 1;
}
static int l_lovrColliderSetEnabled(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool enable = lua_toboolean(L, 2);
lovrColliderSetEnabled(collider, enable);
return 1;
}
static int l_lovrColliderGetWorld(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
World* world = lovrColliderGetWorld(collider);
@ -123,6 +137,33 @@ static int l_lovrColliderSetKinematic(lua_State* L) {
return 0;
}
static int l_lovrColliderIsSensor(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
lua_pushboolean(L, lovrColliderIsSensor(collider));
return 1;
}
static int l_lovrColliderSetSensor(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool sensor = lua_toboolean(L, 2);
lovrColliderSetSensor(collider, sensor);
return 0;
}
static int l_lovrColliderIsContinuous(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool continuous = lovrColliderIsContinuous(collider);
lua_pushboolean(L, continuous);
return 1;
}
static int l_lovrColliderSetContinuous(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool continuous = lua_toboolean(L, 2);
lovrColliderSetContinuous(collider, continuous);
return 0;
}
static int l_lovrColliderGetGravityScale(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float scale = lovrColliderGetGravityScale(collider);
@ -382,6 +423,28 @@ static int l_lovrColliderApplyTorque(lua_State* L) {
return 0;
}
static int l_lovrColliderApplyLinearImpulse(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float impulse[3];
int index = luax_readvec3(L, 2, impulse, NULL);
if (lua_gettop(L) >= index) {
float position[3];
luax_readvec3(L, index, position, NULL);
lovrColliderApplyLinearImpulseAtPosition(collider, impulse, position);
} else {
lovrColliderApplyLinearImpulse(collider, impulse);
}
return 0;
}
static int l_lovrColliderApplyAngularImpulse(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float impulse[3];
luax_readvec3(L, 2, impulse, NULL);
lovrColliderApplyAngularImpulse(collider, impulse);
return 0;
}
static int l_lovrColliderGetLocalCenter(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float x, y, z;
@ -549,6 +612,8 @@ static int l_lovrColliderSetGravityIgnored(lua_State* L) {
const luaL_Reg lovrCollider[] = {
{ "destroy", l_lovrColliderDestroy },
{ "isDestroyed", l_lovrColliderIsDestroyed },
{ "isEnabled", l_lovrColliderIsEnabled },
{ "setEnabled", l_lovrColliderSetEnabled },
{ "getWorld", l_lovrColliderGetWorld },
{ "getShape", l_lovrColliderGetShape },
{ "setShape", l_lovrColliderSetShape },
@ -559,6 +624,10 @@ const luaL_Reg lovrCollider[] = {
{ "setUserData", l_lovrColliderSetUserData },
{ "isKinematic", l_lovrColliderIsKinematic },
{ "setKinematic", l_lovrColliderSetKinematic },
{ "isSensor", l_lovrColliderIsSensor },
{ "setSensor", l_lovrColliderSetSensor },
{ "isContinuous", l_lovrColliderIsContinuous },
{ "setContinuous", l_lovrColliderSetContinuous },
{ "getGravityScale", l_lovrColliderGetGravityScale },
{ "setGravityScale", l_lovrColliderSetGravityScale },
{ "isSleepingAllowed", l_lovrColliderIsSleepingAllowed },
@ -585,6 +654,8 @@ const luaL_Reg lovrCollider[] = {
{ "setAngularDamping", l_lovrColliderSetAngularDamping },
{ "applyForce", l_lovrColliderApplyForce },
{ "applyTorque", l_lovrColliderApplyTorque },
{ "applyLinearImpulse", l_lovrColliderApplyLinearImpulse },
{ "applyAngularImpulse", l_lovrColliderApplyAngularImpulse },
{ "getLocalCenter", l_lovrColliderGetLocalCenter },
{ "getLocalPoint", l_lovrColliderGetLocalPoint },
{ "getWorldPoint", l_lovrColliderGetWorldPoint },

View File

@ -93,17 +93,17 @@ Shape* luax_newmeshshape(lua_State* L, int index) {
}
Shape* luax_newterrainshape(lua_State* L, int index) {
float horizontalScale = luax_checkfloat(L, index++);
float scaleXZ = luax_checkfloat(L, index++);
int type = lua_type(L, index);
if (type == LUA_TNIL || type == LUA_TNONE) {
float vertices[4] = { 0.f };
return lovrTerrainShapeCreate(vertices, 2, 2, horizontalScale, 1.f);
return lovrTerrainShapeCreate(vertices, 2, scaleXZ, 1.f);
} else if (type == LUA_TFUNCTION) {
uint32_t samples = luax_optu32(L, index + 1, 100);
float* vertices = lovrMalloc(sizeof(float) * samples * samples);
for (uint32_t i = 0; i < samples * samples; i++) {
float x = horizontalScale * (-.5f + ((float) (i % samples)) / samples);
float z = horizontalScale * (-.5f + ((float) (i / samples)) / samples);
uint32_t n = luax_optu32(L, index + 1, 100);
float* vertices = lovrMalloc(sizeof(float) * n * n);
for (uint32_t i = 0; i < n * n; i++) {
float x = scaleXZ * (-.5f + ((float) (i % n)) / n);
float z = scaleXZ * (-.5f + ((float) (i / n)) / n);
lua_pushvalue(L, index);
lua_pushnumber(L, x);
lua_pushnumber(L, z);
@ -112,23 +112,23 @@ Shape* luax_newterrainshape(lua_State* L, int index) {
vertices[i] = luax_tofloat(L, -1);
lua_pop(L, 1);
}
TerrainShape* shape = lovrTerrainShapeCreate(vertices, samples, samples, horizontalScale, 1.f);
TerrainShape* shape = lovrTerrainShapeCreate(vertices, n, scaleXZ, 1.f);
lovrFree(vertices);
return shape;
} else if (type == LUA_TUSERDATA) {
Image* image = luax_checktype(L, index, Image);
uint32_t imageWidth = lovrImageGetWidth(image, 0);
uint32_t imageHeight = lovrImageGetHeight(image, 0);
float verticalScale = luax_optfloat(L, index + 1, 1.f);
float* vertices = lovrMalloc(sizeof(float) * imageWidth * imageHeight);
for (uint32_t y = 0; y < imageHeight; y++) {
for (uint32_t x = 0; x < imageWidth; x++) {
uint32_t n = lovrImageGetWidth(image, 0);
lovrCheck(lovrImageGetHeight(image, 0) == n, "TerrainShape images must be square");
float scaleY = luax_optfloat(L, index + 1, 1.f);
float* vertices = lovrMalloc(sizeof(float) * n * n);
for (uint32_t y = 0; y < n; y++) {
for (uint32_t x = 0; x < n; x++) {
float pixel[4];
lovrImageGetPixel(image, x, y, pixel);
vertices[x + y * imageWidth] = pixel[0];
vertices[x + y * n] = pixel[0];
}
}
TerrainShape* shape = lovrTerrainShapeCreate(vertices, imageWidth, imageHeight, horizontalScale, verticalScale);
TerrainShape* shape = lovrTerrainShapeCreate(vertices, n, scaleXZ, scaleY);
lovrFree(vertices);
return shape;
} else {
@ -229,32 +229,6 @@ static int l_lovrShapeGetType(lua_State* L) {
return 1;
}
static int l_lovrShapeIsEnabled(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lua_pushboolean(L, lovrShapeIsEnabled(shape));
return 1;
}
static int l_lovrShapeSetEnabled(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
bool enabled = lua_toboolean(L, 2);
lovrShapeSetEnabled(shape, enabled);
return 0;
}
static int l_lovrShapeIsSensor(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lua_pushboolean(L, lovrShapeIsSensor(shape));
return 1;
}
static int l_lovrShapeSetSensor(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
bool sensor = lua_toboolean(L, 2);
lovrShapeSetSensor(shape, sensor);
return 0;
}
static void luax_pushshapestash(lua_State* L) {
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrshapestash");
@ -321,10 +295,6 @@ static int l_lovrShapeGetAABB(lua_State* L) {
#define lovrShape \
{ "destroy", l_lovrShapeDestroy }, \
{ "getType", l_lovrShapeGetType }, \
{ "isEnabled", l_lovrShapeIsEnabled }, \
{ "setEnabled", l_lovrShapeSetEnabled }, \
{ "isSensor", l_lovrShapeIsSensor }, \
{ "setSensor", l_lovrShapeSetSensor }, \
{ "getUserData", l_lovrShapeGetUserData }, \
{ "setUserData", l_lovrShapeSetUserData }, \
{ "getMass", l_lovrShapeGetMass }, \

View File

@ -90,6 +90,8 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float
void lovrColliderDestroy(void* ref);
void lovrColliderDestroyData(Collider* collider);
bool lovrColliderIsDestroyed(Collider* collider);
bool lovrColliderIsEnabled(Collider* collider);
void lovrColliderSetEnabled(Collider* collider, bool enable);
void lovrColliderInitInertia(Collider* collider, Shape* shape);
World* lovrColliderGetWorld(Collider* collider);
Collider* lovrColliderGetNext(Collider* collider);
@ -106,6 +108,10 @@ float lovrColliderGetRestitution(Collider* collider);
void lovrColliderSetRestitution(Collider* collider, float restitution);
bool lovrColliderIsKinematic(Collider* collider);
void lovrColliderSetKinematic(Collider* collider, bool kinematic);
bool lovrColliderIsSensor(Collider* collider);
void lovrColliderSetSensor(Collider* collider, bool sensor);
bool lovrColliderIsContinuous(Collider* collider);
void lovrColliderSetContinuous(Collider* collider, bool continuous);
float lovrColliderGetGravityScale(Collider* collider);
void lovrColliderSetGravityScale(Collider* collider, float scale);
bool lovrColliderIsSleepingAllowed(Collider* collider);
@ -131,6 +137,9 @@ void lovrColliderSetAngularDamping(Collider* collider, float damping, float thre
void lovrColliderApplyForce(Collider* collider, float x, float y, float z);
void lovrColliderApplyForceAtPosition(Collider* collider, float x, float y, float z, float cx, float cy, float cz);
void lovrColliderApplyTorque(Collider* collider, float x, float y, float z);
void lovrColliderApplyLinearImpulse(Collider* collider, float impulse[3]);
void lovrColliderApplyLinearImpulseAtPosition(Collider* collider, float impulse[3], float position[3]);
void lovrColliderApplyAngularImpulse(Collider* collider, float impulse[3]);
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z);
void lovrColliderGetLocalPoint(Collider* collider, float wx, float wy, float wz, float* x, float* y, float* z);
void lovrColliderGetWorldPoint(Collider* collider, float x, float y, float z, float* wx, float* wy, float* wz);
@ -155,10 +164,6 @@ typedef enum {
void lovrShapeDestroy(void* ref);
void lovrShapeDestroyData(Shape* shape);
ShapeType lovrShapeGetType(Shape* shape);
bool lovrShapeIsEnabled(Shape* shape);
void lovrShapeSetEnabled(Shape* shape, bool enabled);
bool lovrShapeIsSensor(Shape* shape);
void lovrShapeSetSensor(Shape* shape, bool sensor);
void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]);
void lovrShapeGetAABB(Shape* shape, float aabb[6]);
@ -178,7 +183,7 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder);
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]);
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale);
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY);
CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze);
bool lovrCompoundShapeIsFrozen(CompoundShape* shape);

View File

@ -319,9 +319,12 @@ void lovrWorldSetAngularDamping(World* world, float damping, float threshold) {
// Collider
Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z) {
uint32_t count = JPH_PhysicsSystem_GetNumBodies(world->system);
uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system);
lovrCheck(count < limit, "Too many colliders!");
if (!shape) shape = state.pointShape;
// todo: crashes when too many are added
Collider* collider = lovrCalloc(sizeof(Collider));
collider->ref = 1;
collider->world = world;
@ -396,6 +399,18 @@ bool lovrColliderIsDestroyed(Collider* collider) {
return !collider->body;
}
bool lovrColliderIsEnabled(Collider* collider) {
return JPH_BodyInterface_IsAdded(collider->world->bodies, collider->id);
}
void lovrColliderSetEnabled(Collider* collider, bool enable) {
if (enable && !lovrColliderIsEnabled(collider)) {
JPH_BodyInterface_AddBody(collider->world->bodies, collider->id, JPH_Activation_DontActivate);
} else if (!enable && lovrColliderIsEnabled(collider)) {
JPH_BodyInterface_RemoveBody(collider->world->bodies, collider->id);
}
}
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
//
}
@ -535,6 +550,23 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
}
}
bool lovrColliderIsSensor(Collider* collider) {
return JPH_Body_IsSensor(collider->body);
}
void lovrColliderSetSensor(Collider* collider, bool sensor) {
JPH_Body_SetIsSensor(collider->body, sensor);
}
bool lovrColliderIsContinuous(Collider* collider) {
return JPH_BodyInterface_GetMotionQuality(collider->world->bodies, collider->id) == JPH_MotionQuality_LinearCast;
}
void lovrColliderSetContinuous(Collider* collider, bool continuous) {
JPH_MotionQuality quality = continuous ? JPH_MotionQuality_LinearCast : JPH_MotionQuality_Discrete;
return JPH_BodyInterface_SetMotionQuality(collider->world->bodies, collider->id, quality);
}
float lovrColliderGetGravityScale(Collider* collider) {
return JPH_BodyInterface_GetGravityFactor(collider->world->bodies, collider->id);
}
@ -691,6 +723,22 @@ void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
JPH_BodyInterface_AddTorque(collider->world->bodies, collider->id, &torque);
}
void lovrColliderApplyLinearImpulse(Collider* collider, float impulse[3]) {
JPH_Vec3 vector = { impulse[0], impulse[1], impulse[2] };
JPH_BodyInterface_AddImpulse(collider->world->bodies, collider->id, &vector);
}
void lovrColliderApplyLinearImpulseAtPosition(Collider* collider, float impulse[3], float position[3]) {
JPH_Vec3 vector = { impulse[0], impulse[1], impulse[2] };
JPH_Vec3 point = { position[0], position[1], position[2] };
JPH_BodyInterface_AddImpulse2(collider->world->bodies, collider->id, &vector, &point);
}
void lovrColliderApplyAngularImpulse(Collider* collider, float impulse[3]) {
JPH_Vec3 vector = { impulse[0], impulse[1], impulse[2] };
JPH_BodyInterface_AddAngularImpulse(collider->world->bodies, collider->id, &vector);
}
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
// todo: applicable for CompoundShape and OffsetCenterOfMassShape
*x = 0.f;
@ -797,24 +845,6 @@ ShapeType lovrShapeGetType(Shape* shape) {
return shape->type;
}
bool lovrShapeIsEnabled(Shape* shape) {
return true;
}
void lovrShapeSetEnabled(Shape* shape, bool enabled) {
if (!enabled) {
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support disabling shapes");
}
}
bool lovrShapeIsSensor(Shape* shape) {
lovrThrow("NYI");
}
void lovrShapeSetSensor(Shape* shape, bool sensor) {
lovrThrow("NYI");
}
void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
//
}
@ -920,24 +950,22 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount
return mesh;
}
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale) {
lovrCheck(widthSamples == depthSamples, "Jolt needs terrain width and depth to be the same");
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY) {
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
terrain->ref = 1;
terrain->type = SHAPE_TERRAIN;
const JPH_Vec3 offset = {
.x = -.5f * horizontalScale,
.x = -.5f * scaleXZ,
.y = 0.f,
.z = -.5f * horizontalScale
.z = -.5f * scaleXZ
};
const JPH_Vec3 scale = {
.x = horizontalScale / widthSamples,
.y = verticalScale,
.z = horizontalScale / depthSamples
.x = scaleXZ / n,
.y = scaleY,
.z = scaleXZ / n
};
JPH_HeightFieldShapeSettings* shape_settings = JPH_HeightFieldShapeSettings_Create(
vertices, &offset, &scale, widthSamples);
JPH_HeightFieldShapeSettings* shape_settings = JPH_HeightFieldShapeSettings_Create(vertices, &offset, &scale, n);
terrain->shape = (JPH_Shape*) JPH_HeightFieldShapeSettings_CreateShape(shape_settings);
JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) shape_settings);
return terrain;

View File

@ -26,6 +26,7 @@ struct Collider {
arr_t(Joint*) joints;
float friction;
float restitution;
bool sensor;
};
struct Shape {
@ -35,7 +36,6 @@ struct Shape {
Collider* collider;
void* vertices;
void* indices;
bool sensor;
};
struct Joint {
@ -279,7 +279,7 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float res
int contactCount = dCollide(a->id, b->id, MAX_CONTACTS, &contacts[0].geom, sizeof(dContact));
if (!a->sensor && !b->sensor) {
if (!colliderA->sensor && !colliderB->sensor) {
for (int c = 0; c < contactCount; c++) {
dJointID joint = dJointCreateContact(world->id, world->contactGroup, &contacts[c]);
dJointAttach(joint, colliderA->body, colliderB->body);
@ -500,6 +500,14 @@ bool lovrColliderIsDestroyed(Collider* collider) {
return !collider->body;
}
bool lovrColliderIsEnabled(Collider* collider) {
return true;
}
void lovrColliderSetEnabled(Collider* collider, bool enable) {
//
}
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
// compute inertia matrix for default density
const float density = 1.0f;
@ -617,6 +625,22 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
}
}
bool lovrColliderIsSensor(Collider* collider) {
return collider->sensor;
}
void lovrColliderSetSensor(Collider* collider, bool sensor) {
collider->sensor = sensor;
}
bool lovrColliderIsContinuous(Collider* collider) {
return false;
}
void lovrColliderSetContinuous(Collider* collider, bool continuous) {
//
}
float lovrColliderGetGravityScale(Collider* collider) {
return dBodyGetGravityMode(collider->body) ? 1.f : 0.f;
}
@ -767,6 +791,18 @@ void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
dBodyAddTorque(collider->body, x, y, z);
}
void lovrColliderApplyLinearImpulse(Collider* collider, float impulse[3]) {
//
}
void lovrColliderApplyLinearImpulseAtPosition(Collider* collider, float impulse[3], float position[3]) {
//
}
void lovrColliderApplyAngularImpulse(Collider* collider, float impulse[3]) {
//
}
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
dMass m;
dBodyGetMass(collider->body, &m);
@ -875,26 +911,6 @@ Collider* lovrShapeGetCollider(Shape* shape) {
return shape->collider;
}
bool lovrShapeIsEnabled(Shape* shape) {
return dGeomIsEnabled(shape->id);
}
void lovrShapeSetEnabled(Shape* shape, bool enabled) {
if (enabled) {
dGeomEnable(shape->id);
} else {
dGeomDisable(shape->id);
}
}
bool lovrShapeIsSensor(Shape* shape) {
return shape->sensor;
}
void lovrShapeSetSensor(Shape* shape, bool sensor) {
shape->sensor = sensor;
}
void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
dMass m;
dMassSetZero(&m);
@ -1083,13 +1099,12 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount,
return mesh;
}
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale) {
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY) {
const float thickness = 10.f;
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
terrain->ref = 1;
dHeightfieldDataID dataID = dGeomHeightfieldDataCreate();
dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, horizontalScale, horizontalScale,
widthSamples, depthSamples, verticalScale, 0.f, thickness, 0);
dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, scaleXZ, scaleXZ, n, n, scaleY, 0.f, thickness, 0);
terrain->id = dCreateHeightfield(0, dataID, 1);
terrain->type = SHAPE_TERRAIN;
dGeomSetData(terrain->id, terrain);