X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fsceneload.cc;fp=src%2Fsceneload.cc;h=b2b00ebedeaddb7a919b28fcfea51988580c381f;hp=0000000000000000000000000000000000000000;hb=b7c92831285013b2a0783bccaf3d900545ebb5ba;hpb=a58455a92c7ecab980cbe1b7e282aeb6bfe7e889 diff --git a/src/sceneload.cc b/src/sceneload.cc new file mode 100644 index 0000000..b2b00eb --- /dev/null +++ b/src/sceneload.cc @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scene.h" +#include "objmesh.h" + +static bool load_material(Material *mat, const aiMaterial *aimat); +static SceneNode *load_node(const aiScene *aiscn, const aiNode *ainode); +static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh); + +/*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); +*/ + +static std::map node_by_name; +static std::map mesh_by_aimesh; + +bool Scene::load(const char *fname) +{ + unsigned int ppflags = aiProcess_CalcTangentSpace | + aiProcess_GenNormals | + aiProcess_JoinIdenticalVertices | + aiProcess_Triangulate | + aiProcess_SortByPType | + aiProcess_TransformUVCoords; + + const aiScene *aiscn = aiImportFile(fname, ppflags); + if(!aiscn) { + fprintf(stderr, "failed to load scene file: %s\n", fname); + return false; + } + + /* + 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_scaling = root_matrix.get_scaling(); + }*/ + + // load all meshes + for(unsigned int i=0; imNumMeshes; i++) { + aiMesh *aimesh = aiscn->mMeshes[i]; + Mesh *mesh; + + switch(aimesh->mPrimitiveTypes) { + case aiPrimitiveType_TRIANGLE: + if((mesh = load_mesh(aiscn, aimesh))) { + mesh_by_aimesh[aimesh] = mesh; + meshes.push_back(mesh); + } + break; + + default: + fprintf(stderr, "unsupported primitive type: %u\n", aimesh->mPrimitiveTypes); + break; + } + } + + SceneNode *root = new SceneNode; + + // load all the nodes recursively + for(unsigned int i=0; imRootNode->mNumChildren; i++) { + SceneNode *node = load_node(aiscn, aiscn->mRootNode->mChildren[i]); + if(node) { + root->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()); + return true; +} + +static bool load_material(Material *mat, const aiMaterial *aimat) +{ + aiColor4D aicol; + float shin, shin_str; + + if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_DIFFUSE, &aicol) == 0) { + mat->diffuse = Vec3(aicol[0], aicol[1], aicol[2]); + } + if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_SPECULAR, &aicol) == 0) { + mat->specular = Vec3(aicol[0], aicol[1], aicol[2]); + } + + unsigned int count = 1; + if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS_STRENGTH, &shin_str, &count) != 0) { + shin_str = 1.0; + } + if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS, &shin, &count) == 0) { + // XXX can't remember how I came up with this... + mat->shininess = shin * shin_str * 0.0001 * 128.0; + } + + /* + // load textures + struct { int type; aiTextureType aitype; } textypes[] = { + {TEX_DIFFUSE, aiTextureType_DIFFUSE}, + {TEX_NORMAL, aiTextureType_NORMALS}, + {TEX_SPECULAR, aiTextureType_SPECULAR} + }; + + for(size_t i=0; itex[textypes[i].type] = texset.get(fname); + } + } + } + */ + + return true; +} + +static SceneNode *load_node(const aiScene *aiscn, const aiNode *ainode) +{ + SceneNode *node = new SceneNode; + node->set_name(ainode->mName.data); + + for(unsigned int i=0; imNumMeshes; i++) { + aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[0]]; + + Mesh *mesh = mesh_by_aimesh[aimesh]; + if(mesh) { + ObjMesh *obj = new ObjMesh; + obj->mesh = mesh; + // also grab the material of this mesh + load_material(&obj->mtl, aiscn->mMaterials[aimesh->mMaterialIndex]); + + node->add_object(obj); + } + } + + /* recurse to all children */ + for(unsigned int i=0; imNumChildren; i++) { + SceneNode *child = load_node(aiscn, ainode->mChildren[i]); + if(child) { + node->add_child(child); + } + } + + node_by_name[node->get_name()] = node; + return node; +} + +static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh) +{ + Mesh *mesh = new Mesh; + + int num_verts = aimesh->mNumVertices; + int num_faces = aimesh->mNumFaces; + + mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, (float*)aimesh->mVertices); + + if(aimesh->mNormals) { + mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, (float*)aimesh->mNormals); + } + if(aimesh->mTangents) { + mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, (float*)aimesh->mTangents); + } + if(aimesh->mTextureCoords[0]) { + mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 3, num_verts, (float*)aimesh->mTextureCoords[0]); + } + + unsigned int *iptr = mesh->set_index_data(num_faces * 3); + for(int i=0; imFaces[i].mIndices[j]; + } + } + + return mesh; +} + +#if 0 +static Vec3 assimp_vector(const aiVector3D &v) +{ + return Vec3(v[0], v[1], v[2]); +} + +static Quat assimp_quat(const aiQuaternion &q) +{ + return Quat(q.x, q.y, q.z, q.w); +} + +static Mat4 assimp_matrix(const aiMatrix4x4 &aim) +{ + Mat4 m; + memcpy(m[0], &aim, 16 * sizeof(float)); + m.transpose(); + return m; +} + +/* convert an assimp keyframe time (ticks) into milliseconds */ +static long assimp_time(const aiAnimation *anim, double aitime) +{ + double sec; + if(anim->mTicksPerSecond < 1e-6) { + // assume time is in frames? + sec = aitime / 30.0; + } else { + sec = aitime / anim->mTicksPerSecond; + } + return (long)(sec * 1000.0); +} + +static void print_hierarchy(const aiNode *node) +{ + static int lvl; + static int lvlopen[256]; + + for(int i=0; i= lvl - 1 ? '+' : '|'); + } else { + putchar(i >= lvl - 1 ? '+' : ' '); + } + } + printf("- \"%s\"\n", node->mName.data); + + lvlopen[lvl] = 1; + + lvl++; + for(unsigned int i=0; imNumChildren; i++) { + if(i == node->mNumChildren - 1) { + lvlopen[lvl - 1] = 0; + } + print_hierarchy(node->mChildren[i]); + } + lvl--; +} +#endif /* 0 */