mirror of https://github.com/bjornbytes/lovr.git
Semantic tags;
This commit is contained in:
parent
00142b7a74
commit
39400776dc
|
@ -33,7 +33,27 @@ int l_lovrPhysicsInit(lua_State* L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int l_lovrPhysicsNewWorld(lua_State* L) {
|
int l_lovrPhysicsNewWorld(lua_State* L) {
|
||||||
World* world = lovrWorldCreate();
|
float xg = luaL_optnumber(L, 1, 0.f);
|
||||||
|
float yg = luaL_optnumber(L, 2, -9.81);
|
||||||
|
float zg = luaL_optnumber(L, 3, 0.f);
|
||||||
|
int allowSleep = lua_gettop(L) < 4 || lua_toboolean(L, 4);
|
||||||
|
const char* tags[16];
|
||||||
|
int tagCount;
|
||||||
|
if (lua_type(L, 5) == LUA_TTABLE) {
|
||||||
|
tagCount = lua_objlen(L, 5);
|
||||||
|
for (int i = 0; i < tagCount; i++) {
|
||||||
|
lua_rawgeti(L, -1, i + 1);
|
||||||
|
if (lua_isstring(L, -1)) {
|
||||||
|
tags[i] = lua_tostring(L, -1);
|
||||||
|
} else {
|
||||||
|
return luaL_error(L, "World tags must be a table of strings");
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tagCount = 0;
|
||||||
|
}
|
||||||
|
World* world = lovrWorldCreate(xg, yg, zg, allowSleep, tags, tagCount);
|
||||||
luax_pushtype(L, World, world);
|
luax_pushtype(L, World, world);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -449,6 +449,27 @@ int l_lovrColliderSetRestitution(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int l_lovrColliderGetTag(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
lua_pushstring(L, lovrColliderGetTag(collider));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_lovrColliderSetTag(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
if (lua_isnoneornil(L, 2)) {
|
||||||
|
lovrColliderSetTag(collider, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* tag = luaL_checkstring(L, 2);
|
||||||
|
if (lovrColliderSetTag(collider, tag)) {
|
||||||
|
return luaL_error(L, "Invalid tag %s", tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const luaL_Reg lovrCollider[] = {
|
const luaL_Reg lovrCollider[] = {
|
||||||
{ "destroy", l_lovrColliderDestroy },
|
{ "destroy", l_lovrColliderDestroy },
|
||||||
{ "getWorld", l_lovrColliderGetWorld },
|
{ "getWorld", l_lovrColliderGetWorld },
|
||||||
|
@ -495,5 +516,7 @@ const luaL_Reg lovrCollider[] = {
|
||||||
{ "setFriction", l_lovrColliderSetFriction },
|
{ "setFriction", l_lovrColliderSetFriction },
|
||||||
{ "getRestitution", l_lovrColliderGetRestitution },
|
{ "getRestitution", l_lovrColliderGetRestitution },
|
||||||
{ "setRestitution", l_lovrColliderSetRestitution },
|
{ "setRestitution", l_lovrColliderSetRestitution },
|
||||||
|
{ "getTag", l_lovrColliderGetTag },
|
||||||
|
{ "setTag", l_lovrColliderSetTag },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -200,6 +200,30 @@ int l_lovrWorldRaycast(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int l_lovrWorldDisableCollisionBetween(lua_State* L) {
|
||||||
|
World* world = luax_checktype(L, 1, World);
|
||||||
|
const char* tag1 = luaL_checkstring(L, 2);
|
||||||
|
const char* tag2 = luaL_checkstring(L, 3);
|
||||||
|
lovrWorldDisableCollisionBetween(world, tag1, tag2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_lovrWorldEnableCollisionBetween(lua_State* L) {
|
||||||
|
World* world = luax_checktype(L, 1, World);
|
||||||
|
const char* tag1 = luaL_checkstring(L, 2);
|
||||||
|
const char* tag2 = luaL_checkstring(L, 3);
|
||||||
|
lovrWorldEnableCollisionBetween(world, tag1, tag2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int l_lovrWorldIsCollisionEnabledBetween(lua_State* L) {
|
||||||
|
World* world = luax_checktype(L, 1, World);
|
||||||
|
const char* tag1 = luaL_checkstring(L, 2);
|
||||||
|
const char* tag2 = luaL_checkstring(L, 3);
|
||||||
|
lua_pushboolean(L, lovrWorldIsCollisionEnabledBetween(world, tag1, tag2));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
const luaL_Reg lovrWorld[] = {
|
const luaL_Reg lovrWorld[] = {
|
||||||
{ "newCollider", l_lovrWorldNewCollider },
|
{ "newCollider", l_lovrWorldNewCollider },
|
||||||
{ "newBoxCollider", l_lovrWorldNewBoxCollider },
|
{ "newBoxCollider", l_lovrWorldNewBoxCollider },
|
||||||
|
@ -220,5 +244,8 @@ const luaL_Reg lovrWorld[] = {
|
||||||
{ "isSleepingAllowed", l_lovrWorldIsSleepingAllowed },
|
{ "isSleepingAllowed", l_lovrWorldIsSleepingAllowed },
|
||||||
{ "setSleepingAllowed", l_lovrWorldSetSleepingAllowed },
|
{ "setSleepingAllowed", l_lovrWorldSetSleepingAllowed },
|
||||||
{ "raycast", l_lovrWorldRaycast },
|
{ "raycast", l_lovrWorldRaycast },
|
||||||
|
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
|
||||||
|
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
|
||||||
|
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,7 +42,7 @@ void lovrPhysicsDestroy() {
|
||||||
dCloseODE();
|
dCloseODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
World* lovrWorldCreate() {
|
World* lovrWorldCreate(float xg, float yg, float zg, int allowSleep, const char** tags, int tagCount) {
|
||||||
World* world = lovrAlloc(sizeof(World), lovrWorldDestroy);
|
World* world = lovrAlloc(sizeof(World), lovrWorldDestroy);
|
||||||
if (!world) return NULL;
|
if (!world) return NULL;
|
||||||
|
|
||||||
|
@ -51,6 +51,16 @@ World* lovrWorldCreate() {
|
||||||
dHashSpaceSetLevels(world->space, -4, 8);
|
dHashSpaceSetLevels(world->space, -4, 8);
|
||||||
world->contactGroup = dJointGroupCreate(0);
|
world->contactGroup = dJointGroupCreate(0);
|
||||||
vec_init(&world->overlaps);
|
vec_init(&world->overlaps);
|
||||||
|
lovrWorldSetGravity(world, xg, yg, zg);
|
||||||
|
lovrWorldSetSleepingAllowed(world, allowSleep);
|
||||||
|
map_init(&world->tags);
|
||||||
|
for (int i = 0; i < tagCount; i++) {
|
||||||
|
map_set(&world->tags, tags[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_TAGS; i++) {
|
||||||
|
world->masks[i] = ~0;
|
||||||
|
}
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
@ -111,10 +121,14 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float res
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dContact contacts[MAX_CONTACTS];
|
|
||||||
|
|
||||||
Collider* colliderA = a->collider;
|
Collider* colliderA = a->collider;
|
||||||
Collider* colliderB = b->collider;
|
Collider* colliderB = b->collider;
|
||||||
|
int tag1 = colliderA->tag;
|
||||||
|
int tag2 = colliderB->tag;
|
||||||
|
|
||||||
|
if (tag1 != NO_TAG && tag2 != NO_TAG && !((world->masks[tag1] & (1 << tag2)) && (world->masks[tag2] & (1 << tag1)))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (friction < 0) {
|
if (friction < 0) {
|
||||||
friction = sqrt(colliderA->friction * colliderB->friction);
|
friction = sqrt(colliderA->friction * colliderB->friction);
|
||||||
|
@ -124,6 +138,7 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float res
|
||||||
restitution = MAX(colliderA->restitution, colliderB->restitution);
|
restitution = MAX(colliderA->restitution, colliderB->restitution);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dContact contacts[MAX_CONTACTS];
|
||||||
for (int i = 0; i < MAX_CONTACTS; i++) {
|
for (int i = 0; i < MAX_CONTACTS; i++) {
|
||||||
contacts[i].surface.mode = 0;
|
contacts[i].surface.mode = 0;
|
||||||
contacts[i].surface.mu = friction;
|
contacts[i].surface.mu = friction;
|
||||||
|
@ -197,6 +212,56 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa
|
||||||
dGeomDestroy(ray);
|
dGeomDestroy(ray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* lovrWorldGetTagName(World* world, int tag) {
|
||||||
|
if (tag == NO_TAG) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* key;
|
||||||
|
map_iter_t iter = map_iter(&world->tags);
|
||||||
|
while ((key = map_next(&world->tags, &iter))) {
|
||||||
|
if (*map_get(&world->tags, key) == tag) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char* tag2) {
|
||||||
|
int* index1 = map_get(&world->tags, tag1);
|
||||||
|
int* index2 = map_get(&world->tags, tag2);
|
||||||
|
if (!index1 || !index2) {
|
||||||
|
return NO_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
world->masks[*index1] &= ~(1 << *index2);
|
||||||
|
world->masks[*index2] &= ~(1 << *index1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2) {
|
||||||
|
int* index1 = map_get(&world->tags, tag1);
|
||||||
|
int* index2 = map_get(&world->tags, tag2);
|
||||||
|
if (!index1 || !index2) {
|
||||||
|
return NO_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
world->masks[*index1] |= (1 << *index2);
|
||||||
|
world->masks[*index2] |= (1 << *index1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag2) {
|
||||||
|
int* index1 = map_get(&world->tags, tag1);
|
||||||
|
int* index2 = map_get(&world->tags, tag2);
|
||||||
|
if (!index1 || !index2) {
|
||||||
|
return NO_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (world->masks[*index1] & (1 << *index2)) && (world->masks[*index2] & (1 << *index1));
|
||||||
|
}
|
||||||
|
|
||||||
Collider* lovrColliderCreate(World* world) {
|
Collider* lovrColliderCreate(World* world) {
|
||||||
if (!world) {
|
if (!world) {
|
||||||
error("No world specified");
|
error("No world specified");
|
||||||
|
@ -209,6 +274,7 @@ Collider* lovrColliderCreate(World* world) {
|
||||||
collider->world = world;
|
collider->world = world;
|
||||||
collider->friction = 0;
|
collider->friction = 0;
|
||||||
collider->restitution = 0;
|
collider->restitution = 0;
|
||||||
|
collider->tag = NO_TAG;
|
||||||
dBodySetData(collider->body, collider);
|
dBodySetData(collider->body, collider);
|
||||||
vec_init(&collider->shapes);
|
vec_init(&collider->shapes);
|
||||||
vec_init(&collider->joints);
|
vec_init(&collider->joints);
|
||||||
|
@ -539,6 +605,26 @@ void lovrColliderGetAABB(Collider* collider, float aabb[6]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* lovrColliderGetTag(Collider* collider) {
|
||||||
|
return lovrWorldGetTagName(collider->world, collider->tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lovrColliderSetTag(Collider* collider, const char* tag) {
|
||||||
|
if (tag == NULL) {
|
||||||
|
collider->tag = NO_TAG;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int* index = map_get(&collider->world->tags, tag);
|
||||||
|
|
||||||
|
if (!index) {
|
||||||
|
return NO_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
collider->tag = *index;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void lovrShapeDestroy(const Ref* ref) {
|
void lovrShapeDestroy(const Ref* ref) {
|
||||||
Shape* shape = containerof(ref, Shape);
|
Shape* shape = containerof(ref, Shape);
|
||||||
lovrShapeDestroyData(shape);
|
lovrShapeDestroyData(shape);
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "lib/vec/vec.h"
|
#include "lib/vec/vec.h"
|
||||||
|
#include "lib/map/map.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <ode/ode.h>
|
#include <ode/ode.h>
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MAX_CONTACTS 4
|
#define MAX_CONTACTS 4
|
||||||
|
#define MAX_TAGS 16
|
||||||
|
#define NO_TAG ~0
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHAPE_SPHERE,
|
SHAPE_SPHERE,
|
||||||
|
@ -26,6 +29,8 @@ typedef struct {
|
||||||
dSpaceID space;
|
dSpaceID space;
|
||||||
dJointGroupID contactGroup;
|
dJointGroupID contactGroup;
|
||||||
vec_void_t overlaps;
|
vec_void_t overlaps;
|
||||||
|
map_int_t tags;
|
||||||
|
uint16_t masks[MAX_TAGS];
|
||||||
} World;
|
} World;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -33,6 +38,7 @@ typedef struct {
|
||||||
dBodyID body;
|
dBodyID body;
|
||||||
World* world;
|
World* world;
|
||||||
void* userdata;
|
void* userdata;
|
||||||
|
int tag;
|
||||||
vec_void_t shapes;
|
vec_void_t shapes;
|
||||||
vec_void_t joints;
|
vec_void_t joints;
|
||||||
float friction;
|
float friction;
|
||||||
|
@ -74,7 +80,7 @@ typedef struct {
|
||||||
void lovrPhysicsInit();
|
void lovrPhysicsInit();
|
||||||
void lovrPhysicsDestroy();
|
void lovrPhysicsDestroy();
|
||||||
|
|
||||||
World* lovrWorldCreate();
|
World* lovrWorldCreate(float xg, float yg, float zg, int allowSleep, const char** tags, int tagCount);
|
||||||
void lovrWorldDestroy(const Ref* ref);
|
void lovrWorldDestroy(const Ref* ref);
|
||||||
void lovrWorldDestroyData(World* world);
|
void lovrWorldDestroyData(World* world);
|
||||||
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata);
|
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata);
|
||||||
|
@ -90,6 +96,10 @@ void lovrWorldSetAngularDamping(World* world, float damping, float threshold);
|
||||||
int lovrWorldIsSleepingAllowed(World* world);
|
int lovrWorldIsSleepingAllowed(World* world);
|
||||||
void lovrWorldSetSleepingAllowed(World* world, int allowed);
|
void lovrWorldSetSleepingAllowed(World* world, int allowed);
|
||||||
void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, float y2, float z2, RaycastCallback callback, void* userdata);
|
void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, float y2, float z2, RaycastCallback callback, void* userdata);
|
||||||
|
const char* lovrWorldGetTagName(World* world, int tag);
|
||||||
|
int lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||||
|
int lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||||
|
int lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag);
|
||||||
|
|
||||||
Collider* lovrColliderCreate();
|
Collider* lovrColliderCreate();
|
||||||
void lovrColliderDestroy(const Ref* ref);
|
void lovrColliderDestroy(const Ref* ref);
|
||||||
|
@ -140,6 +150,8 @@ float lovrColliderGetFriction(Collider* collider);
|
||||||
void lovrColliderSetFriction(Collider* collider, float friction);
|
void lovrColliderSetFriction(Collider* collider, float friction);
|
||||||
float lovrColliderGetRestitution(Collider* collider);
|
float lovrColliderGetRestitution(Collider* collider);
|
||||||
void lovrColliderSetRestitution(Collider* collider, float restitution);
|
void lovrColliderSetRestitution(Collider* collider, float restitution);
|
||||||
|
const char* lovrColliderGetTag(Collider* collider);
|
||||||
|
int lovrColliderSetTag(Collider* collider, const char* tag);
|
||||||
|
|
||||||
void lovrShapeDestroy(const Ref* ref);
|
void lovrShapeDestroy(const Ref* ref);
|
||||||
void lovrShapeDestroyData(Shape* shape);
|
void lovrShapeDestroyData(Shape* shape);
|
||||||
|
|
Loading…
Reference in New Issue