mirror of https://github.com/bjornbytes/lovr.git
Add physics heightfield shape
This commit is contained in:
parent
36e1471cf0
commit
34611f2069
|
@ -10,6 +10,7 @@ StringEntry lovrShapeType[] = {
|
|||
[SHAPE_CAPSULE] = ENTRY("capsule"),
|
||||
[SHAPE_CYLINDER] = ENTRY("cylinder"),
|
||||
[SHAPE_MESH] = ENTRY("mesh"),
|
||||
[SHAPE_TERRAIN] = ENTRY("terrain"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ void luax_pushshape(lua_State* L, Shape* shape) {
|
|||
case SHAPE_CAPSULE: luax_pushtype(L, CapsuleShape, shape); break;
|
||||
case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, shape); break;
|
||||
case SHAPE_MESH: luax_pushtype(L, MeshShape, shape); break;
|
||||
case SHAPE_TERRAIN: luax_pushtype(L, TerrainShape, shape); break;
|
||||
default: lovrUnreachable();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "api.h"
|
||||
#include "physics/physics.h"
|
||||
#include "data/image.h"
|
||||
#include "util.h"
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
@ -42,6 +43,16 @@ static void raycastCallback(Shape* shape, float x, float y, float z, float nx, f
|
|||
lua_call(L, 7, 0);
|
||||
}
|
||||
|
||||
static float terrainCallback(lua_State * L, int fn_index, float x, float z) {
|
||||
lua_pushvalue(L, fn_index);
|
||||
lua_pushnumber(L, x);
|
||||
lua_pushnumber(L, z);
|
||||
lua_call(L, 2, 1);
|
||||
float height = luax_checkfloat(L, -1);
|
||||
lua_remove(L, -1);
|
||||
return height;
|
||||
}
|
||||
|
||||
static int l_lovrWorldNewCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
float position[4];
|
||||
|
@ -148,6 +159,49 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
TerrainShape* shape;
|
||||
float horizontalScale = luax_checkfloat(L, 2);
|
||||
int type = lua_type(L, 3);
|
||||
if (type == LUA_TNIL || type == LUA_TNONE) {
|
||||
float vertices[4] = {0.f};
|
||||
shape = lovrTerrainShapeCreate(vertices, 2, 2, horizontalScale, 1.f);
|
||||
} else if (type == LUA_TFUNCTION) {
|
||||
unsigned samples = luax_optu32(L, 4, 100);
|
||||
float* vertices = malloc(sizeof(float) * samples * samples);
|
||||
for (unsigned i = 0; i < samples * samples; i++) {
|
||||
float x = horizontalScale * (-0.5f + ((float) (i % samples)) / samples);
|
||||
float z = horizontalScale * (-0.5f + ((float) (i / samples)) / samples);
|
||||
vertices[i] = terrainCallback(L, 3, x, z);
|
||||
}
|
||||
shape = lovrTerrainShapeCreate(vertices, samples, samples, horizontalScale, 1.f);
|
||||
free(vertices);
|
||||
} else if (type == LUA_TUSERDATA) {
|
||||
Image* image = luax_checktype(L, 3, Image);
|
||||
uint32_t imageWidth = lovrImageGetWidth(image, 0);
|
||||
uint32_t imageHeight = lovrImageGetHeight(image, 0);
|
||||
float verticalScale = luax_optfloat(L, 4, 1.f);
|
||||
float* vertices = malloc(sizeof(float) * imageWidth * imageHeight);
|
||||
for (int y = 0; y < imageHeight; y++) {
|
||||
for (int x = 0; x < imageWidth; x++) {
|
||||
float pixel[4];
|
||||
lovrImageGetPixel(image, x, y, pixel);
|
||||
vertices[x + y * imageWidth] = pixel[0];
|
||||
}
|
||||
}
|
||||
shape = lovrTerrainShapeCreate(vertices, imageWidth, imageHeight, horizontalScale, verticalScale);
|
||||
free(vertices);
|
||||
}
|
||||
Collider* collider = lovrColliderCreate(world, 0, 0, 0);
|
||||
lovrColliderAddShape(collider, shape);
|
||||
lovrColliderSetKinematic(collider, true);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
lovrRelease(shape, lovrShapeDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrWorldGetColliders(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
|
||||
|
@ -388,6 +442,7 @@ const luaL_Reg lovrWorld[] = {
|
|||
{ "newCylinderCollider", l_lovrWorldNewCylinderCollider },
|
||||
{ "newSphereCollider", l_lovrWorldNewSphereCollider },
|
||||
{ "newMeshCollider", l_lovrWorldNewMeshCollider },
|
||||
{ "newTerrainCollider", l_lovrWorldNewTerrainCollider },
|
||||
{ "getColliders", l_lovrWorldGetColliders },
|
||||
{ "destroy", l_lovrWorldDestroy },
|
||||
{ "update", l_lovrWorldUpdate },
|
||||
|
|
|
@ -798,6 +798,9 @@ void lovrShapeDestroyData(Shape* shape) {
|
|||
dGeomTriMeshDataDestroy(dataID);
|
||||
free(shape->vertices);
|
||||
free(shape->indices);
|
||||
} else if (shape->type == SHAPE_TERRAIN) {
|
||||
dHeightfieldDataID dataID = dGeomHeightfieldGetHeightfieldData(shape->id);
|
||||
dGeomHeightfieldDataDestroy(dataID);
|
||||
}
|
||||
dGeomDestroy(shape->id);
|
||||
shape->id = NULL;
|
||||
|
@ -1049,6 +1052,20 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount,
|
|||
return mesh;
|
||||
}
|
||||
|
||||
TerrainShape* lovrTerrainShapeCreate(float* vertices, int widthSamples, int depthSamples, float horizontalScale, float verticalScale) {
|
||||
const float thickness = 10.f;
|
||||
TerrainShape* terrain = calloc(1, sizeof(TerrainShape));
|
||||
lovrAssert(terrain, "Out of memory");
|
||||
terrain->ref = 1;
|
||||
dHeightfieldDataID dataID = dGeomHeightfieldDataCreate();
|
||||
dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, horizontalScale, horizontalScale,
|
||||
widthSamples, depthSamples, verticalScale, 0.f, thickness, 0);
|
||||
terrain->id = dCreateHeightfield(0, dataID, 1);
|
||||
terrain->type = SHAPE_TERRAIN;
|
||||
dGeomSetData(terrain->id, terrain);
|
||||
return terrain;
|
||||
}
|
||||
|
||||
void lovrJointDestroy(void* ref) {
|
||||
Joint* joint = ref;
|
||||
lovrJointDestroyData(joint);
|
||||
|
|
|
@ -18,6 +18,7 @@ typedef Shape BoxShape;
|
|||
typedef Shape CapsuleShape;
|
||||
typedef Shape CylinderShape;
|
||||
typedef Shape MeshShape;
|
||||
typedef Shape TerrainShape;
|
||||
|
||||
typedef Joint BallJoint;
|
||||
typedef Joint DistanceJoint;
|
||||
|
@ -131,6 +132,7 @@ typedef enum {
|
|||
SHAPE_CAPSULE,
|
||||
SHAPE_CYLINDER,
|
||||
SHAPE_MESH,
|
||||
SHAPE_TERRAIN,
|
||||
} ShapeType;
|
||||
|
||||
void lovrShapeDestroy(void* ref);
|
||||
|
@ -171,6 +173,7 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder);
|
|||
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
|
||||
|
||||
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]);
|
||||
TerrainShape* lovrTerrainShapeCreate(float* vertices, int widthSamples, int depthSamples, float horizontalScale, float verticalScale);
|
||||
|
||||
// These tokens need to exist for Lua bindings
|
||||
#define lovrSphereShapeDestroy lovrShapeDestroy
|
||||
|
@ -178,6 +181,7 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount
|
|||
#define lovrCapsuleShapeDestroy lovrShapeDestroy
|
||||
#define lovrCylinderShapeDestroy lovrShapeDestroy
|
||||
#define lovrMeshShapeDestroy lovrShapeDestroy
|
||||
#define lovrTerrainShapeDestroy lovrShapeDestroy
|
||||
|
||||
// Joints
|
||||
|
||||
|
|
Loading…
Reference in New Issue