mirror of
https://github.com/bjornbytes/lovr.git
synced 2024-07-03 04:53:35 +00:00
Merge branch 'master' into dev
This commit is contained in:
commit
c61d6b059b
|
@ -34,8 +34,7 @@ option(LOVR_SYSTEM_OPENXR "Use the system-provided OpenXR" OFF)
|
||||||
option(LOVR_BUILD_EXE "Build an executable (or an apk on Android)" ON)
|
option(LOVR_BUILD_EXE "Build an executable (or an apk on Android)" ON)
|
||||||
option(LOVR_BUILD_SHARED "Build a shared library (takes precedence over LOVR_BUILD_EXE)" OFF)
|
option(LOVR_BUILD_SHARED "Build a shared library (takes precedence over LOVR_BUILD_EXE)" OFF)
|
||||||
option(LOVR_BUILD_BUNDLE "On macOS, build a .app bundle instead of a raw program" OFF)
|
option(LOVR_BUILD_BUNDLE "On macOS, build a .app bundle instead of a raw program" OFF)
|
||||||
|
option(LOVR_BUILD_WITH_SYMBOLS "Build with C function symbols exposed" OFF)
|
||||||
set(LOVR_SYMBOL_VISIBILITY "hidden" CACHE STRING "What should the C symbol visibility be? hidden reduces binary size, default lets other binaries use this one.")
|
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
if(EMSCRIPTEN)
|
if(EMSCRIPTEN)
|
||||||
|
@ -299,7 +298,9 @@ endif()
|
||||||
# Plugins
|
# Plugins
|
||||||
set(LOVR 1)
|
set(LOVR 1)
|
||||||
link_libraries(${LOVR_LUA})
|
link_libraries(${LOVR_LUA})
|
||||||
file(GLOB LOVR_PLUGINS ${CMAKE_SOURCE_DIR}/plugins/*)
|
if(NOT DEFINED LOVR_PLUGINS)
|
||||||
|
file(GLOB LOVR_PLUGINS ${CMAKE_SOURCE_DIR}/plugins/*)
|
||||||
|
endif()
|
||||||
foreach(PLUGIN_PATH ${LOVR_PLUGINS})
|
foreach(PLUGIN_PATH ${LOVR_PLUGINS})
|
||||||
if(IS_DIRECTORY ${PLUGIN_PATH} AND EXISTS ${PLUGIN_PATH}/CMakeLists.txt)
|
if(IS_DIRECTORY ${PLUGIN_PATH} AND EXISTS ${PLUGIN_PATH}/CMakeLists.txt)
|
||||||
get_filename_component(PLUGIN "${PLUGIN_PATH}" NAME)
|
get_filename_component(PLUGIN "${PLUGIN_PATH}" NAME)
|
||||||
|
@ -338,10 +339,22 @@ if(NOT LOVR_BUILD_EXE)
|
||||||
target_compile_definitions(lovr PUBLIC LOVR_OMIT_MAIN) # specifically for win32 WinMain
|
target_compile_definitions(lovr PUBLIC LOVR_OMIT_MAIN) # specifically for win32 WinMain
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(lovr PROPERTIES C_VISIBILITY_PRESET ${LOVR_SYMBOL_VISIBILITY})
|
if(LOVR_BUILD_WITH_SYMBOLS)
|
||||||
|
set_target_properties(lovr PROPERTIES C_VISIBILITY_PRESET "default")
|
||||||
|
else()
|
||||||
|
set_target_properties(lovr PROPERTIES C_VISIBILITY_PRESET "hidden")
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(lovr PROPERTIES C_STANDARD 11)
|
set_target_properties(lovr PROPERTIES C_STANDARD 11)
|
||||||
set_target_properties(lovr PROPERTIES C_STANDARD_REQUIRED ON)
|
set_target_properties(lovr PROPERTIES C_STANDARD_REQUIRED ON)
|
||||||
target_include_directories(lovr PRIVATE src src/modules src/lib/stdatomic etc)
|
|
||||||
|
target_include_directories(lovr PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/modules
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/stdatomic
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/etc
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(lovr
|
target_link_libraries(lovr
|
||||||
${LOVR_GLFW}
|
${LOVR_GLFW}
|
||||||
${LOVR_LUA}
|
${LOVR_LUA}
|
||||||
|
|
|
@ -182,4 +182,10 @@ void luax_pushjoint(struct lua_State* L, struct Joint* joint);
|
||||||
void luax_pushshape(struct lua_State* L, struct Shape* shape);
|
void luax_pushshape(struct lua_State* L, struct Shape* shape);
|
||||||
struct Joint* luax_checkjoint(struct lua_State* L, int index);
|
struct Joint* luax_checkjoint(struct lua_State* L, int index);
|
||||||
struct Shape* luax_checkshape(struct lua_State* L, int index);
|
struct Shape* luax_checkshape(struct lua_State* L, int index);
|
||||||
|
struct Shape* luax_newsphereshape(struct lua_State* L, int index);
|
||||||
|
struct Shape* luax_newboxshape(struct lua_State* L, int index);
|
||||||
|
struct Shape* luax_newcapsuleshape(struct lua_State* L, int index);
|
||||||
|
struct Shape* luax_newcylindershape(struct lua_State* L, int index);
|
||||||
|
struct Shape* luax_newmeshshape(struct lua_State* L, int index);
|
||||||
|
struct Shape* luax_newterrainshape(struct lua_State* L, int index);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,27 +61,21 @@ static int l_lovrPhysicsNewBallJoint(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_lovrPhysicsNewBoxShape(lua_State* L) {
|
static int l_lovrPhysicsNewBoxShape(lua_State* L) {
|
||||||
float size[4];
|
BoxShape* box = luax_newboxshape(L, 1);
|
||||||
luax_readscale(L, 1, size, 3, NULL);
|
|
||||||
BoxShape* box = lovrBoxShapeCreate(size[0], size[1], size[2]);
|
|
||||||
luax_pushtype(L, BoxShape, box);
|
luax_pushtype(L, BoxShape, box);
|
||||||
lovrRelease(box, lovrShapeDestroy);
|
lovrRelease(box, lovrShapeDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_lovrPhysicsNewCapsuleShape(lua_State* L) {
|
static int l_lovrPhysicsNewCapsuleShape(lua_State* L) {
|
||||||
float radius = luax_optfloat(L, 1, 1.f);
|
CapsuleShape* capsule = luax_newcapsuleshape(L, 1);
|
||||||
float length = luax_optfloat(L, 2, 1.f);
|
|
||||||
CapsuleShape* capsule = lovrCapsuleShapeCreate(radius, length);
|
|
||||||
luax_pushtype(L, CapsuleShape, capsule);
|
luax_pushtype(L, CapsuleShape, capsule);
|
||||||
lovrRelease(capsule, lovrShapeDestroy);
|
lovrRelease(capsule, lovrShapeDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_lovrPhysicsNewCylinderShape(lua_State* L) {
|
static int l_lovrPhysicsNewCylinderShape(lua_State* L) {
|
||||||
float radius = luax_optfloat(L, 1, 1.f);
|
CylinderShape* cylinder = luax_newcylindershape(L, 1);
|
||||||
float length = luax_optfloat(L, 2, 1.f);
|
|
||||||
CylinderShape* cylinder = lovrCylinderShapeCreate(radius, length);
|
|
||||||
luax_pushtype(L, CylinderShape, cylinder);
|
luax_pushtype(L, CylinderShape, cylinder);
|
||||||
lovrRelease(cylinder, lovrShapeDestroy);
|
lovrRelease(cylinder, lovrShapeDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -112,6 +106,13 @@ static int l_lovrPhysicsNewHingeJoint(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_lovrPhysicsNewMeshShape(lua_State* L) {
|
||||||
|
MeshShape* mesh = luax_newmeshshape(L, 1);
|
||||||
|
luax_pushtype(L, MeshShape, mesh);
|
||||||
|
lovrRelease(mesh, lovrShapeDestroy);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int l_lovrPhysicsNewSliderJoint(lua_State* L) {
|
static int l_lovrPhysicsNewSliderJoint(lua_State* L) {
|
||||||
Collider* a = luax_checktype(L, 1, Collider);
|
Collider* a = luax_checktype(L, 1, Collider);
|
||||||
Collider* b = luax_checktype(L, 2, Collider);
|
Collider* b = luax_checktype(L, 2, Collider);
|
||||||
|
@ -124,13 +125,19 @@ static int l_lovrPhysicsNewSliderJoint(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_lovrPhysicsNewSphereShape(lua_State* L) {
|
static int l_lovrPhysicsNewSphereShape(lua_State* L) {
|
||||||
float radius = luax_optfloat(L, 1, 1.f);
|
SphereShape* sphere = luax_newsphereshape(L, 1);
|
||||||
SphereShape* sphere = lovrSphereShapeCreate(radius);
|
|
||||||
luax_pushtype(L, SphereShape, sphere);
|
luax_pushtype(L, SphereShape, sphere);
|
||||||
lovrRelease(sphere, lovrShapeDestroy);
|
lovrRelease(sphere, lovrShapeDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_lovrPhysicsNewTerrainShape(lua_State* L) {
|
||||||
|
TerrainShape* terrain = luax_newterrainshape(L, 1);
|
||||||
|
luax_pushtype(L, TerrainShape, terrain);
|
||||||
|
lovrRelease(terrain, lovrShapeDestroy);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg lovrPhysics[] = {
|
static const luaL_Reg lovrPhysics[] = {
|
||||||
{ "newWorld", l_lovrPhysicsNewWorld },
|
{ "newWorld", l_lovrPhysicsNewWorld },
|
||||||
{ "newBallJoint", l_lovrPhysicsNewBallJoint },
|
{ "newBallJoint", l_lovrPhysicsNewBallJoint },
|
||||||
|
@ -139,8 +146,10 @@ static const luaL_Reg lovrPhysics[] = {
|
||||||
{ "newCylinderShape", l_lovrPhysicsNewCylinderShape },
|
{ "newCylinderShape", l_lovrPhysicsNewCylinderShape },
|
||||||
{ "newDistanceJoint", l_lovrPhysicsNewDistanceJoint },
|
{ "newDistanceJoint", l_lovrPhysicsNewDistanceJoint },
|
||||||
{ "newHingeJoint", l_lovrPhysicsNewHingeJoint },
|
{ "newHingeJoint", l_lovrPhysicsNewHingeJoint },
|
||||||
|
{ "newMeshShape", l_lovrPhysicsNewMeshShape },
|
||||||
{ "newSliderJoint", l_lovrPhysicsNewSliderJoint },
|
{ "newSliderJoint", l_lovrPhysicsNewSliderJoint },
|
||||||
{ "newSphereShape", l_lovrPhysicsNewSphereShape },
|
{ "newSphereShape", l_lovrPhysicsNewSphereShape },
|
||||||
|
{ "newTerrainShape", l_lovrPhysicsNewTerrainShape },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,6 +164,7 @@ extern const luaL_Reg lovrBoxShape[];
|
||||||
extern const luaL_Reg lovrCapsuleShape[];
|
extern const luaL_Reg lovrCapsuleShape[];
|
||||||
extern const luaL_Reg lovrCylinderShape[];
|
extern const luaL_Reg lovrCylinderShape[];
|
||||||
extern const luaL_Reg lovrMeshShape[];
|
extern const luaL_Reg lovrMeshShape[];
|
||||||
|
extern const luaL_Reg lovrTerrainShape[];
|
||||||
|
|
||||||
int luaopen_lovr_physics(lua_State* L) {
|
int luaopen_lovr_physics(lua_State* L) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
@ -170,6 +180,7 @@ int luaopen_lovr_physics(lua_State* L) {
|
||||||
luax_registertype(L, CapsuleShape);
|
luax_registertype(L, CapsuleShape);
|
||||||
luax_registertype(L, CylinderShape);
|
luax_registertype(L, CylinderShape);
|
||||||
luax_registertype(L, MeshShape);
|
luax_registertype(L, MeshShape);
|
||||||
|
luax_registertype(L, TerrainShape);
|
||||||
if (lovrPhysicsInit()) {
|
if (lovrPhysicsInit()) {
|
||||||
luax_atexit(L, lovrPhysicsDestroy);
|
luax_atexit(L, lovrPhysicsDestroy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include "physics/physics.h"
|
#include "physics/physics.h"
|
||||||
|
#include "data/image.h"
|
||||||
#include "core/maf.h"
|
#include "core/maf.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
void luax_pushshape(lua_State* L, Shape* shape) {
|
void luax_pushshape(lua_State* L, Shape* shape) {
|
||||||
|
@ -28,6 +30,7 @@ Shape* luax_checkshape(lua_State* L, int index) {
|
||||||
hash64("CapsuleShape", strlen("CapsuleShape")),
|
hash64("CapsuleShape", strlen("CapsuleShape")),
|
||||||
hash64("CylinderShape", strlen("CylinderShape")),
|
hash64("CylinderShape", strlen("CylinderShape")),
|
||||||
hash64("MeshShape", strlen("MeshShape")),
|
hash64("MeshShape", strlen("MeshShape")),
|
||||||
|
hash64("TerrainShape", strlen("TerrainShape"))
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < COUNTOF(hashes); i++) {
|
for (size_t i = 0; i < COUNTOF(hashes); i++) {
|
||||||
|
@ -41,6 +44,102 @@ Shape* luax_checkshape(lua_State* L, int index) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shape* luax_newsphereshape(lua_State* L, int index) {
|
||||||
|
float radius = luax_optfloat(L, index, 1.f);
|
||||||
|
return lovrSphereShapeCreate(radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* luax_newboxshape(lua_State* L, int index) {
|
||||||
|
float size[4];
|
||||||
|
luax_readscale(L, index, size, 3, NULL);
|
||||||
|
return lovrBoxShapeCreate(size[0], size[1], size[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* luax_newcapsuleshape(lua_State* L, int index) {
|
||||||
|
float radius = luax_optfloat(L, index + 0, 1.f);
|
||||||
|
float length = luax_optfloat(L, index + 1, 1.f);
|
||||||
|
return lovrCapsuleShapeCreate(radius, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* luax_newcylindershape(lua_State* L, int index) {
|
||||||
|
float radius = luax_optfloat(L, index + 0, 1.f);
|
||||||
|
float length = luax_optfloat(L, index + 1, 1.f);
|
||||||
|
return lovrCylinderShapeCreate(radius, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* luax_newmeshshape(lua_State* L, int index) {
|
||||||
|
float* vertices;
|
||||||
|
uint32_t* indices;
|
||||||
|
uint32_t vertexCount;
|
||||||
|
uint32_t indexCount;
|
||||||
|
bool shouldFree;
|
||||||
|
|
||||||
|
luax_readmesh(L, index, &vertices, &vertexCount, &indices, &indexCount, &shouldFree);
|
||||||
|
|
||||||
|
// If we do not own the mesh data, we must make a copy
|
||||||
|
// ode's trimesh collider needs to own the triangle info for the lifetime of the geom
|
||||||
|
// Note that if shouldFree is true, we don't free the data and let the physics module do it when
|
||||||
|
// the collider/shape is destroyed
|
||||||
|
if (!shouldFree) {
|
||||||
|
float* v = vertices;
|
||||||
|
uint32_t* i = indices;
|
||||||
|
vertices = malloc(3 * vertexCount * sizeof(float));
|
||||||
|
indices = malloc(indexCount * sizeof(uint32_t));
|
||||||
|
lovrAssert(vertices && indices, "Out of memory");
|
||||||
|
memcpy(vertices, v, 3 * vertexCount * sizeof(float));
|
||||||
|
memcpy(indices, i, indexCount * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lovrMeshShapeCreate(vertexCount, vertices, indexCount, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* luax_newterrainshape(lua_State* L, int index) {
|
||||||
|
float horizontalScale = 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);
|
||||||
|
} else if (type == LUA_TFUNCTION) {
|
||||||
|
uint32_t samples = luax_optu32(L, index + 1, 100);
|
||||||
|
float* vertices = malloc(sizeof(float) * samples * samples);
|
||||||
|
lovrAssert(vertices, "Out of memory");
|
||||||
|
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);
|
||||||
|
lua_pushvalue(L, index);
|
||||||
|
lua_pushnumber(L, x);
|
||||||
|
lua_pushnumber(L, z);
|
||||||
|
lua_call(L, 2, 1);
|
||||||
|
lovrCheck(lua_type(L, -1) == LUA_TNUMBER, "Expected TerrainShape callback to return a number");
|
||||||
|
vertices[i] = luax_tofloat(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
TerrainShape* shape = lovrTerrainShapeCreate(vertices, samples, samples, horizontalScale, 1.f);
|
||||||
|
free(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 = malloc(sizeof(float) * imageWidth * imageHeight);
|
||||||
|
lovrAssert(vertices, "Out of memory");
|
||||||
|
for (uint32_t y = 0; y < imageHeight; y++) {
|
||||||
|
for (uint32_t x = 0; x < imageWidth; x++) {
|
||||||
|
float pixel[4];
|
||||||
|
lovrImageGetPixel(image, x, y, pixel);
|
||||||
|
vertices[x + y * imageWidth] = pixel[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerrainShape* shape = lovrTerrainShapeCreate(vertices, imageWidth, imageHeight, horizontalScale, verticalScale);
|
||||||
|
free(vertices);
|
||||||
|
return shape;
|
||||||
|
} else {
|
||||||
|
luax_typeerror(L, index, "Image, number, or function");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int l_lovrShapeDestroy(lua_State* L) {
|
static int l_lovrShapeDestroy(lua_State* L) {
|
||||||
Shape* shape = luax_checkshape(L, 1);
|
Shape* shape = luax_checkshape(L, 1);
|
||||||
lovrShapeDestroyData(shape);
|
lovrShapeDestroyData(shape);
|
||||||
|
@ -313,3 +412,8 @@ const luaL_Reg lovrMeshShape[] = {
|
||||||
lovrShape,
|
lovrShape,
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const luaL_Reg lovrTerrainShape[] = {
|
||||||
|
lovrShape,
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include "physics/physics.h"
|
#include "physics/physics.h"
|
||||||
#include "data/image.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -43,16 +41,6 @@ static void raycastCallback(Shape* shape, float x, float y, float z, float nx, f
|
||||||
lua_call(L, 7, 0);
|
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) {
|
static int l_lovrWorldNewCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[4];
|
float position[4];
|
||||||
|
@ -65,11 +53,10 @@ static int l_lovrWorldNewCollider(lua_State* L) {
|
||||||
|
|
||||||
static int l_lovrWorldNewBoxCollider(lua_State* L) {
|
static int l_lovrWorldNewBoxCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[4], size[4];
|
float position[4];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
luax_readscale(L, index, size, 3, NULL);
|
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||||
BoxShape* shape = lovrBoxShapeCreate(size[0], size[1], size[2]);
|
BoxShape* shape = luax_newboxshape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
lovrColliderAddShape(collider, shape);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
|
@ -82,10 +69,8 @@ static int l_lovrWorldNewCapsuleCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[4];
|
float position[4];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
float radius = luax_optfloat(L, index++, 1.f);
|
|
||||||
float length = luax_optfloat(L, index, 1.f);
|
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||||
CapsuleShape* shape = lovrCapsuleShapeCreate(radius, length);
|
CapsuleShape* shape = luax_newcapsuleshape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
lovrColliderAddShape(collider, shape);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
|
@ -98,10 +83,8 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[4];
|
float position[4];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
float radius = luax_optfloat(L, index++, 1.f);
|
|
||||||
float length = luax_optfloat(L, index, 1.f);
|
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||||
CylinderShape* shape = lovrCylinderShapeCreate(radius, length);
|
CylinderShape* shape = luax_newcylindershape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
lovrColliderAddShape(collider, shape);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
|
@ -114,9 +97,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[4];
|
float position[4];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
float radius = luax_optfloat(L, index, 1.f);
|
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||||
SphereShape* shape = lovrSphereShapeCreate(radius);
|
SphereShape* shape = luax_newsphereshape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
lovrColliderAddShape(collider, shape);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
|
@ -127,30 +109,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
||||||
|
|
||||||
static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
|
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
|
||||||
float* vertices;
|
MeshShape* shape = luax_newmeshshape(L, 2);
|
||||||
uint32_t* indices;
|
|
||||||
uint32_t vertexCount;
|
|
||||||
uint32_t indexCount;
|
|
||||||
bool shouldFree;
|
|
||||||
luax_readmesh(L, 2, &vertices, &vertexCount, &indices, &indexCount, &shouldFree);
|
|
||||||
|
|
||||||
// If we do not own the mesh data, we must make a copy
|
|
||||||
// ode's trimesh collider needs to own the triangle info for the lifetime of the geom
|
|
||||||
// Note that if shouldFree is true, we don't free the data and let the physics module do it when
|
|
||||||
// the collider/shape is destroyed
|
|
||||||
if (!shouldFree) {
|
|
||||||
float* v = vertices;
|
|
||||||
uint32_t* i = indices;
|
|
||||||
vertices = malloc(3 * vertexCount * sizeof(float));
|
|
||||||
indices = malloc(indexCount * sizeof(uint32_t));
|
|
||||||
lovrAssert(vertices && indices, "Out of memory");
|
|
||||||
memcpy(vertices, v, 3 * vertexCount * sizeof(float));
|
|
||||||
memcpy(indices, i, indexCount * sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
Collider* collider = lovrColliderCreate(world, 0, 0, 0);
|
|
||||||
MeshShape* shape = lovrMeshShapeCreate(vertexCount, vertices, indexCount, indices);
|
|
||||||
lovrColliderAddShape(collider, shape);
|
lovrColliderAddShape(collider, shape);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
|
@ -161,39 +121,8 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
||||||
|
|
||||||
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
|
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
TerrainShape* shape;
|
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
|
||||||
float horizontalScale = luax_checkfloat(L, 2);
|
TerrainShape* shape = luax_newterrainshape(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);
|
lovrColliderAddShape(collider, shape);
|
||||||
lovrColliderSetKinematic(collider, true);
|
lovrColliderSetKinematic(collider, true);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
typedef struct gpu_buffer gpu_buffer;
|
typedef struct gpu_buffer gpu_buffer;
|
||||||
typedef struct gpu_texture gpu_texture;
|
typedef struct gpu_texture gpu_texture;
|
||||||
typedef struct gpu_sampler gpu_sampler;
|
typedef struct gpu_sampler gpu_sampler;
|
||||||
|
|
|
@ -420,6 +420,16 @@ static void countVertices(ModelData* model, uint32_t nodeIndex, uint32_t* vertex
|
||||||
for (uint32_t i = 0; i < node->primitiveCount; i++) {
|
for (uint32_t i = 0; i < node->primitiveCount; i++) {
|
||||||
ModelPrimitive* primitive = &model->primitives[node->primitiveIndex + i];
|
ModelPrimitive* primitive = &model->primitives[node->primitiveIndex + i];
|
||||||
ModelAttribute* positions = primitive->attributes[ATTR_POSITION];
|
ModelAttribute* positions = primitive->attributes[ATTR_POSITION];
|
||||||
|
if (!positions) continue;
|
||||||
|
|
||||||
|
// If 2 meshes in the node use the same vertex buffer, don't count the vertices twice
|
||||||
|
for (uint32_t j = 0; j < i; j++) {
|
||||||
|
if (model->primitives[node->primitiveIndex + j].attributes[ATTR_POSITION] == positions) {
|
||||||
|
positions = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ModelAttribute* indices = primitive->indices;
|
ModelAttribute* indices = primitive->indices;
|
||||||
uint32_t count = positions ? positions->count : 0;
|
uint32_t count = positions ? positions->count : 0;
|
||||||
*vertexCount += count;
|
*vertexCount += count;
|
||||||
|
@ -448,43 +458,59 @@ static void collectVertices(ModelData* model, uint32_t nodeIndex, float** vertic
|
||||||
mat4_scale(m, S[0], S[1], S[2]);
|
mat4_scale(m, S[0], S[1], S[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t nodeBase = *baseIndex;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < node->primitiveCount; i++) {
|
for (uint32_t i = 0; i < node->primitiveCount; i++) {
|
||||||
ModelPrimitive* primitive = &model->primitives[node->primitiveIndex + i];
|
ModelPrimitive* primitive = &model->primitives[node->primitiveIndex + i];
|
||||||
ModelAttribute* positions = primitive->attributes[ATTR_POSITION];
|
ModelAttribute* positions = primitive->attributes[ATTR_POSITION];
|
||||||
ModelAttribute* index = primitive->indices;
|
ModelAttribute* index = primitive->indices;
|
||||||
if (!positions) continue;
|
if (!positions) continue;
|
||||||
|
|
||||||
char* data = (char*) model->buffers[positions->buffer].data + positions->offset;
|
uint32_t base = nodeBase;
|
||||||
size_t stride = positions->stride == 0 ? 3 * sizeof(float) : positions->stride;
|
|
||||||
|
|
||||||
for (uint32_t j = 0; j < positions->count; j++) {
|
// If 2 meshes in the node use the same vertex buffer, don't add the vertices twice
|
||||||
float v[4];
|
for (uint32_t j = 0; j < i; j++) {
|
||||||
memcpy(v, data, 3 * sizeof(float));
|
if (model->primitives[node->primitiveIndex + j].attributes[ATTR_POSITION] == positions) {
|
||||||
mat4_transform(m, v);
|
break;
|
||||||
memcpy(*vertices, v, 3 * sizeof(float));
|
} else {
|
||||||
*vertices += 3;
|
base += model->primitives[node->primitiveIndex + j].attributes[ATTR_POSITION]->count;
|
||||||
data += stride;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base == *baseIndex) {
|
||||||
|
char* data = (char*) model->buffers[positions->buffer].data + positions->offset;
|
||||||
|
size_t stride = positions->stride == 0 ? 3 * sizeof(float) : positions->stride;
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < positions->count; j++) {
|
||||||
|
float v[4];
|
||||||
|
memcpy(v, data, 3 * sizeof(float));
|
||||||
|
mat4_transform(m, v);
|
||||||
|
memcpy(*vertices, v, 3 * sizeof(float));
|
||||||
|
*vertices += 3;
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
*baseIndex += positions->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index) {
|
if (index) {
|
||||||
lovrAssert(index->type == U16 || index->type == U32, "Unreachable");
|
lovrAssert(index->type == U16 || index->type == U32, "Unreachable");
|
||||||
|
|
||||||
data = (char*) model->buffers[index->buffer].data + index->offset;
|
char* data = (char*) model->buffers[index->buffer].data + index->offset;
|
||||||
size_t stride = index->stride == 0 ? (index->type == U16 ? 2 : 4) : index->stride;
|
size_t stride = index->stride == 0 ? (index->type == U16 ? 2 : 4) : index->stride;
|
||||||
|
|
||||||
for (uint32_t j = 0; j < index->count; j++) {
|
for (uint32_t j = 0; j < index->count; j++) {
|
||||||
**indices = (index->type == U16 ? ((uint32_t) *(uint16_t*) data) : *(uint32_t*) data) + *baseIndex;
|
**indices = (index->type == U16 ? ((uint32_t) *(uint16_t*) data) : *(uint32_t*) data) + base;
|
||||||
*indices += 1;
|
*indices += 1;
|
||||||
data += stride;
|
data += stride;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t j = 0; j < positions->count; j++) {
|
for (uint32_t j = 0; j < positions->count; j++) {
|
||||||
**indices = j + *baseIndex;
|
**indices = j + base;
|
||||||
*indices += 1;
|
*indices += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*baseIndex += positions->count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < node->childCount; i++) {
|
for (uint32_t i = 0; i < node->childCount; i++) {
|
||||||
|
|
|
@ -901,6 +901,10 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float*
|
||||||
dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);
|
dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SHAPE_TERRAIN: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dReal* position = dGeomGetOffsetPosition(shape->id);
|
const dReal* position = dGeomGetOffsetPosition(shape->id);
|
||||||
|
@ -1052,7 +1056,7 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount,
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainShape* lovrTerrainShapeCreate(float* vertices, int widthSamples, int depthSamples, float horizontalScale, float verticalScale) {
|
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale) {
|
||||||
const float thickness = 10.f;
|
const float thickness = 10.f;
|
||||||
TerrainShape* terrain = calloc(1, sizeof(TerrainShape));
|
TerrainShape* terrain = calloc(1, sizeof(TerrainShape));
|
||||||
lovrAssert(terrain, "Out of memory");
|
lovrAssert(terrain, "Out of memory");
|
||||||
|
|
|
@ -132,7 +132,7 @@ typedef enum {
|
||||||
SHAPE_CAPSULE,
|
SHAPE_CAPSULE,
|
||||||
SHAPE_CYLINDER,
|
SHAPE_CYLINDER,
|
||||||
SHAPE_MESH,
|
SHAPE_MESH,
|
||||||
SHAPE_TERRAIN,
|
SHAPE_TERRAIN
|
||||||
} ShapeType;
|
} ShapeType;
|
||||||
|
|
||||||
void lovrShapeDestroy(void* ref);
|
void lovrShapeDestroy(void* ref);
|
||||||
|
@ -173,7 +173,8 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder);
|
||||||
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
|
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, int widthSamples, int depthSamples, float horizontalScale, float verticalScale);
|
|
||||||
|
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale);
|
||||||
|
|
||||||
// These tokens need to exist for Lua bindings
|
// These tokens need to exist for Lua bindings
|
||||||
#define lovrSphereShapeDestroy lovrShapeDestroy
|
#define lovrSphereShapeDestroy lovrShapeDestroy
|
||||||
|
|
Loading…
Reference in a new issue