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 /src/scene_tree_node.c | |
parent | be49795636e5a9ede3742d077701f48e9316e121 (diff) |
create basic scene tree node
Diffstat (limited to 'src/scene_tree_node.c')
-rw-r--r-- | src/scene_tree_node.c | 320 |
1 files changed, 320 insertions, 0 deletions
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; +} |