diff --git a/.gitignore b/.gitignore index e19fc7bf..eb8f32df 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ deps data src/obj src/Tupfile +/watch.sh *.lua *.glsl .DS_Store diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index b583ae94..6cb32836 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -15,9 +15,6 @@ static GraphicsState state; // Base void lovrGraphicsInit() { - for (int i = 0; i < MAX_TRANSFORMS; i++) { - state.transforms[i] = mat4_init(); - } for (int i = 0; i < MAX_CANVASES; i++) { state.canvases[i] = malloc(sizeof(CanvasState)); } @@ -39,9 +36,6 @@ void lovrGraphicsInit() { void lovrGraphicsDestroy() { lovrGraphicsSetShader(NULL); glUseProgram(0); - for (int i = 0; i < MAX_TRANSFORMS; i++) { - free(state.transforms[i]); - } for (int i = 0; i < MAX_CANVASES; i++) { free(state.canvases[i]); } @@ -342,27 +336,20 @@ void lovrGraphicsTranslate(float x, float y, float z) { } void lovrGraphicsRotate(float angle, float ax, float ay, float az) { - float rotation[4]; - float axis[3] = { ax, ay, az }; - quat_fromAngleAxis(rotation, angle, axis); - mat4_rotate(state.transforms[state.transform], rotation); + mat4_rotate(state.transforms[state.transform], angle, ax, ay, az); } void lovrGraphicsScale(float x, float y, float z) { mat4_scale(state.transforms[state.transform], x, y, z); } +// M *= T * S * R void lovrGraphicsTransform(float tx, float ty, float tz, float sx, float sy, float sz, float angle, float ax, float ay, float az) { - float rotation[4]; - float axis[3] = { ax, ay, az }; - quat_fromAngleAxis(rotation, angle, axis); - - // M *= T * S * R float transform[16]; mat4_identity(transform); mat4_translate(transform, tx, ty, tz); mat4_scale(transform, sx, sy, sz); - mat4_rotate(transform, rotation); + mat4_rotate(transform, angle, ax, ay, az); lovrGraphicsMatrixTransform(transform); } diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h index 22f77a85..68553a34 100644 --- a/src/graphics/graphics.h +++ b/src/graphics/graphics.h @@ -50,10 +50,10 @@ typedef struct { Shader* skyboxShader; Shader* fullscreenShader; Texture* defaultTexture; - int transform; - mat4 transforms[MAX_TRANSFORMS]; - int canvas; + float transforms[MAX_TRANSFORMS][16]; CanvasState* canvases[MAX_CANVASES]; + int transform; + int canvas; unsigned int color; char colorMask; int isScissorEnabled; diff --git a/src/graphics/model.c b/src/graphics/model.c index d4362051..9e7fcd47 100644 --- a/src/graphics/model.c +++ b/src/graphics/model.c @@ -3,10 +3,12 @@ #include static void visitNode(ModelData* modelData, ModelNode* node, mat4 transform, vec_float_t* vertices, vec_uint_t* indices) { - mat4 newTransform = mat4_init(); + float newTransform[16]; if (transform) { mat4_set(newTransform, transform); + } else { + mat4_identity(newTransform); } mat4_multiply(newTransform, node->transform); @@ -21,12 +23,8 @@ static void visitNode(ModelData* modelData, ModelNode* node, mat4 transform, vec for (int v = 0; v < mesh->vertices.length; v++) { ModelVertex vertex = mesh->vertices.data[v]; - float vec[3] = { - vertex.x, - vertex.y, - vertex.z - }; - + float vec[3]; + vec3_set(vec, vertex.x, vertex.y, vertex.z); vec3_transform(vec, newTransform); vec_pusharr(vertices, vec, 3); @@ -56,8 +54,6 @@ static void visitNode(ModelData* modelData, ModelNode* node, mat4 transform, vec for (int c = 0; c < node->children.length; c++) { visitNode(modelData, node->children.data[c], newTransform, vertices, indices); } - - free(newTransform); } Model* lovrModelCreate(ModelData* modelData) { @@ -133,7 +129,6 @@ void lovrModelDataDestroy(ModelData* modelData) { while (nodes.length > 0) { ModelNode* node = vec_first(&nodes); vec_extend(&nodes, &node->children); - free(node->transform); vec_deinit(&node->meshes); vec_deinit(&node->children); vec_splice(&nodes, 0, 1); diff --git a/src/graphics/model.h b/src/graphics/model.h index 835fda52..c1ce9d3b 100644 --- a/src/graphics/model.h +++ b/src/graphics/model.h @@ -33,7 +33,7 @@ typedef struct { typedef vec_t(ModelMesh*) vec_model_mesh_t; typedef struct ModelNode { - mat4 transform; + float transform[16]; vec_uint_t meshes; vec_void_t children; } ModelNode; diff --git a/src/graphics/shader.c b/src/graphics/shader.c index f3883b41..a404f51e 100644 --- a/src/graphics/shader.c +++ b/src/graphics/shader.c @@ -162,8 +162,8 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) { // Initial state shader->id = id; - shader->transform = mat4_init(); - shader->projection = mat4_init(); + mat4_identity(shader->transform); + mat4_identity(shader->projection); shader->color = 0; // Send initial uniform values to shader @@ -175,8 +175,6 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) { void lovrShaderDestroy(const Ref* ref) { Shader* shader = containerof(ref, Shader); glDeleteProgram(shader->id); - free(shader->transform); - free(shader->projection); map_deinit(&shader->uniforms); free(shader); } diff --git a/src/graphics/shader.h b/src/graphics/shader.h index 751062f1..78513208 100644 --- a/src/graphics/shader.h +++ b/src/graphics/shader.h @@ -26,8 +26,8 @@ typedef struct { Ref ref; int id; map_uniform_t uniforms; - mat4 transform; - mat4 projection; + float transform[16]; + float projection[16]; unsigned int color; } Shader; #endif diff --git a/src/headset/headset.c b/src/headset/headset.c index d113d63b..e8d7d301 100644 --- a/src/headset/headset.c +++ b/src/headset/headset.c @@ -108,13 +108,13 @@ void lovrHeadsetGetPosition(float* x, float* y, float* z) { headset->getPosition(headset, x, y, z); } -void lovrHeadsetGetOrientation(float* w, float* x, float* y, float* z) { +void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float* z) { if (!headset) { - *w = *x = *y = *z = 0.f; + *angle = *x = *y = *z = 0.f; return; } - headset->getOrientation(headset, w, x, y, z); + headset->getOrientation(headset, angle, x, y, z); } void lovrHeadsetGetVelocity(float* x, float* y, float* z) { @@ -160,13 +160,13 @@ void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y headset->controllerGetPosition(headset, controller, x, y, z); } -void lovrHeadsetControllerGetOrientation(Controller* controller, float* w, float* x, float* y, float* z) { +void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z) { if (!headset || !controller) { - *w = *x = *y = *z = 0.f; + *angle = *x = *y = *z = 0.f; return; } - headset->controllerGetOrientation(headset, controller, w, x, y, z); + headset->controllerGetOrientation(headset, controller, angle, x, y, z); } float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis) { diff --git a/src/headset/headset.h b/src/headset/headset.h index 707fdd25..f5fdd5c8 100644 --- a/src/headset/headset.h +++ b/src/headset/headset.h @@ -44,13 +44,13 @@ typedef struct { char (*isBoundsVisible)(void* headset); void (*setBoundsVisible)(void* headset, char visible); void (*getPosition)(void* headset, float* x, float* y, float* z); - void (*getOrientation)(void* headset, float* w, float* x, float* y, float* z); + void (*getOrientation)(void* headset, float* angle, float* x, float* y, float* z); void (*getVelocity)(void* headset, float* x, float* y, float* z); void (*getAngularVelocity)(void* headset, float* x, float* y, float* z); vec_controller_t* (*getControllers)(void* headset); char (*controllerIsPresent)(void* headset, Controller* controller); void (*controllerGetPosition)(void* headset, Controller* controller, float* x, float* y, float* z); - void (*controllerGetOrientation)(void* headset, Controller* controller, float* w, float* x, float* y, float* z); + void (*controllerGetOrientation)(void* headset, Controller* controller, float* angle, float* x, float* y, float* z); float (*controllerGetAxis)(void* headset, Controller* controller, ControllerAxis axis); int (*controllerIsDown)(void* headset, Controller* controller, ControllerButton button); void (*controllerVibrate)(void* headset, Controller* controller, float duration); @@ -73,13 +73,13 @@ void lovrHeadsetGetBoundsGeometry(float* geometry); char lovrHeadsetIsBoundsVisible(); void lovrHeadsetSetBoundsVisible(char visible); void lovrHeadsetGetPosition(float* x, float* y, float* z); -void lovrHeadsetGetOrientation(float* w, float* x, float* y, float* z); +void lovrHeadsetGetOrientation(float* angle, float* x, float* y, float* z); void lovrHeadsetGetVelocity(float* x, float* y, float* z); void lovrHeadsetGetAngularVelocity(float* x, float* y, float* z); vec_controller_t* lovrHeadsetGetControllers(); char lovrHeadsetControllerIsPresent(Controller* controller); void lovrHeadsetControllerGetPosition(Controller* controller, float* x, float* y, float* z); -void lovrHeadsetControllerGetOrientation(Controller* controller, float* w, float* x, float* y, float* z); +void lovrHeadsetControllerGetOrientation(Controller* controller, float* angle, float* x, float* y, float* z); float lovrHeadsetControllerGetAxis(Controller* controller, ControllerAxis axis); int lovrHeadsetControllerIsDown(Controller* controller, ControllerButton button); void lovrHeadsetControllerVibrate(Controller* controller, float duration); diff --git a/src/headset/vive.c b/src/headset/vive.c index 2b4b2ab8..40030585 100644 --- a/src/headset/vive.c +++ b/src/headset/vive.c @@ -257,19 +257,19 @@ void viveGetPosition(void* headset, float* x, float* y, float* z) { *z = pose.mDeviceToAbsoluteTracking.m[2][3]; } -void viveGetOrientation(void* headset, float* w, float* x, float* y, float *z) { +void viveGetOrientation(void* headset, float* angle, float* x, float* y, float *z) { Vive* vive = (Vive*) headset; TrackedDevicePose_t pose = viveGetPose(vive, vive->headsetIndex); if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) { - *w = *x = *y = *z = 0.f; + *angle = *x = *y = *z = 0.f; return; } float matrix[16]; float rotation[4]; - mat4_toQuat(mat4_fromMat44(matrix, pose.mDeviceToAbsoluteTracking.m), rotation); - quat_toAngleAxis(rotation, w, x, y, z); + quat_fromMat4(rotation, mat4_fromMat44(matrix, pose.mDeviceToAbsoluteTracking.m)); + quat_getAngleAxis(rotation, angle, x, y, z); } void viveGetVelocity(void* headset, float* x, float* y, float* z) { @@ -343,19 +343,19 @@ void viveControllerGetPosition(void* headset, Controller* controller, float* x, *z = pose.mDeviceToAbsoluteTracking.m[2][3]; } -void viveControllerGetOrientation(void* headset, Controller* controller, float* w, float* x, float* y, float* z) { +void viveControllerGetOrientation(void* headset, Controller* controller, float* angle, float* x, float* y, float* z) { Vive* vive = (Vive*) headset; TrackedDevicePose_t pose = viveGetPose(vive, controller->id); if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) { - *w = *x = *y = *z = 0.f; + *angle = *x = *y = *z = 0.f; return; } float matrix[16]; float rotation[4]; - mat4_toQuat(mat4_fromMat44(matrix, pose.mDeviceToAbsoluteTracking.m), rotation); - quat_toAngleAxis(rotation, w, x, y, z); + quat_fromMat4(rotation, mat4_fromMat44(matrix, pose.mDeviceToAbsoluteTracking.m)); + quat_getAngleAxis(rotation, angle, x, y, z); } float viveControllerGetAxis(void* headset, Controller* controller, ControllerAxis axis) { diff --git a/src/headset/vive.h b/src/headset/vive.h index b0794ce5..1a484c44 100644 --- a/src/headset/vive.h +++ b/src/headset/vive.h @@ -47,14 +47,14 @@ void viveGetBoundsGeometry(void* headset, float* geometry); char viveIsBoundsVisible(void* headset); void viveSetBoundsVisible(void* headset, char visible); void viveGetPosition(void* headset, float* x, float* y, float* z); -void viveGetOrientation(void* headset, float* w, float* x, float* y, float* z); +void viveGetOrientation(void* headset, float* angle, float* x, float* y, float* z); void viveGetVelocity(void* headset, float* x, float* y, float* z); void viveGetAngularVelocity(void* headset, float* x, float* y, float* z); Controller* viveAddController(void* headset, unsigned int deviceIndex); vec_controller_t* viveGetControllers(void* headset); char viveControllerIsPresent(void* headset, Controller* controller); void viveControllerGetPosition(void* headset, Controller* controller, float* x, float* y, float* z); -void viveControllerGetOrientation(void* headset, Controller* controller, float* w, float* x, float* y, float* z); +void viveControllerGetOrientation(void* headset, Controller* controller, float* angle, float* x, float* y, float* z); float viveControllerGetAxis(void* headset, Controller* controller, ControllerAxis axis); int viveControllerIsDown(void* headset, Controller* controller, ControllerButton button); void viveControllerVibrate(void* headset, Controller* controller, float duration); diff --git a/src/loaders/model.c b/src/loaders/model.c index b06a9a7f..c3974a87 100644 --- a/src/loaders/model.c +++ b/src/loaders/model.c @@ -9,7 +9,7 @@ static void assimpNodeTraversal(ModelNode* node, struct aiNode* assimpNode) { // Transform struct aiMatrix4x4 m = assimpNode->mTransformation; aiTransposeMatrix4(&m); - node->transform = mat4_set(mat4_init(), (float*) &m); + mat4_set(node->transform, (float*) &m); // Meshes vec_init(&node->meshes); @@ -148,7 +148,6 @@ ModelData* lovrModelDataFromOpenVRModel(OpenVRModel* vrModel) { } ModelNode* root = malloc(sizeof(ModelNode)); - root->transform = mat4_init(); vec_init(&root->meshes); vec_push(&root->meshes, 0); vec_init(&root->children); diff --git a/src/lovr/headset.c b/src/lovr/headset.c index a399aba2..50f8d9c0 100644 --- a/src/lovr/headset.c +++ b/src/lovr/headset.c @@ -155,9 +155,9 @@ int l_lovrHeadsetGetPosition(lua_State* L) { } int l_lovrHeadsetGetOrientation(lua_State* L) { - float w, x, y, z; - lovrHeadsetGetOrientation(&w, &x, &y, &z); - lua_pushnumber(L, w); + float angle, x, y, z; + lovrHeadsetGetOrientation(&angle, &x, &y, &z); + lua_pushnumber(L, angle); lua_pushnumber(L, x); lua_pushnumber(L, y); lua_pushnumber(L, z); diff --git a/src/lovr/math.c b/src/lovr/math.c index a6ea107b..39c8f494 100644 --- a/src/lovr/math.c +++ b/src/lovr/math.c @@ -24,17 +24,18 @@ int l_lovrMathInit(lua_State* L) { } int l_lovrMathNewVector(lua_State* L) { + float x, y, z; + if (lua_gettop(L) == 1) { - vec3 v = luax_newvector(L); - v[0] = v[1] = v[2] = luaL_checknumber(L, 1); - return 1; + x = y = z = luaL_checknumber(L, 1); } else { - vec3 v = luax_newvector(L); - v[0] = luaL_checknumber(L, 1); - v[1] = luaL_checknumber(L, 2); - v[2] = luaL_checknumber(L, 3); - return 1; + x = luaL_checknumber(L, 1); + y = luaL_checknumber(L, 2); + z = luaL_checknumber(L, 3); } + + vec3_set(luax_newvector(L), x, y, z); + return 1; } int l_lovrMathNewRotation(lua_State* L) { @@ -68,12 +69,9 @@ int l_lovrMathNewTransform(lua_State* L) { float ax = luaL_optnumber(L, 6, 0); float ay = luaL_optnumber(L, 7, 0); float az = luaL_optnumber(L, 8, 0); - float rotation[4]; - float axis[3] = { ax, ay, az }; - quat_fromAngleAxis(rotation, angle, axis); mat4_translate(m, x, y, z); mat4_scale(m, s, s, s); - mat4_rotate(m, rotation); + mat4_rotate(m, angle, ax, ay, az); } return 1; diff --git a/src/lovr/types/controller.c b/src/lovr/types/controller.c index c3bfecd4..56630276 100644 --- a/src/lovr/types/controller.c +++ b/src/lovr/types/controller.c @@ -34,9 +34,9 @@ int l_lovrControllerGetPosition(lua_State* L) { int l_lovrControllerGetOrientation(lua_State* L) { Controller* controller = luax_checktype(L, 1, Controller); - float w, x, y, z; - lovrHeadsetControllerGetOrientation(controller, &w, &x, &y, &z); - lua_pushnumber(L, w); + float angle, x, y, z; + lovrHeadsetControllerGetOrientation(controller, &angle, &x, &y, &z); + lua_pushnumber(L, angle); lua_pushnumber(L, x); lua_pushnumber(L, y); lua_pushnumber(L, z); diff --git a/src/lovr/types/rotation.c b/src/lovr/types/rotation.c index 2211688a..5c18f05b 100644 --- a/src/lovr/types/rotation.c +++ b/src/lovr/types/rotation.c @@ -1,4 +1,5 @@ #include "lovr/types/rotation.h" +#include "lovr/types/vector.h" #include "math/vec3.h" #include "util.h" @@ -16,9 +17,10 @@ quat luax_checkrotation(lua_State* L, int i) { const luaL_Reg lovrRotation[] = { { "clone", l_lovrRotationClone }, { "unpack", l_lovrRotationUnpack }, + { "apply", l_lovrRotationApply }, { "normalize", l_lovrRotationNormalize }, { "rotate", l_lovrRotationRotate }, - { "slerp", l_lovrRotationSlerp }, + { "mix", l_lovrRotationMix }, { "__mul", l_lovrRotationMul }, { "__len", l_lovrRotationLen }, { NULL, NULL } @@ -26,14 +28,14 @@ const luaL_Reg lovrRotation[] = { int l_lovrRotationClone(lua_State* L) { quat q = luax_checkrotation(L, 1); - quat_set(luax_newrotation(L), q); + quat_init(luax_newrotation(L), q); return 1; } int l_lovrRotationUnpack(lua_State* L) { quat q = luax_checkrotation(L, 1); float angle, x, y, z; - quat_toAngleAxis(q, &angle, &x, &y, &z); + quat_getAngleAxis(q, &angle, &x, &y, &z); lua_pushnumber(L, angle); lua_pushnumber(L, x); lua_pushnumber(L, y); @@ -41,6 +43,14 @@ int l_lovrRotationUnpack(lua_State* L) { return 4; } +int l_lovrRotationApply(lua_State* L) { + quat q = luax_checkrotation(L, 1); + quat r = luax_checkrotation(L, 2); + quat_multiply(q, r); + lua_pushvalue(L, 1); + return 1; +} + int l_lovrRotationNormalize(lua_State* L) { quat q = luax_checkrotation(L, 1); quat_normalize(q); @@ -49,30 +59,42 @@ int l_lovrRotationNormalize(lua_State* L) { int l_lovrRotationRotate(lua_State* L) { quat q = luax_checkrotation(L, 1); - float v[3]; - v[0] = luaL_checknumber(L, 2); - v[1] = luaL_checknumber(L, 3); - v[2] = luaL_checknumber(L, 4); - vec3_rotate(v, q); - lua_pushnumber(L, v[0]); - lua_pushnumber(L, v[1]); - lua_pushnumber(L, v[2]); - return 3; + if (lua_isnumber(L, 2)) { + float x = luaL_checknumber(L, 2); + float y = luaL_checknumber(L, 3); + float z = luaL_checknumber(L, 4); + float v[3]; + vec3_rotate(vec3_set(v, x, y, z), q); + lua_pushnumber(L, v[0]); + lua_pushnumber(L, v[1]); + lua_pushnumber(L, v[2]); + return 3; + } else { + vec3 v = luax_checkvector(L, 2); + vec3_rotate(v, q); + return 1; + } } -int l_lovrRotationSlerp(lua_State* L) { +int l_lovrRotationMix(lua_State* L) { quat q = luax_checkrotation(L, 1); quat r = luax_checkrotation(L, 2); float t = luaL_checknumber(L, 3); - quat_slerp(quat_set(luax_newrotation(L), q), r, t); + quat_slerp(quat_init(luax_newrotation(L), q), r, t); return 1; } int l_lovrRotationMul(lua_State* L) { quat q = luax_checkrotation(L, 1); - quat r = luax_checkrotation(L, 2); - quat_multiply(quat_set(luax_newrotation(L), q), r); - return 1; + if (luax_istype(L, 2, "Rotation")) { + quat r = luax_checkrotation(L, 2); + quat_multiply(quat_init(luax_newrotation(L), q), r); + return 1; + } else { + vec3 v = luax_checkvector(L, 2); + vec3_rotate(vec3_init(luax_newvector(L), v), q); + return 1; + } } int l_lovrRotationLen(lua_State* L) { diff --git a/src/lovr/types/rotation.h b/src/lovr/types/rotation.h index 90855c28..da67036d 100644 --- a/src/lovr/types/rotation.h +++ b/src/lovr/types/rotation.h @@ -9,8 +9,9 @@ vec3 luax_checkrotation(lua_State* L, int i); extern const luaL_Reg lovrRotation[]; int l_lovrRotationClone(lua_State* L); int l_lovrRotationUnpack(lua_State* L); +int l_lovrRotationApply(lua_State* L); int l_lovrRotationNormalize(lua_State* L); int l_lovrRotationRotate(lua_State* L); -int l_lovrRotationSlerp(lua_State* L); +int l_lovrRotationMix(lua_State* L); int l_lovrRotationMul(lua_State* L); int l_lovrRotationLen(lua_State* L); diff --git a/src/lovr/types/transform.c b/src/lovr/types/transform.c index 47494a17..6e071019 100644 --- a/src/lovr/types/transform.c +++ b/src/lovr/types/transform.c @@ -1,5 +1,6 @@ #include "lovr/types/transform.h" #include "lovr/types/rotation.h" +#include "lovr/types/vector.h" #include "math/vec3.h" #include "util.h" @@ -17,8 +18,8 @@ mat4 luax_checktransform(lua_State* L, int i) { const luaL_Reg lovrTransform[] = { { "clone", l_lovrTransformClone }, { "unpack", l_lovrTransformUnpack }, - { "inverse", l_lovrTransformInverse }, { "apply", l_lovrTransformApply }, + { "inverse", l_lovrTransformInverse }, { "origin", l_lovrTransformOrigin }, { "translate", l_lovrTransformTranslate }, { "rotate", l_lovrTransformRotate }, @@ -38,16 +39,24 @@ int l_lovrTransformUnpack(lua_State* L) { return 0; } -int l_lovrTransformInverse(lua_State* L) { +int l_lovrTransformApply(lua_State* L) { mat4 m = luax_checktransform(L, 1); - mat4_invert(mat4_set(luax_newtransform(L), m)); + + if (luax_istype(L, 2, "Transform")) { + mat4 n = luax_checktransform(L, 2); + mat4_multiply(m, n); + } else { + quat q = luax_checkrotation(L, 2); + mat4_rotateQuat(m, q); + } + + lua_pushvalue(L, 1); return 1; } -int l_lovrTransformApply(lua_State* L) { +int l_lovrTransformInverse(lua_State* L) { mat4 m = luax_checktransform(L, 1); - mat4 n = luax_checktransform(L, 2); - mat4_multiply(m, n); + mat4_invert(mat4_set(luax_newtransform(L), m)); return 1; } @@ -59,11 +68,18 @@ int l_lovrTransformOrigin(lua_State* L) { int l_lovrTransformTranslate(lua_State* L) { mat4 m = luax_checktransform(L, 1); - float x = luaL_checknumber(L, 2); - float y = luaL_checknumber(L, 3); - float z = luaL_checknumber(L, 4); - mat4_translate(m, x, y, z); - lua_settop(L, 1); + + if (lua_isnumber(L, 2)) { + float x = luaL_checknumber(L, 2); + float y = luaL_checknumber(L, 3); + float z = luaL_checknumber(L, 4); + mat4_translate(m, x, y, z); + } else { + vec3 v = luax_checkvector(L, 1); + mat4_translate(m, v[0], v[1], v[2]); + } + + lua_pushvalue(L, 1); return 1; } @@ -72,43 +88,53 @@ int l_lovrTransformRotate(lua_State* L) { if (lua_isnumber(L, 2)) { float angle = luaL_checknumber(L, 2); - float axis[3]; - axis[0] = luaL_checknumber(L, 3); - axis[1] = luaL_checknumber(L, 4); - axis[2] = luaL_checknumber(L, 5); - float q[4]; - quat_fromAngleAxis(q, angle, axis); - mat4_rotate(m, q); + float x = luaL_checknumber(L, 3); + float y = luaL_checknumber(L, 4); + float z = luaL_checknumber(L, 5); + mat4_rotate(m, angle, x, y, z); } else if (luax_istype(L, 2, "Rotation")) { quat q = luax_checkrotation(L, 2); - mat4_rotate(m, q); + mat4_rotateQuat(m, q); } - lua_settop(L, 1); + lua_pushvalue(L, 1); return 1; } int l_lovrTransformScale(lua_State* L) { mat4 m = luax_checktransform(L, 1); - float x = luaL_checknumber(L, 2); - float y = lua_gettop(L) > 2 ? luaL_checknumber(L, 3) : x; - float z = lua_gettop(L) > 2 ? luaL_checknumber(L, 4) : x; - mat4_scale(m, x, y, z); - lua_settop(L, 1); + + if (lua_isnumber(L, 2)) { + float x = luaL_checknumber(L, 2); + float y = lua_gettop(L) > 2 ? luaL_checknumber(L, 3) : x; + float z = lua_gettop(L) > 2 ? luaL_checknumber(L, 4) : x; + mat4_scale(m, x, y, z); + } else { + vec3 v = luax_checkvector(L, 1); + mat4_scale(m, v[0], v[1], v[2]); + } + + lua_pushvalue(L, 1); return 1; } int l_lovrTransformTransform(lua_State* L) { mat4 m = luax_checktransform(L, 1); - float v[3]; - v[0] = luaL_checknumber(L, 2); - v[1] = luaL_checknumber(L, 3); - v[2] = luaL_checknumber(L, 4); - vec3_transform(v, m); - lua_pushnumber(L, v[0]); - lua_pushnumber(L, v[1]); - lua_pushnumber(L, v[2]); - return 3; + if (lua_isnumber(L, 2)) { + float x = luaL_checknumber(L, 2); + float y = luaL_checknumber(L, 3); + float z = luaL_checknumber(L, 4); + float v[3]; + vec3_transform(vec3_set(v, x, y, z), m); + lua_pushnumber(L, v[0]); + lua_pushnumber(L, v[1]); + lua_pushnumber(L, v[2]); + return 3; + } else { + vec3 v = luax_checkvector(L, 2); + vec3_transform(v, m); + return 1; + } } int l_lovrTransformMul(lua_State* L) { diff --git a/src/lovr/types/transform.h b/src/lovr/types/transform.h index 41773b3e..c784f977 100644 --- a/src/lovr/types/transform.h +++ b/src/lovr/types/transform.h @@ -9,8 +9,8 @@ mat4 luax_checktransform(lua_State* L, int i); extern const luaL_Reg lovrTransform[]; int l_lovrTransformClone(lua_State* L); int l_lovrTransformUnpack(lua_State* L); -int l_lovrTransformInverse(lua_State* L); int l_lovrTransformApply(lua_State* L); +int l_lovrTransformInverse(lua_State* L); int l_lovrTransformOrigin(lua_State* L); int l_lovrTransformTranslate(lua_State* L); int l_lovrTransformRotate(lua_State* L); diff --git a/src/lovr/types/vector.c b/src/lovr/types/vector.c index 24d4fcf5..5bfcdd70 100644 --- a/src/lovr/types/vector.c +++ b/src/lovr/types/vector.c @@ -1,4 +1,6 @@ #include "lovr/types/vector.h" +#include "lovr/types/rotation.h" +#include "lovr/types/transform.h" #include "util.h" vec3 luax_newvector(lua_State* L) { @@ -15,6 +17,7 @@ vec3 luax_checkvector(lua_State* L, int i) { const luaL_Reg lovrVector[] = { { "clone", l_lovrVectorClone }, { "unpack", l_lovrVectorUnpack }, + { "apply", l_lovrVectorApply }, { "scale", l_lovrVectorScale }, { "normalize", l_lovrVectorNormalize }, { "distance", l_lovrVectorDistance }, @@ -26,13 +29,13 @@ const luaL_Reg lovrVector[] = { { "__sub", l_lovrVectorSub }, { "__mul", l_lovrVectorMul }, { "__div", l_lovrVectorDiv }, - { "__len", l_lovrVectorLength }, + { "__len", l_lovrVectorLen }, { NULL, NULL } }; int l_lovrVectorClone(lua_State* L) { vec3 v = luax_checkvector(L, 1); - vec3_set(luax_newvector(L), v); + vec3_init(luax_newvector(L), v); return 1; } @@ -44,6 +47,21 @@ int l_lovrVectorUnpack(lua_State* L) { return 3; } +int l_lovrVectorApply(lua_State* L) { + vec3 v = luax_checkvector(L, 1); + + if (luax_istype(L, 2, "Rotation")) { + quat q = luax_checkrotation(L, 2); + vec3_rotate(v, q); + } else if (luax_istype(L, 2, "Transform")) { + mat4 m = luax_checktransform(L, 2); + vec3_transform(v, m); + } + + lua_pushvalue(L, 1); + return 1; +} + int l_lovrVectorScale(lua_State* L) { vec3 v = luax_checkvector(L, 1); float s = luaL_checknumber(L, 2); @@ -81,7 +99,7 @@ int l_lovrVectorDot(lua_State* L) { int l_lovrVectorCross(lua_State* L) { vec3 u = luax_checkvector(L, 1); vec3 v = luax_checkvector(L, 2); - vec3_cross(vec3_set(luax_newvector(L), u), v); + vec3_cross(vec3_init(luax_newvector(L), u), v); return 1; } @@ -89,39 +107,39 @@ int l_lovrVectorLerp(lua_State* L) { vec3 u = luax_checkvector(L, 1); vec3 v = luax_checkvector(L, 2); float t = luaL_checknumber(L, 3); - vec3_lerp(vec3_set(luax_newvector(L), u), v, t); + vec3_lerp(vec3_init(luax_newvector(L), u), v, t); return 1; } int l_lovrVectorAdd(lua_State* L) { vec3 u = luax_checkvector(L, 1); vec3 v = luax_checkvector(L, 2); - vec3_add(vec3_set(luax_newvector(L), u), v); + vec3_add(vec3_init(luax_newvector(L), u), v); return 1; } int l_lovrVectorSub(lua_State* L) { vec3 u = luax_checkvector(L, 1); vec3 v = luax_checkvector(L, 2); - vec3_sub(vec3_set(luax_newvector(L), u), v); + vec3_sub(vec3_init(luax_newvector(L), u), v); return 1; } int l_lovrVectorMul(lua_State* L) { vec3 u = luax_checkvector(L, 1); vec3 v = luax_checkvector(L, 2); - vec3_mul(vec3_set(luax_newvector(L), u), v); + vec3_mul(vec3_init(luax_newvector(L), u), v); return 1; } int l_lovrVectorDiv(lua_State* L) { vec3 u = luax_checkvector(L, 1); vec3 v = luax_checkvector(L, 2); - vec3_div(vec3_set(luax_newvector(L), u), v); + vec3_div(vec3_init(luax_newvector(L), u), v); return 1; } -int l_lovrVectorLength(lua_State* L) { +int l_lovrVectorLen(lua_State* L) { vec3 u = luax_checkvector(L, 1); lua_pushnumber(L, vec3_length(u)); return 1; diff --git a/src/lovr/types/vector.h b/src/lovr/types/vector.h index bcf87d6e..042af39a 100644 --- a/src/lovr/types/vector.h +++ b/src/lovr/types/vector.h @@ -9,6 +9,7 @@ vec3 luax_checkvector(lua_State* L, int i); extern const luaL_Reg lovrVector[]; int l_lovrVectorClone(lua_State* L); int l_lovrVectorUnpack(lua_State* L); +int l_lovrVectorApply(lua_State* L); int l_lovrVectorScale(lua_State* L); int l_lovrVectorNormalize(lua_State* L); int l_lovrVectorDistance(lua_State* L); @@ -20,4 +21,4 @@ int l_lovrVectorAdd(lua_State* L); int l_lovrVectorSub(lua_State* L); int l_lovrVectorMul(lua_State* L); int l_lovrVectorDiv(lua_State* L); -int l_lovrVectorLength(lua_State* L); +int l_lovrVectorLen(lua_State* L); diff --git a/src/math/mat4.c b/src/math/mat4.c index de396b21..14ac3ec4 100644 --- a/src/math/mat4.c +++ b/src/math/mat4.c @@ -1,5 +1,6 @@ #include "math/mat4.h" -#include "util.h" +#include "math/quat.h" +#include "math/vec3.h" #include #include #include @@ -9,9 +10,8 @@ // m2 m6 m10 m14 // m3 m7 m11 m15 -mat4 mat4_init() { - mat4 m = malloc(16 * sizeof(float)); - return mat4_identity(m); +mat4 mat4_set(mat4 m, mat4 n) { + return memcpy(m, n, 16 * sizeof(float)); } mat4 mat4_fromMat34(mat4 m, float (*n)[4]) { @@ -54,10 +54,6 @@ mat4 mat4_fromMat44(mat4 m, float (*n)[4]) { return m; } -mat4 mat4_set(mat4 m, mat4 n) { - return memcpy(m, n, 16 * sizeof(float)); -} - mat4 mat4_identity(mat4 m) { memset(m, 0, 16 * sizeof(float)); m[0] = m[5] = m[10] = m[15] = 1.f; @@ -172,7 +168,14 @@ mat4 mat4_translate(mat4 m, float x, float y, float z) { return m; } -mat4 mat4_rotate(mat4 m, quat q) { +mat4 mat4_rotate(mat4 m, float angle, float x, float y, float z) { + float q[4]; + float v[3]; + quat_fromAngleAxis(q, angle, vec3_set(v, x, y, z)); + return mat4_rotateQuat(m, q); +} + +mat4 mat4_rotateQuat(mat4 m, quat q) { float x = q[0]; float y = q[1]; float z = q[2]; @@ -237,21 +240,3 @@ mat4 mat4_perspective(mat4 m, float near, float far, float fovy, float aspect) { m[15] = 0.0f; return m; } - -quat mat4_toQuat(mat4 m, quat q) { - float x = sqrt(MAX(0, 1 + m[0] - m[5] - m[10])) / 2; - float y = sqrt(MAX(0, 1 - m[0] + m[5] - m[10])) / 2; - float z = sqrt(MAX(0, 1 - m[0] - m[5] + m[10])) / 2; - float w = sqrt(MAX(0, 1 + m[0] + m[5] + m[10])) / 2; - - x = (m[9] - m[6]) > 0 ? -x : x; - y = (m[2] - m[8]) > 0 ? -y : y; - z = (m[4] - m[1]) > 0 ? -z : z; - - q[0] = x; - q[1] = y; - q[2] = z; - q[3] = w; - - return q; -} diff --git a/src/math/mat4.h b/src/math/mat4.h index a7a2959c..02d232c1 100644 --- a/src/math/mat4.h +++ b/src/math/mat4.h @@ -1,16 +1,16 @@ #include "math/math.h" -mat4 mat4_init(); +#define mat4_init mat4_set +mat4 mat4_set(mat4 m, mat4 n); mat4 mat4_fromMat34(mat4 m, float (*n)[4]); mat4 mat4_fromMat44(mat4 m, float (*n)[4]); -mat4 mat4_set(mat4 m, mat4 n); mat4 mat4_identity(mat4 m); mat4 mat4_transpose(mat4 m); mat4 mat4_invert(mat4 m); mat4 mat4_multiply(mat4 m, mat4 n); mat4 mat4_translate(mat4 m, float x, float y, float z); -mat4 mat4_rotate(mat4 m, quat q); +mat4 mat4_rotate(mat4 m, float angle, float x, float y, float z); +mat4 mat4_rotateQuat(mat4 m, quat q); mat4 mat4_scale(mat4 m, float x, float y, float z); mat4 mat4_orthographic(mat4 m, float left, float right, float top, float bottom, float near, float far); mat4 mat4_perspective(mat4 m, float near, float far, float fov, float aspect); -quat mat4_toQuat(mat4 m, quat q); diff --git a/src/math/quat.c b/src/math/quat.c index b5913b63..d0700a0e 100644 --- a/src/math/quat.c +++ b/src/math/quat.c @@ -1,10 +1,14 @@ #include "math/quat.h" #include "math/vec3.h" +#include "util.h" #include #include -quat quat_init(float x, float y, float z, float w) { - quat q = malloc(4 * sizeof(float)); +quat quat_init(quat q, quat r) { + return quat_set(q, r[0], r[1], r[2], r[3]); +} + +quat quat_set(quat q, float x, float y, float z, float w) { q[0] = x; q[1] = y; q[2] = z; @@ -25,19 +29,28 @@ quat quat_fromAngleAxis(quat q, float angle, vec3 axis) { quat quat_fromDirection(quat q, vec3 forward, vec3 up) { vec3 qq = (vec3) q; - vec3_set(qq, forward); + vec3_init(qq, forward); vec3_normalize(qq); - vec3_normalize(up); q[3] = 1 + vec3_dot(qq, up); vec3_cross(qq, up); return q; } -quat quat_set(quat q, quat r) { - q[0] = r[0]; - q[1] = r[1]; - q[2] = r[2]; - q[3] = r[3]; +quat quat_fromMat4(quat q, mat4 m) { + float x = sqrt(MAX(0, 1 + m[0] - m[5] - m[10])) / 2; + float y = sqrt(MAX(0, 1 - m[0] + m[5] - m[10])) / 2; + float z = sqrt(MAX(0, 1 - m[0] - m[5] + m[10])) / 2; + float w = sqrt(MAX(0, 1 + m[0] + m[5] + m[10])) / 2; + + x = (m[9] - m[6]) > 0 ? -x : x; + y = (m[2] - m[8]) > 0 ? -y : y; + z = (m[4] - m[1]) > 0 ? -z : z; + + q[0] = x; + q[1] = y; + q[2] = z; + q[3] = w; + return q; } @@ -111,25 +124,22 @@ quat quat_between(quat q, vec3 u, vec3 v) { q[3] = 1.f; return q; } else if (dot < -.99999) { - float axis[3] = { 1, 0, 0 }; - vec3_cross(axis, u); + float axis[3]; + vec3_cross(vec3_set(axis, 1, 0, 0), u); if (vec3_length(axis) < .00001) { - axis[0] = 0; - axis[1] = 1; - axis[2] = 0; - vec3_cross(axis, u); + vec3_cross(vec3_set(axis, 0, 1, 0), u); } vec3_normalize(axis); quat_fromAngleAxis(q, M_PI, axis); return q; } - vec3_cross(vec3_set(q, u), v); + vec3_cross(vec3_init(q, u), v); q[3] = 1 + dot; return quat_normalize(q); } -void quat_toAngleAxis(quat q, float* angle, float* x, float* y, float* z) { +void quat_getAngleAxis(quat q, float* angle, float* x, float* y, float* z) { if (q[3] > 1 || q[3] < -1) { quat_normalize(q); } diff --git a/src/math/quat.h b/src/math/quat.h index cfbc67bd..a6866b66 100644 --- a/src/math/quat.h +++ b/src/math/quat.h @@ -1,12 +1,13 @@ #include "math/math.h" -quat quat_init(float x, float y, float z, float w); +quat quat_init(quat q, quat r); +quat quat_set(quat q, float x, float y, float z, float w); quat quat_fromAngleAxis(quat q, float angle, vec3 axis); quat quat_fromDirection(quat q, vec3 forward, vec3 up); -quat quat_set(quat q, quat r); +quat quat_fromMat4(quat q, mat4 m); quat quat_multiply(quat q, quat r); quat quat_normalize(quat q); float quat_length(quat q); quat quat_slerp(quat q, quat r, float t); quat quat_between(quat q, vec3 u, vec3 v); -void quat_toAngleAxis(quat q, float* angle, float* x, float* y, float* z); +void quat_getAngleAxis(quat q, float* angle, float* x, float* y, float* z); diff --git a/src/math/vec3.c b/src/math/vec3.c index 9e7db735..4125f67b 100644 --- a/src/math/vec3.c +++ b/src/math/vec3.c @@ -3,21 +3,17 @@ #include #include -vec3 vec3_init(float x, float y, float z) { - vec3 v = malloc(3 * sizeof(float)); +vec3 vec3_init(vec3 v, vec3 u) { + return vec3_set(v, u[0], u[1], u[2]); +} + +vec3 vec3_set(vec3 v, float x, float y, float z) { v[0] = x; v[1] = y; v[2] = z; return v; } -vec3 vec3_set(vec3 v, vec3 u) { - v[0] = u[0]; - v[1] = u[1]; - v[2] = u[2]; - return v; -} - vec3 vec3_add(vec3 v, vec3 u) { v[0] += u[0]; v[1] += u[1]; @@ -55,15 +51,7 @@ vec3 vec3_scale(vec3 v, float s) { vec3 vec3_normalize(vec3 v) { float len = vec3_length(v); - if (len == 0) { - return v; - } - - len = 1 / len; - v[0] *= len; - v[1] *= len; - v[2] *= len; - return v; + return len == 0 ? v : vec3_scale(v, 1 / len); } float vec3_length(vec3 v) { @@ -86,21 +74,19 @@ float vec3_dot(vec3 v, vec3 u) { } vec3 vec3_cross(vec3 v, vec3 u) { - float v0 = v[0]; - float v1 = v[1]; - float v2 = v[2]; - v[0] = v1 * u[2] - v2 * u[1]; - v[1] = v0 * u[2] - v2 * u[0]; - v[2] = v0 * u[1] - v1 * u[0]; - return v; + return vec3_set(v, + v[1] * u[2] - v[2] * u[1], + v[2] * u[0] - v[0] * u[2], + v[0] * u[1] - v[1] * u[0] + ); } vec3 vec3_rotate(vec3 v, quat q) { float s = q[3]; float u[3]; float c[3]; - vec3_set(u, q); - vec3_cross(vec3_set(c, u), v); + vec3_init(u, q); + vec3_cross(vec3_init(c, u), v); float uu = vec3_dot(u, u); float uv = vec3_dot(u, v); vec3_scale(u, 2 * uv); @@ -110,13 +96,11 @@ vec3 vec3_rotate(vec3 v, quat q) { } vec3 vec3_transform(vec3 v, mat4 m) { - float v0 = v[0]; - float v1 = v[1]; - float v2 = v[2]; - v[0] = v0 * m[0] + v1 * m[4] + v2 * m[8] + m[12]; - v[1] = v0 * m[1] + v1 * m[5] + v2 * m[9] + m[13]; - v[2] = v0 * m[2] + v1 * m[6] + v2 * m[10] + m[14]; - return v; + return vec3_set(v, + v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12], + v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13], + v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14] + ); } vec3 vec3_lerp(vec3 v, vec3 u, float t) { diff --git a/src/math/vec3.h b/src/math/vec3.h index a3fef7de..e0d1c406 100644 --- a/src/math/vec3.h +++ b/src/math/vec3.h @@ -1,7 +1,7 @@ #include "math/math.h" -vec3 vec3_init(float x, float y, float z); -vec3 vec3_set(vec3 v, vec3 u); +vec3 vec3_init(vec3 v, vec3 u); +vec3 vec3_set(vec3 v, float x, float y, float z); vec3 vec3_add(vec3 v, vec3 u); vec3 vec3_sub(vec3 v, vec3 u); vec3 vec3_mul(vec3 v, vec3 u);