nuclear@29: #include nuclear@29: #include nuclear@29: #include "goat3d.h" nuclear@29: #include "assimp/cimport.h" nuclear@29: #include "assimp/postprocess.h" nuclear@29: #include "assimp/scene.h" nuclear@29: nuclear@29: int convert(const char *infname, const char *outfname); nuclear@29: void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl); nuclear@29: void process_node(struct goat3d *goat, struct goat3d_node *parent, struct aiNode *ainode); nuclear@29: nuclear@29: int main(int argc, char **argv) nuclear@29: { nuclear@29: int i, num_done = 0; nuclear@29: nuclear@29: for(i=1; i %s\n", argv[i], outfname); nuclear@29: convert(argv[i], outfname); nuclear@29: num_done++; nuclear@29: } nuclear@29: } nuclear@29: nuclear@29: if(!num_done) { nuclear@29: fprintf(stderr, "you must specify a 3D scene file to convert\n"); nuclear@29: return 1; nuclear@29: } nuclear@29: nuclear@29: return 0; nuclear@29: } nuclear@29: nuclear@29: #define PPFLAGS \ nuclear@29: (aiProcess_Triangulate | \ nuclear@29: aiProcess_GenNormals | \ nuclear@29: aiProcess_JoinIdenticalVertices | \ nuclear@29: aiProcess_CalcTangentSpace | \ nuclear@29: aiProcess_LimitBoneWeights | \ nuclear@29: aiProcess_GenUVCoords) nuclear@29: nuclear@29: int convert(const char *infname, const char *outfname) nuclear@29: { nuclear@29: int i; nuclear@29: const struct aiScene *aiscn; nuclear@29: struct goat3d *goat; nuclear@29: nuclear@29: if(!(aiscn = aiImportFile(infname, PPFLAGS))) { nuclear@29: fprintf(stderr, "failed to import %s\n", infname); nuclear@29: return -1; nuclear@29: } nuclear@29: nuclear@29: goat = goat3d_create(); nuclear@29: nuclear@29: for(i=0; i<(int)aiscn->mNumMaterials; i++) { nuclear@29: struct aiMaterial *aimat = aiscn->mMaterials[i]; nuclear@29: struct goat3d_material *mat = goat3d_create_mtl(); nuclear@29: nuclear@29: process_material(mat, aimat); nuclear@29: goat3d_add_mtl(goat, mat); nuclear@29: } nuclear@29: nuclear@29: for(i=0; i<(int)aiscn->mRootNode->mNumChildren; i++) { nuclear@29: process_node(goat, 0, aiscn->mRootNode->mChildren[i]); nuclear@29: } nuclear@29: nuclear@29: goat3d_save(goat, outfname); nuclear@29: goat3d_free(goat); nuclear@29: aiReleaseImport(aiscn); nuclear@29: return 0; nuclear@29: } nuclear@29: nuclear@29: void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl) nuclear@29: { nuclear@29: struct aiString aistr; nuclear@29: struct aiColor4D color; nuclear@29: float val; nuclear@29: nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_NAME, &aistr) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_name(mtl, aistr.data); nuclear@29: } nuclear@29: nuclear@29: if(aiGetMaterialColor(aimtl, AI_MATKEY_COLOR_DIFFUSE, &color) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, color.r, color.g, color.b); nuclear@29: } nuclear@29: nuclear@29: if(aiGetMaterialColor(aimtl, AI_MATKEY_COLOR_SPECULAR, &color) == aiReturn_SUCCESS) { nuclear@29: float sstr = 1.0; nuclear@29: aiGetMaterialFloatArray(aimtl, AI_MATKEY_SHININESS_STRENGTH, &sstr, 0); nuclear@29: goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_SPECULAR, color.r * sstr, color.g * sstr, color.b * sstr); nuclear@29: } nuclear@29: nuclear@29: if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_BUMPSCALING, &val, 0) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_BUMP, val, val, val); nuclear@29: } nuclear@29: nuclear@29: if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_REFLECTIVITY, &val, 0) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_REFLECTION, val); nuclear@29: } nuclear@29: nuclear@29: if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_OPACITY, &val, 0) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, 1.0 - val); nuclear@29: } nuclear@29: nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_DIFFUSE(0), &aistr) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_DIFFUSE, aistr.data); nuclear@29: } nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_SPECULAR(0), &aistr) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SPECULAR, aistr.data); nuclear@29: } nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_SHININESS(0), &aistr) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SHININESS, aistr.data); nuclear@29: } nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_NORMALS(0), &aistr) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_NORMAL, aistr.data); nuclear@29: } nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_REFLECTION(0), &aistr) == aiReturn_SUCCESS) { nuclear@29: goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_REFLECTION, aistr.data); nuclear@29: } nuclear@29: if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_OPACITY(0), &aistr) == aiReturn_SUCCESS) { nuclear@29: // TODO this is semantically inverted... maybe add an alpha attribute? nuclear@29: goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, aistr.data); nuclear@29: } nuclear@29: } nuclear@29: nuclear@29: void process_node(struct goat3d *goat, struct goat3d_node *parent, struct aiNode *ainode) nuclear@29: { nuclear@29: int i; nuclear@29: struct goat3d_node *node; nuclear@29: nuclear@29: node = goat3d_create_node(); nuclear@29: goat3d_set_node_name(node, ainode->mName.data); nuclear@29: nuclear@29: for(i=0; imNumChildren; i++) { nuclear@29: process_node(goat, node, ainode->mChildren[i]); nuclear@29: } nuclear@29: nuclear@29: goat3d_add_node(goat, node); nuclear@29: }