rev |
line source |
nuclear@13
|
1 #include <stdio.h>
|
nuclear@13
|
2 #include "assload.h"
|
nuclear@13
|
3 #include "logger.h"
|
nuclear@13
|
4
|
nuclear@13
|
5 #ifdef USE_ASSIMP
|
nuclear@13
|
6
|
nuclear@13
|
7 #include <vector>
|
nuclear@13
|
8 #include <map>
|
nuclear@13
|
9 #include "assimp/cimport.h"
|
nuclear@13
|
10 #include "assimp/scene.h"
|
nuclear@13
|
11 #include "assimp/postprocess.h"
|
nuclear@13
|
12 #include "texman.h"
|
nuclear@13
|
13 #include "material.h"
|
nuclear@13
|
14 #include "scene.h"
|
nuclear@13
|
15
|
nuclear@13
|
16 using namespace std;
|
nuclear@13
|
17
|
nuclear@13
|
18 static bool load_material(Material *mat, const aiMaterial *aimat);
|
nuclear@13
|
19 static Object *load_node(const aiScene *aiscn, const aiNode *ainode);
|
nuclear@13
|
20 static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh);
|
nuclear@13
|
21 static Curve *load_curve(const aiScene *aiscn, const aiMesh *aimesh);
|
nuclear@13
|
22 static bool load_bones(Mesh *mesh, const aiMesh *aimesh);
|
nuclear@13
|
23
|
nuclear@13
|
24 static Vector3 assimp_vector(const aiVector3D &v);
|
nuclear@13
|
25 static Quaternion assimp_quat(const aiQuaternion &q);
|
nuclear@13
|
26 static Matrix4x4 assimp_matrix(const aiMatrix4x4 &aim);
|
nuclear@13
|
27 static long assimp_time(const aiAnimation *anim, double aitime);
|
nuclear@13
|
28 static void print_hierarchy(const aiNode *node);
|
nuclear@13
|
29
|
nuclear@13
|
30 static map<string, Object*> obj_by_name;
|
nuclear@13
|
31 static map<aiMesh*, Mesh*> mesh_by_aimesh;
|
nuclear@13
|
32
|
nuclear@13
|
33 bool load_ass(Scene *scn, const char *fname)
|
nuclear@13
|
34 {
|
nuclear@13
|
35 static bool init_done;
|
nuclear@13
|
36
|
nuclear@13
|
37 if(!init_done) {
|
nuclear@13
|
38 static aiLogStream log_stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, 0);
|
nuclear@13
|
39 aiAttachLogStream(&log_stream);
|
nuclear@13
|
40 //aiEnableVerboseLogging(1);
|
nuclear@13
|
41 init_done = true;
|
nuclear@13
|
42 }
|
nuclear@13
|
43
|
nuclear@13
|
44 unsigned int proc_flags = aiProcess_JoinIdenticalVertices |
|
nuclear@13
|
45 aiProcess_CalcTangentSpace |
|
nuclear@13
|
46 aiProcess_Triangulate |
|
nuclear@13
|
47 aiProcess_SortByPType |
|
nuclear@13
|
48 aiProcess_FlipUVs;
|
nuclear@13
|
49
|
nuclear@13
|
50 const aiScene *aiscn = aiImportFile(datafile_path(fname).c_str(), proc_flags);
|
nuclear@13
|
51 if(!aiscn) {
|
nuclear@13
|
52 error_log("failed to load file: %s\n", fname);
|
nuclear@13
|
53 return false;
|
nuclear@13
|
54 }
|
nuclear@13
|
55
|
nuclear@13
|
56 info_log("NODE HIERARCHY:\n");
|
nuclear@13
|
57 print_hierarchy(aiscn->mRootNode);
|
nuclear@13
|
58 info_log("-------------------\n");
|
nuclear@13
|
59
|
nuclear@13
|
60 Vector3 root_pos, root_scaling(1.0, 1.0, 1.0);
|
nuclear@13
|
61 Quaternion root_rot;
|
nuclear@13
|
62
|
nuclear@13
|
63 if(aiscn->mRootNode) {
|
nuclear@13
|
64 Matrix4x4 root_matrix = assimp_matrix(aiscn->mRootNode->mTransformation);
|
nuclear@13
|
65 root_pos = root_matrix.get_translation();
|
nuclear@13
|
66 root_rot = root_matrix.get_rotation_quat();
|
nuclear@13
|
67 root_scaling = root_matrix.get_scaling();
|
nuclear@13
|
68 }
|
nuclear@13
|
69
|
nuclear@13
|
70 // load all meshes
|
nuclear@13
|
71 for(unsigned int i=0; i<aiscn->mNumMeshes; i++) {
|
nuclear@13
|
72 aiMesh *aimesh = aiscn->mMeshes[i];
|
nuclear@13
|
73 Mesh *mesh;
|
nuclear@13
|
74 Curve *curve;
|
nuclear@13
|
75
|
nuclear@13
|
76 switch(aimesh->mPrimitiveTypes) {
|
nuclear@13
|
77 case aiPrimitiveType_TRIANGLE:
|
nuclear@13
|
78 if((mesh = load_mesh(aiscn, aimesh))) {
|
nuclear@13
|
79 mesh_by_aimesh[aimesh] = mesh;
|
nuclear@13
|
80 scn->meshes.push_back(mesh);
|
nuclear@13
|
81 }
|
nuclear@13
|
82 break;
|
nuclear@13
|
83
|
nuclear@13
|
84 case aiPrimitiveType_LINE:
|
nuclear@13
|
85 if((curve = load_curve(aiscn, aimesh))) {
|
nuclear@13
|
86 scn->curves.push_back(curve);
|
nuclear@13
|
87 }
|
nuclear@13
|
88 break;
|
nuclear@13
|
89
|
nuclear@13
|
90 default:
|
nuclear@13
|
91 error_log("unsupported primitive type: %u\n", aimesh->mPrimitiveTypes);
|
nuclear@13
|
92 break;
|
nuclear@13
|
93 }
|
nuclear@13
|
94 }
|
nuclear@13
|
95
|
nuclear@13
|
96 // load all the nodes recursively
|
nuclear@13
|
97 for(unsigned int i=0; i<aiscn->mRootNode->mNumChildren; i++) {
|
nuclear@13
|
98 Object *obj = load_node(aiscn, aiscn->mRootNode->mChildren[i]);
|
nuclear@13
|
99 if(obj) {
|
nuclear@13
|
100 Object *dummy = new Object;
|
nuclear@13
|
101 dummy->set_name((string("dummyroot_") + string(obj->get_name())).c_str());
|
nuclear@13
|
102 dummy->set_position(root_pos);
|
nuclear@13
|
103 dummy->set_rotation(root_rot);
|
nuclear@13
|
104 dummy->set_scaling(root_scaling);
|
nuclear@13
|
105 dummy->add_child(obj);
|
nuclear@13
|
106
|
nuclear@13
|
107 obj = dummy;
|
nuclear@13
|
108 scn->objects.push_back(obj);
|
nuclear@13
|
109 }
|
nuclear@13
|
110 }
|
nuclear@13
|
111
|
nuclear@13
|
112 // load and attach the bones to the meshes
|
nuclear@13
|
113 for(unsigned int i=0; i<aiscn->mNumMeshes; i++) {
|
nuclear@13
|
114 aiMesh *aimesh = aiscn->mMeshes[i];
|
nuclear@13
|
115
|
nuclear@13
|
116 Mesh *mesh = mesh_by_aimesh[aimesh];
|
nuclear@13
|
117 load_bones(mesh, aimesh);
|
nuclear@13
|
118 }
|
nuclear@13
|
119
|
nuclear@13
|
120 obj_by_name.clear();
|
nuclear@13
|
121 mesh_by_aimesh.clear();
|
nuclear@13
|
122
|
nuclear@13
|
123 aiReleaseImport(aiscn);
|
nuclear@13
|
124 return true;
|
nuclear@13
|
125 }
|
nuclear@13
|
126
|
nuclear@13
|
127 static bool load_material(Material *mat, const aiMaterial *aimat)
|
nuclear@13
|
128 {
|
nuclear@13
|
129 aiColor4D aicol;
|
nuclear@13
|
130 float shin, shin_str;
|
nuclear@13
|
131
|
nuclear@13
|
132 if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_DIFFUSE, &aicol) == 0) {
|
nuclear@13
|
133 mat->diffuse = Vector3(aicol[0], aicol[1], aicol[2]);
|
nuclear@13
|
134 }
|
nuclear@13
|
135 if(aiGetMaterialColor(aimat, AI_MATKEY_COLOR_SPECULAR, &aicol) == 0) {
|
nuclear@13
|
136 mat->specular = Vector3(aicol[0], aicol[1], aicol[2]);
|
nuclear@13
|
137 }
|
nuclear@13
|
138
|
nuclear@13
|
139 unsigned int count = 1;
|
nuclear@13
|
140 if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS_STRENGTH, &shin_str, &count) != 0) {
|
nuclear@13
|
141 shin_str = 1.0;
|
nuclear@13
|
142 }
|
nuclear@13
|
143 if(aiGetMaterialFloatArray(aimat, AI_MATKEY_SHININESS, &shin, &count) == 0) {
|
nuclear@13
|
144 // XXX can't remember how I came up with this...
|
nuclear@13
|
145 mat->shininess = shin * shin_str * 0.0001 * 128.0;
|
nuclear@13
|
146 }
|
nuclear@13
|
147
|
nuclear@13
|
148 // load textures
|
nuclear@13
|
149 struct { int type; aiTextureType aitype; } textypes[] = {
|
nuclear@13
|
150 {TEX_DIFFUSE, aiTextureType_DIFFUSE},
|
nuclear@13
|
151 {TEX_NORMAL, aiTextureType_NORMALS},
|
nuclear@13
|
152 {TEX_SPECULAR, aiTextureType_SPECULAR}
|
nuclear@13
|
153 };
|
nuclear@13
|
154
|
nuclear@13
|
155 for(int i=0; i<sizeof textypes / sizeof *textypes; i++) {
|
nuclear@13
|
156 aiString aipath;
|
nuclear@13
|
157
|
nuclear@13
|
158 if(aiGetMaterialTexture(aimat, textypes[i].aitype, 0, &aipath) == 0) {
|
nuclear@13
|
159 char *tmp, *fname = aipath.data;
|
nuclear@13
|
160
|
nuclear@13
|
161 if((tmp = strrchr(fname, '/'))) {
|
nuclear@13
|
162 fname = tmp + 1;
|
nuclear@13
|
163 }
|
nuclear@13
|
164 if((tmp = strrchr(fname, '\\'))) {
|
nuclear@13
|
165 fname = tmp + 1;
|
nuclear@13
|
166 }
|
nuclear@13
|
167
|
nuclear@13
|
168 if(*fname) {
|
nuclear@13
|
169 mat->tex[textypes[i].type] = texset.get(fname);
|
nuclear@13
|
170 }
|
nuclear@13
|
171 }
|
nuclear@13
|
172 }
|
nuclear@13
|
173
|
nuclear@13
|
174 return true;
|
nuclear@13
|
175 }
|
nuclear@13
|
176
|
nuclear@13
|
177 static Object *load_node(const aiScene *aiscn, const aiNode *ainode)
|
nuclear@13
|
178 {
|
nuclear@13
|
179 Object *obj = new Object;
|
nuclear@13
|
180 obj->set_name(ainode->mName.data);
|
nuclear@13
|
181
|
nuclear@13
|
182 if(ainode->mNumMeshes) {
|
nuclear@13
|
183 if(ainode->mNumMeshes > 1) {
|
nuclear@13
|
184 info_log("%s warning: node %s has more than one meshes (%u)\n", __FUNCTION__,
|
nuclear@13
|
185 ainode->mName.data, ainode->mNumMeshes);
|
nuclear@13
|
186 }
|
nuclear@13
|
187
|
nuclear@13
|
188 aiMesh *aimesh = aiscn->mMeshes[ainode->mMeshes[0]];
|
nuclear@13
|
189 obj->set_mesh(mesh_by_aimesh[aimesh]);
|
nuclear@13
|
190
|
nuclear@13
|
191 // also grab the material of this mesh
|
nuclear@13
|
192 load_material(&obj->material, aiscn->mMaterials[aimesh->mMaterialIndex]);
|
nuclear@13
|
193 }
|
nuclear@13
|
194
|
nuclear@13
|
195 // if there are animations, grab the first and try to use it
|
nuclear@13
|
196 if(aiscn->mNumAnimations) {
|
nuclear@13
|
197 aiAnimation *aianim = aiscn->mAnimations[0];
|
nuclear@13
|
198 aiNodeAnim *ainodeanim = 0;
|
nuclear@13
|
199 for(unsigned int i=0; i<aianim->mNumChannels; i++) {
|
nuclear@13
|
200 if(strcmp(aianim->mChannels[i]->mNodeName.data, ainode->mName.data) == 0) {
|
nuclear@13
|
201 ainodeanim = aianim->mChannels[i];
|
nuclear@13
|
202 break;
|
nuclear@13
|
203 }
|
nuclear@13
|
204 }
|
nuclear@13
|
205
|
nuclear@13
|
206 if(ainodeanim) {
|
nuclear@13
|
207 // load all position (translation) keyframes
|
nuclear@13
|
208 for(unsigned int i=0; i<ainodeanim->mNumPositionKeys; i++) {
|
nuclear@13
|
209 Vector3 pos = assimp_vector(ainodeanim->mPositionKeys[i].mValue);
|
nuclear@13
|
210 long msec = assimp_time(aianim, ainodeanim->mPositionKeys[i].mTime);
|
nuclear@13
|
211 obj->set_position(pos, msec);
|
nuclear@13
|
212 }
|
nuclear@13
|
213
|
nuclear@13
|
214 // load all rotation keyframes
|
nuclear@13
|
215 for(unsigned int i=0; i<ainodeanim->mNumRotationKeys; i++) {
|
nuclear@13
|
216 Quaternion rot = assimp_quat(ainodeanim->mRotationKeys[i].mValue);
|
nuclear@13
|
217 if(rot.length_sq() < SMALL_NUMBER) {
|
nuclear@13
|
218 continue;
|
nuclear@13
|
219 }
|
nuclear@13
|
220 rot.normalize();
|
nuclear@13
|
221 long msec = assimp_time(aianim, ainodeanim->mRotationKeys[i].mTime);
|
nuclear@13
|
222 obj->set_rotation(rot, msec);
|
nuclear@13
|
223 }
|
nuclear@13
|
224
|
nuclear@13
|
225 // load all scaling keyframes
|
nuclear@13
|
226 for(unsigned int i=0; i<ainodeanim->mNumScalingKeys; i++) {
|
nuclear@13
|
227 Vector3 scale = assimp_vector(ainodeanim->mScalingKeys[i].mValue);
|
nuclear@13
|
228 long msec = assimp_time(aianim, ainodeanim->mScalingKeys[i].mTime);
|
nuclear@13
|
229 obj->set_scaling(scale, msec);
|
nuclear@13
|
230 }
|
nuclear@13
|
231
|
nuclear@13
|
232 obj->set_extrapolator(EXTRAP_REPEAT); // loop animation
|
nuclear@13
|
233 } else {
|
nuclear@13
|
234 Matrix4x4 local_matrix = assimp_matrix(ainode->mTransformation);
|
nuclear@13
|
235 obj->set_local_matrix(local_matrix);
|
nuclear@13
|
236 }
|
nuclear@13
|
237 }
|
nuclear@13
|
238
|
nuclear@13
|
239 /* recurse to all children */
|
nuclear@13
|
240 for(unsigned int i=0; i<ainode->mNumChildren; i++) {
|
nuclear@13
|
241 Object *child = load_node(aiscn, ainode->mChildren[i]);
|
nuclear@13
|
242 if(child) {
|
nuclear@13
|
243 obj->add_child(child);
|
nuclear@13
|
244 }
|
nuclear@13
|
245 }
|
nuclear@13
|
246
|
nuclear@13
|
247 obj_by_name[obj->get_name()] = obj;
|
nuclear@13
|
248 return obj;
|
nuclear@13
|
249 }
|
nuclear@13
|
250
|
nuclear@13
|
251 static Mesh *load_mesh(const aiScene *aiscn, const aiMesh *aimesh)
|
nuclear@13
|
252 {
|
nuclear@13
|
253 Mesh *mesh = new Mesh;
|
nuclear@13
|
254
|
nuclear@13
|
255 int num_verts = aimesh->mNumVertices;
|
nuclear@13
|
256 int num_faces = aimesh->mNumFaces;
|
nuclear@13
|
257
|
nuclear@13
|
258 mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, (float*)aimesh->mVertices);
|
nuclear@13
|
259
|
nuclear@13
|
260 if(aimesh->mNormals) {
|
nuclear@13
|
261 mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, (float*)aimesh->mNormals);
|
nuclear@13
|
262 }
|
nuclear@13
|
263 if(aimesh->mTangents) {
|
nuclear@13
|
264 mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, (float*)aimesh->mTangents);
|
nuclear@13
|
265 }
|
nuclear@13
|
266 if(aimesh->mTextureCoords[0]) {
|
nuclear@13
|
267 mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 3, num_verts, (float*)aimesh->mTextureCoords[0]);
|
nuclear@13
|
268 }
|
nuclear@13
|
269
|
nuclear@13
|
270 if(aimesh->mBones) {
|
nuclear@13
|
271 float *weights = mesh->set_attrib_data(MESH_ATTR_BONEWEIGHTS, 4, num_verts, 0);
|
nuclear@13
|
272 float *boneidx = mesh->set_attrib_data(MESH_ATTR_BONEIDX, 4, num_verts, 0);
|
nuclear@13
|
273
|
nuclear@13
|
274 memset(weights, 0, num_verts * 4 * sizeof *weights);
|
nuclear@13
|
275 memset(boneidx, 0, num_verts * 4 * sizeof *boneidx);
|
nuclear@13
|
276
|
nuclear@13
|
277 int *vertex_bone_count = new int[num_verts];
|
nuclear@13
|
278 memset(vertex_bone_count, 0, num_verts * sizeof *vertex_bone_count);
|
nuclear@13
|
279
|
nuclear@13
|
280 for(unsigned int i=0; i<aimesh->mNumBones; i++) {
|
nuclear@13
|
281 aiBone *aibone = aimesh->mBones[i];
|
nuclear@13
|
282
|
nuclear@13
|
283 // for every vertex affected by this bone:
|
nuclear@13
|
284 for(unsigned int j=0; j<aibone->mNumWeights; j++) {
|
nuclear@13
|
285 aiVertexWeight *aiweight = aibone->mWeights + j;
|
nuclear@13
|
286 int vidx = aiweight->mVertexId;
|
nuclear@13
|
287 int vert_boneidx = vertex_bone_count[vidx];
|
nuclear@13
|
288 if(vert_boneidx >= 4) {
|
nuclear@13
|
289 error_log("WARNING vertex with more than 4 bones found\n");
|
nuclear@13
|
290 continue;
|
nuclear@13
|
291 }
|
nuclear@13
|
292
|
nuclear@13
|
293 weights[vidx * 4 + vert_boneidx] = aiweight->mWeight;
|
nuclear@13
|
294 boneidx[vidx * 4 + vert_boneidx] = (float)i;
|
nuclear@13
|
295 vertex_bone_count[vidx]++;
|
nuclear@13
|
296 }
|
nuclear@13
|
297 }
|
nuclear@13
|
298
|
nuclear@13
|
299 delete [] vertex_bone_count;
|
nuclear@13
|
300
|
nuclear@13
|
301 // normalize weights
|
nuclear@13
|
302 for(int i=0; i<num_verts; i++) {
|
nuclear@13
|
303
|
nuclear@13
|
304 float wsum = 0.0f;
|
nuclear@13
|
305
|
nuclear@13
|
306 for(int j=0; j<4; j++) {
|
nuclear@13
|
307 wsum += weights[i * 4 + j];
|
nuclear@13
|
308 }
|
nuclear@13
|
309
|
nuclear@13
|
310 if(1.0 - wsum > 1e-4) {
|
nuclear@13
|
311 error_log("WARNING vertex with weights < 1 (%f), normalizing...\n", wsum);
|
nuclear@13
|
312
|
nuclear@13
|
313 if(wsum < 1e-6) {
|
nuclear@13
|
314 // this is clearly broken, let's use the first bone in full
|
nuclear@13
|
315 weights[i * 4] = 1.0;
|
nuclear@13
|
316 } else {
|
nuclear@13
|
317 weights[i * 4] /= wsum;
|
nuclear@13
|
318 weights[i * 4 + 1] /= wsum;
|
nuclear@13
|
319 weights[i * 4 + 2] /= wsum;
|
nuclear@13
|
320 weights[i * 4 + 3] /= wsum;
|
nuclear@13
|
321 }
|
nuclear@13
|
322 }
|
nuclear@13
|
323 }
|
nuclear@13
|
324 }
|
nuclear@13
|
325
|
nuclear@13
|
326 unsigned int *iptr = mesh->set_index_data(num_faces * 3);
|
nuclear@13
|
327 for(int i=0; i<num_faces; i++) {
|
nuclear@13
|
328 for(int j=0; j<3; j++) {
|
nuclear@13
|
329 *iptr++ = aimesh->mFaces[i].mIndices[j];
|
nuclear@13
|
330 }
|
nuclear@13
|
331 }
|
nuclear@13
|
332
|
nuclear@13
|
333 return mesh;
|
nuclear@13
|
334 }
|
nuclear@13
|
335
|
nuclear@13
|
336 static Curve *load_curve(const aiScene *aiscn, const aiMesh *aimesh)
|
nuclear@13
|
337 {
|
nuclear@13
|
338 Curve *curve = new Curve;
|
nuclear@13
|
339
|
nuclear@13
|
340 for(unsigned int i=0; i<aimesh->mNumVertices; i++) {
|
nuclear@13
|
341 Vector3 pt = assimp_vector(aimesh->mVertices[i]);
|
nuclear@13
|
342 curve->add_point(pt);
|
nuclear@13
|
343 }
|
nuclear@13
|
344 info_log("loaded curve with %d points\n", aimesh->mNumVertices);
|
nuclear@13
|
345
|
nuclear@13
|
346 return curve;
|
nuclear@13
|
347 }
|
nuclear@13
|
348
|
nuclear@13
|
349 static bool load_bones(Mesh *mesh, const aiMesh *aimesh)
|
nuclear@13
|
350 {
|
nuclear@13
|
351 if(!aimesh->mNumBones) {
|
nuclear@13
|
352 return false;
|
nuclear@13
|
353 }
|
nuclear@13
|
354
|
nuclear@13
|
355 for(unsigned int i=0; i<aimesh->mNumBones; i++) {
|
nuclear@13
|
356 aiBone *aibone = aimesh->mBones[i];
|
nuclear@13
|
357 Object *obj = obj_by_name[aibone->mName.data];
|
nuclear@13
|
358 if(!obj) {
|
nuclear@13
|
359 error_log("bone %s not found\n", aibone->mName.data);
|
nuclear@13
|
360 continue;
|
nuclear@13
|
361 }
|
nuclear@13
|
362
|
nuclear@13
|
363 obj->set_bone_matrix(assimp_matrix(aibone->mOffsetMatrix));
|
nuclear@13
|
364 mesh->add_bone(obj);
|
nuclear@13
|
365
|
nuclear@13
|
366 info_log("adding bone: %s\n", obj->get_name());
|
nuclear@13
|
367 }
|
nuclear@13
|
368
|
nuclear@13
|
369 return true;
|
nuclear@13
|
370 }
|
nuclear@13
|
371
|
nuclear@13
|
372 static Vector3 assimp_vector(const aiVector3D &v)
|
nuclear@13
|
373 {
|
nuclear@13
|
374 return Vector3(v[0], v[1], v[2]);
|
nuclear@13
|
375 }
|
nuclear@13
|
376
|
nuclear@13
|
377 static Quaternion assimp_quat(const aiQuaternion &q)
|
nuclear@13
|
378 {
|
nuclear@13
|
379 return Quaternion(q.w, Vector3(q.x, q.y, q.z));
|
nuclear@13
|
380 }
|
nuclear@13
|
381
|
nuclear@13
|
382 static Matrix4x4 assimp_matrix(const aiMatrix4x4 &aim)
|
nuclear@13
|
383 {
|
nuclear@13
|
384 Matrix4x4 m;
|
nuclear@13
|
385 memcpy(m[0], &aim, 16 * sizeof(float));
|
nuclear@13
|
386 return m;
|
nuclear@13
|
387 }
|
nuclear@13
|
388
|
nuclear@13
|
389 /* convert an assimp keyframe time (ticks) into milliseconds */
|
nuclear@13
|
390 static long assimp_time(const aiAnimation *anim, double aitime)
|
nuclear@13
|
391 {
|
nuclear@13
|
392 double sec;
|
nuclear@13
|
393 if(anim->mTicksPerSecond < 1e-6) {
|
nuclear@13
|
394 // assume time is in frames?
|
nuclear@13
|
395 sec = aitime / 30.0;
|
nuclear@13
|
396 } else {
|
nuclear@13
|
397 sec = aitime / anim->mTicksPerSecond;
|
nuclear@13
|
398 }
|
nuclear@13
|
399 return (long)(sec * 1000.0);
|
nuclear@13
|
400 }
|
nuclear@13
|
401
|
nuclear@13
|
402 static void print_hierarchy(const aiNode *node)
|
nuclear@13
|
403 {
|
nuclear@13
|
404 static int lvl;
|
nuclear@13
|
405 static int lvlopen[256];
|
nuclear@13
|
406
|
nuclear@13
|
407 for(int i=0; i<lvl; i++) {
|
nuclear@13
|
408 putchar(' ');
|
nuclear@13
|
409 if(lvlopen[i]) {
|
nuclear@13
|
410 putchar(i >= lvl - 1 ? '+' : '|');
|
nuclear@13
|
411 } else {
|
nuclear@13
|
412 putchar(i >= lvl - 1 ? '+' : ' ');
|
nuclear@13
|
413 }
|
nuclear@13
|
414 }
|
nuclear@13
|
415 info_log("- \"%s\"\n", node->mName.data);
|
nuclear@13
|
416
|
nuclear@13
|
417 lvlopen[lvl] = 1;
|
nuclear@13
|
418
|
nuclear@13
|
419 lvl++;
|
nuclear@13
|
420 for(unsigned int i=0; i<node->mNumChildren; i++) {
|
nuclear@13
|
421 if(i == node->mNumChildren - 1) {
|
nuclear@13
|
422 lvlopen[lvl - 1] = 0;
|
nuclear@13
|
423 }
|
nuclear@13
|
424 print_hierarchy(node->mChildren[i]);
|
nuclear@13
|
425 }
|
nuclear@13
|
426 lvl--;
|
nuclear@13
|
427 }
|
nuclear@13
|
428
|
nuclear@13
|
429 #else // !defined USE_ASSIMP
|
nuclear@13
|
430
|
nuclear@13
|
431 bool load_ass(Scene *scn, const char *fname)
|
nuclear@13
|
432 {
|
nuclear@13
|
433 error_log("load_ass: assimp support not compiled in\n");
|
nuclear@13
|
434 return false;
|
nuclear@13
|
435 }
|
nuclear@13
|
436
|
nuclear@13
|
437 #endif
|