diff options
Diffstat (limited to 'src/import')
| -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); +}  | 
