rev |
line source |
nuclear@29
|
1 #include <stdio.h>
|
nuclear@29
|
2 #include <stdlib.h>
|
nuclear@29
|
3 #include "goat3d.h"
|
nuclear@29
|
4 #include "assimp/cimport.h"
|
nuclear@29
|
5 #include "assimp/postprocess.h"
|
nuclear@29
|
6 #include "assimp/scene.h"
|
nuclear@29
|
7
|
nuclear@29
|
8 int convert(const char *infname, const char *outfname);
|
nuclear@29
|
9 void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl);
|
nuclear@29
|
10 void process_node(struct goat3d *goat, struct goat3d_node *parent, struct aiNode *ainode);
|
nuclear@29
|
11
|
nuclear@29
|
12 int main(int argc, char **argv)
|
nuclear@29
|
13 {
|
nuclear@29
|
14 int i, num_done = 0;
|
nuclear@29
|
15
|
nuclear@29
|
16 for(i=1; i<argc; i++) {
|
nuclear@29
|
17 if(argv[i][0] == '-') {
|
nuclear@29
|
18 } else {
|
nuclear@29
|
19 char *lastdot;
|
nuclear@29
|
20 char *outfname = malloc(strlen(argv[i]) + 4);
|
nuclear@29
|
21 strcpy(outfname, argv[i]);
|
nuclear@29
|
22
|
nuclear@29
|
23 if((lastdot = strrchr(outfname, '.'))) {
|
nuclear@29
|
24 *lastdot = 0;
|
nuclear@29
|
25 }
|
nuclear@29
|
26 strcat(outfname, ".xml");
|
nuclear@29
|
27
|
nuclear@29
|
28 printf("converting %s -> %s\n", argv[i], outfname);
|
nuclear@29
|
29 convert(argv[i], outfname);
|
nuclear@29
|
30 num_done++;
|
nuclear@29
|
31 }
|
nuclear@29
|
32 }
|
nuclear@29
|
33
|
nuclear@29
|
34 if(!num_done) {
|
nuclear@29
|
35 fprintf(stderr, "you must specify a 3D scene file to convert\n");
|
nuclear@29
|
36 return 1;
|
nuclear@29
|
37 }
|
nuclear@29
|
38
|
nuclear@29
|
39 return 0;
|
nuclear@29
|
40 }
|
nuclear@29
|
41
|
nuclear@29
|
42 #define PPFLAGS \
|
nuclear@29
|
43 (aiProcess_Triangulate | \
|
nuclear@29
|
44 aiProcess_GenNormals | \
|
nuclear@29
|
45 aiProcess_JoinIdenticalVertices | \
|
nuclear@29
|
46 aiProcess_CalcTangentSpace | \
|
nuclear@29
|
47 aiProcess_LimitBoneWeights | \
|
nuclear@29
|
48 aiProcess_GenUVCoords)
|
nuclear@29
|
49
|
nuclear@29
|
50 int convert(const char *infname, const char *outfname)
|
nuclear@29
|
51 {
|
nuclear@29
|
52 int i;
|
nuclear@29
|
53 const struct aiScene *aiscn;
|
nuclear@29
|
54 struct goat3d *goat;
|
nuclear@29
|
55
|
nuclear@29
|
56 if(!(aiscn = aiImportFile(infname, PPFLAGS))) {
|
nuclear@29
|
57 fprintf(stderr, "failed to import %s\n", infname);
|
nuclear@29
|
58 return -1;
|
nuclear@29
|
59 }
|
nuclear@29
|
60
|
nuclear@29
|
61 goat = goat3d_create();
|
nuclear@29
|
62
|
nuclear@29
|
63 for(i=0; i<(int)aiscn->mNumMaterials; i++) {
|
nuclear@29
|
64 struct aiMaterial *aimat = aiscn->mMaterials[i];
|
nuclear@29
|
65 struct goat3d_material *mat = goat3d_create_mtl();
|
nuclear@29
|
66
|
nuclear@29
|
67 process_material(mat, aimat);
|
nuclear@29
|
68 goat3d_add_mtl(goat, mat);
|
nuclear@29
|
69 }
|
nuclear@29
|
70
|
nuclear@29
|
71 for(i=0; i<(int)aiscn->mRootNode->mNumChildren; i++) {
|
nuclear@29
|
72 process_node(goat, 0, aiscn->mRootNode->mChildren[i]);
|
nuclear@29
|
73 }
|
nuclear@29
|
74
|
nuclear@29
|
75 goat3d_save(goat, outfname);
|
nuclear@29
|
76 goat3d_free(goat);
|
nuclear@29
|
77 aiReleaseImport(aiscn);
|
nuclear@29
|
78 return 0;
|
nuclear@29
|
79 }
|
nuclear@29
|
80
|
nuclear@29
|
81 void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl)
|
nuclear@29
|
82 {
|
nuclear@29
|
83 struct aiString aistr;
|
nuclear@29
|
84 struct aiColor4D color;
|
nuclear@29
|
85 float val;
|
nuclear@29
|
86
|
nuclear@29
|
87 if(aiGetMaterialString(aimtl, AI_MATKEY_NAME, &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
88 goat3d_set_mtl_name(mtl, aistr.data);
|
nuclear@29
|
89 }
|
nuclear@29
|
90
|
nuclear@29
|
91 if(aiGetMaterialColor(aimtl, AI_MATKEY_COLOR_DIFFUSE, &color) == aiReturn_SUCCESS) {
|
nuclear@29
|
92 goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, color.r, color.g, color.b);
|
nuclear@29
|
93 }
|
nuclear@29
|
94
|
nuclear@29
|
95 if(aiGetMaterialColor(aimtl, AI_MATKEY_COLOR_SPECULAR, &color) == aiReturn_SUCCESS) {
|
nuclear@29
|
96 float sstr = 1.0;
|
nuclear@29
|
97 aiGetMaterialFloatArray(aimtl, AI_MATKEY_SHININESS_STRENGTH, &sstr, 0);
|
nuclear@29
|
98 goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_SPECULAR, color.r * sstr, color.g * sstr, color.b * sstr);
|
nuclear@29
|
99 }
|
nuclear@29
|
100
|
nuclear@29
|
101 if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_BUMPSCALING, &val, 0) == aiReturn_SUCCESS) {
|
nuclear@29
|
102 goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_BUMP, val, val, val);
|
nuclear@29
|
103 }
|
nuclear@29
|
104
|
nuclear@29
|
105 if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_REFLECTIVITY, &val, 0) == aiReturn_SUCCESS) {
|
nuclear@29
|
106 goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_REFLECTION, val);
|
nuclear@29
|
107 }
|
nuclear@29
|
108
|
nuclear@29
|
109 if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_OPACITY, &val, 0) == aiReturn_SUCCESS) {
|
nuclear@29
|
110 goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, 1.0 - val);
|
nuclear@29
|
111 }
|
nuclear@29
|
112
|
nuclear@29
|
113 if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_DIFFUSE(0), &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
114 goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_DIFFUSE, aistr.data);
|
nuclear@29
|
115 }
|
nuclear@29
|
116 if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_SPECULAR(0), &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
117 goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SPECULAR, aistr.data);
|
nuclear@29
|
118 }
|
nuclear@29
|
119 if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_SHININESS(0), &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
120 goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SHININESS, aistr.data);
|
nuclear@29
|
121 }
|
nuclear@29
|
122 if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_NORMALS(0), &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
123 goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_NORMAL, aistr.data);
|
nuclear@29
|
124 }
|
nuclear@29
|
125 if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_REFLECTION(0), &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
126 goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_REFLECTION, aistr.data);
|
nuclear@29
|
127 }
|
nuclear@29
|
128 if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_OPACITY(0), &aistr) == aiReturn_SUCCESS) {
|
nuclear@29
|
129 // TODO this is semantically inverted... maybe add an alpha attribute?
|
nuclear@29
|
130 goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, aistr.data);
|
nuclear@29
|
131 }
|
nuclear@29
|
132 }
|
nuclear@29
|
133
|
nuclear@29
|
134 void process_node(struct goat3d *goat, struct goat3d_node *parent, struct aiNode *ainode)
|
nuclear@29
|
135 {
|
nuclear@29
|
136 int i;
|
nuclear@29
|
137 struct goat3d_node *node;
|
nuclear@29
|
138
|
nuclear@29
|
139 node = goat3d_create_node();
|
nuclear@29
|
140 goat3d_set_node_name(node, ainode->mName.data);
|
nuclear@29
|
141
|
nuclear@29
|
142 for(i=0; i<ainode->mNumChildren; i++) {
|
nuclear@29
|
143 process_node(goat, node, ainode->mChildren[i]);
|
nuclear@29
|
144 }
|
nuclear@29
|
145
|
nuclear@29
|
146 goat3d_add_node(goat, node);
|
nuclear@29
|
147 }
|