Compare commits

...

2 Commits

Author SHA1 Message Date
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
4 changed files with 30 additions and 30 deletions

View File

@ -91,17 +91,17 @@ Shape* luax_newmeshshape(lua_State* L, int index) {
} }
Shape* luax_newterrainshape(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); int type = lua_type(L, index);
if (type == LUA_TNIL || type == LUA_TNONE) { if (type == LUA_TNIL || type == LUA_TNONE) {
float vertices[4] = { 0.f }; 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) { } else if (type == LUA_TFUNCTION) {
uint32_t samples = luax_optu32(L, index + 1, 100); uint32_t n = luax_optu32(L, index + 1, 100);
float* vertices = lovrMalloc(sizeof(float) * samples * samples); float* vertices = lovrMalloc(sizeof(float) * n * n);
for (uint32_t i = 0; i < samples * samples; i++) { for (uint32_t i = 0; i < n * n; i++) {
float x = horizontalScale * (-.5f + ((float) (i % samples)) / samples); float x = scaleXZ * (-.5f + ((float) (i % n)) / n);
float z = horizontalScale * (-.5f + ((float) (i / samples)) / samples); float z = scaleXZ * (-.5f + ((float) (i / n)) / n);
lua_pushvalue(L, index); lua_pushvalue(L, index);
lua_pushnumber(L, x); lua_pushnumber(L, x);
lua_pushnumber(L, z); lua_pushnumber(L, z);
@ -110,23 +110,23 @@ Shape* luax_newterrainshape(lua_State* L, int index) {
vertices[i] = luax_tofloat(L, -1); vertices[i] = luax_tofloat(L, -1);
lua_pop(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); lovrFree(vertices);
return shape; return shape;
} else if (type == LUA_TUSERDATA) { } else if (type == LUA_TUSERDATA) {
Image* image = luax_checktype(L, index, Image); Image* image = luax_checktype(L, index, Image);
uint32_t imageWidth = lovrImageGetWidth(image, 0); uint32_t n = lovrImageGetWidth(image, 0);
uint32_t imageHeight = lovrImageGetHeight(image, 0); lovrCheck(lovrImageGetHeight(image, 0) == n, "TerrainShape images must be square");
float verticalScale = luax_optfloat(L, index + 1, 1.f); float scaleY = luax_optfloat(L, index + 1, 1.f);
float* vertices = lovrMalloc(sizeof(float) * imageWidth * imageHeight); float* vertices = lovrMalloc(sizeof(float) * n * n);
for (uint32_t y = 0; y < imageHeight; y++) { for (uint32_t y = 0; y < n; y++) {
for (uint32_t x = 0; x < imageWidth; x++) { for (uint32_t x = 0; x < n; x++) {
float pixel[4]; float pixel[4];
lovrImageGetPixel(image, x, y, pixel); 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); lovrFree(vertices);
return shape; return shape;
} else { } else {

View File

@ -191,7 +191,7 @@ void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]); 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);
// These tokens need to exist for Lua bindings // These tokens need to exist for Lua bindings
#define lovrSphereShapeDestroy lovrShapeDestroy #define lovrSphereShapeDestroy lovrShapeDestroy

View File

@ -316,7 +316,10 @@ void lovrWorldSetAngularDamping(World* world, float damping, float threshold) {
// Collider // Collider
Collider* lovrColliderCreate(World* world, float x, float y, float z) { Collider* lovrColliderCreate(World* world, float x, float y, float z) {
// todo: crashes when too many are added uint32_t count = JPH_PhysicsSystem_GetNumBodies(world->system);
uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system);
lovrCheck(count < limit, "Too many colliders!");
Collider* collider = lovrCalloc(sizeof(Collider)); Collider* collider = lovrCalloc(sizeof(Collider));
collider->ref = 1; collider->ref = 1;
collider->world = world; collider->world = world;
@ -956,24 +959,22 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount
return mesh; 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) {
lovrCheck(widthSamples == depthSamples, "Jolt needs terrain width and depth to be the same");
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape)); TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
terrain->ref = 1; terrain->ref = 1;
terrain->type = SHAPE_TERRAIN; terrain->type = SHAPE_TERRAIN;
const JPH_Vec3 offset = { const JPH_Vec3 offset = {
.x = -.5f * horizontalScale, .x = -.5f * scaleXZ,
.y = 0.f, .y = 0.f,
.z = -.5f * horizontalScale .z = -.5f * scaleXZ
}; };
const JPH_Vec3 scale = { const JPH_Vec3 scale = {
.x = horizontalScale / widthSamples, .x = scaleXZ / n,
.y = verticalScale, .y = scaleY,
.z = horizontalScale / depthSamples .z = scaleXZ / n
}; };
JPH_HeightFieldShapeSettings* shape_settings = JPH_HeightFieldShapeSettings_Create( JPH_HeightFieldShapeSettings* shape_settings = JPH_HeightFieldShapeSettings_Create(vertices, &offset, &scale, n);
vertices, &offset, &scale, widthSamples);
terrain->shape = (JPH_Shape*) JPH_HeightFieldShapeSettings_CreateShape(shape_settings); terrain->shape = (JPH_Shape*) JPH_HeightFieldShapeSettings_CreateShape(shape_settings);
JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) shape_settings); JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) shape_settings);
return terrain; return terrain;

View File

@ -1119,13 +1119,12 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount,
return mesh; 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; const float thickness = 10.f;
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape)); TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
terrain->ref = 1; terrain->ref = 1;
dHeightfieldDataID dataID = dGeomHeightfieldDataCreate(); dHeightfieldDataID dataID = dGeomHeightfieldDataCreate();
dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, horizontalScale, horizontalScale, dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, scaleXZ, scaleXZ, n, n, scaleY, 0.f, thickness, 0);
widthSamples, depthSamples, verticalScale, 0.f, thickness, 0);
terrain->id = dCreateHeightfield(0, dataID, 1); terrain->id = dCreateHeightfield(0, dataID, 1);
terrain->type = SHAPE_TERRAIN; terrain->type = SHAPE_TERRAIN;
dGeomSetData(terrain->id, terrain); dGeomSetData(terrain->id, terrain);