#include <stdio.h>
+#include <assert.h>
#include <vector>
#include <map>
#include <gmath/gmath.h>
#include <assimp/quaternion.h>
#include "scene.h"
#include "objmesh.h"
+#include "datamap.h"
-static bool load_material(Material *mat, const aiMaterial *aimat);
-static SceneNode *load_node(const aiScene *aiscn, unsigned int flags, const aiNode *ainode);
-static Mesh *load_mesh(const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh);
+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 const char *mprop_semantic(int x);
+static int count_textures(const aiMaterial *aimat);*/
+static int assimp_textype(aiTextureType type);
+static const char *assimp_textypestr(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);
*/
aiProcess_JoinIdenticalVertices |
aiProcess_Triangulate |
aiProcess_SortByPType |
- aiProcess_TransformUVCoords | aiProcess_PreTransformVertices;
+ aiProcess_GenUVCoords |
+ //aiProcess_PreTransformVertices |
+ aiProcess_TransformUVCoords;
if(flags & SCNLOAD_FLIPTEX) {
ppflags |= aiProcess_FlipUVs;
}
+ printf("Loading scene file: %s\n", fname);
+
const aiScene *aiscn = aiImportFile(fname, ppflags);
if(!aiscn) {
fprintf(stderr, "failed to load scene file: %s\n", fname);
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();
- }*/
+ }
// load all meshes
for(unsigned int i=0; i<aiscn->mNumMeshes; i++) {
switch(aimesh->mPrimitiveTypes) {
case aiPrimitiveType_TRIANGLE:
- if((mesh = load_mesh(aiscn, flags, aimesh))) {
+ if((mesh = load_mesh(this, aiscn, flags, aimesh))) {
mesh_by_aimesh[aimesh] = mesh;
meshes.push_back(mesh);
}
}
}
- SceneNode *root = new SceneNode;
+ if(!nodes) {
+ nodes = new SceneNode;
+ nodes->scene = this;
+ 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(aiscn, flags, aiscn->mRootNode->mChildren[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);
return true;
}
-static bool load_material(Material *mat, const aiMaterial *aimat)
+static bool load_material(Scene *scn, Material *mat, const aiMaterial *aimat)
{
+ aiString name;
aiColor4D aicol;
float shin, shin_str;
+ if(aiGetMaterialString(aimat, AI_MATKEY_NAME, &name) == 0) {
+ mat->name = name.data;
+ } else {
+ mat->name = "unknown";
+ }
+ //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]);
}
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; i<sizeof textypes / sizeof *textypes; i++) {
- aiString aipath;
+ const int num_tex_types = aiTextureType_UNKNOWN + 1;
+ for(int i=0; i<num_tex_types; i++) {
+ aiTextureType aitype = (aiTextureType)i;
+ int count = aiGetMaterialTextureCount(aimat, aitype);
- if(aiGetMaterialTexture(aimat, textypes[i].aitype, 0, &aipath) == 0) {
- char *tmp, *fname = aipath.data;
-
- if((tmp = strrchr(fname, '/'))) {
- fname = tmp + 1;
+ for(int j=0; j<count; j++) {
+ aiString aipath;
+ if(aiGetMaterialTexture(aimat, aitype, j, &aipath) != 0) {
+ continue;
}
- if((tmp = strrchr(fname, '\\'))) {
- fname = tmp + 1;
+
+ char *fname;
+ int nsize = datamap_path_size(aipath.data);
+ if(nsize) {
+ fname = new char[nsize];
+ datamap_lookup(aipath.data, fname, nsize);
+ } else {
+ fname = new char[strlen(aipath.data) + 1];
+ char *dptr = fname;
+ char *sptr = aipath.data;
+ do {
+ *dptr++ = *sptr == '\\' ? '/' : *sptr;
+ } while(*sptr++);
}
- if(*fname) {
- mat->tex[textypes[i].type] = texset.get(fname);
+ int textype = assimp_textype(aitype);
+ printf("loading %s texture: %s\n", assimp_textypestr(aitype), fname);
+
+ Texture *tex = scn->texset->get_texture(fname, TEX_2D);
+ assert(tex);
+ mat->textures.push_back(tex);
+
+ if(textype != MTL_TEX_UNKNOWN && !mat->stdtex[textype]) {
+ mat->stdtex[textype] = tex;
}
}
}
- */
return true;
}
-static SceneNode *load_node(const aiScene *aiscn, unsigned int flags, const aiNode *ainode)
+static SceneNode *load_node(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiNode *ainode)
{
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) {
ObjMesh *obj = new ObjMesh;
+ obj->set_name(mesh->get_name());
obj->mesh = mesh;
// also grab the material of this mesh
- load_material(&obj->mtl, aiscn->mMaterials[aimesh->mMaterialIndex]);
+ load_material(scn, &obj->mtl, aiscn->mMaterials[aimesh->mMaterialIndex]);
node->add_object(obj);
+ scn->objects.push_back(obj);
}
}
/* recurse to all children */
for(unsigned int i=0; i<ainode->mNumChildren; i++) {
- SceneNode *child = load_node(aiscn, flags, ainode->mChildren[i]);
+ SceneNode *child = load_node(scn, aiscn, flags, ainode->mChildren[i]);
if(child) {
node->add_child(child);
}
return node;
}
-static Mesh *load_mesh(const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh)
+static Mesh *load_mesh(Scene *scn, const aiScene *aiscn, unsigned int flags, const aiMesh *aimesh)
{
Mesh *mesh = new Mesh;
+ mesh->set_name(aimesh->mName.data);
int num_verts = aimesh->mNumVertices;
int num_faces = aimesh->mNumFaces;
if(aimesh->mTextureCoords[0]) {
mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 3, num_verts, (float*)aimesh->mTextureCoords[0]);
}
+ if(aimesh->mTextureCoords[1]) {
+ mesh->set_attrib_data(MESH_ATTR_TEXCOORD2, 3, num_verts, (float*)aimesh->mTextureCoords[1]);
+ }
if(flags & SCNLOAD_FLIPYZ) {
Vec3 *vptr = (Vec3*)mesh->get_attrib_data(MESH_ATTR_VERTEX);
iptr[2] = aimesh->mFaces[i].mIndices[flags & SCNLOAD_FLIPYZ ? 1 : 2];
iptr += 3;
}
-
return mesh;
}
-#if 0
-static Vec3 assimp_vector(const aiVector3D &v)
+static int assimp_textype(aiTextureType type)
{
- return Vec3(v[0], v[1], v[2]);
+ switch(type) {
+ case aiTextureType_DIFFUSE:
+ return MTL_TEX_DIFFUSE;
+ case aiTextureType_SPECULAR:
+ return MTL_TEX_SPECULAR;
+ case aiTextureType_NORMALS:
+ return MTL_TEX_NORMALMAP;
+ case aiTextureType_LIGHTMAP:
+ case aiTextureType_EMISSIVE:
+ return MTL_TEX_LIGHTMAP;
+ case aiTextureType_REFLECTION:
+ return MTL_TEX_ENVMAP;
+ default:
+ break;
+ }
+ return MTL_TEX_UNKNOWN;
}
-static Quat assimp_quat(const aiQuaternion &q)
+static const char *assimp_textypestr(aiTextureType type)
{
- return Quat(q.x, q.y, q.z, q.w);
+ switch(type) {
+ case aiTextureType_DIFFUSE:
+ return "diffuse";
+ case aiTextureType_SPECULAR:
+ return "specular";
+ case aiTextureType_NORMALS:
+ return "normalmap";
+ case aiTextureType_LIGHTMAP:
+ case aiTextureType_EMISSIVE:
+ return "lightmap";
+ case aiTextureType_REFLECTION:
+ return "envmap";
+ default:
+ break;
+ }
+ return "unknown";
}
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; i++) {
- putchar(' ');
- if(lvlopen[i]) {
- putchar(i >= lvl - 1 ? '+' : '|');
- } else {
- putchar(i >= lvl - 1 ? '+' : ' ');
- }
- }
- printf("- \"%s\"\n", node->mName.data);
-
- lvlopen[lvl] = 1;
-
- lvl++;
- for(unsigned int i=0; i<node->mNumChildren; i++) {
- if(i == node->mNumChildren - 1) {
- lvlopen[lvl - 1] = 0;
- }
- print_hierarchy(node->mChildren[i]);
- }
- lvl--;
+ return transpose(m);
}
-#endif /* 0 */