diff options
author | sanine <sanine.not@pm.me> | 2022-09-22 18:30:08 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-09-22 18:30:08 -0500 |
commit | dc6c3052e4df6eecd60ded1b913e7e6476eb9921 (patch) | |
tree | f4d25c457fe0cbd5d417bcd1beab894e65689adb /src | |
parent | db0bc36c52a223f96bf0b517ef1053ba6b6b16d9 (diff) |
add basic recursive aiNode push
Diffstat (limited to 'src')
-rw-r--r-- | src/import/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/import/import.c | 37 | ||||
-rw-r--r-- | src/import/import.test.c | 572 | ||||
-rw-r--r-- | src/import/import.test.h | 18 | ||||
-rw-r--r-- | src/import/import_mesh.test.c | 570 | ||||
-rw-r--r-- | src/import/import_node.test.c | 116 |
6 files changed, 742 insertions, 573 deletions
diff --git a/src/import/CMakeLists.txt b/src/import/CMakeLists.txt index fc35779..5b9238b 100644 --- a/src/import/CMakeLists.txt +++ b/src/import/CMakeLists.txt @@ -7,4 +7,6 @@ target_sources(honey PUBLIC target_sources(test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/import.test.c + ${CMAKE_CURRENT_LIST_DIR}/import_mesh.test.c + ${CMAKE_CURRENT_LIST_DIR}/import_node.test.c ) diff --git a/src/import/import.c b/src/import/import.c index d58de0f..400f1d9 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -4,7 +4,7 @@ #include "import.h" -void push_vector(lua_State *L, struct aiVector3D vec) +static void push_vector(lua_State *L, struct aiVector3D vec) { hs_create_table(L, hs_str_num("x", vec.x), @@ -14,7 +14,7 @@ void push_vector(lua_State *L, struct aiVector3D vec) } -void push_face(lua_State *L, struct aiFace face) +static void push_face(lua_State *L, struct aiFace face) { lua_createtable(L, face.mNumIndices, 0); int tbl = lua_gettop(L); @@ -27,7 +27,7 @@ void push_face(lua_State *L, struct aiFace face) } -void push_aistring(lua_State *L, struct aiString str) +static void push_aistring(lua_State *L, struct aiString str) { lua_pushstring(L, str.data); } @@ -57,7 +57,7 @@ void push_aistring(lua_State *L, struct aiString str) * mPrimitiveTypes * mTextureCoordsNames */ -void push_mesh(lua_State *L, struct aiMesh mesh) +static void push_mesh(lua_State *L, struct aiMesh mesh) { /* --=== create mesh table ===-- */ lua_createtable(L, 0, 1); @@ -196,3 +196,32 @@ void push_mesh(lua_State *L, struct aiMesh mesh) /* --=== clean up ===-- */ lua_pop(L, pop_count); } + + +static void push_node(lua_State *L, struct aiNode *node) +{ + lua_createtable(L, 0, 0); + int nodetbl = lua_gettop(L); + + int pop_count = 0; + + if (node->mMeshes != NULL) { + lua_createtable(L, node->mNumMeshes, 0); + int meshes = lua_gettop(L); + for (int i=0; i<node->mNumMeshes; i++) { + lua_pushinteger(L, node->mMeshes[i]+1); + lua_rawseti(L, meshes, i+1); + } + lua_setfield(L, nodetbl, "meshes"); + } + + if (node->mChildren != NULL) { + lua_createtable(L, node->mNumChildren, 0); + int children = lua_gettop(L); + for (int i=0; i<node->mNumChildren; i++) { + push_node(L, node->mChildren[i]); + lua_rawseti(L, children, i+1); + } + lua_setfield(L, nodetbl, "children"); + } +} diff --git a/src/import/import.test.c b/src/import/import.test.c index bd15205..558398a 100644 --- a/src/import/import.test.c +++ b/src/import/import.test.c @@ -1,573 +1,5 @@ -#include <string.h> -#include <lua.h> -#include <lauxlib.h> -#include <honeysuckle.h> #include "test/honey-test.h" - - -#include "import.c" - - -void test_push_vector() -{ - lua_State *L = luaL_newstate(); - struct aiVector3D v; - v.x = 1.5; - v.y = 2.0; - v.z = 3.6; - - push_vector(L, v); - - lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); - - lua_getfield(L, -1, "x"); - lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); - lily_assert_float_equal(lua_tonumber(L, -1), 1.5, 0.1); - lua_pop(L, 1); - - lua_getfield(L, -1, "y"); - lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); - lily_assert_float_equal(lua_tonumber(L, -1), 2.0, 0.1); - lua_pop(L, 1); - - lua_getfield(L, -1, "z"); - lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); - lily_assert_float_equal(lua_tonumber(L, -1), 3.6, 0.1); - lua_pop(L, 1); - - lua_close(L); -} - - -void test_push_face() -{ - lua_State *L = luaL_newstate(); - struct aiFace face; - int indices[] = { 0, 1, 2, 3, 4, 5 }; - face.mIndices = indices; - face.mNumIndices = 6; - - push_face(L, face); - - lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); - int facetbl = lua_gettop(L); - lily_assert_int_equal(lua_objlen(L, facetbl), 6); - - /* the numbers should be one higher because of lua's 1-indexing */ - lua_rawgeti(L, facetbl, 1); - lily_assert_int_equal(lua_tointeger(L, -1), 1); - lua_rawgeti(L, facetbl, 2); - lily_assert_int_equal(lua_tointeger(L, -1), 2); - lua_rawgeti(L, facetbl, 3); - lily_assert_int_equal(lua_tointeger(L, -1), 3); - lua_rawgeti(L, facetbl, 4); - lily_assert_int_equal(lua_tointeger(L, -1), 4); - lua_rawgeti(L, facetbl, 5); - lily_assert_int_equal(lua_tointeger(L, -1), 5); - lua_rawgeti(L, facetbl, 6); - lily_assert_int_equal(lua_tointeger(L, -1), 6); - - lua_close(L); -} - - -void test_push_aistring() -{ - lua_State *L = luaL_newstate(); - struct aiString str; - strcpy(str.data, "hello, world!"); - - push_aistring(L, str); - - lily_assert_int_equal(lua_type(L, -1), LUA_TSTRING); - lily_assert_string_equal((char*) lua_tostring(L, -1), "hello, world!"); - - lua_close(L); -} - - -/* --===== mesh tests =====-- */ - - -void create_vertices(struct aiMesh *mesh); -void test_vertices(lua_State *L, int meshtbl); - -void create_faces(struct aiMesh *mesh); -void test_faces(lua_State *L, int meshtbl); - -void create_normals(struct aiMesh *mesh); -void test_normals(lua_State *L, int meshtbl); - -void create_tangents(struct aiMesh *mesh); -void test_tangents(lua_State *L, int meshtbl); - -void create_uvs(struct aiMesh *mesh); -void test_uvs(lua_State *L, int meshtbl); - -void test_nil(lua_State *L, int meshtbl, const char *field); - - -#define NUM_MESH_VERTICES 4 -#define NUM_MESH_FACES 2 - - -#define ALLOCATE_MEMORY() \ - struct aiVector3D vertices[NUM_MESH_VERTICES]; \ - mesh.mVertices = vertices; \ - struct aiVector3D normals[NUM_MESH_VERTICES]; \ - mesh.mNormals = normals; \ - struct aiVector3D tangents[NUM_MESH_VERTICES]; \ - struct aiVector3D bitangents[NUM_MESH_VERTICES]; \ - mesh.mTangents = tangents; \ - mesh.mBitangents = bitangents; \ - struct aiVector3D uvs[AI_MAX_NUMBER_OF_TEXTURECOORDS * NUM_MESH_VERTICES]; \ - for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) \ - mesh.mTextureCoords[i] = uvs + (i*NUM_MESH_VERTICES); \ - struct aiFace faces[NUM_MESH_FACES]; \ - unsigned int index_array[3*NUM_MESH_FACES]; \ - for (int i=0; i<NUM_MESH_FACES; i++) \ - faces[i].mIndices = index_array + (3*i); \ - mesh.mFaces = faces; - - - -void test_push_mesh() -{ - lua_State *L = luaL_newstate(); - struct aiMesh mesh; - mesh.mNumVertices = NUM_MESH_VERTICES; - mesh.mNumFaces = 0; - - /* allocate memory */ - ALLOCATE_MEMORY(); - mesh.mNormals = NULL; - mesh.mTangents = NULL; - mesh.mBitangents = NULL; - for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) - mesh.mTextureCoords[i] = NULL; - - /* setup mesh */ - create_vertices(&mesh); - - /* push */ - int top_before = lua_gettop(L); - push_mesh(L, mesh); - int meshtbl = lua_gettop(L); - - /* check output */ - lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); - lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ - test_vertices(L, meshtbl); - test_nil(L, meshtbl, "faces"); - - lua_close(L); -} - - -void test_push_mesh_faces() -{ - lua_State *L = luaL_newstate(); - struct aiMesh mesh; - mesh.mNumVertices = NUM_MESH_VERTICES; - mesh.mNumFaces = NUM_MESH_FACES; - - /* allocate memory */ - ALLOCATE_MEMORY(); - mesh.mNormals = NULL; - mesh.mTangents = NULL; - mesh.mBitangents = NULL; - for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) - mesh.mTextureCoords[i] = NULL; - - /* setup mesh */ - create_vertices(&mesh); - create_faces(&mesh); - - /* push */ - int top_before = lua_gettop(L); - push_mesh(L, mesh); - int meshtbl = lua_gettop(L); - - /* check output */ - lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); - lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ - test_vertices(L, meshtbl); - test_faces(L, meshtbl); - - lua_close(L); -} - - -void test_push_mesh_normals() -{ - lua_State *L = luaL_newstate(); - struct aiMesh mesh; - mesh.mNumVertices = NUM_MESH_VERTICES; - mesh.mNumFaces = NUM_MESH_FACES; - - /* allocate memory */ - ALLOCATE_MEMORY(); - mesh.mTangents = NULL; - mesh.mBitangents = NULL; - for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) - mesh.mTextureCoords[i] = NULL; - - /* setup mesh */ - create_vertices(&mesh); - create_faces(&mesh); - create_normals(&mesh); - - /* push */ - int top_before = lua_gettop(L); - push_mesh(L, mesh); - int meshtbl = lua_gettop(L); - - /* check output */ - lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); - lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ - test_vertices(L, meshtbl); - test_faces(L, meshtbl); - test_normals(L, meshtbl); - - lua_close(L); -} - - -void test_push_mesh_tangents() -{ - lua_State *L = luaL_newstate(); - struct aiMesh mesh; - mesh.mNumVertices = NUM_MESH_VERTICES; - mesh.mNumFaces = NUM_MESH_FACES; - - /* allocate memory */ - ALLOCATE_MEMORY(); - for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) - mesh.mTextureCoords[i] = NULL; - - /* setup mesh */ - create_vertices(&mesh); - create_faces(&mesh); - create_normals(&mesh); - create_tangents(&mesh); - - /* push */ - int top_before = lua_gettop(L); - push_mesh(L, mesh); - int meshtbl = lua_gettop(L); - - /* check output */ - lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); - lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ - test_vertices(L, meshtbl); - test_faces(L, meshtbl); - test_normals(L, meshtbl); - test_tangents(L, meshtbl); - - lua_close(L); - -} - - -void test_push_mesh_uvs() -{ - lua_State *L = luaL_newstate(); - struct aiMesh mesh; - mesh.mNumVertices = NUM_MESH_VERTICES; - mesh.mNumFaces = NUM_MESH_FACES; - - /* allocate memory */ - ALLOCATE_MEMORY(); - - /* setup mesh */ - create_vertices(&mesh); - create_faces(&mesh); - create_normals(&mesh); - create_tangents(&mesh); - create_uvs(&mesh); - - /* push */ - int top_before = lua_gettop(L); - push_mesh(L, mesh); - int meshtbl = lua_gettop(L); - - /* check output */ - lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); - lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ - test_vertices(L, meshtbl); - test_faces(L, meshtbl); - test_normals(L, meshtbl); - test_tangents(L, meshtbl); - test_uvs(L, meshtbl); - - lua_close(L); - -} - - -void create_vertices(struct aiMesh *mesh) -{ - mesh->mVertices[0] = (struct aiVector3D) { 0, 0, 0 }; - mesh->mVertices[1] = (struct aiVector3D) { 0, 0, 1 }; - mesh->mVertices[2] = (struct aiVector3D) { 1, 0, 0 }; - mesh->mVertices[3] = (struct aiVector3D) { 1, 0, 1 }; -} - - -static int check_vector(lua_State *L, int meshtbl, const char *field, int index, - float x, float y, float z) -{ - lua_getfield(L, meshtbl, field); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "field '%s' is not a table!", field); - lua_rawgeti(L, -1, index); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "%s[%d] is not a table!", field, index); - - lua_getfield(L, -1, "x"); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d].x is not a number!", field, index); - float vx = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "y"); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d].y is not a number!", field, index); - float vy = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "z"); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d].z is not a number!", field, index); - float vz = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_pop(L, 2); - lily_assert( - (fabs(vx - x) < 0.1) && - (fabs(vy - y) < 0.1) && - (fabs(vz - z) < 0.1), - "%s[%d] is [%f, %f, %f], but expected [%f, %f, %f]!", - field, index, - vx, vy, vz, - x, y, z - ); -} - - -void test_vertices(lua_State *L, int meshtbl) -{ - check_vector(L, meshtbl, "vertices", 1, 0, 0, 0); - check_vector(L, meshtbl, "vertices", 2, 0, 0, 1); - check_vector(L, meshtbl, "vertices", 3, 1, 0, 0); - check_vector(L, meshtbl, "vertices", 4, 1, 0, 1); -} - - -static void setup_face(struct aiFace *face, int v0, int v1, int v2) -{ - face->mNumIndices = 3; - face->mIndices[0] = v0; - face->mIndices[1] = v1; - face->mIndices[2] = v2; -} - - -void create_faces(struct aiMesh *mesh) -{ - setup_face(mesh->mFaces + 0, 0, 1, 3); - setup_face(mesh->mFaces + 1, 0, 3, 2); -} - - -static int check_face(lua_State *L, int meshtbl, const char *field, int index, - int v0, int v1, int v2) -{ - lua_getfield(L, meshtbl, field); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "field '%s' is not a table!", field); - lua_rawgeti(L, -1, index); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "%s[%d] is not a table!", field, index); - - lua_rawgeti(L, -1, 1); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d][1] is not a number!", field, index); - int vv0 = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_rawgeti(L, -1, 2); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d][2] is not a number!", field, index); - int vv1 = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_rawgeti(L, -1, 3); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d][3] is not a number!", field, index); - int vv2 = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_pop(L, 2); - lily_assert( - (v0 == vv0) && - (v1 == vv1) && - (v2 == vv2), - "%s[%d] is [%d, %d, %d], but expected [%d, %d, %d]!", - field, index, - vv0, vv1, vv2, - v0, v1, v2 - ); -} - - -void test_faces(lua_State *L, int meshtbl) -{ - check_face(L, meshtbl, "faces", 1, 1, 2, 4); - check_face(L, meshtbl, "faces", 2, 1, 4, 3); -} - - -void create_normals(struct aiMesh *mesh) -{ - /* these normals are deliberately not, uh, normalized - * in order to distinguish them for the purposes of testing. - * (this could also happen in real life -- assimp won't normalize - * normals taken straight from the object file) - */ - mesh->mNormals[0] = (struct aiVector3D) { 0, 0.1, 0 }; - mesh->mNormals[1] = (struct aiVector3D) { 0, 0.2, 0 }; - mesh->mNormals[2] = (struct aiVector3D) { 0, 0.4, 0 }; - mesh->mNormals[3] = (struct aiVector3D) { 0, 1.0, 0 }; -} - - -void test_normals(lua_State *L, int meshtbl) -{ - check_vector(L, meshtbl, "normals", 1, 0, 0.1, 0); - check_vector(L, meshtbl, "normals", 2, 0, 0.2, 0); - check_vector(L, meshtbl, "normals", 3, 0, 0.4, 0); - check_vector(L, meshtbl, "normals", 4, 0, 1.0, 0); -} - - -void create_tangents(struct aiMesh *mesh) -{ - /* these tangents are not normalized -- see note in create_normals */ - mesh->mTangents[0] = (struct aiVector3D) { 0.1, 0, 0 }; - mesh->mTangents[1] = (struct aiVector3D) { 0.2, 0, 0 }; - mesh->mTangents[2] = (struct aiVector3D) { 0.4, 0, 0 }; - mesh->mTangents[3] = (struct aiVector3D) { 1.0, 0, 0 }; - - mesh->mBitangents[0] = (struct aiVector3D) { 0, 0, 0.1 }; - mesh->mBitangents[1] = (struct aiVector3D) { 0, 0, 0.2 }; - mesh->mBitangents[2] = (struct aiVector3D) { 0, 0, 0.4 }; - mesh->mBitangents[3] = (struct aiVector3D) { 0, 0, 1.0 }; -} - - -void test_tangents(lua_State *L, int meshtbl) -{ - check_vector(L, meshtbl, "tangents", 1, 0.1, 0, 0); - check_vector(L, meshtbl, "tangents", 2, 0.2, 0, 0); - check_vector(L, meshtbl, "tangents", 3, 0.4, 0, 0); - check_vector(L, meshtbl, "tangents", 4, 1.0, 0, 0); - - check_vector(L, meshtbl, "bitangents", 1, 0, 0, 0.1); - check_vector(L, meshtbl, "bitangents", 2, 0, 0, 0.2); - check_vector(L, meshtbl, "bitangents", 3, 0, 0, 0.4); - check_vector(L, meshtbl, "bitangents", 4, 0, 0, 1.0); -} - - -void create_uvs(struct aiMesh *mesh) -{ - mesh->mNumUVComponents[0] = 2; - mesh->mTextureCoords[0][0] = (struct aiVector3D) { 0, 0, 0 }; - mesh->mTextureCoords[0][1] = (struct aiVector3D) { 0, 1, 0 }; - mesh->mTextureCoords[0][2] = (struct aiVector3D) { 1, 0, 0 }; - mesh->mTextureCoords[0][3] = (struct aiVector3D) { 1, 1, 0 }; - - mesh->mNumUVComponents[1] = 1; - mesh->mTextureCoords[1][0] = (struct aiVector3D) { 0.0, 0, 0 }; - mesh->mTextureCoords[1][1] = (struct aiVector3D) { 0.2, 0, 0 }; - mesh->mTextureCoords[1][2] = (struct aiVector3D) { 0.4, 0, 0 }; - mesh->mTextureCoords[1][3] = (struct aiVector3D) { 0.8, 0, 0 }; - - for (int i=2; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) - mesh->mTextureCoords[i] = NULL; -} - - -static int check_uv(lua_State *L, int meshtbl, int channel, int index, - float x, float y, float z) -{ - lua_getfield(L, meshtbl, "uvs"); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "field 'uvs' is not a table!"); - lua_rawgeti(L, -1, channel); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "uvs[%d] is not a table!", channel); - lua_rawgeti(L, -1, index); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "uvs[%d][%d] is not a table!", channel, index); - - lua_getfield(L, -1, "x"); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "uvs[%d][%d].x is not a number!", channel, index); - float vx = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "y"); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "uvs[%d][%d].y is not a number!", channel, index); - float vy = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "z"); - lily_assert(lua_type(L, -1) == LUA_TNUMBER, "uvs[%d][%d].z is not a number!", channel, index); - float vz = lua_tonumber(L, -1); - lua_pop(L, 1); - - lua_pop(L, 3); - lily_assert( - (fabs(vx - x) < 0.1) && - (fabs(vy - y) < 0.1) && - (fabs(vz - z) < 0.1), - "uvs[%d][%d] is [%f, %f, %f], but expected [%f, %f, %f]!", - channel, index, - vx, vy, vz, - x, y, z - ); -} - - -void test_uvs(lua_State *L, int meshtbl) -{ - lua_getfield(L, meshtbl, "numUvComponents"); - lily_assert(lua_type(L, -1) == LUA_TTABLE, "field 'numUvComponents' is not a table!"); - lua_rawgeti(L, -1, 1); - lily_assert_int_equal(lua_tointeger(L, -1), 2); - lua_pop(L, 1); - lua_rawgeti(L, -1, 2); - lily_assert_int_equal(lua_tointeger(L, -1), 1); - lua_pop(L, 1); - - check_uv(L, meshtbl, 1, 1, 0, 0, 0); - check_uv(L, meshtbl, 1, 2, 0, 1, 0); - check_uv(L, meshtbl, 1, 3, 1, 0, 0); - check_uv(L, meshtbl, 1, 4, 1, 1, 0); - - check_uv(L, meshtbl, 2, 1, 0.0, 0, 0); - check_uv(L, meshtbl, 2, 2, 0.2, 0, 0); - check_uv(L, meshtbl, 2, 3, 0.4, 0, 0); - check_uv(L, meshtbl, 2, 4, 0.8, 0, 0); - - lua_getfield(L, meshtbl, "uvs"); - int uvtbl = lua_gettop(L); - for (int i=2; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { - lua_rawgeti(L, uvtbl, i+1); - lily_assert(lua_type(L, -1) == LUA_TNIL, "uv channel %d is non-nil!", i+1); - lua_pop(L, 1); - } - lua_pop(L, 1); -} - -void test_nil(lua_State *L, int meshtbl, const char *field) -{ - lua_getfield(L, meshtbl, field); - lily_assert(lua_type(L, -1) == LUA_TNIL, "field '%s' is not nil!"); - lua_pop(L, 1); -} - - -/* --===== end mesh tests =====-- */ - +#include "import.test.h" void suite_import() { @@ -580,4 +12,6 @@ void suite_import() lily_run_test(test_push_mesh_normals); lily_run_test(test_push_mesh_tangents); lily_run_test(test_push_mesh_uvs); + + lily_run_test(test_push_node); } diff --git a/src/import/import.test.h b/src/import/import.test.h new file mode 100644 index 0000000..5aafdb3 --- /dev/null +++ b/src/import/import.test.h @@ -0,0 +1,18 @@ +#ifndef HONEY_IMPORT_TEST_H +#define HONEY_IMPORT_TEST_H + +void test_push_vector(); +void test_push_face(); +void test_push_aistring(); + +/* mesh tests */ +void test_push_mesh(); +void test_push_mesh_faces(); +void test_push_mesh_normals(); +void test_push_mesh_tangents(); +void test_push_mesh_uvs(); + +/* node tests */ +void test_push_node(); + +#endif diff --git a/src/import/import_mesh.test.c b/src/import/import_mesh.test.c new file mode 100644 index 0000000..07400fd --- /dev/null +++ b/src/import/import_mesh.test.c @@ -0,0 +1,570 @@ +#include <string.h> +#include <lua.h> +#include <lauxlib.h> +#include <honeysuckle.h> +#include "test/honey-test.h" +#include "import.test.h" + + +#include "import.c" + + +void test_push_vector() +{ + lua_State *L = luaL_newstate(); + struct aiVector3D v; + v.x = 1.5; + v.y = 2.0; + v.z = 3.6; + + push_vector(L, v); + + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + + lua_getfield(L, -1, "x"); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_float_equal(lua_tonumber(L, -1), 1.5, 0.1); + lua_pop(L, 1); + + lua_getfield(L, -1, "y"); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_float_equal(lua_tonumber(L, -1), 2.0, 0.1); + lua_pop(L, 1); + + lua_getfield(L, -1, "z"); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_float_equal(lua_tonumber(L, -1), 3.6, 0.1); + lua_pop(L, 1); + + lua_close(L); +} + + +void test_push_face() +{ + lua_State *L = luaL_newstate(); + struct aiFace face; + int indices[] = { 0, 1, 2, 3, 4, 5 }; + face.mIndices = indices; + face.mNumIndices = 6; + + push_face(L, face); + + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + int facetbl = lua_gettop(L); + lily_assert_int_equal(lua_objlen(L, facetbl), 6); + + /* the numbers should be one higher because of lua's 1-indexing */ + lua_rawgeti(L, facetbl, 1); + lily_assert_int_equal(lua_tointeger(L, -1), 1); + lua_rawgeti(L, facetbl, 2); + lily_assert_int_equal(lua_tointeger(L, -1), 2); + lua_rawgeti(L, facetbl, 3); + lily_assert_int_equal(lua_tointeger(L, -1), 3); + lua_rawgeti(L, facetbl, 4); + lily_assert_int_equal(lua_tointeger(L, -1), 4); + lua_rawgeti(L, facetbl, 5); + lily_assert_int_equal(lua_tointeger(L, -1), 5); + lua_rawgeti(L, facetbl, 6); + lily_assert_int_equal(lua_tointeger(L, -1), 6); + + lua_close(L); +} + + +void test_push_aistring() +{ + lua_State *L = luaL_newstate(); + struct aiString str; + strcpy(str.data, "hello, world!"); + + push_aistring(L, str); + + lily_assert_int_equal(lua_type(L, -1), LUA_TSTRING); + lily_assert_string_equal((char*) lua_tostring(L, -1), "hello, world!"); + + lua_close(L); +} + + +/* --===== mesh tests =====-- */ + + +void create_vertices(struct aiMesh *mesh); +void test_vertices(lua_State *L, int meshtbl); + +void create_faces(struct aiMesh *mesh); +void test_faces(lua_State *L, int meshtbl); + +void create_normals(struct aiMesh *mesh); +void test_normals(lua_State *L, int meshtbl); + +void create_tangents(struct aiMesh *mesh); +void test_tangents(lua_State *L, int meshtbl); + +void create_uvs(struct aiMesh *mesh); +void test_uvs(lua_State *L, int meshtbl); + +void test_nil(lua_State *L, int meshtbl, const char *field); + + +#define NUM_MESH_VERTICES 4 +#define NUM_MESH_FACES 2 + + +#define ALLOCATE_MEMORY() \ + struct aiVector3D vertices[NUM_MESH_VERTICES]; \ + mesh.mVertices = vertices; \ + struct aiVector3D normals[NUM_MESH_VERTICES]; \ + mesh.mNormals = normals; \ + struct aiVector3D tangents[NUM_MESH_VERTICES]; \ + struct aiVector3D bitangents[NUM_MESH_VERTICES]; \ + mesh.mTangents = tangents; \ + mesh.mBitangents = bitangents; \ + struct aiVector3D uvs[AI_MAX_NUMBER_OF_TEXTURECOORDS * NUM_MESH_VERTICES]; \ + for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) \ + mesh.mTextureCoords[i] = uvs + (i*NUM_MESH_VERTICES); \ + struct aiFace faces[NUM_MESH_FACES]; \ + unsigned int index_array[3*NUM_MESH_FACES]; \ + for (int i=0; i<NUM_MESH_FACES; i++) \ + faces[i].mIndices = index_array + (3*i); \ + mesh.mFaces = faces; + + + +void test_push_mesh() +{ + lua_State *L = luaL_newstate(); + struct aiMesh mesh; + mesh.mNumVertices = NUM_MESH_VERTICES; + mesh.mNumFaces = 0; + + /* allocate memory */ + ALLOCATE_MEMORY(); + mesh.mNormals = NULL; + mesh.mTangents = NULL; + mesh.mBitangents = NULL; + for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) + mesh.mTextureCoords[i] = NULL; + + /* setup mesh */ + create_vertices(&mesh); + + /* push */ + int top_before = lua_gettop(L); + push_mesh(L, mesh); + int meshtbl = lua_gettop(L); + + /* check output */ + lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); + lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ + test_vertices(L, meshtbl); + test_nil(L, meshtbl, "faces"); + + lua_close(L); +} + + +void test_push_mesh_faces() +{ + lua_State *L = luaL_newstate(); + struct aiMesh mesh; + mesh.mNumVertices = NUM_MESH_VERTICES; + mesh.mNumFaces = NUM_MESH_FACES; + + /* allocate memory */ + ALLOCATE_MEMORY(); + mesh.mNormals = NULL; + mesh.mTangents = NULL; + mesh.mBitangents = NULL; + for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) + mesh.mTextureCoords[i] = NULL; + + /* setup mesh */ + create_vertices(&mesh); + create_faces(&mesh); + + /* push */ + int top_before = lua_gettop(L); + push_mesh(L, mesh); + int meshtbl = lua_gettop(L); + + /* check output */ + lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); + lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ + test_vertices(L, meshtbl); + test_faces(L, meshtbl); + + lua_close(L); +} + + +void test_push_mesh_normals() +{ + lua_State *L = luaL_newstate(); + struct aiMesh mesh; + mesh.mNumVertices = NUM_MESH_VERTICES; + mesh.mNumFaces = NUM_MESH_FACES; + + /* allocate memory */ + ALLOCATE_MEMORY(); + mesh.mTangents = NULL; + mesh.mBitangents = NULL; + for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) + mesh.mTextureCoords[i] = NULL; + + /* setup mesh */ + create_vertices(&mesh); + create_faces(&mesh); + create_normals(&mesh); + + /* push */ + int top_before = lua_gettop(L); + push_mesh(L, mesh); + int meshtbl = lua_gettop(L); + + /* check output */ + lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); + lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ + test_vertices(L, meshtbl); + test_faces(L, meshtbl); + test_normals(L, meshtbl); + + lua_close(L); +} + + +void test_push_mesh_tangents() +{ + lua_State *L = luaL_newstate(); + struct aiMesh mesh; + mesh.mNumVertices = NUM_MESH_VERTICES; + mesh.mNumFaces = NUM_MESH_FACES; + + /* allocate memory */ + ALLOCATE_MEMORY(); + for (int i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) + mesh.mTextureCoords[i] = NULL; + + /* setup mesh */ + create_vertices(&mesh); + create_faces(&mesh); + create_normals(&mesh); + create_tangents(&mesh); + + /* push */ + int top_before = lua_gettop(L); + push_mesh(L, mesh); + int meshtbl = lua_gettop(L); + + /* check output */ + lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); + lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ + test_vertices(L, meshtbl); + test_faces(L, meshtbl); + test_normals(L, meshtbl); + test_tangents(L, meshtbl); + + lua_close(L); + +} + + +void test_push_mesh_uvs() +{ + lua_State *L = luaL_newstate(); + struct aiMesh mesh; + mesh.mNumVertices = NUM_MESH_VERTICES; + mesh.mNumFaces = NUM_MESH_FACES; + + /* allocate memory */ + ALLOCATE_MEMORY(); + + /* setup mesh */ + create_vertices(&mesh); + create_faces(&mesh); + create_normals(&mesh); + create_tangents(&mesh); + create_uvs(&mesh); + + /* push */ + int top_before = lua_gettop(L); + push_mesh(L, mesh); + int meshtbl = lua_gettop(L); + + /* check output */ + lily_assert_int_equal(lua_type(L, meshtbl), LUA_TTABLE); + lily_assert_int_equal(meshtbl - top_before, 1); /* make sure we cleaned up correctly */ + test_vertices(L, meshtbl); + test_faces(L, meshtbl); + test_normals(L, meshtbl); + test_tangents(L, meshtbl); + test_uvs(L, meshtbl); + + lua_close(L); + +} + + +void create_vertices(struct aiMesh *mesh) +{ + mesh->mVertices[0] = (struct aiVector3D) { 0, 0, 0 }; + mesh->mVertices[1] = (struct aiVector3D) { 0, 0, 1 }; + mesh->mVertices[2] = (struct aiVector3D) { 1, 0, 0 }; + mesh->mVertices[3] = (struct aiVector3D) { 1, 0, 1 }; +} + + +static int check_vector(lua_State *L, int meshtbl, const char *field, int index, + float x, float y, float z) +{ + lua_getfield(L, meshtbl, field); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "field '%s' is not a table!", field); + lua_rawgeti(L, -1, index); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "%s[%d] is not a table!", field, index); + + lua_getfield(L, -1, "x"); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d].x is not a number!", field, index); + float vx = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "y"); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d].y is not a number!", field, index); + float vy = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "z"); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d].z is not a number!", field, index); + float vz = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_pop(L, 2); + lily_assert( + (fabs(vx - x) < 0.1) && + (fabs(vy - y) < 0.1) && + (fabs(vz - z) < 0.1), + "%s[%d] is [%f, %f, %f], but expected [%f, %f, %f]!", + field, index, + vx, vy, vz, + x, y, z + ); +} + + +void test_vertices(lua_State *L, int meshtbl) +{ + check_vector(L, meshtbl, "vertices", 1, 0, 0, 0); + check_vector(L, meshtbl, "vertices", 2, 0, 0, 1); + check_vector(L, meshtbl, "vertices", 3, 1, 0, 0); + check_vector(L, meshtbl, "vertices", 4, 1, 0, 1); +} + + +static void setup_face(struct aiFace *face, int v0, int v1, int v2) +{ + face->mNumIndices = 3; + face->mIndices[0] = v0; + face->mIndices[1] = v1; + face->mIndices[2] = v2; +} + + +void create_faces(struct aiMesh *mesh) +{ + setup_face(mesh->mFaces + 0, 0, 1, 3); + setup_face(mesh->mFaces + 1, 0, 3, 2); +} + + +static int check_face(lua_State *L, int meshtbl, const char *field, int index, + int v0, int v1, int v2) +{ + lua_getfield(L, meshtbl, field); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "field '%s' is not a table!", field); + lua_rawgeti(L, -1, index); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "%s[%d] is not a table!", field, index); + + lua_rawgeti(L, -1, 1); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d][1] is not a number!", field, index); + int vv0 = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 2); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d][2] is not a number!", field, index); + int vv1 = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 3); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "%s[%d][3] is not a number!", field, index); + int vv2 = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_pop(L, 2); + lily_assert( + (v0 == vv0) && + (v1 == vv1) && + (v2 == vv2), + "%s[%d] is [%d, %d, %d], but expected [%d, %d, %d]!", + field, index, + vv0, vv1, vv2, + v0, v1, v2 + ); +} + + +void test_faces(lua_State *L, int meshtbl) +{ + check_face(L, meshtbl, "faces", 1, 1, 2, 4); + check_face(L, meshtbl, "faces", 2, 1, 4, 3); +} + + +void create_normals(struct aiMesh *mesh) +{ + /* these normals are deliberately not, uh, normalized + * in order to distinguish them for the purposes of testing. + * (this could also happen in real life -- assimp won't normalize + * normals taken straight from the object file) + */ + mesh->mNormals[0] = (struct aiVector3D) { 0, 0.1, 0 }; + mesh->mNormals[1] = (struct aiVector3D) { 0, 0.2, 0 }; + mesh->mNormals[2] = (struct aiVector3D) { 0, 0.4, 0 }; + mesh->mNormals[3] = (struct aiVector3D) { 0, 1.0, 0 }; +} + + +void test_normals(lua_State *L, int meshtbl) +{ + check_vector(L, meshtbl, "normals", 1, 0, 0.1, 0); + check_vector(L, meshtbl, "normals", 2, 0, 0.2, 0); + check_vector(L, meshtbl, "normals", 3, 0, 0.4, 0); + check_vector(L, meshtbl, "normals", 4, 0, 1.0, 0); +} + + +void create_tangents(struct aiMesh *mesh) +{ + /* these tangents are not normalized -- see note in create_normals */ + mesh->mTangents[0] = (struct aiVector3D) { 0.1, 0, 0 }; + mesh->mTangents[1] = (struct aiVector3D) { 0.2, 0, 0 }; + mesh->mTangents[2] = (struct aiVector3D) { 0.4, 0, 0 }; + mesh->mTangents[3] = (struct aiVector3D) { 1.0, 0, 0 }; + + mesh->mBitangents[0] = (struct aiVector3D) { 0, 0, 0.1 }; + mesh->mBitangents[1] = (struct aiVector3D) { 0, 0, 0.2 }; + mesh->mBitangents[2] = (struct aiVector3D) { 0, 0, 0.4 }; + mesh->mBitangents[3] = (struct aiVector3D) { 0, 0, 1.0 }; +} + + +void test_tangents(lua_State *L, int meshtbl) +{ + check_vector(L, meshtbl, "tangents", 1, 0.1, 0, 0); + check_vector(L, meshtbl, "tangents", 2, 0.2, 0, 0); + check_vector(L, meshtbl, "tangents", 3, 0.4, 0, 0); + check_vector(L, meshtbl, "tangents", 4, 1.0, 0, 0); + + check_vector(L, meshtbl, "bitangents", 1, 0, 0, 0.1); + check_vector(L, meshtbl, "bitangents", 2, 0, 0, 0.2); + check_vector(L, meshtbl, "bitangents", 3, 0, 0, 0.4); + check_vector(L, meshtbl, "bitangents", 4, 0, 0, 1.0); +} + + +void create_uvs(struct aiMesh *mesh) +{ + mesh->mNumUVComponents[0] = 2; + mesh->mTextureCoords[0][0] = (struct aiVector3D) { 0, 0, 0 }; + mesh->mTextureCoords[0][1] = (struct aiVector3D) { 0, 1, 0 }; + mesh->mTextureCoords[0][2] = (struct aiVector3D) { 1, 0, 0 }; + mesh->mTextureCoords[0][3] = (struct aiVector3D) { 1, 1, 0 }; + + mesh->mNumUVComponents[1] = 1; + mesh->mTextureCoords[1][0] = (struct aiVector3D) { 0.0, 0, 0 }; + mesh->mTextureCoords[1][1] = (struct aiVector3D) { 0.2, 0, 0 }; + mesh->mTextureCoords[1][2] = (struct aiVector3D) { 0.4, 0, 0 }; + mesh->mTextureCoords[1][3] = (struct aiVector3D) { 0.8, 0, 0 }; + + for (int i=2; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) + mesh->mTextureCoords[i] = NULL; +} + + +static int check_uv(lua_State *L, int meshtbl, int channel, int index, + float x, float y, float z) +{ + lua_getfield(L, meshtbl, "uvs"); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "field 'uvs' is not a table!"); + lua_rawgeti(L, -1, channel); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "uvs[%d] is not a table!", channel); + lua_rawgeti(L, -1, index); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "uvs[%d][%d] is not a table!", channel, index); + + lua_getfield(L, -1, "x"); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "uvs[%d][%d].x is not a number!", channel, index); + float vx = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "y"); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "uvs[%d][%d].y is not a number!", channel, index); + float vy = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "z"); + lily_assert(lua_type(L, -1) == LUA_TNUMBER, "uvs[%d][%d].z is not a number!", channel, index); + float vz = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_pop(L, 3); + lily_assert( + (fabs(vx - x) < 0.1) && + (fabs(vy - y) < 0.1) && + (fabs(vz - z) < 0.1), + "uvs[%d][%d] is [%f, %f, %f], but expected [%f, %f, %f]!", + channel, index, + vx, vy, vz, + x, y, z + ); +} + + +void test_uvs(lua_State *L, int meshtbl) +{ + lua_getfield(L, meshtbl, "numUvComponents"); + lily_assert(lua_type(L, -1) == LUA_TTABLE, "field 'numUvComponents' is not a table!"); + lua_rawgeti(L, -1, 1); + lily_assert_int_equal(lua_tointeger(L, -1), 2); + lua_pop(L, 1); + lua_rawgeti(L, -1, 2); + lily_assert_int_equal(lua_tointeger(L, -1), 1); + lua_pop(L, 1); + + check_uv(L, meshtbl, 1, 1, 0, 0, 0); + check_uv(L, meshtbl, 1, 2, 0, 1, 0); + check_uv(L, meshtbl, 1, 3, 1, 0, 0); + check_uv(L, meshtbl, 1, 4, 1, 1, 0); + + check_uv(L, meshtbl, 2, 1, 0.0, 0, 0); + check_uv(L, meshtbl, 2, 2, 0.2, 0, 0); + check_uv(L, meshtbl, 2, 3, 0.4, 0, 0); + check_uv(L, meshtbl, 2, 4, 0.8, 0, 0); + + lua_getfield(L, meshtbl, "uvs"); + int uvtbl = lua_gettop(L); + for (int i=2; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { + lua_rawgeti(L, uvtbl, i+1); + lily_assert(lua_type(L, -1) == LUA_TNIL, "uv channel %d is non-nil!", i+1); + lua_pop(L, 1); + } + lua_pop(L, 1); +} + +void test_nil(lua_State *L, int meshtbl, const char *field) +{ + lua_getfield(L, meshtbl, field); + lily_assert(lua_type(L, -1) == LUA_TNIL, "field '%s' is not nil!"); + lua_pop(L, 1); +} + + +/* --===== end mesh tests =====-- */ diff --git a/src/import/import_node.test.c b/src/import/import_node.test.c new file mode 100644 index 0000000..4d5c9ef --- /dev/null +++ b/src/import/import_node.test.c @@ -0,0 +1,116 @@ +#include <assimp/scene.h> +#include <lua.h> +#include <lauxlib.h> +#include <honeysuckle.h> +#include "test/lily-test.h" +#include "import.test.h" + + +#include "import.c" + + +#define MESH_COUNT 13 +void test_push_node() +{ + lua_State *L = luaL_newstate(); + + int meshes[MESH_COUNT]; + for (int i=0; i<MESH_COUNT; i++) + meshes[i] = i; + + /* first layer node */ + struct aiNode root; + root.mParent = NULL; + root.mMeshes = meshes; + root.mNumMeshes = 3; + + /* second layer nodes */ + struct aiNode nodeA, nodeB; + struct aiNode *root_children[] = { &nodeA, &nodeB }; + root.mChildren = root_children; + root.mNumChildren = 2; + + nodeA.mMeshes = meshes + 3; + nodeA.mNumMeshes = 2; + nodeA.mChildren = NULL; + + nodeB.mMeshes = meshes + 5; + nodeB.mNumMeshes = 2; + nodeB.mChildren = NULL; + + /* push */ + int top = lua_gettop(L); + push_node(L, &root); + + /* check */ + lily_assert_int_equal(top+1, lua_gettop(L)); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + + int nodetbl = lua_gettop(L); + + /* check meshes */ + lua_getfield(L, nodetbl, "meshes"); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + + lua_rawgeti(L, -1, 1); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 1); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 2); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 2); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 3); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 3); + lua_pop(L, 1); + + /* check children */ + lua_getfield(L, nodetbl, "children"); + int childrentbl = lua_gettop(L); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + + lua_rawgeti(L, childrentbl, 1); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + int atbl = lua_gettop(L); + lua_getfield(L, atbl, "meshes"); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + + lua_rawgeti(L, -1, 1); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 4); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 2); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 5); + lua_pop(L, 2); + + lua_getfield(L, atbl, "children"); + lily_assert_int_equal(lua_type(L, -1), LUA_TNIL); + lua_pop(L, 2); + + lua_rawgeti(L, childrentbl, 2); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + int btbl = lua_gettop(L); + lua_getfield(L, btbl, "meshes"); + lily_assert_int_equal(lua_type(L, -1), LUA_TTABLE); + + lua_rawgeti(L, -1, 1); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 6); + lua_pop(L, 1); + + lua_rawgeti(L, -1, 2); + lily_assert_int_equal(lua_type(L, -1), LUA_TNUMBER); + lily_assert_int_equal(lua_tointeger(L, -1), 7); + lua_pop(L, 2); + + lua_getfield(L, btbl, "children"); + lily_assert_int_equal(lua_type(L, -1), LUA_TNIL); + lua_pop(L, 2); + + lua_close(L); +} |