diff options
author | sanine-a <sanine.not@pm.me> | 2020-12-02 01:42:21 -0600 |
---|---|---|
committer | sanine-a <sanine.not@pm.me> | 2020-12-02 01:42:21 -0600 |
commit | f417d2b047369cac234c471ef37ab8281181d69f (patch) | |
tree | 3b21174fc4efcd5643b1f4d1e8a202020f85cede | |
parent | be49795636e5a9ede3742d077701f48e9316e121 (diff) |
create basic scene tree node
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | demo/main.lua | 14 | ||||
-rw-r--r-- | src/glm_bindings.c | 41 | ||||
-rw-r--r-- | src/glm_bindings.h | 4 | ||||
-rw-r--r-- | src/honey.c | 2 | ||||
-rw-r--r-- | src/scene_tree.h | 23 | ||||
-rw-r--r-- | src/scene_tree_node.c | 320 |
7 files changed, 403 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index aeeb8ff..7bd7243 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ set(SOURCE_FILES src/mesh.c src/primitives.c src/shader.c + src/scene_tree_node.c src/texture.c src/window.c) diff --git a/demo/main.lua b/demo/main.lua index 3fabe00..ec0bac1 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -1,9 +1,19 @@ +local root = honey.node(nil, + honey.glm.vec3{0,0,0}, + honey.glm.vec3{0,0,0}, + honey.glm.vec3{1,1,1}) + +local child = honey.node(root, + honey.glm.vec3{0,0,0}, + honey.glm.vec3{0,0,0}, + honey.glm.vec3{1,1,1}) + local v = honey.glm.vec3{1, 2, 3} -local M = honey.glm.mat3() +local M = honey.glm.mat4() M:set(1,3, 1) -print(M:mulv(v)) +print(M:mul(M)) print(v) print(honey.glm.vec3{2, 0.001, 0}) diff --git a/src/glm_bindings.c b/src/glm_bindings.c index 173e2eb..6893534 100644 --- a/src/glm_bindings.c +++ b/src/glm_bindings.c @@ -5,6 +5,33 @@ int honey_glm_vec4_mt_ref = LUA_NOREF; int honey_glm_mat3_mt_ref = LUA_NOREF; int honey_glm_mat4_mt_ref = LUA_NOREF; +int honey_glm_UNIT_X_ref = LUA_NOREF; +int honey_glm_UNIT_Y_ref = LUA_NOREF; +int honey_glm_UNIT_Z_ref = LUA_NOREF; + +static void create_vec3(lua_State* L, + int x, int y, int z, + int* ref) +{ + lua_createtable(L, 3, 0); + + lua_pushnumber(L, x); + lua_rawseti(L, -2, 1); + + lua_pushnumber(L, y); + lua_rawseti(L, -2, 2); + + lua_pushnumber(L, z); + lua_rawseti(L, -2, 3); + + lua_pushcfunction(L, honey_glm_new_vec3); + lua_pushvalue(L, -2); + honey_lua_pcall(L, 1, 1); + + *ref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pop(L, 1); +} + void honey_setup_glm(lua_State* L) { /* vec3 metatable */ @@ -127,6 +154,10 @@ void honey_setup_glm(lua_State* L) HONEY_FUNCTION, "__gc", honey_glm_array_destroy); honey_glm_mat4_mt_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + create_vec3(L, 1, 0, 0, &honey_glm_UNIT_X_ref); + create_vec3(L, 0, 1, 0, &honey_glm_UNIT_Y_ref); + create_vec3(L, 0, 0, 1, &honey_glm_UNIT_Z_ref); /* glm table */ honey_lua_create_table @@ -135,6 +166,16 @@ void honey_setup_glm(lua_State* L) HONEY_FUNCTION, "vec4", honey_glm_new_vec4, HONEY_FUNCTION, "mat3", honey_glm_new_mat3, HONEY_FUNCTION, "mat4", honey_glm_new_mat4); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_glm_UNIT_X_ref); + lua_setfield(L, -2, "UNIT_X"); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_glm_UNIT_Y_ref); + lua_setfield(L, -2, "UNIT_Y"); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_glm_UNIT_Z_ref); + lua_setfield(L, -2, "UNIT_Z"); + lua_setfield(L, -2, "glm"); } diff --git a/src/glm_bindings.h b/src/glm_bindings.h index 1b86de2..b04016e 100644 --- a/src/glm_bindings.h +++ b/src/glm_bindings.h @@ -12,6 +12,10 @@ extern int honey_glm_vec4_mt_ref; extern int honey_glm_mat3_mt_ref; extern int honey_glm_mat4_mt_ref; +extern honey_glm_array UNIT_X; +extern honey_glm_array UNIT_Y; +extern honey_glm_array UNIT_Z; + /** @brief Push the honey glm binding functions to the lua stack. * * @returns Nothing. diff --git a/src/honey.c b/src/honey.c index 4757f53..f58be3e 100644 --- a/src/honey.c +++ b/src/honey.c @@ -131,6 +131,8 @@ bool honey_setup(lua_State** L) honey_setup_texture(*L); + honey_setup_scene_tree(*L); + lua_pushcfunction(*L, honey_exit); lua_setfield(*L, -2, "exit"); diff --git a/src/scene_tree.h b/src/scene_tree.h new file mode 100644 index 0000000..ea1e37b --- /dev/null +++ b/src/scene_tree.h @@ -0,0 +1,23 @@ +#include "common.h" + +/* @file Defines the basic scene tree nodes and functions to manipulate them. */ + +extern int honey_node_mt_ref; + +void honey_setup_scene_tree(lua_State* L); + +int honey_node_new(lua_State* L); + +int honey_node_update_transform(lua_State* L); + +int honey_node_update_cascade(lua_State* L); + +int honey_node_draw_cascade(lua_State* L); + +int honey_node_translate(lua_State* L); + +int honey_node_rotate(lua_State* L); + +int honey_node_scale(lua_State* L); + + diff --git a/src/scene_tree_node.c b/src/scene_tree_node.c new file mode 100644 index 0000000..a3ca27e --- /dev/null +++ b/src/scene_tree_node.c @@ -0,0 +1,320 @@ +#include "scene_tree.h" +#include "glm_bindings.h" + +int honey_node_mt_ref = LUA_NOREF; + +void honey_setup_scene_tree(lua_State* L) +{ + honey_lua_create_table + (L, 1, + HONEY_TABLE, "__index", 6, + HONEY_FUNCTION, "updateTransform", honey_node_update_transform, + HONEY_FUNCTION, "updateCascade", honey_node_update_cascade, + HONEY_FUNCTION, "drawCascade", honey_node_draw_cascade, + HONEY_FUNCTION, "translate", honey_node_translate, + HONEY_FUNCTION, "rotate", honey_node_rotate, + HONEY_FUNCTION, "scale", honey_node_scale); + honey_node_mt_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + lua_pushcfunction(L, honey_node_new); + lua_setfield(L, -2, "node"); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Basic node functions + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +int honey_node_new(lua_State* L) +{ + honey_glm_array *position, *rotation, *scale; + honey_lua_parse_arguments + (L, 1, 4, + HONEY_ANY, NULL, + HONEY_USERDATA, &position, + HONEY_USERDATA, &rotation, + HONEY_USERDATA, &scale); + + lua_createtable(L, 5, 0); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_node_mt_ref); + lua_setmetatable(L, -2); + + lua_pushvalue(L, 1); + if (!lua_isnil(L, -1)) { + /* add self to parent.children */ + lua_getfield(L, -1, "children"); + int length = lua_objlen(L, -1); + + lua_pushinteger(L, length+1); + lua_pushvalue(L, 5); + lua_settable(L, -3); + lua_pop(L, 1); + } + lua_setfield(L, -2, "parent"); + + if (position->type != VEC3) + honey_lua_throw_error + (L, "position vector must be of type VEC3 (%d); got %d instead", + VEC3, position->type); + lua_pushvalue(L, 2); + lua_setfield(L, -2, "position"); + + if (rotation->type != VEC3) + honey_lua_throw_error + (L, "rotation vector must be of type VEC3 (%d); got %d instead", + VEC3, rotation->type); + lua_pushvalue(L, 3); + lua_setfield(L, -2, "rotation"); + + if (scale->type != VEC3) + honey_lua_throw_error + (L, "scale vector must be of type VEC3 (%d); got %d instead", + VEC3, scale->type); + lua_pushvalue(L, 4); + lua_setfield(L, -2, "scale"); + + /* create transform */ + lua_pushcfunction(L, honey_glm_new_mat4); + honey_lua_pcall(L, 0, 1); + + /* call honey.glm.eye() */ + lua_pushcfunction(L, honey_glm_mat4_eye); + lua_pushvalue(L, -2); + honey_lua_pcall(L, 1, 0); + + lua_setfield(L, -2, "transform"); + + /* call node:updateTransform() */ + lua_getfield(L, -1, "updateTransform"); + lua_pushvalue(L, -2); + honey_lua_pcall(L, 1, 0); + + /* create children */ + lua_createtable(L, 0, 0); + lua_setfield(L, -2, "children"); + + return 1; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_node_update_transform(lua_State* L) +{ + honey_lua_parse_arguments(L, 1, 1, HONEY_TABLE, NULL); + + /* self.transform:eye() */ + lua_pushcfunction(L, honey_glm_mat4_eye); + lua_getfield(L, 1, "transform"); + lua_pushvalue(L, -1); + honey_lua_pcall(L, 1, 0); + + /* self.transform:translate(self.position) */ + lua_pushcfunction(L, honey_glm_translate); + lua_pushvalue(L, 2); + lua_getfield(L, 1, "position"); + honey_lua_pcall(L, 2, 0); + + /* self.transform:rotateZ(self.rotation:at(2)) */ + lua_pushcfunction(L, honey_glm_rotate_z); + lua_pushvalue(L, 2); + lua_getfield(L, 1, "position"); + honey_glm_array* position = lua_touserdata(L, -1); + lua_pop(L, 1); + lua_pushnumber(L, position->data[2]); + honey_lua_pcall(L, 2, 0); + + /* self.transform:rotateY(self.rotation:at(1)) */ + lua_pushcfunction(L, honey_glm_rotate_y); + lua_pushvalue(L, 2); + lua_pushnumber(L, position->data[1]); + honey_lua_pcall(L, 2, 0); + + /* self.transform:rotateX(self.rotation:at(0)) */ + lua_pushcfunction(L, honey_glm_rotate_x); + lua_pushvalue(L, 2); + lua_pushnumber(L, position->data[0]); + honey_lua_pcall(L, 2, 0); + + lua_getfield(L, 1, "parent"); + if (!lua_isnil(L, -1)) { + lua_pushcfunction(L, honey_glm_mat4_mul); + lua_getfield(L, -2, "transform"); + lua_pushvalue(L, 2); + lua_pushvalue(L, -1); + honey_lua_pcall(L, 3, 0); + } + lua_pop(L, 1); + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_node_update_cascade(lua_State* L) +{ + float dt; + honey_lua_parse_arguments(L, 1, 2, HONEY_TABLE, NULL, HONEY_NUMBER, &dt); + + /* call self.update if it exists */ + lua_getfield(L, 1, "update"); + if (!lua_isnil(L, -1)) { + lua_pushvalue(L, 1); + lua_pushnumber(L, dt); + honey_lua_pcall(L, 2, 0); + } + else + lua_pop(L, 1); + + lua_pushcfunction(L, honey_node_update_transform); + lua_pushvalue(L, 1); + honey_lua_pcall(L, 1, 0); + + /* update cascade for each child node */ + lua_getfield(L, 1, "children"); + int n_children = lua_objlen(L, -1); + for (int i=0; i<n_children; i++) { + lua_rawgeti(L, -1, i+1); + lua_pushcfunction(L, honey_node_update_cascade); + lua_pushvalue(L, -2); + lua_pushnumber(L, dt); + honey_lua_pcall(L, 2, 0); + lua_pop(L, 1); + } + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_node_draw_cascade(lua_State* L) +{ + honey_lua_parse_arguments(L, 1, 1, HONEY_TABLE, NULL); + + /* call self.draw if it exists */ + lua_getfield(L, 1, "draw"); + if (!lua_isnil(L, -1)) { + lua_pushvalue(L, 1); + honey_lua_pcall(L, 1, 0); + } + else + lua_pop(L, 1); + + /* draw cascade for each child node */ + lua_getfield(L, 1, "children"); + int n_children = lua_objlen(L, -1); + for (int i=0; i<n_children; i++) { + lua_rawgeti(L, -1, i+1); + lua_pushcfunction(L, honey_node_draw_cascade); + lua_pushvalue(L, -2); + honey_lua_pcall(L, 1, 0); + lua_pop(L, 1); + } + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_node_translate(lua_State* L) +{ + honey_glm_array* v; + honey_lua_parse_arguments(L, 1, 2, HONEY_TABLE, NULL, HONEY_USERDATA, &v); + + lua_pushcfunction(L, honey_glm_vec3_add); + lua_getfield(L, 1, "transform"); + lua_pushvalue(L, 2); + lua_pushvalue(L, -2); + honey_lua_pcall(L, 3, 0); + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_node_rotate(lua_State* L) +{ + char* axisName; + float angle; + int index; + + honey_lua_parse_arguments + (L, 1, 3, + HONEY_TABLE, NULL, HONEY_STRING, &axisName, HONEY_NUMBER, &angle); + + switch (axisName[0]) { + case 'x': + index = 0; + break; + + case 'y': + index = 1; + break; + + case 'z': + index = 2; + break; + + default: + honey_lua_throw_error + (L, "axis string must be one of 'x', 'y', or 'z'; got '%s' instead", axisName); + } + + lua_getfield(L, 1, "rotation"); + honey_glm_array* rotation = lua_touserdata(L, -1); + lua_pop(L, 1); + + rotation->data[index] += angle; + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_node_scale(lua_State* L) +{ + char* axisName; + float s; + int index; + + int choice = honey_lua_parse_arguments + (L, 2, + 2, + HONEY_TABLE, NULL, HONEY_NUMBER, &s, + 3, + HONEY_TABLE, NULL, HONEY_STRING, &axisName, HONEY_NUMBER, &s); + + lua_getfield(L, 1, "scale"); + honey_glm_array* scale = lua_touserdata(L, -1); + lua_pop(L, 1); + + if (choice == 0) { + for (int i=0; i<3; i++) + scale->data[i] *= s; + } + else { + switch (axisName[0]) { + case 'x': + index = 0; + break; + + case 'y': + index = 1; + break; + + case 'z': + index = 2; + break; + + default: + honey_lua_throw_error + (L, "axis string must be one of 'x', 'y', or 'z'; got '%s' instead", axisName); + } + + scale->data[index] *= s; + } + + return 0; +} |