proper scene graph
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Wed, 2 Nov 2016 05:20:18 +0000 (07:20 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Wed, 2 Nov 2016 05:20:18 +0000 (07:20 +0200)
src/objmesh.cc
src/sceneload.cc
src/snode.cc
src/snode.h

index 60fa7f9..3076e67 100644 (file)
@@ -27,6 +27,7 @@ void ObjMesh::draw() const
        mesh->draw();
 
        if(node) {
+               glMatrixMode(GL_MODELVIEW);
                glPopMatrix();
        }
 }
index 865a4c8..1ae167b 100644 (file)
 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; i<aiscn->mNumMeshes; 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; i<aiscn->mRootNode->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; i<sizeof textypes / sizeof *textypes; i++) {
-               aiString aipath;
-
-               if(aiGetMaterialTexture(aimat, textypes[i].aitype, 0, &aipath) == 0) {
-                       char *tmp, *fname = aipath.data;
-
-                       if((tmp = strrchr(fname, '/'))) {
-                               fname = tmp + 1;
-                       }
-                       if((tmp = strrchr(fname, '\\'))) {
-                               fname = tmp + 1;
-                       }
-
-                       if(*fname) {
-                               mat->tex[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; i<ainode->mNumMeshes; 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; i<lvl; i++) {
+               fputs("  ", stdout);
+       }
+       printf("%s[%s] p(%g %g %g) rq(%g %+gi %+gj %+gk) s(%g %g %g)\n", type, node->get_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; i<nchld; i++) {
+               print_nodes(node->get_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);
+}
index fac6c65..101fe62 100644 (file)
@@ -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);
 }
index 21cf16d..11651c6 100644 (file)
@@ -22,6 +22,8 @@ private:
        Mat4 inv_xform;
 
 public:
+       Mat4 dbg_xform;
+
        SceneNode();
        explicit SceneNode(Object *obj);
        ~SceneNode();