From 873255c40ab793b8c569eca3728d918339686000 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 2 Nov 2016 07:20:18 +0200 Subject: [PATCH] proper scene graph --- src/objmesh.cc | 1 + src/sceneload.cc | 110 ++++++++++++++++++++++++++++++++++-------------------- src/snode.cc | 6 ++- src/snode.h | 2 + 4 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/objmesh.cc b/src/objmesh.cc index 60fa7f9..3076e67 100644 --- a/src/objmesh.cc +++ b/src/objmesh.cc @@ -27,6 +27,7 @@ void ObjMesh::draw() const mesh->draw(); if(node) { + glMatrixMode(GL_MODELVIEW); glPopMatrix(); } } diff --git a/src/sceneload.cc b/src/sceneload.cc index 865a4c8..1ae167b 100644 --- a/src/sceneload.cc +++ b/src/sceneload.cc @@ -18,13 +18,15 @@ static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat); static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiNode *ainode); static Mesh *load_mesh(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh); +static void print_nodes(SceneNode *node, int lvl = 0); /*static const char *mprop_semantic(int x); static int count_textures(const aiMaterial *aimat);*/ static int assimp_textype(aiTextureType type); +static Mat4 assimp_matrix(const aiMatrix4x4 &aim); + /*static Vec3 assimp_vector(const aiVector3D &v); static Quat assimp_quat(const aiQuaternion &q); -static Mat4 assimp_matrix(const aiMatrix4x4 &aim); static long assimp_time(const aiAnimation *anim, double aitime); static void print_hierarchy(const aiNode *node); */ @@ -39,7 +41,8 @@ bool Scene::load(const char *fname, unsigned int flags) aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType | - aiProcess_TransformUVCoords | aiProcess_PreTransformVertices; + aiProcess_GenUVCoords | + aiProcess_TransformUVCoords; if(flags & SCNLOAD_FLIPTEX) { ppflags |= aiProcess_FlipUVs; @@ -51,16 +54,21 @@ bool Scene::load(const char *fname, unsigned int flags) return false; } - /* + // assimp adds its own root node, which might have transformations Vec3 root_pos, root_scaling(1.0, 1.0, 1.0); Quat root_rot; if(aiscn->mRootNode) { Mat4 root_matrix = assimp_matrix(aiscn->mRootNode->mTransformation); root_pos = root_matrix.get_translation(); - root_rot = root_matrix.get_rotation_quat(); + root_rot = root_matrix.get_rotation(); root_scaling = root_matrix.get_scaling(); - }*/ + + printf("assimp root node: %s\n", aiscn->mRootNode->mName.data); + printf(" pos: %f %f %f\n", root_pos.x, root_pos.y, root_pos.z); + printf(" rot: %f %+f %+f %+f\n", root_rot.w, root_rot.x, root_rot.y, root_rot.z); + printf(" scaling: %f %f %f\n", root_scaling.x, root_scaling.y, root_scaling.z); + } // load all meshes for(unsigned int i=0; imNumMeshes; i++) { @@ -81,32 +89,29 @@ bool Scene::load(const char *fname, unsigned int flags) } } - SceneNode *root = new SceneNode; + if(!nodes) { + nodes = new SceneNode; + nodes->set_name("root"); + nodes->set_position(root_pos); + nodes->set_rotation(root_rot); + nodes->set_scaling(root_scaling); + } // load all the nodes recursively for(unsigned int i=0; imRootNode->mNumChildren; i++) { SceneNode *node = load_node(this, aiscn, flags, aiscn->mRootNode->mChildren[i]); if(node) { - root->add_child(node); + nodes->add_child(node); } } - int nnodes = root->get_num_children(); - if(nnodes <= 0) { - delete root; - } else if(nnodes == 1) { - nodes = root->get_child(0); - root->remove_child(nodes); - delete root; - } else { - nodes = root; - } - node_by_name.clear(); mesh_by_aimesh.clear(); aiReleaseImport(aiscn); printf("loaded scene file: %s, %d meshes\n", fname, (int)meshes.size()); + nodes->update(0); + print_nodes(nodes); return true; } @@ -121,7 +126,7 @@ static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat) } else { mat->name = "unknown"; } - printf("load_material: %s\n", mat->name.c_str()); + //printf("load_material: %s\n", mat->name.c_str()); if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_DIFFUSE, &aicol) == 0) { mat->diffuse = Vec3(aicol[0], aicol[1], aicol[2]); @@ -183,27 +188,6 @@ static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat) } } - /* - for(size_t i=0; itex[textypes[i].type] = texset.get(fname); - } - } - } - */ - return true; } @@ -212,8 +196,20 @@ static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags SceneNode *node = new SceneNode; node->set_name(ainode->mName.data); + // transformation + Mat4 matrix = assimp_matrix(ainode->mTransformation); + Vec3 pos = matrix.get_translation(); + Quat rot = matrix.get_rotation(); + Vec3 scale = matrix.get_scaling(); + + node->set_position(pos); + node->set_rotation(rot); + node->set_scaling(scale); + node->dbg_xform = matrix; + + // meshes for(unsigned int i=0; imNumMeshes; i++) { - aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[0]]; + aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[i]]; Mesh *mesh = mesh_by_aimesh[aimesh]; if(mesh) { @@ -292,6 +288,31 @@ static Mesh *load_mesh(Scene *scn, const aiScene *aiscn, unsigned int flags, con return mesh; } +static void print_nodes(SceneNode *node, int lvl) +{ + Vec3 pos = node->get_node_position(); + Quat rot = node->get_node_rotation(); + Vec3 scale = node->get_node_scaling(); + + const char *type = node->get_num_objects() > 0 ? "mesh node" : "null node"; + + for(int i=0; iget_name(), + pos.x, pos.y, pos.z, rot.w, rot.x, rot.y, rot.z, scale.x, scale.y, scale.z); + + if(node->get_num_objects()) { + Mat4 xform = node->get_matrix(); + xform.print(stdout); + } + + int nchld = node->get_num_children(); + for(int i=0; iget_child(i), lvl + 1); + } +} + static int assimp_textype(aiTextureType type) { switch(type) { @@ -310,3 +331,10 @@ static int assimp_textype(aiTextureType type) } return MTL_TEX_UNKNOWN; } + +static Mat4 assimp_matrix(const aiMatrix4x4 &aim) +{ + Mat4 m; + memcpy(m[0], &aim, 16 * sizeof(float)); + return transpose(m); +} diff --git a/src/snode.cc b/src/snode.cc index fac6c65..101fe62 100644 --- a/src/snode.cc +++ b/src/snode.cc @@ -37,6 +37,8 @@ const char *SceneNode::get_name() const void SceneNode::add_child(SceneNode *node) { + if(!node) return; + if(node->parent) { if(node->parent == this) { return; @@ -50,6 +52,8 @@ void SceneNode::add_child(SceneNode *node) bool SceneNode::remove_child(SceneNode *node) { + if(!node) return false; + auto it = std::find(children.begin(), children.end(), node); if(it != children.end()) { assert(node->parent == this); @@ -177,7 +181,7 @@ void SceneNode::update_node(float dt) xform.pre_scale(scale); if(parent) { - xform = parent->xform * xform; + xform = xform * parent->xform; } inv_xform = inverse(xform); } diff --git a/src/snode.h b/src/snode.h index 21cf16d..11651c6 100644 --- a/src/snode.h +++ b/src/snode.h @@ -22,6 +22,8 @@ private: Mat4 inv_xform; public: + Mat4 dbg_xform; + SceneNode(); explicit SceneNode(Object *obj); ~SceneNode(); -- 1.7.10.4