COLLADA branch: bone animation import works!
[blender-staging.git] / source / blender / collada / DocumentImporter.cpp
1 // TODO:
2 // * name imported objects
3 // * import object rotation as euler
4
5 #include "COLLADAFWRoot.h"
6 #include "COLLADAFWIWriter.h"
7 #include "COLLADAFWStableHeaders.h"
8 #include "COLLADAFWAnimationCurve.h"
9 #include "COLLADAFWAnimationList.h"
10 #include "COLLADAFWCamera.h"
11 #include "COLLADAFWColorOrTexture.h"
12 #include "COLLADAFWEffect.h"
13 #include "COLLADAFWFloatOrDoubleArray.h"
14 #include "COLLADAFWGeometry.h"
15 #include "COLLADAFWImage.h"
16 #include "COLLADAFWIndexList.h"
17 #include "COLLADAFWInstanceGeometry.h"
18 #include "COLLADAFWLight.h"
19 #include "COLLADAFWMaterial.h"
20 #include "COLLADAFWMesh.h"
21 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
22 #include "COLLADAFWNode.h"
23 #include "COLLADAFWPolygons.h"
24 #include "COLLADAFWSampler.h"
25 #include "COLLADAFWSkinController.h"
26 #include "COLLADAFWSkinControllerData.h"
27 #include "COLLADAFWTransformation.h"
28 #include "COLLADAFWTranslate.h"
29 #include "COLLADAFWRotate.h"
30 #include "COLLADAFWScale.h"
31 #include "COLLADAFWMatrix.h"
32 #include "COLLADAFWTypes.h"
33 #include "COLLADAFWVisualScene.h"
34 #include "COLLADAFWFileInfo.h"
35 #include "COLLADAFWArrayPrimitiveType.h"
36
37 #include "COLLADASaxFWLLoader.h"
38
39 // TODO move "extern C" into header files
40 extern "C" 
41 {
42 #include "ED_keyframing.h"
43 #include "ED_armature.h"
44 #include "ED_mesh.h" // ED_vgroup_vert_add, ...
45 #include "ED_anim_api.h"
46 #include "WM_types.h"
47 #include "WM_api.h"
48
49 #include "BKE_main.h"
50 #include "BKE_customdata.h"
51 #include "BKE_library.h"
52 #include "BKE_texture.h"
53 #include "BKE_fcurve.h"
54 #include "BKE_depsgraph.h"
55 #include "BLI_util.h"
56 #include "BKE_displist.h"
57 #include "BLI_math.h"
58 #include "BKE_scene.h"
59 }
60 #include "BKE_armature.h"
61 #include "BKE_mesh.h"
62 #include "BKE_global.h"
63 #include "BKE_context.h"
64 #include "BKE_object.h"
65 #include "BKE_image.h"
66 #include "BKE_material.h"
67 #include "BKE_utildefines.h"
68 #include "BKE_action.h"
69
70 #include "BLI_math.h"
71 #include "BLI_listbase.h"
72 #include "BLI_string.h"
73
74 #include "DNA_lamp_types.h"
75 #include "DNA_armature_types.h"
76 #include "DNA_anim_types.h"
77 #include "DNA_curve_types.h"
78 #include "DNA_texture_types.h"
79 #include "DNA_camera_types.h"
80 #include "DNA_object_types.h"
81 #include "DNA_meshdata_types.h"
82 #include "DNA_mesh_types.h"
83 #include "DNA_material_types.h"
84 #include "DNA_scene_types.h"
85
86 #include "MEM_guardedalloc.h"
87
88 #include "DocumentImporter.h"
89 #include "collada_internal.h"
90
91 #include <string>
92 #include <map>
93 #include <algorithm> // sort()
94
95 #include <math.h>
96 #include <float.h>
97
98 // #define COLLADA_DEBUG
99 #define ARMATURE_TEST
100
101 char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
102
103 // armature module internal func, it's not good to use it here? (Arystan)
104 struct EditBone *addEditBone(struct bArmature *arm, char *name);
105
106 const char *primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
107 {
108         using namespace COLLADAFW;
109         
110         switch (type) {
111         case MeshPrimitive::LINES:
112                 return "LINES";
113         case MeshPrimitive::LINE_STRIPS:
114                 return "LINESTRIPS";
115         case MeshPrimitive::POLYGONS:
116                 return "POLYGONS";
117         case MeshPrimitive::POLYLIST:
118                 return "POLYLIST";
119         case MeshPrimitive::TRIANGLES:
120                 return "TRIANGLES";
121         case MeshPrimitive::TRIANGLE_FANS:
122                 return "TRIANGLE_FANS";
123         case MeshPrimitive::TRIANGLE_STRIPS:
124                 return "TRIANGLE_FANS";
125         case MeshPrimitive::POINTS:
126                 return "POINTS";
127         case MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
128                 return "UNDEFINED_PRIMITIVE_TYPE";
129         }
130         return "UNKNOWN";
131 }
132 const char *geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
133 {
134         switch (type) {
135         case COLLADAFW::Geometry::GEO_TYPE_MESH:
136                 return "MESH";
137         case COLLADAFW::Geometry::GEO_TYPE_SPLINE:
138                 return "SPLINE";
139         case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
140                 return "CONVEX_MESH";
141         case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN:
142         default:
143                 return "UNKNOWN";
144         }
145 }
146
147 // works for COLLADAFW::Node, COLLADAFW::Geometry
148 template<class T>
149 const char *get_dae_name(T *node)
150 {
151         const std::string& name = node->getName();
152         return name.size() ? name.c_str() : node->getOriginalId().c_str();
153 }
154
155 // use this for retrieving bone names, since these must be unique
156 template<class T>
157 const char *get_joint_name(T *node)
158 {
159         const std::string& id = node->getOriginalId();
160         return id.size() ? id.c_str() : node->getName().c_str();
161 }
162
163 float get_float_value(const COLLADAFW::FloatOrDoubleArray& array, int index)
164 {
165         if (index >= array.getValuesCount())
166                 return 0.0f;
167
168         if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT)
169                 return array.getFloatValues()->getData()[index];
170         else 
171                 return array.getDoubleValues()->getData()[index];
172 }
173
174 typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > TexIndexTextureArrayMap;
175
176 class TransformReader : public TransformBase
177 {
178 protected:
179
180         UnitConverter *unit_converter;
181
182         struct Animation {
183                 Object *ob;
184                 COLLADAFW::Node *node;
185                 COLLADAFW::Transformation *tm; // which transform is animated by an AnimationList->id
186         };
187
188 public:
189
190         TransformReader(UnitConverter* conv) : unit_converter(conv) {}
191
192         void get_node_mat(float mat[][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map,
193                                           Object *ob)
194         {
195                 float cur[4][4];
196                 float copy[4][4];
197
198                 unit_m4(mat);
199                 
200                 for (int i = 0; i < node->getTransformations().getCount(); i++) {
201
202                         COLLADAFW::Transformation *tm = node->getTransformations()[i];
203                         COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
204
205                         switch(type) {
206                         case COLLADAFW::Transformation::TRANSLATE:
207                                 dae_translate_to_mat4(tm, cur);
208                                 break;
209                         case COLLADAFW::Transformation::ROTATE:
210                                 dae_rotate_to_mat4(tm, cur);
211                                 break;
212                         case COLLADAFW::Transformation::SCALE:
213                                 dae_scale_to_mat4(tm, cur);
214                                 break;
215                         case COLLADAFW::Transformation::MATRIX:
216                                 dae_matrix_to_mat4(tm, cur);
217                                 break;
218                         case COLLADAFW::Transformation::LOOKAT:
219                         case COLLADAFW::Transformation::SKEW:
220                                 fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n");
221                                 break;
222                         }
223
224                         copy_m4_m4(copy, mat);
225                         mul_m4_m4m4(mat, cur, copy);
226
227                         if (animation_map) {
228                                 // AnimationList that drives this Transformation
229                                 const COLLADAFW::UniqueId& anim_list_id = tm->getAnimationList();
230                         
231                                 // store this so later we can link animation data with ob
232                                 Animation anim = {ob, node, tm};
233                                 (*animation_map)[anim_list_id] = anim;
234                         }
235                 }
236         }
237
238         void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
239         {
240                 COLLADAFW::Rotate *ro = (COLLADAFW::Rotate*)tm;
241                 COLLADABU::Math::Vector3& axis = ro->getRotationAxis();
242                 float angle = (float)(ro->getRotationAngle() * M_PI / 180.0f);
243                 float ax[] = {axis[0], axis[1], axis[2]};
244                 // float quat[4];
245                 // axis_angle_to_quat(quat, axis, angle);
246                 // quat_to_mat4(m, quat);
247                 axis_angle_to_mat4(m, ax, angle);
248         }
249
250         void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
251         {
252                 COLLADAFW::Translate *tra = (COLLADAFW::Translate*)tm;
253                 COLLADABU::Math::Vector3& t = tra->getTranslation();
254
255                 unit_m4(m);
256
257                 m[3][0] = (float)t[0];
258                 m[3][1] = (float)t[1];
259                 m[3][2] = (float)t[2];
260         }
261
262         void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
263         {
264                 COLLADABU::Math::Vector3& s = ((COLLADAFW::Scale*)tm)->getScale();
265                 float size[3] = {(float)s[0], (float)s[1], (float)s[2]};
266                 size_to_mat4(m, size);
267         }
268
269         void dae_matrix_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
270         {
271                 unit_converter->dae_matrix_to_mat4(m, ((COLLADAFW::Matrix*)tm)->getMatrix());
272         }
273 };
274
275 // only for ArmatureImporter to "see" MeshImporter::get_object_by_geom_uid
276 class MeshImporterBase
277 {
278 public:
279         virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) = 0;
280 };
281
282 // ditto as above
283 class AnimationImporterBase
284 {
285 public:
286         // virtual void change_eul_to_quat(Object *ob, bAction *act) = 0;
287 };
288
289 class ArmatureImporter : private TransformReader
290 {
291 private:
292         Scene *scene;
293         UnitConverter *unit_converter;
294
295         // std::map<int, JointData> joint_index_to_joint_info_map;
296         // std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map;
297
298         struct LeafBone {
299                 // COLLADAFW::Node *node;
300                 EditBone *bone;
301                 char name[32];
302                 float mat[4][4]; // bone matrix, derived from inv_bind_mat
303         };
304         std::vector<LeafBone> leaf_bones;
305         // int bone_direction_row; // XXX not used
306         float leaf_bone_length;
307         int totbone;
308         // XXX not used
309         // float min_angle; // minimum angle between bone head-tail and a row of bone matrix
310
311 #if 0
312         struct ArmatureJoints {
313                 Object *ob_arm;
314                 std::vector<COLLADAFW::Node*> root_joints;
315         };
316         std::vector<ArmatureJoints> armature_joints;
317 #endif
318
319         Object *empty; // empty for leaf bones
320
321         std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> geom_uid_by_controller_uid;
322         std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints
323         std::vector<COLLADAFW::Node*> root_joints;
324
325         std::vector<Object*> armature_objects;
326
327         MeshImporterBase *mesh_importer;
328         AnimationImporterBase *anim_importer;
329
330         // This is used to store data passed in write_controller_data.
331         // Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members
332         // so that arrays don't get freed until we free them explicitly.
333         class SkinInfo
334         {
335         private:
336                 // to build armature bones from inverse bind matrices
337                 struct JointData {
338                         float inv_bind_mat[4][4]; // joint inverse bind matrix
339                         COLLADAFW::UniqueId joint_uid; // joint node UID
340                         // Object *ob_arm;                        // armature object
341                 };
342
343                 float bind_shape_matrix[4][4];
344
345                 // data from COLLADAFW::SkinControllerData, each array should be freed
346                 COLLADAFW::UIntValuesArray joints_per_vertex;
347                 COLLADAFW::UIntValuesArray weight_indices;
348                 COLLADAFW::IntValuesArray joint_indices;
349                 // COLLADAFW::FloatOrDoubleArray weights;
350                 std::vector<float> weights;
351
352                 std::vector<JointData> joint_data; // index to this vector is joint index
353
354                 UnitConverter *unit_converter;
355
356                 Object *ob_arm;
357                 COLLADAFW::UniqueId controller_uid;
358
359         public:
360
361                 SkinInfo() {}
362
363                 SkinInfo(const SkinInfo& skin) : weights(skin.weights),
364                                                                                  joint_data(skin.joint_data),
365                                                                                  unit_converter(skin.unit_converter),
366                                                                                  ob_arm(skin.ob_arm),
367                                                                                  controller_uid(skin.controller_uid)
368                 {
369                         copy_m4_m4(bind_shape_matrix, (float (*)[4])skin.bind_shape_matrix);
370
371                         transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex);
372                         transfer_uint_array_data_const(skin.weight_indices, weight_indices);
373                         transfer_int_array_data_const(skin.joint_indices, joint_indices);
374                 }
375
376                 SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL) {}
377
378                 // nobody owns the data after this, so it should be freed manually with releaseMemory
379                 template <class T>
380                 void transfer_array_data(T& src, T& dest)
381                 {
382                         dest.setData(src.getData(), src.getCount());
383                         src.yieldOwnerShip();
384                         dest.yieldOwnerShip();
385                 }
386
387                 // when src is const we cannot src.yieldOwnerShip, this is used by copy constructor
388                 void transfer_int_array_data_const(const COLLADAFW::IntValuesArray& src, COLLADAFW::IntValuesArray& dest)
389                 {
390                         dest.setData((int*)src.getData(), src.getCount());
391                         dest.yieldOwnerShip();
392                 }
393
394                 void transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray& src, COLLADAFW::UIntValuesArray& dest)
395                 {
396                         dest.setData((unsigned int*)src.getData(), src.getCount());
397                         dest.yieldOwnerShip();
398                 }
399
400                 void borrow_skin_controller_data(const COLLADAFW::SkinControllerData* skin)
401                 {
402                         transfer_array_data((COLLADAFW::UIntValuesArray&)skin->getJointsPerVertex(), joints_per_vertex);
403                         transfer_array_data((COLLADAFW::UIntValuesArray&)skin->getWeightIndices(), weight_indices);
404                         transfer_array_data((COLLADAFW::IntValuesArray&)skin->getJointIndices(), joint_indices);
405                         // transfer_array_data(skin->getWeights(), weights);
406
407                         // cannot transfer data for FloatOrDoubleArray, copy values manually
408                         const COLLADAFW::FloatOrDoubleArray& weight = skin->getWeights();
409                         for (int i = 0; i < weight.getValuesCount(); i++)
410                                 weights.push_back(get_float_value(weight, i));
411
412                         unit_converter->dae_matrix_to_mat4(bind_shape_matrix, skin->getBindShapeMatrix());
413                 }
414                         
415                 void free()
416                 {
417                         joints_per_vertex.releaseMemory();
418                         weight_indices.releaseMemory();
419                         joint_indices.releaseMemory();
420                         // weights.releaseMemory();
421                 }
422
423                 // using inverse bind matrices to construct armature
424                 // it is safe to invert them to get the original matrices
425                 // because if they are inverse matrices, they can be inverted
426                 void add_joint(const COLLADABU::Math::Matrix4& matrix)
427                 {
428                         JointData jd;
429                         unit_converter->dae_matrix_to_mat4(jd.inv_bind_mat, matrix);
430                         joint_data.push_back(jd);
431                 }
432
433                 // called from write_controller
434                 Object *create_armature(const COLLADAFW::SkinController* co, Scene *scene)
435                 {
436                         ob_arm = add_object(scene, OB_ARMATURE);
437
438                         controller_uid = co->getUniqueId();
439
440                         const COLLADAFW::UniqueIdArray& joint_uids = co->getJoints();
441                         for (int i = 0; i < joint_uids.getCount(); i++) {
442                                 joint_data[i].joint_uid = joint_uids[i];
443
444                                 // // store armature pointer
445                                 // JointData& jd = joint_index_to_joint_info_map[i];
446                                 // jd.ob_arm = ob_arm;
447
448                                 // now we'll be able to get inv bind matrix from joint id
449                                 // joint_id_to_joint_index_map[joint_ids[i]] = i;
450                         }
451
452                         return ob_arm;
453                 }
454
455                 bool get_joint_inv_bind_matrix(float inv_bind_mat[][4], COLLADAFW::Node *node)
456                 {
457                         const COLLADAFW::UniqueId& uid = node->getUniqueId();
458                         std::vector<JointData>::iterator it;
459                         for (it = joint_data.begin(); it != joint_data.end(); it++) {
460                                 if ((*it).joint_uid == uid) {
461                                         copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat);
462                                         return true;
463                                 }
464                         }
465
466                         return false;
467                 }
468
469                 Object *get_armature()
470                 {
471                         return ob_arm;
472                 }
473
474                 const COLLADAFW::UniqueId& get_controller_uid()
475                 {
476                         return controller_uid;
477                 }
478
479                 // some nodes may not be referenced by SkinController,
480                 // in this case to determine if the node belongs to this armature,
481                 // we need to search down the tree
482                 bool uses_joint(COLLADAFW::Node *node)
483                 {
484                         const COLLADAFW::UniqueId& uid = node->getUniqueId();
485                         std::vector<JointData>::iterator it;
486                         for (it = joint_data.begin(); it != joint_data.end(); it++) {
487                                 if ((*it).joint_uid == uid)
488                                         return true;
489                         }
490
491                         COLLADAFW::NodePointerArray& children = node->getChildNodes();
492                         for (int i = 0; i < children.getCount(); i++) {
493                                 if (this->uses_joint(children[i]))
494                                         return true;
495                         }
496
497                         return false;
498                 }
499
500                 void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
501                                                    TransformReader *tm)
502                 {
503                         tm->decompose(bind_shape_matrix, ob->loc, ob->rot, NULL, ob->size);
504
505                         ob->parent = ob_arm;
506                         ob->partype = PARSKEL;
507                         ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
508
509                         ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP;
510
511                         // we need armature matrix here... where do we get it from I wonder...
512                         // root node/joint? or node with <instance_controller>?
513                         float parmat[4][4];
514                         unit_m4(parmat);
515                         invert_m4_m4(ob->parentinv, parmat);
516
517                         // create all vertex groups
518                         std::vector<JointData>::iterator it;
519                         int joint_index;
520                         for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
521                                 const char *name = "Group";
522
523                                 // name group by joint node name
524                                 if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
525                                         name = get_joint_name(joint_by_uid[(*it).joint_uid]);
526                                 }
527
528                                 ED_vgroup_add_name(ob, (char*)name);
529                         }
530
531                         // <vcount> - number of joints per vertex - joints_per_vertex
532                         // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
533                         // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?
534
535                         // for each vertex in weight indices
536                         //   for each bone index in vertex
537                         //     add vertex to group at group index
538                         //     treat group index -1 specially
539
540                         // get def group by index with BLI_findlink
541
542                         for (int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {
543
544                                 int limit = weight + joints_per_vertex[vertex];
545                                 for ( ; weight < limit; weight++) {
546                                         int joint = joint_indices[weight], joint_weight = weight_indices[weight];
547
548                                         // -1 means "weight towards the bind shape", we just don't assign it to any group
549                                         if (joint != -1) {
550                                                 bDeformGroup *def = (bDeformGroup*)BLI_findlink(&ob->defbase, joint);
551
552                                                 ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
553                                         }
554                                 }
555                         }
556
557                         DAG_scene_sort(CTX_data_scene(C));
558                         ED_anim_dag_flush_update(C);
559                         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
560                 }
561
562                 bPoseChannel *get_pose_channel_from_node(COLLADAFW::Node *node)
563                 {
564                         return get_pose_channel(ob_arm->pose, get_joint_name(node));
565                 }
566         };
567
568         std::map<COLLADAFW::UniqueId, SkinInfo> skin_by_data_uid; // data UID = skin controller data UID
569 #if 0
570         JointData *get_joint_data(COLLADAFW::Node *node)
571         {
572                 const COLLADAFW::UniqueId& joint_id = node->getUniqueId();
573
574                 if (joint_id_to_joint_index_map.find(joint_id) == joint_id_to_joint_index_map.end()) {
575                         fprintf(stderr, "Cannot find a joint index by joint id for %s.\n",
576                                         node->getOriginalId().c_str());
577                         return NULL;
578                 }
579
580                 int joint_index = joint_id_to_joint_index_map[joint_id];
581
582                 return &joint_index_to_joint_info_map[joint_index];
583         }
584 #endif
585
586         void create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
587                                          float parent_mat[][4], bArmature *arm)
588         {
589                 float joint_inv_bind_mat[4][4];
590
591                 // JointData* jd = get_joint_data(node);
592
593                 float mat[4][4];
594
595                 if (skin.get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
596                         // get original world-space matrix
597                         invert_m4_m4(mat, joint_inv_bind_mat);
598                 }
599                 // create a bone even if there's no joint data for it (i.e. it has no influence)
600                 else {
601                         float obmat[4][4];
602
603                         // object-space
604                         get_node_mat(obmat, node, NULL, NULL);
605
606                         // get world-space
607                         if (parent)
608                                 mul_m4_m4m4(mat, obmat, parent_mat);
609                         else
610                                 copy_m4_m4(mat, obmat);
611                 }
612
613                 // TODO rename from Node "name" attrs later
614                 EditBone *bone = addEditBone(arm, (char*)get_joint_name(node));
615                 totbone++;
616
617                 if (parent) bone->parent = parent;
618
619                 // set head
620                 copy_v3_v3(bone->head, mat[3]);
621
622                 // set tail, don't set it to head because 0-length bones are not allowed
623                 float vec[3] = {0.0f, 0.5f, 0.0f};
624                 add_v3_v3v3(bone->tail, bone->head, vec);
625
626                 // set parent tail
627                 if (parent && totchild == 1) {
628                         copy_v3_v3(parent->tail, bone->head);
629
630                         // XXX increase this to prevent "very" small bones?
631                         const float epsilon = 0.000001f;
632
633                         // derive leaf bone length
634                         float length = len_v3v3(parent->head, parent->tail);
635                         if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
636                                 leaf_bone_length = length;
637                         }
638
639                         // treat zero-sized bone like a leaf bone
640                         if (length <= epsilon) {
641                                 add_leaf_bone(parent_mat, parent);
642                         }
643
644                         /*
645 #if 0
646                         // and which row in mat is bone direction
647                         float vec[3];
648                         sub_v3_v3v3(vec, parent->tail, parent->head);
649 #ifdef COLLADA_DEBUG
650                         print_v3("tail - head", vec);
651                         print_m4("matrix", parent_mat);
652 #endif
653                         for (int i = 0; i < 3; i++) {
654 #ifdef COLLADA_DEBUG
655                                 char *axis_names[] = {"X", "Y", "Z"};
656                                 printf("%s-axis length is %f\n", axis_names[i], len_v3(parent_mat[i]));
657 #endif
658                                 float angle = angle_v2v2(vec, parent_mat[i]);
659                                 if (angle < min_angle) {
660 #ifdef COLLADA_DEBUG
661                                         print_v3("picking", parent_mat[i]);
662                                         printf("^ %s axis of %s's matrix\n", axis_names[i], get_dae_name(node));
663 #endif
664                                         bone_direction_row = i;
665                                         min_angle = angle;
666                                 }
667                         }
668 #endif
669                         */
670                 }
671
672                 COLLADAFW::NodePointerArray& children = node->getChildNodes();
673                 for (int i = 0; i < children.getCount(); i++) {
674                         create_bone(skin, children[i], bone, children.getCount(), mat, arm);
675                 }
676
677                 // in second case it's not a leaf bone, but we handle it the same way
678                 if (!children.getCount() || children.getCount() > 1) {
679                         add_leaf_bone(mat, bone);
680                 }
681         }
682
683         void add_leaf_bone(float mat[][4], EditBone *bone)
684         {
685                 LeafBone leaf;
686
687                 leaf.bone = bone;
688                 copy_m4_m4(leaf.mat, mat);
689                 BLI_strncpy(leaf.name, bone->name, sizeof(leaf.name));
690
691                 leaf_bones.push_back(leaf);
692         }
693
694         void fix_leaf_bones()
695         {
696                 // just setting tail for leaf bones here
697
698                 std::vector<LeafBone>::iterator it;
699                 for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
700                         LeafBone& leaf = *it;
701
702                         // pointing up
703                         float vec[3] = {0.0f, 0.0f, 1.0f};
704
705                         mul_v3_fl(vec, leaf_bone_length);
706
707                         copy_v3_v3(leaf.bone->tail, leaf.bone->head);
708                         add_v3_v3v3(leaf.bone->tail, leaf.bone->head, vec);
709                 }
710         }
711
712         void set_leaf_bone_shapes(Object *ob_arm)
713         {
714                 bPose *pose = ob_arm->pose;
715
716                 std::vector<LeafBone>::iterator it;
717                 for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
718                         LeafBone& leaf = *it;
719
720                         bPoseChannel *pchan = get_pose_channel(pose, leaf.name);
721                         if (pchan) {
722                                 pchan->custom = get_empty_for_leaves();
723                         }
724                         else {
725                                 fprintf(stderr, "Cannot find a pose channel for leaf bone %s\n", leaf.name);
726                         }
727                 }
728         }
729
730 #if 0
731         void set_euler_rotmode()
732         {
733                 // just set rotmode = ROT_MODE_EUL on pose channel for each joint
734
735                 std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>::iterator it;
736
737                 for (it = joint_by_uid.begin(); it != joint_by_uid.end(); it++) {
738
739                         COLLADAFW::Node *joint = it->second;
740
741                         std::map<COLLADAFW::UniqueId, SkinInfo>::iterator sit;
742                         
743                         for (sit = skin_by_data_uid.begin(); sit != skin_by_data_uid.end(); sit++) {
744                                 SkinInfo& skin = sit->second;
745
746                                 if (skin.uses_joint(joint)) {
747                                         bPoseChannel *pchan = skin.get_pose_channel_from_node(joint);
748
749                                         if (pchan) {
750                                                 pchan->rotmode = ROT_MODE_EUL;
751                                         }
752                                         else {
753                                                 fprintf(stderr, "Cannot find pose channel for %s.\n", get_joint_name(joint));
754                                         }
755
756                                         break;
757                                 }
758                         }
759                 }
760         }
761 #endif
762
763         Object *get_empty_for_leaves()
764         {
765                 if (empty) return empty;
766                 
767                 empty = add_object(scene, OB_EMPTY);
768                 empty->empty_drawtype = OB_EMPTY_SPHERE;
769
770                 return empty;
771         }
772
773 #if 0
774         Object *find_armature(COLLADAFW::Node *node)
775         {
776                 JointData* jd = get_joint_data(node);
777                 if (jd) return jd->ob_arm;
778
779                 COLLADAFW::NodePointerArray& children = node->getChildNodes();
780                 for (int i = 0; i < children.getCount(); i++) {
781                         Object *ob_arm = find_armature(children[i]);
782                         if (ob_arm) return ob_arm;
783                 }
784
785                 return NULL;
786         }
787
788         ArmatureJoints& get_armature_joints(Object *ob_arm)
789         {
790                 // try finding it
791                 std::vector<ArmatureJoints>::iterator it;
792                 for (it = armature_joints.begin(); it != armature_joints.end(); it++) {
793                         if ((*it).ob_arm == ob_arm) return *it;
794                 }
795
796                 // not found, create one
797                 ArmatureJoints aj;
798                 aj.ob_arm = ob_arm;
799                 armature_joints.push_back(aj);
800
801                 return armature_joints.back();
802         }
803 #endif
804
805         void create_armature_bones(SkinInfo& skin)
806         {
807                 // just do like so:
808                 // - get armature
809                 // - enter editmode
810                 // - add edit bones and head/tail properties using matrices and parent-child info
811                 // - exit edit mode
812                 // - set a sphere shape to leaf bones
813
814                 Object *ob_arm = skin.get_armature();
815
816                 // enter armature edit mode
817                 ED_armature_to_edit(ob_arm);
818
819                 leaf_bones.clear();
820                 totbone = 0;
821                 // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row
822                 leaf_bone_length = 0.1f;
823                 // min_angle = 360.0f;          // minimum angle between bone head-tail and a row of bone matrix
824
825                 // create bones
826
827                 std::vector<COLLADAFW::Node*>::iterator it;
828                 for (it = root_joints.begin(); it != root_joints.end(); it++) {
829                         // since root_joints may contain joints for multiple controllers, we need to filter
830                         if (skin.uses_joint(*it)) {
831                                 create_bone(skin, *it, NULL, (*it)->getChildNodes().getCount(), NULL, (bArmature*)ob_arm->data);
832                         }
833                 }
834
835                 fix_leaf_bones();
836
837                 // exit armature edit mode
838                 ED_armature_from_edit(ob_arm);
839                 ED_armature_edit_free(ob_arm);
840                 DAG_id_flush_update(&ob_arm->id, OB_RECALC_OB|OB_RECALC_DATA);
841
842                 set_leaf_bone_shapes(ob_arm);
843
844                 // set_euler_rotmode();
845         }
846         
847
848 public:
849
850         ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, AnimationImporterBase *anim, Scene *sce) :
851                 TransformReader(conv), scene(sce), empty(NULL), mesh_importer(mesh), anim_importer(anim) {}
852
853         ~ArmatureImporter()
854         {
855                 // free skin controller data if we forget to do this earlier
856                 std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
857                 for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
858                         it->second.free();
859                 }
860         }
861
862         // root - if this joint is the top joint in hierarchy, if a joint
863         // is a child of a node (not joint), root should be true since
864         // this is where we build armature bones from
865         void add_joint(COLLADAFW::Node *node, bool root)
866         {
867                 joint_by_uid[node->getUniqueId()] = node;
868                 if (root) root_joints.push_back(node);
869         }
870
871 #if 0
872         void add_root_joint(COLLADAFW::Node *node)
873         {
874                 // root_joints.push_back(node);
875                 Object *ob_arm = find_armature(node);
876                 if (ob_arm)     {
877                         get_armature_joints(ob_arm).root_joints.push_back(node);
878                 }
879 #ifdef COLLADA_DEBUG
880                 else {
881                         fprintf(stderr, "%s cannot be added to armature.\n", get_joint_name(node));
882                 }
883 #endif
884         }
885 #endif
886
887         // here we add bones to armatures, having armatures previously created in write_controller
888         void make_armatures(bContext *C)
889         {
890                 std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
891                 for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
892
893                         SkinInfo& skin = it->second;
894
895                         create_armature_bones(skin);
896
897                         // link armature with an object
898                         Object *ob = mesh_importer->get_object_by_geom_uid(*get_geometry_uid(skin.get_controller_uid()));
899                         if (ob) {
900                                 skin.link_armature(C, ob, joint_by_uid, this);
901                         }
902                         else {
903                                 fprintf(stderr, "Cannot find object to link armature with.\n");
904                         }
905
906                         // free memory stolen from SkinControllerData
907                         skin.free();
908                 }
909         }
910
911 #if 0
912         // link with meshes, create vertex groups, assign weights
913         void link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id)
914         {
915                 Object *ob = mesh_importer->get_object_by_geom_uid(geom_id);
916
917                 if (!ob) {
918                         fprintf(stderr, "Cannot find object by geometry UID.\n");
919                         return;
920                 }
921
922                 if (skin_by_data_uid.find(controller_data_id) == skin_by_data_uid.end()) {
923                         fprintf(stderr, "Cannot find skin info by controller data UID.\n");
924                         return;
925                 }
926
927                 SkinInfo& skin = skin_by_data_uid[conroller_data_id];
928
929                 // create vertex groups
930         }
931 #endif
932
933         bool write_skin_controller_data(const COLLADAFW::SkinControllerData* data)
934         {
935                 // at this stage we get vertex influence info that should go into me->verts and ob->defbase
936                 // there's no info to which object this should be long so we associate it with skin controller data UID
937
938                 // don't forget to call unique_vertexgroup_name before we copy
939
940                 // controller data uid -> [armature] -> joint data, 
941                 // [mesh object]
942                 // 
943
944                 SkinInfo skin(unit_converter);
945                 skin.borrow_skin_controller_data(data);
946
947                 // store join inv bind matrix to use it later in armature construction
948                 const COLLADAFW::Matrix4Array& inv_bind_mats = data->getInverseBindMatrices();
949                 for (int i = 0; i < data->getJointsCount(); i++) {
950                         skin.add_joint(inv_bind_mats[i]);
951                 }
952
953                 skin_by_data_uid[data->getUniqueId()] = skin;
954
955                 return true;
956         }
957
958         bool write_controller(const COLLADAFW::Controller* controller)
959         {
960                 // - create and store armature object
961
962                 const COLLADAFW::UniqueId& skin_id = controller->getUniqueId();
963
964                 if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
965
966                         COLLADAFW::SkinController *co = (COLLADAFW::SkinController*)controller;
967
968                         // to find geom id by controller id
969                         geom_uid_by_controller_uid[skin_id] = co->getSource();
970
971                         const COLLADAFW::UniqueId& data_uid = co->getSkinControllerData();
972                         if (skin_by_data_uid.find(data_uid) == skin_by_data_uid.end()) {
973                                 fprintf(stderr, "Cannot find skin by controller data UID.\n");
974                                 return true;
975                         }
976
977                         Object *ob_arm = skin_by_data_uid[data_uid].create_armature(co, scene);
978
979                         armature_objects.push_back(ob_arm);
980                 }
981                 // morph controller
982                 else {
983                         // shape keys? :)
984                         fprintf(stderr, "Morph controller is not supported yet.\n");
985                 }
986
987                 return true;
988         }
989
990         COLLADAFW::UniqueId *get_geometry_uid(const COLLADAFW::UniqueId& controller_uid)
991         {
992                 if (geom_uid_by_controller_uid.find(controller_uid) == geom_uid_by_controller_uid.end())
993                         return NULL;
994
995                 return &geom_uid_by_controller_uid[controller_uid];
996         }
997
998         Object *get_armature_for_joint(COLLADAFW::Node *node)
999         {
1000                 std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
1001                 for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
1002                         SkinInfo& skin = it->second;
1003
1004                         if (skin.uses_joint(node))
1005                                 return skin.get_armature();
1006                 }
1007
1008                 return NULL;
1009         }
1010
1011         void get_rna_path_for_joint(COLLADAFW::Node *node, char *joint_path, size_t count)
1012         {
1013                 BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", get_joint_name(node));
1014         }
1015         
1016 #if 0
1017         void fix_animation()
1018         {
1019                 /* Change Euler rotation to Quaternion for bone animation */
1020                 std::vector<Object*>::iterator it;
1021                 for (it = armature_objects.begin(); it != armature_objects.end(); it++) {
1022                         Object *ob = *it;
1023                         if (!ob || !ob->adt || !ob->adt->action) continue;
1024                         anim_importer->change_eul_to_quat(ob, ob->adt->action);
1025                 }
1026         }
1027 #endif
1028
1029         // gives a world-space mat
1030         bool get_joint_bind_mat(float m[][4], COLLADAFW::Node *joint)
1031         {
1032                 std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
1033                 bool found = false;
1034                 for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
1035                         SkinInfo& skin = it->second;
1036                         if ((found = skin.get_joint_inv_bind_matrix(m, joint))) {
1037                                 invert_m4(m);
1038                                 break;
1039                         }
1040                 }
1041
1042                 return found;
1043         }
1044 };
1045
1046 class MeshImporter : public MeshImporterBase
1047 {
1048 private:
1049
1050         Scene *scene;
1051         ArmatureImporter *armature_importer;
1052
1053         std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map
1054         std::map<COLLADAFW::UniqueId, Object*> uid_object_map; // geom uid-to-object
1055         // this structure is used to assign material indices to faces
1056         // it holds a portion of Mesh faces and corresponds to a DAE primitive list (<triangles>, <polylist>, etc.)
1057         struct Primitive {
1058                 MFace *mface;
1059                 unsigned int totface;
1060         };
1061         typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap;
1062         std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map; // crazy name!
1063         
1064         class UVDataWrapper
1065         {
1066                 COLLADAFW::MeshVertexData *mVData;
1067         public:
1068                 UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata)
1069                 {}
1070
1071 #ifdef COLLADA_DEBUG
1072                 void print()
1073                 {
1074                         fprintf(stderr, "UVs:\n");
1075                         switch(mVData->getType()) {
1076                         case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
1077                                 {
1078                                         COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
1079                                         if (values->getCount()) {
1080                                                 for (int i = 0; i < values->getCount(); i += 2) {
1081                                                         fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i+1]);
1082                                                 }
1083                                         }
1084                                 }
1085                                 break;
1086                         case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
1087                                 {
1088                                         COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
1089                                         if (values->getCount()) {
1090                                                 for (int i = 0; i < values->getCount(); i += 2) {
1091                                                         fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i+1]);
1092                                                 }
1093                                         }
1094                                 }
1095                                 break;
1096                         }
1097                         fprintf(stderr, "\n");
1098                 }
1099 #endif
1100
1101                 void getUV(int uv_set_index, int uv_index[2], float *uv)
1102                 {
1103                         switch(mVData->getType()) {
1104                         case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
1105                                 {
1106                                         COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
1107                                         if (values->empty()) return;
1108                                         uv[0] = (*values)[uv_index[0]];
1109                                         uv[1] = (*values)[uv_index[1]];
1110                                         
1111                                 }
1112                                 break;
1113                         case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
1114                                 {
1115                                         COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
1116                                         if (values->empty()) return;
1117                                         uv[0] = (float)(*values)[uv_index[0]];
1118                                         uv[1] = (float)(*values)[uv_index[1]];
1119                                         
1120                                 }
1121                                 break;
1122                         case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN:      
1123                         default:
1124                                 fprintf(stderr, "MeshImporter.getUV(): unknown data type\n");
1125                         }
1126                 }
1127         };
1128
1129         void set_face_indices(MFace *mface, unsigned int *indices, bool quad)
1130         {
1131                 mface->v1 = indices[0];
1132                 mface->v2 = indices[1];
1133                 mface->v3 = indices[2];
1134                 if (quad) mface->v4 = indices[3];
1135                 else mface->v4 = 0;
1136 #ifdef COLLADA_DEBUG
1137                 // fprintf(stderr, "%u, %u, %u \n", indices[0], indices[1], indices[2]);
1138 #endif
1139         }
1140
1141         // not used anymore, test_index_face from blenkernel is better
1142 #if 0
1143         // change face indices order so that v4 is not 0
1144         void rotate_face_indices(MFace *mface) {
1145                 mface->v4 = mface->v1;
1146                 mface->v1 = mface->v2;
1147                 mface->v2 = mface->v3;
1148                 mface->v3 = 0;
1149         }
1150 #endif
1151         
1152         void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, int uv_set_index,
1153                                          COLLADAFW::IndexList& index_list, unsigned int *tris_indices)
1154         {
1155                 int uv_indices[4][2];
1156
1157                 // per face vertex indices, this means for quad we have 4 indices, not 8
1158                 COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
1159
1160                 // make indices into FloatOrDoubleArray
1161                 for (int i = 0; i < 3; i++) {
1162                         int uv_index = indices[tris_indices[i]];
1163                         uv_indices[i][0] = uv_index * 2;
1164                         uv_indices[i][1] = uv_index * 2 + 1;
1165                 }
1166
1167                 uvs.getUV(uv_set_index, uv_indices[0], mtface->uv[0]);
1168                 uvs.getUV(uv_set_index, uv_indices[1], mtface->uv[1]);
1169                 uvs.getUV(uv_set_index, uv_indices[2], mtface->uv[2]);
1170         }
1171
1172         void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, int uv_set_index,
1173                                         COLLADAFW::IndexList& index_list, int index, bool quad)
1174         {
1175                 int uv_indices[4][2];
1176
1177                 // per face vertex indices, this means for quad we have 4 indices, not 8
1178                 COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
1179
1180                 // make indices into FloatOrDoubleArray
1181                 for (int i = 0; i < (quad ? 4 : 3); i++) {
1182                         int uv_index = indices[index + i];
1183                         uv_indices[i][0] = uv_index * 2;
1184                         uv_indices[i][1] = uv_index * 2 + 1;
1185                 }
1186
1187                 uvs.getUV(uv_set_index, uv_indices[0], mtface->uv[0]);
1188                 uvs.getUV(uv_set_index, uv_indices[1], mtface->uv[1]);
1189                 uvs.getUV(uv_set_index, uv_indices[2], mtface->uv[2]);
1190
1191                 if (quad) uvs.getUV(uv_set_index, uv_indices[3], mtface->uv[3]);
1192
1193 #ifdef COLLADA_DEBUG
1194                 /*if (quad) {
1195                         fprintf(stderr, "face uv:\n"
1196                                         "((%d, %d), (%d, %d), (%d, %d), (%d, %d))\n"
1197                                         "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
1198
1199                                         uv_indices[0][0], uv_indices[0][1],
1200                                         uv_indices[1][0], uv_indices[1][1],
1201                                         uv_indices[2][0], uv_indices[2][1],
1202                                         uv_indices[3][0], uv_indices[3][1],
1203
1204                                         mtface->uv[0][0], mtface->uv[0][1],
1205                                         mtface->uv[1][0], mtface->uv[1][1],
1206                                         mtface->uv[2][0], mtface->uv[2][1],
1207                                         mtface->uv[3][0], mtface->uv[3][1]);
1208                 }
1209                 else {
1210                         fprintf(stderr, "face uv:\n"
1211                                         "((%d, %d), (%d, %d), (%d, %d))\n"
1212                                         "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
1213
1214                                         uv_indices[0][0], uv_indices[0][1],
1215                                         uv_indices[1][0], uv_indices[1][1],
1216                                         uv_indices[2][0], uv_indices[2][1],
1217
1218                                         mtface->uv[0][0], mtface->uv[0][1],
1219                                         mtface->uv[1][0], mtface->uv[1][1],
1220                                         mtface->uv[2][0], mtface->uv[2][1]);
1221                 }*/
1222 #endif
1223         }
1224
1225 #ifdef COLLADA_DEBUG
1226         void print_index_list(COLLADAFW::IndexList& index_list)
1227         {
1228                 fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str());
1229                 for (int i = 0; i < index_list.getIndicesCount(); i += 2) {
1230                         fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1));
1231                 }
1232                 fprintf(stderr, "\n");
1233         }
1234 #endif
1235
1236         bool is_nice_mesh(COLLADAFW::Mesh *mesh)
1237         {
1238                 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
1239                 int i;
1240
1241                 const char *name = get_dae_name(mesh);
1242                 
1243                 for (i = 0; i < prim_arr.getCount(); i++) {
1244                         
1245                         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
1246                         COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
1247
1248                         const char *type_str = primTypeToStr(type);
1249                         
1250                         // OpenCollada passes POLYGONS type for <polylist>
1251                         if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
1252
1253                                 COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp;
1254                                 COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
1255                                 
1256                                 for(int j = 0; j < vca.getCount(); j++){
1257                                         int count = vca[j];
1258                                         if (count < 3) {
1259                                                 fprintf(stderr, "Primitive %s in %s has at least one face with vertex count < 3\n",
1260                                                                 type_str, name);
1261                                                 return false;
1262                                         }
1263                                 }
1264                                         
1265                         }
1266                         else if(type != COLLADAFW::MeshPrimitive::TRIANGLES) {
1267                                 fprintf(stderr, "Primitive type %s is not supported.\n", type_str);
1268                                 return false;
1269                         }
1270                 }
1271                 
1272                 if (mesh->getPositions().empty()) {
1273                         fprintf(stderr, "Mesh %s has no vertices.\n", name);
1274                         return false;
1275                 }
1276
1277                 return true;
1278         }
1279
1280         void read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
1281         {
1282                 // vertices     
1283                 me->totvert = mesh->getPositions().getFloatValues()->getCount() / 3;
1284                 me->mvert = (MVert*)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
1285
1286                 const COLLADAFW::MeshVertexData& pos = mesh->getPositions();
1287                 MVert *mvert;
1288                 int i, j;
1289
1290                 for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
1291                         j = i * 3;
1292
1293                         if (pos.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT) {
1294                                 const float *array = pos.getFloatValues()->getData();
1295                                 mvert->co[0] = array[j];
1296                                 mvert->co[1] = array[j + 1];
1297                                 mvert->co[2] = array[j + 2];
1298                         }
1299                         else if (pos.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE){
1300                                 const double *array = pos.getDoubleValues()->getData();
1301                                 mvert->co[0] = (float)array[j];
1302                                 mvert->co[1] = (float)array[j + 1];
1303                                 mvert->co[2] = (float)array[j + 2];
1304                         }
1305                         else {
1306                                 fprintf(stderr, "Cannot read vertex positions: unknown data type.\n");
1307                                 break;
1308                         }
1309                 }
1310         }
1311         
1312         int triangulate_poly(unsigned int *indices, int totvert, MVert *verts, std::vector<unsigned int>& tri)
1313         {
1314                 ListBase dispbase;
1315                 DispList *dl;
1316                 float *vert;
1317                 int i = 0;
1318                 
1319                 dispbase.first = dispbase.last = NULL;
1320                 
1321                 dl = (DispList*)MEM_callocN(sizeof(DispList), "poly disp");
1322                 dl->nr = totvert;
1323                 dl->type = DL_POLY;
1324                 dl->parts = 1;
1325                 dl->verts = vert = (float*)MEM_callocN(totvert * 3 * sizeof(float), "poly verts");
1326                 dl->index = (int*)MEM_callocN(sizeof(int) * 3 * totvert, "dl index");
1327
1328                 BLI_addtail(&dispbase, dl);
1329                 
1330                 for (i = 0; i < totvert; i++) {
1331                         copy_v3_v3(vert, verts[indices[i]].co);
1332                         vert += 3;
1333                 }
1334                 
1335                 filldisplist(&dispbase, &dispbase);
1336
1337                 int tottri = 0;
1338                 dl= (DispList*)dispbase.first;
1339
1340                 if (dl->type == DL_INDEX3) {
1341                         tottri = dl->parts;
1342
1343                         int *index = dl->index;
1344                         for (i= 0; i < tottri; i++) {
1345                                 int t[3]= {*index, *(index + 1), *(index + 2)};
1346
1347                                 std::sort(t, t + 3);
1348
1349                                 tri.push_back(t[0]);
1350                                 tri.push_back(t[1]);
1351                                 tri.push_back(t[2]);
1352
1353                                 index += 3;
1354                         }
1355                 }
1356
1357                 freedisplist(&dispbase);
1358
1359                 return tottri;
1360         }
1361         
1362         int count_new_tris(COLLADAFW::Mesh *mesh, Mesh *me)
1363         {
1364                 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
1365                 int i, j;
1366                 int tottri = 0;
1367                 
1368                 for (i = 0; i < prim_arr.getCount(); i++) {
1369                         
1370                         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
1371                         int type = mp->getPrimitiveType();
1372                         size_t prim_totface = mp->getFaceCount();
1373                         unsigned int *indices = mp->getPositionIndices().getData();
1374                         
1375                         if (type == COLLADAFW::MeshPrimitive::POLYLIST ||
1376                                 type == COLLADAFW::MeshPrimitive::POLYGONS) {
1377                                 
1378                                 COLLADAFW::Polygons *mpvc =     (COLLADAFW::Polygons*)mp;
1379                                 COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
1380                                 
1381                                 for (j = 0; j < prim_totface; j++) {
1382                                         int vcount = vcounta[j];
1383                                         
1384                                         if (vcount > 4) {
1385                                                 std::vector<unsigned int> tri;
1386                                                 
1387                                                 // tottri += triangulate_poly(indices, vcount, me->mvert, tri) - 1; // XXX why - 1?!
1388                                                 tottri += triangulate_poly(indices, vcount, me->mvert, tri);
1389                                         }
1390
1391                                         indices += vcount;
1392                                 }
1393                         }
1394                 }
1395                 return tottri;
1396         }
1397         
1398         // TODO: import uv set names
1399         void read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris)
1400         {
1401                 int i;
1402                 
1403                 // allocate faces
1404                 me->totface = mesh->getFacesCount() + new_tris;
1405                 me->mface = (MFace*)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
1406                 
1407                 // allocate UV layers
1408                 int totuvset = mesh->getUVCoords().getInputInfosArray().getCount();
1409
1410                 for (i = 0; i < totuvset; i++) {
1411                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface);
1412                         //this->set_layername_map[i] = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
1413                 }
1414
1415                 // activate the first uv layer
1416                 if (totuvset) me->mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, 0);
1417
1418                 UVDataWrapper uvs(mesh->getUVCoords());
1419
1420 #ifdef COLLADA_DEBUG
1421                 // uvs.print();
1422 #endif
1423
1424                 MFace *mface = me->mface;
1425
1426                 MaterialIdPrimitiveArrayMap mat_prim_map;
1427
1428                 int face_index = 0;
1429
1430                 COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
1431
1432                 for (i = 0; i < prim_arr.getCount(); i++) {
1433                         
1434                         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
1435
1436                         // faces
1437                         size_t prim_totface = mp->getFaceCount();
1438                         unsigned int *indices = mp->getPositionIndices().getData();
1439                         int j, k;
1440                         int type = mp->getPrimitiveType();
1441                         int index = 0;
1442                         
1443                         // since we cannot set mface->mat_nr here, we store a portion of me->mface in Primitive
1444                         Primitive prim = {mface, 0};
1445                         COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray();
1446
1447 #ifdef COLLADA_DEBUG
1448                         /*
1449                         fprintf(stderr, "Primitive %d:\n", i);
1450                         for (int j = 0; j < totuvset; j++) {
1451                                 print_index_list(*index_list_array[j]);
1452                         }
1453                         */
1454 #endif
1455                         
1456                         if (type == COLLADAFW::MeshPrimitive::TRIANGLES) {
1457                                 for (j = 0; j < prim_totface; j++){
1458                                         
1459                                         set_face_indices(mface, indices, false);
1460                                         indices += 3;
1461
1462                                         for (k = 0; k < totuvset; k++) {
1463                                                 // get mtface by face index and uv set index
1464                                                 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
1465                                                 set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false);
1466                                         }
1467
1468                                         test_index_face(mface, &me->fdata, face_index, 3);
1469                                         
1470                                         index += 3;
1471                                         mface++;
1472                                         face_index++;
1473                                         prim.totface++;
1474                                 }
1475                         }
1476                         else if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
1477                                 COLLADAFW::Polygons *mpvc =     (COLLADAFW::Polygons*)mp;
1478                                 COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
1479                                 
1480                                 for (j = 0; j < prim_totface; j++) {
1481                                         
1482                                         // face
1483                                         int vcount = vcounta[j];
1484                                         if (vcount == 3 || vcount == 4) {
1485                                                 
1486                                                 set_face_indices(mface, indices, vcount == 4);
1487                                                 
1488                                                 // set mtface for each uv set
1489                                                 // it is assumed that all primitives have equal number of UV sets
1490                                                 
1491                                                 for (k = 0; k < totuvset; k++) {
1492                                                         // get mtface by face index and uv set index
1493                                                         MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
1494                                                         set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0);
1495                                                 }
1496
1497                                                 test_index_face(mface, &me->fdata, face_index, vcount);
1498                                                 
1499                                                 mface++;
1500                                                 face_index++;
1501                                                 prim.totface++;
1502                                                 
1503                                         }
1504                                         else {
1505                                                 std::vector<unsigned int> tri;
1506                                                 
1507                                                 triangulate_poly(indices, vcount, me->mvert, tri);
1508                                                 
1509                                                 for (k = 0; k < tri.size() / 3; k++) {
1510                                                         int v = k * 3;
1511                                                         unsigned int uv_indices[3] = {
1512                                                                 index + tri[v],
1513                                                                 index + tri[v + 1],
1514                                                                 index + tri[v + 2]
1515                                                         };
1516                                                         unsigned int tri_indices[3] = {
1517                                                                 indices[tri[v]],
1518                                                                 indices[tri[v + 1]],
1519                                                                 indices[tri[v + 2]]
1520                                                         };
1521
1522                                                         set_face_indices(mface, tri_indices, false);
1523                                                         
1524                                                         for (int l = 0; l < totuvset; l++) {
1525                                                                 // get mtface by face index and uv set index
1526                                                                 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, l);
1527                                                                 set_face_uv(&mtface[face_index], uvs, l, *index_list_array[l], uv_indices);
1528                                                         }
1529
1530                                                         test_index_face(mface, &me->fdata, face_index, 3);
1531                                                         
1532                                                         mface++;
1533                                                         face_index++;
1534                                                         prim.totface++;
1535                                                 }
1536                                         }
1537
1538                                         index += vcount;
1539                                         indices += vcount;
1540                                 }
1541                         }
1542                         
1543                         mat_prim_map[mp->getMaterialId()].push_back(prim);
1544                 }
1545
1546                 geom_uid_mat_mapping_map[mesh->getUniqueId()] = mat_prim_map;
1547         }
1548
1549 public:
1550
1551         MeshImporter(ArmatureImporter *arm, Scene *sce) : scene(sce), armature_importer(arm) {}
1552
1553         virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid)
1554         {
1555                 if (uid_object_map.find(geom_uid) != uid_object_map.end())
1556                         return uid_object_map[geom_uid];
1557                 return NULL;
1558         }
1559         
1560         MTex *assign_textures_to_uvlayer(COLLADAFW::InstanceGeometry::TextureCoordinateBinding &ctexture,
1561                                                                          Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
1562                                                                          MTex *color_texture)
1563         {
1564                 
1565                 COLLADAFW::TextureMapId texture_index = ctexture.textureMapId;
1566                 
1567                 char *uvname = CustomData_get_layer_name(&me->fdata, CD_MTFACE, ctexture.setIndex);
1568                 
1569                 if (texindex_texarray_map.find(texture_index) == texindex_texarray_map.end()) {
1570                         
1571                         fprintf(stderr, "Cannot find texture array by texture index.\n");
1572                         return color_texture;
1573                 }
1574                 
1575                 std::vector<MTex*> textures = texindex_texarray_map[texture_index];
1576                 
1577                 std::vector<MTex*>::iterator it;
1578                 
1579                 for (it = textures.begin(); it != textures.end(); it++) {
1580                         
1581                         MTex *texture = *it;
1582                         
1583                         if (texture) {
1584                                 strcpy(texture->uvname, uvname);
1585                                 if (texture->mapto == MAP_COL) color_texture = texture;
1586                         }
1587                 }
1588                 return color_texture;
1589         }
1590         
1591         MTFace *assign_material_to_geom(COLLADAFW::InstanceGeometry::MaterialBinding cmaterial,
1592                                                                         std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
1593                                                                         Object *ob, const COLLADAFW::UniqueId *geom_uid, 
1594                                                                         MTex **color_texture, char *layername, MTFace *texture_face,
1595                                                                         std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, int mat_index)
1596         {
1597                 Mesh *me = (Mesh*)ob->data;
1598                 const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
1599                 
1600                 // do we know this material?
1601                 if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
1602                         
1603                         fprintf(stderr, "Cannot find material by UID.\n");
1604                         return NULL;
1605                 }
1606                 
1607                 Material *ma = uid_material_map[ma_uid];
1608                 assign_material(ob, ma, ob->totcol + 1);
1609                 
1610                 COLLADAFW::InstanceGeometry::TextureCoordinateBindingArray& tex_array = 
1611                         cmaterial.getTextureCoordinateBindingArray();
1612                 TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
1613                 unsigned int i;
1614                 // loop through <bind_vertex_inputs>
1615                 for (i = 0; i < tex_array.getCount(); i++) {
1616                         
1617                         *color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
1618                                                                                                                 *color_texture);
1619                 }
1620                 
1621                 // set texture face
1622                 if (*color_texture &&
1623                         strlen((*color_texture)->uvname) &&
1624                         strcmp(layername, (*color_texture)->uvname) != 0) {
1625                         
1626                         texture_face = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
1627                                                                                                                            (*color_texture)->uvname);
1628                         strcpy(layername, (*color_texture)->uvname);
1629                 }
1630                 
1631                 MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
1632                 COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
1633                 
1634                 // assign material indices to mesh faces
1635                 if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
1636                         
1637                         std::vector<Primitive>& prims = mat_prim_map[mat_id];
1638                         
1639                         std::vector<Primitive>::iterator it;
1640                         
1641                         for (it = prims.begin(); it != prims.end(); it++) {
1642                                 Primitive& prim = *it;
1643                                 i = 0;
1644                                 while (i++ < prim.totface) {
1645                                         prim.mface->mat_nr = mat_index;
1646                                         prim.mface++;
1647                                         // bind texture images to faces
1648                                         if (texture_face && (*color_texture)) {
1649                                                 texture_face->mode = TF_TEX;
1650                                                 texture_face->tpage = (Image*)(*color_texture)->tex->ima;
1651                                                 texture_face++;
1652                                         }
1653                                 }
1654                         }
1655                 }
1656                 
1657                 return texture_face;
1658         }
1659         
1660         
1661         Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
1662                                                            bool isController,
1663                                                            std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
1664                                                            std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map)
1665         {
1666                 const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
1667                 
1668                 // check if node instanciates controller or geometry
1669                 if (isController) {
1670                         
1671                         geom_uid = armature_importer->get_geometry_uid(*geom_uid);
1672                         
1673                         if (!geom_uid) {
1674                                 fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
1675                                 return NULL;
1676                         }
1677                 }
1678                 else {
1679                         
1680                         if (uid_mesh_map.find(*geom_uid) == uid_mesh_map.end()) {
1681                                 // this could happen if a mesh was not created
1682                                 // (e.g. if it contains unsupported geometry)
1683                                 fprintf(stderr, "Couldn't find a mesh by UID.\n");
1684                                 return NULL;
1685                         }
1686                 }
1687                 if (!uid_mesh_map[*geom_uid]) return NULL;
1688                 
1689                 Object *ob = add_object(scene, OB_MESH);
1690
1691                 // store object pointer for ArmatureImporter
1692                 uid_object_map[*geom_uid] = ob;
1693                 
1694                 // name Object
1695                 const std::string& id = node->getOriginalId();
1696                 if (id.length())
1697                         rename_id(&ob->id, (char*)id.c_str());
1698                 
1699                 // replace ob->data freeing the old one
1700                 Mesh *old_mesh = (Mesh*)ob->data;
1701
1702                 set_mesh(ob, uid_mesh_map[*geom_uid]);
1703                 
1704                 if (old_mesh->id.us == 0) free_libblock(&G.main->mesh, old_mesh);
1705                 
1706                 char layername[100];
1707                 MTFace *texture_face = NULL;
1708                 MTex *color_texture = NULL;
1709                 
1710                 COLLADAFW::InstanceGeometry::MaterialBindingArray& mat_array = 
1711                         geom->getMaterialBindings();
1712                 
1713                 // loop through geom's materials
1714                 for (unsigned int i = 0; i < mat_array.getCount(); i++) {
1715                         
1716                         texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
1717                                                                                                    &color_texture, layername, texture_face,
1718                                                                                                    material_texture_mapping_map, i);
1719                 }
1720                         
1721                 return ob;
1722         }
1723
1724         // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
1725         bool write_geometry(const COLLADAFW::Geometry* geom) 
1726         {
1727                 // TODO: import also uvs, normals
1728                 // XXX what to do with normal indices?
1729                 // XXX num_normals may be != num verts, then what to do?
1730
1731                 // check geometry->getType() first
1732                 if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
1733                         // TODO: report warning
1734                         fprintf(stderr, "Mesh type %s is not supported\n", geomTypeToStr(geom->getType()));
1735                         return true;
1736                 }
1737                 
1738                 COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh*)geom;
1739                 
1740                 if (!is_nice_mesh(mesh)) {
1741                         fprintf(stderr, "Ignoring mesh %s\n", get_dae_name(mesh));
1742                         return true;
1743                 }
1744                 
1745                 const std::string& str_geom_id = mesh->getOriginalId();
1746                 Mesh *me = add_mesh((char*)str_geom_id.c_str());
1747
1748                 // store the Mesh pointer to link it later with an Object
1749                 this->uid_mesh_map[mesh->getUniqueId()] = me;
1750                 
1751                 int new_tris = 0;
1752                 
1753                 read_vertices(mesh, me);
1754
1755                 new_tris = count_new_tris(mesh, me);
1756                 
1757                 read_faces(mesh, me, new_tris);
1758
1759                 make_edges(me, 0);
1760                 
1761                 mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
1762
1763                 return true;
1764         }
1765
1766 };
1767
1768 class AnimationImporter : private TransformReader, public AnimationImporterBase
1769 {
1770 private:
1771
1772         ArmatureImporter *armature_importer;
1773         Scene *scene;
1774
1775         std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > curve_map;
1776         std::map<COLLADAFW::UniqueId, TransformReader::Animation> uid_animated_map;
1777         // std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map;
1778         std::map<COLLADAFW::UniqueId, const COLLADAFW::AnimationList*> animlist_map;
1779         std::vector<FCurve*> unused_curves;
1780         std::map<COLLADAFW::UniqueId, Object*> joint_objects;
1781         
1782         FCurve *create_fcurve(int array_index, const char *rna_path)
1783         {
1784                 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1785                 
1786                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1787                 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
1788                 fcu->array_index = array_index;
1789                 return fcu;
1790         }
1791         
1792         void create_bezt(FCurve *fcu, float frame, float output)
1793         {
1794                 BezTriple bez;
1795                 memset(&bez, 0, sizeof(BezTriple));
1796                 bez.vec[1][0] = frame;
1797                 bez.vec[1][1] = output;
1798                 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1799                 bez.f1 = bez.f2 = bez.f3 = SELECT;
1800                 bez.h1 = bez.h2 = HD_AUTO;
1801                 insert_bezt_fcurve(fcu, &bez, 0);
1802                 calchandles_fcurve(fcu);
1803         }
1804
1805         // create one or several fcurves depending on the number of parameters being animated
1806         void animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
1807         {
1808                 COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
1809                 COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
1810                 // COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
1811                 // COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
1812                 float fps = (float)FPS;
1813                 size_t dim = curve->getOutDimension();
1814                 int i;
1815
1816                 std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
1817
1818                 if (dim == 1) {
1819                         FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1820
1821                         fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1822                         // fcu->rna_path = BLI_strdupn(path, strlen(path));
1823                         fcu->array_index = 0;
1824                         //fcu->totvert = curve->getKeyCount();
1825                         
1826                         // create beztriple for each key
1827                         for (i = 0; i < curve->getKeyCount(); i++) {
1828                                 BezTriple bez;
1829                                 memset(&bez, 0, sizeof(BezTriple));
1830
1831                                 // intangent
1832                                 // bez.vec[0][0] = get_float_value(intan, i + i) * fps;
1833                                 // bez.vec[0][1] = get_float_value(intan, i + i + 1);
1834
1835                                 // input, output
1836                                 bez.vec[1][0] = get_float_value(input, i) * fps;
1837                                 bez.vec[1][1] = get_float_value(output, i);
1838
1839                                 // outtangent
1840                                 // bez.vec[2][0] = get_float_value(outtan, i + i) * fps;
1841                                 // bez.vec[2][1] = get_float_value(outtan, i + i + 1);
1842                                 
1843                                 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1844                                 bez.f1 = bez.f2 = bez.f3 = SELECT;
1845                                 bez.h1 = bez.h2 = HD_AUTO;
1846                                 insert_bezt_fcurve(fcu, &bez, 0);
1847                         }
1848
1849                         calchandles_fcurve(fcu);
1850
1851                         fcurves.push_back(fcu);
1852                 }
1853                 else if(dim == 3) {
1854                         for (i = 0; i < dim; i++ ) {
1855                                 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1856                                 
1857                                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1858                                 // fcu->rna_path = BLI_strdupn(path, strlen(path));
1859                                 fcu->array_index = 0;
1860                                 //fcu->totvert = curve->getKeyCount();
1861                                 
1862                                 // create beztriple for each key
1863                                 for (int j = 0; j < curve->getKeyCount(); j++) {
1864                                         BezTriple bez;
1865                                         memset(&bez, 0, sizeof(BezTriple));
1866
1867                                         // intangent
1868                                         // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps;
1869                                         // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1);
1870
1871                                         // input, output
1872                                         bez.vec[1][0] = get_float_value(input, j) * fps; 
1873                                         bez.vec[1][1] = get_float_value(output, j * 3 + i);
1874
1875                                         // outtangent
1876                                         // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps;
1877                                         // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1);
1878
1879                                         bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1880                                         bez.f1 = bez.f2 = bez.f3 = SELECT;
1881                                         bez.h1 = bez.h2 = HD_AUTO;
1882                                         insert_bezt_fcurve(fcu, &bez, 0);
1883                                 }
1884
1885                                 calchandles_fcurve(fcu);
1886
1887                                 fcurves.push_back(fcu);
1888                         }
1889                 }
1890
1891                 for (std::vector<FCurve*>::iterator it = fcurves.begin(); it != fcurves.end(); it++)
1892                         unused_curves.push_back(*it);
1893         }
1894
1895         void fcurve_deg_to_rad(FCurve *cu)
1896         {
1897                 for (int i = 0; i < cu->totvert; i++) {
1898                         // TODO convert handles too
1899                         cu->bezt[i].vec[1][1] *= M_PI / 180.0f;
1900                 }
1901         }
1902
1903 #if 0
1904         void make_fcurves_from_animation(COLLADAFW::AnimationCurve *curve,
1905                                                                          COLLADAFW::FloatOrDoubleArray& input,
1906                                                                          COLLADAFW::FloatOrDoubleArray& output,
1907                                                                          COLLADAFW::FloatOrDoubleArray& intan,
1908                                                                          COLLADAFW::FloatOrDoubleArray& outtan, size_t dim, float fps)
1909         {
1910                 int i;
1911                 // char *path = "location";
1912                 std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
1913
1914                 if (dim == 1) {
1915                         // create fcurve
1916                         FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1917
1918                         fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1919                         // fcu->rna_path = BLI_strdupn(path, strlen(path));
1920                         fcu->array_index = 0;
1921                         //fcu->totvert = curve->getKeyCount();
1922                         
1923                         // create beztriple for each key
1924                         for (i = 0; i < curve->getKeyCount(); i++) {
1925                                 BezTriple bez;
1926                                 memset(&bez, 0, sizeof(BezTriple));
1927                                 // intangent
1928                                 bez.vec[0][0] = get_float_value(intan, i + i) * fps;
1929                                 bez.vec[0][1] = get_float_value(intan, i + i + 1);
1930                                 // input, output
1931                                 bez.vec[1][0] = get_float_value(input, i) * fps;
1932                                 bez.vec[1][1] = get_float_value(output, i);
1933                                 // outtangent
1934                                 bez.vec[2][0] = get_float_value(outtan, i + i) * fps;
1935                                 bez.vec[2][1] = get_float_value(outtan, i + i + 1);
1936                                 
1937                                 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1938                                 bez.f1 = bez.f2 = bez.f3 = SELECT;
1939                                 bez.h1 = bez.h2 = HD_AUTO;
1940                                 insert_bezt_fcurve(fcu, &bez, 0);
1941                                 calchandles_fcurve(fcu);
1942                         }
1943
1944                         fcurves.push_back(fcu);
1945                 }
1946                 else if(dim == 3) {
1947                         for (i = 0; i < dim; i++ ) {
1948                                 // create fcurve
1949                                 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1950                                 
1951                                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1952                                 // fcu->rna_path = BLI_strdupn(path, strlen(path));
1953                                 fcu->array_index = 0;
1954                                 //fcu->totvert = curve->getKeyCount();
1955                                 
1956                                 // create beztriple for each key
1957                                 for (int j = 0; j < curve->getKeyCount(); j++) {
1958                                         BezTriple bez;
1959                                         memset(&bez, 0, sizeof(BezTriple));
1960                                         // intangent
1961                                         bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps;
1962                                         bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1);
1963                                         // input, output
1964                                         bez.vec[1][0] = get_float_value(input, j) * fps; 
1965                                         bez.vec[1][1] = get_float_value(output, j * 3 + i);
1966                                         // outtangent
1967                                         bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps;
1968                                         bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1);
1969
1970                                         bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1971                                         bez.f1 = bez.f2 = bez.f3 = SELECT;
1972                                         bez.h1 = bez.h2 = HD_AUTO;
1973                                         insert_bezt_fcurve(fcu, &bez, 0);
1974                                         calchandles_fcurve(fcu);
1975                                 }
1976
1977                                 fcurves.push_back(fcu);
1978                         }
1979                 }
1980         }
1981 #endif
1982         
1983         void add_fcurves_to_object(Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated)
1984         {
1985                 bAction *act;
1986                 
1987                 if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1);
1988                 else act = ob->adt->action;
1989                 
1990                 std::vector<FCurve*>::iterator it;
1991                 int i;
1992
1993 #if 0
1994                 char *p = strstr(rna_path, "rotation_euler");
1995                 bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0';
1996
1997                 // convert degrees to radians for rotation
1998                 if (is_rotation)
1999                         fcurve_deg_to_rad(fcu);
2000 #endif
2001                 
2002                 for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) {
2003                         FCurve *fcu = *it;
2004                         fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
2005                         
2006                         if (array_index == -1) fcu->array_index = i;
2007                         else fcu->array_index = array_index;
2008                 
2009                         if (ob->type == OB_ARMATURE) {
2010                                 bActionGroup *grp = NULL;
2011                                 const char *bone_name = get_joint_name(animated->node);
2012                                 
2013                                 if (bone_name) {
2014                                         /* try to find group */
2015                                         grp = action_groups_find_named(act, bone_name);
2016                                         
2017                                         /* no matching groups, so add one */
2018                                         if (grp == NULL) {
2019                                                 /* Add a new group, and make it active */
2020                                                 grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
2021                                                 
2022                                                 grp->flag = AGRP_SELECTED;
2023                                                 BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
2024                                                 
2025                                                 BLI_addtail(&act->groups, grp);
2026                                                 BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
2027                                         }
2028                                         
2029                                         /* add F-Curve to group */
2030                                         action_groups_add_channel(act, grp, fcu);
2031                                         
2032                                 }
2033 #if 0
2034                                 if (is_rotation) {
2035                                         fcurves_actionGroup_map[grp].push_back(fcu);
2036                                 }
2037 #endif
2038                         }
2039                         else {
2040                                 BLI_addtail(&act->curves, fcu);
2041                         }
2042
2043                         // curve is used, so remove it from unused_curves
2044                         unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
2045                 }
2046         }
2047 public:
2048
2049         AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
2050                 TransformReader(conv), armature_importer(arm), scene(scene) { }
2051
2052         ~AnimationImporter()
2053         {
2054                 // free unused FCurves
2055                 for (std::vector<FCurve*>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++)
2056                         free_fcurve(*it);
2057
2058                 if (unused_curves.size())
2059                         fprintf(stderr, "removed %u unused curves\n", unused_curves.size());
2060         }
2061
2062         bool write_animation(const COLLADAFW::Animation* anim) 
2063         {
2064                 if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
2065                         COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve*)anim;
2066                         
2067                         // XXX Don't know if it's necessary
2068                         // Should we check outPhysicalDimension?
2069                         if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) {
2070                                 fprintf(stderr, "Inputs physical dimension is not time. \n");
2071                                 return true;
2072                         }
2073
2074                         // a curve can have mixed interpolation type,
2075                         // in this case curve->getInterpolationTypes returns a list of interpolation types per key
2076                         COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
2077
2078                         if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
2079                                 switch (interp) {
2080                                 case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
2081                                 case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
2082                                         animation_to_fcurves(curve);
2083                                         break;
2084                                 default:
2085                                         // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types
2086                                         fprintf(stderr, "CARDINAL, HERMITE, BSPLINE and STEP anim interpolation types not supported yet.\n");
2087                                         break;
2088                                 }
2089                         }
2090                         else {
2091                                 // not supported yet
2092                                 fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n");
2093                         }
2094                 }
2095                 else {
2096                         fprintf(stderr, "FORMULA animation type is not supported yet.\n");
2097                 }
2098                 
2099                 return true;
2100         }
2101         
2102         // called on post-process stage after writeVisualScenes
2103         bool write_animation_list(const COLLADAFW::AnimationList* animlist) 
2104         {
2105                 const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
2106
2107                 animlist_map[animlist_id] = animlist;
2108
2109 #if 0
2110                 // should not happen
2111                 if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
2112                         return true;
2113                 }
2114
2115                 // for bones rna_path is like: pose.bones["bone-name"].rotation
2116                 
2117                 // what does this AnimationList animate?
2118                 Animation& animated = uid_animated_map[animlist_id];
2119                 Object *ob = animated.ob;
2120
2121                 char rna_path[100];
2122                 char joint_path[100];
2123                 bool is_joint = false;
2124
2125                 // if ob is NULL, it should be a JOINT
2126                 if (!ob) {
2127                         ob = armature_importer->get_armature_for_joint(animated.node);
2128
2129                         if (!ob) {
2130                                 fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node));
2131                                 return true;
2132                         }
2133
2134                         armature_importer->get_rna_path_for_joint(animated.node, joint_path, sizeof(joint_path));
2135
2136                         is_joint = true;
2137                 }
2138                 
2139                 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
2140
2141                 switch (animated.tm->getTransformationType()) {
2142                 case COLLADAFW::Transformation::TRANSLATE:
2143                 case COLLADAFW::Transformation::SCALE:
2144                         {
2145                                 bool loc = animated.tm->getTransformationType() == COLLADAFW::Transformation::TRANSLATE;
2146                                 if (is_joint)
2147                                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
2148                                 else
2149                                         BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
2150
2151                                 for (int i = 0; i < bindings.getCount(); i++) {
2152                                         const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
2153                                         COLLADAFW::UniqueId anim_uid = binding.animation;
2154
2155                                         if (curve_map.find(anim_uid) == curve_map.end()) {
2156                                                 fprintf(stderr, "Cannot find FCurve by animation UID.\n");
2157                                                 continue;
2158                                         }
2159
2160                                         std::vector<FCurve*>& fcurves = curve_map[anim_uid];
2161                                         
2162                                         switch (binding.animationClass) {
2163                                         case COLLADAFW::AnimationList::POSITION_X:
2164                                                 add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated);
2165                                                 break;
2166                                         case COLLADAFW::AnimationList::POSITION_Y:
2167                                                 add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated);
2168                                                 break;
2169                                         case COLLADAFW::AnimationList::POSITION_Z:
2170                                                 add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated);
2171                                                 break;
2172                                         case COLLADAFW::AnimationList::POSITION_XYZ:
2173                                                 add_fcurves_to_object(ob, fcurves, rna_path, -1, &animated);
2174                                                 break;
2175                                         default:
2176                                                 fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
2177                                                                 binding.animationClass, loc ? "TRANSLATE" : "SCALE");
2178                                         }
2179                                 }
2180                         }
2181                         break;
2182                 case COLLADAFW::Transformation::ROTATE:
2183                         {
2184                                 if (is_joint)
2185                                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
2186                                 else
2187                                         BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
2188
2189                                 COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)animated.tm;
2190                                 COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
2191                                 
2192                                 for (int i = 0; i < bindings.getCount(); i++) {
2193                                         const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
2194                                         COLLADAFW::UniqueId anim_uid = binding.animation;
2195
2196                                         if (curve_map.find(anim_uid) == curve_map.end()) {
2197                                                 fprintf(stderr, "Cannot find FCurve by animation UID.\n");
2198                                                 continue;
2199                                         }
2200
2201                                         std::vector<FCurve*>& fcurves = curve_map[anim_uid];
2202
2203                                         switch (binding.animationClass) {
2204                                         case COLLADAFW::AnimationList::ANGLE:
2205                                                 if (COLLADABU::Math::Vector3::UNIT_X == axis) {
2206                                                         add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated);
2207                                                 }
2208                                                 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
2209                                                         add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated);
2210                                                 }
2211                                                 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
2212                                                         add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated);
2213                                                 }
2214                                                 break;
2215                                         case COLLADAFW::AnimationList::AXISANGLE:
2216                                                 // TODO convert axis-angle to quat? or XYZ?
2217                                         default:
2218                                                 fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
2219                                                                 binding.animationClass);
2220                                         }
2221                                 }
2222                         }
2223                         break;
2224                 case COLLADAFW::Transformation::MATRIX:
2225                 case COLLADAFW::Transformation::SKEW:
2226                 case COLLADAFW::Transformation::LOOKAT:
2227                         fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
2228                         break;
2229                 }
2230 #endif
2231                 
2232                 return true;
2233         }
2234
2235         void read_node_transform(COLLADAFW::Node *node, Object *ob)
2236         {
2237                 float mat[4][4];
2238                 TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
2239                 if (ob)
2240                         TransformReader::decompose(mat, ob->loc, ob->rot, NULL, ob->size);
2241         }
2242         
2243 #if 0
2244         virtual void change_eul_to_quat(Object *ob, bAction *act)
2245         {
2246                 bActionGroup *grp;
2247                 int i;
2248                 
2249                 for (grp = (bActionGroup*)act->groups.first; grp; grp = grp->next) {
2250
2251                         FCurve *eulcu[3] = {NULL, NULL, NULL};
2252                         
2253                         if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end())
2254                                 continue;
2255
2256                         std::vector<FCurve*> &rot_fcurves = fcurves_actionGroup_map[grp];
2257                         
2258                         if (rot_fcurves.size() > 3) continue;
2259
2260                         for (i = 0; i < rot_fcurves.size(); i++)
2261                                 eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i];
2262
2263                         char joint_path[100];
2264                         char rna_path[100];
2265
2266                         BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name);
2267                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path);
2268
2269                         FCurve *quatcu[4] = {
2270                                 create_fcurve(0, rna_path),
2271                                 create_fcurve(1, rna_path),
2272                                 create_fcurve(2, rna_path),
2273                                 create_fcurve(3, rna_path)
2274                         };
2275
2276                         bPoseChannel *chan = get_pose_channel(ob->pose, grp->name);
2277
2278                         float m4[4][4], irest[3][3];
2279                         invert_m4_m4(m4, chan->bone->arm_mat);
2280                         copy_m3_m4(irest, m4);
2281
2282                         for (i = 0; i < 3; i++) {
2283
2284                                 FCurve *cu = eulcu[i];
2285
2286                                 if (!cu) continue;
2287
2288                                 for (int j = 0; j < cu->totvert; j++) {
2289                                         float frame = cu->bezt[j].vec[1][0];
2290
2291                                         float eul[3] = {
2292                                                 eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f,
2293                                                 eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f,
2294                                                 eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f
2295                                         };
2296
2297                                         // make eul relative to bone rest pose
2298                                         float rot[3][3], rel[3][3], quat[4];
2299
2300                                         /*eul_to_mat3(rot, eul);
2301
2302                                         mul_m3_m3m3(rel, irest, rot);
2303
2304                                         mat3_to_quat(quat, rel);
2305                                         */
2306
2307                                         eul_to_quat(quat, eul);
2308
2309                                         for (int k = 0; k < 4; k++)
2310                                                 create_bezt(quatcu[k], frame, quat[k]);
2311                                 }
2312                         }
2313
2314                         // now replace old Euler curves
2315
2316                         for (i = 0; i < 3; i++) {
2317                                 if (!eulcu[i]) continue;
2318
2319                                 action_groups_remove_channel(act, eulcu[i]);
2320                                 free_fcurve(eulcu[i]);
2321                         }
2322
2323                         chan->rotmode = ROT_MODE_QUAT;
2324
2325                         for (i = 0; i < 4; i++)
2326                                 action_groups_add_channel(act, grp, quatcu[i]);
2327                 }
2328
2329                 bPoseChannel *pchan;
2330                 for (pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
2331                         pchan->rotmode = ROT_MODE_QUAT;
2332                 }
2333         }
2334 #endif
2335
2336         // prerequisites:
2337         // animlist_map - map animlist id -> animlist
2338         // curve_map - map anim id -> curve(s)
2339 #ifdef ARMATURE_TEST
2340         Object *translate_animation(COLLADAFW::Node *node,
2341                                                                 std::map<COLLADAFW::UniqueId, Object*>& object_map,
2342                                                                 std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
2343                                                                 COLLADAFW::Transformation::TransformationType tm_type,
2344                                                                 Object *par_job = NULL)
2345 #else
2346         void translate_animation(COLLADAFW::Node *node,
2347                                                          std::map<COLLADAFW::UniqueId, Object*>& object_map,
2348                                                          std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
2349                                                          COLLADAFW::Transformation::TransformationType tm_type)
2350 #endif
2351         {
2352                 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
2353                 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
2354                 COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
2355                 Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
2356                 const char *bone_name = is_joint ? get_joint_name(node) : NULL;
2357
2358                 if (!ob) {
2359                         fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
2360 #ifdef ARMATURE_TEST
2361                         return NULL;
2362 #else
2363                         return;
2364 #endif
2365                 }
2366
2367                 // frames at which to sample
2368                 std::vector<float> frames;
2369
2370                 // for each <rotate>, <translate>, etc. there is a separate Transformation
2371                 const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
2372
2373                 std::vector<FCurve*> old_curves;
2374
2375                 int i;
2376
2377                 // find frames at which to sample plus convert all keys to radians
2378                 for (i = 0; i < tms.getCount(); i++) {
2379                         COLLADAFW::Transformation *tm = tms[i];
2380                         COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
2381
2382                         if (type == tm_type) {
2383                                 const COLLADAFW::UniqueId& listid = tm->getAnimationList();
2384
2385                                 if (animlist_map.find(listid) != animlist_map.end()) {
2386                                         const COLLADAFW::AnimationList *animlist = animlist_map[listid];
2387                                         const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
2388
2389                                         if (bindings.getCount()) {
2390                                                 for (int j = 0; j < bindings.getCount(); j++) {
2391                                                         std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
2392                                                         bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
2393
2394                                                         if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3)) {
2395                                                                 std::vector<FCurve*>::iterator iter;
2396
2397                                                                 for (iter = curves.begin(); iter != curves.end(); iter++) {
2398                                                                         FCurve *fcu = *iter;
2399
2400                                                                         if (is_rotation)
2401                                                                                 fcurve_deg_to_rad(fcu);
2402
2403                                                                         for (int k = 0; k < fcu->totvert; k++) {
2404                                                                                 float fra = fcu->bezt[k].vec[1][0];
2405                                                                                 if (std::find(frames.begin(), frames.end(), fra) == frames.end())
2406                                                                                         frames.push_back(fra);
2407                                                                         }
2408                                                                 }
2409                                                         }
2410                                                         else {
2411                                                                 fprintf(stderr, "expected 1 or 3 curves, got %u\n", curves.size());
2412                                                         }
2413
2414                                                         for (std::vector<FCurve*>::iterator it = curves.begin(); it != curves.end(); it++)
2415                                                                 old_curves.push_back(*it);
2416                                                 }
2417                                         }
2418                                 }
2419                         }
2420                 }
2421
2422                 sort(frames.begin(), frames.end());
2423
2424                 float irest_dae[4][4];
2425                 float rest[4][4], irest[4][4];
2426
2427                 if (is_joint) {
2428                         if (is_joint)
2429                                 get_joint_rest_mat(irest_dae, root, node);
2430                         else
2431                                 evaluate_transform_at_frame(irest_dae, node, 0.0f);
2432                         invert_m4(irest_dae);
2433
2434                         Bone *bone = get_named_bone((bArmature*)ob->data, bone_name);
2435                         if (!bone) {
2436                                 fprintf(stderr, "cannot find bone \"%s\"", bone_name);
2437 #ifdef ARMATURE_TEST
2438                                 return NULL;
2439 #else
2440                                 return;
2441 #endif
2442                         }
2443
2444                         unit_m4(rest);
2445                         copy_m4_m4(rest, bone->arm_mat);
2446                         invert_m4_m4(irest, rest);
2447                 }
2448
2449                 char rna_path[200];
2450
2451 #ifdef ARMATURE_TEST
2452                 Object *job = get_joint_object(root, node, par_job);
2453                 FCurve *job_curves[4];
2454 #endif
2455
2456                 if (frames.size() == 0) {
2457 #ifdef ARMATURE_TEST
2458                         return job;
2459 #else
2460                         return;
2461 #endif
2462                 }
2463
2464                 const char *tm_str = NULL;
2465                 switch (tm_type) {
2466                 case COLLADAFW::Transformation::ROTATE:
2467                         tm_str = "rotation_quaternion";
2468                         break;
2469                 case COLLADAFW::Transformation::SCALE:
2470                         tm_str = "scale";
2471                         break;
2472                 case COLLADAFW::Transformation::TRANSLATE:
2473                         tm_str = "location";
2474                         break;
2475                 default:
2476 #ifdef ARMATURE_TEST
2477                         return job;
2478 #else
2479                         return;
2480 #endif
2481                 }
2482
2483                 if (is_joint) {
2484                         char joint_path[200];
2485                         armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
2486                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
2487                 }
2488                 else {
2489                         strcpy(rna_path, tm_str);
2490                 }
2491
2492                 // new curves
2493                 FCurve *newcu[4];
2494                 int totcu = is_rotation ? 4 : 3;
2495
2496                 for (i = 0; i < totcu; i++) {
2497                         newcu[i] = create_fcurve(i, rna_path);
2498 #ifdef ARMATURE_TEST
2499                         job_curves[i] = create_fcurve(i, tm_str);
2500 #endif
2501                 }
2502
2503                 std::vector<float>::iterator it;
2504
2505                 // sample values at each frame
2506                 for (it = frames.begin(); it != frames.end(); it++) {
2507                         float fra = *it;
2508
2509                         float mat[4][4];
2510
2511                         unit_m4(mat);
2512
2513                         // calc object-space mat
2514                         evaluate_transform_at_frame(mat, node, fra);
2515
2516                         // for joints, we need a special matrix
2517                         if (is_joint) {
2518                                 // special matrix: iR * M * iR_dae * R
2519                                 // where R, iR are bone rest and inverse rest mats in world space (Blender bones),
2520                                 // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE)
2521                                 float temp[4][4], par[4][4];
2522
2523                                 // calc M
2524                                 calc_joint_parent_mat_rest(par, NULL, root, node);
2525                                 mul_m4_m4m4(temp, mat, par);
2526
2527                                 // evaluate_joint_world_transform_at_frame(temp, NULL, , node, fra);
2528
2529                                 // calc special matrix
2530                                 mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
2531                         }
2532
2533                         float val[4];
2534
2535                         switch (tm_type) {
2536                         case COLLADAFW::Transformation::ROTATE:
2537                                 mat4_to_quat(val, mat);
2538                                 break;
2539                         case COLLADAFW::Transformation::SCALE:
2540                                 mat4_to_size(val, mat);
2541                                 break;
2542                         case COLLADAFW::Transformation::TRANSLATE:
2543                                 copy_v3_v3(val, mat[3]);
2544                                 break;
2545                         default:
2546                                 break;
2547                         }
2548
2549                         // add 4 or 3 keys
2550                         for (i = 0; i < totcu; i++) {
2551                                 add_bezt(newcu[i], fra, val[i]);
2552                         }
2553
2554 #ifdef ARMATURE_TEST
2555                         if (is_joint) {
2556                                 evaluate_transform_at_frame(mat, node, fra);
2557
2558                                 switch (tm_type) {
2559                                 case COLLADAFW::Transformation::ROTATE:
2560                                         mat4_to_quat(val, mat);
2561                                         break;
2562                                 case COLLADAFW::Transformation::SCALE:
2563                                         mat4_to_size(val, mat);
2564                                         break;
2565                                 case COLLADAFW::Transformation::TRANSLATE:
2566                                         copy_v3_v3(val, mat[3]);
2567                                         break;
2568                                 default:
2569                                         break;
2570                                 }
2571
2572                                 for (i = 0; i < totcu; i++)
2573                                         add_bezt(job_curves[i], fra, val[i]);
2574                         }
2575 #endif
2576                 }
2577
2578                 verify_adt_action((ID*)&ob->id, 1);
2579
2580                 ListBase *curves = &ob->adt->action->curves;
2581                 // no longer needed
2582 #if 0
2583                 // remove old curves
2584                 for (std::vector<FCurve*>::iterator it = old_curves.begin(); it != old_curves.end(); it++) {
2585                         if (is_joint)
2586                                 action_groups_remove_channel(ob->adt->action, *it);
2587                         else
2588                                 BLI_remlink(curves, *it);
2589
2590                         // std::remove(unused_curves.begin(), unused_curves.end(), *it);
2591                         // free_fcurve(*it);
2592                 }
2593 #endif
2594
2595                 // add curves
2596                 for (i = 0; i < totcu; i++) {
2597                         if (is_joint)
2598                                 add_bone_fcurve(ob, node, newcu[i]);
2599                         else
2600                                 BLI_addtail(curves, newcu[i]);
2601
2602 #ifdef ARMATURE_TEST
2603                         if (is_joint)
2604                                 BLI_addtail(&job->adt->action->curves, job_curves[i]);
2605 #endif
2606                 }
2607
2608                 if (is_rotation) {
2609                         if (is_joint) {
2610                                 bPoseChannel *chan = get_pose_channel(ob->pose, bone_name);
2611                                 chan->rotmode = ROT_MODE_QUAT;
2612                         }
2613                         else {
2614                                 ob->rotmode = ROT_MODE_QUAT;
2615                         }
2616                 }
2617
2618 #ifdef ARMATURE_TEST
2619                 return job;
2620 #endif
2621         }
2622
2623         // internal, better make it private
2624         // warning: evaluates only rotation
2625         // prerequisites: animlist_map, curve_map
2626         void evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra)
2627         {
2628                 const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
2629
2630                 unit_m4(mat);
2631
2632                 for (int i = 0; i < tms.getCount(); i++) {
2633                         COLLADAFW::Transformation *tm = tms[i];
2634                         COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
2635                         float m[4][4];
2636
2637                         unit_m4(m);
2638
2639                         if (!evaluate_animation(tm, m, fra)) {
2640                                 switch (type) {
2641                                 case COLLADAFW::Transformation::ROTATE:
2642                                         dae_rotate_to_mat4(tm, m);
2643                                         break;
2644                                 case COLLADAFW::Transformation::TRANSLATE:
2645                                         dae_translate_to_mat4(tm, m);
2646                                         break;
2647                                 case COLLADAFW::Transformation::SCALE:
2648                                         dae_scale_to_mat4(tm, m);
2649                                         break;
2650                                 case COLLADAFW::Transformation::MATRIX:
2651                                         dae_matrix_to_mat4(tm, m);
2652                                         break;
2653                                 default:
2654                                         fprintf(stderr, "unsupported transformation type %d\n", type);
2655                                 }
2656                         }
2657
2658                         float temp[4][4];
2659                         copy_m4_m4(temp, mat);
2660
2661                         mul_m4_m4m4(mat, m, temp);
2662                 }
2663         }
2664
2665         bool evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra)
2666         {
2667                 const COLLADAFW::UniqueId& listid = tm->getAnimationList();
2668
2669                 if (animlist_map.find(listid) != animlist_map.end()) {
2670                         const COLLADAFW::AnimationList *animlist = animlist_map[listid];
2671                         const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
2672
2673                         if (bindings.getCount()) {
2674                                 for (int j = 0; j < bindings.getCount(); j++) {
2675                                         std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
2676                                         COLLADAFW::AnimationList::AnimationClass animclass = bindings[j].animationClass;
2677                                         COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
2678                                         bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
2679
2680                                         if (type == COLLADAFW::Transformation::ROTATE) {
2681                                                 if (curves.size() != 1) {
2682                                                         fprintf(stderr, "expected 1 curve, got %u\n", curves.size());
2683                                                 }
2684                                                 else {
2685                                                         if (animclass == COLLADAFW::AnimationList::ANGLE) {
2686                                                                 COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis();
2687                                                                 float ax[3] = {axis[0], axis[1], axis[2]};
2688                                                                 float angle = evaluate_fcurve(curves[0], fra);
2689                                                                 axis_angle_to_mat4(mat, ax, angle);
2690
2691                                                                 return true;
2692                                                         }
2693                                                         else {
2694                                                                 // TODO support other animclasses
2695                                                                 fprintf(stderr, "<rotate> animclass %d is not supported yet\n", bindings[j].animationClass);
2696                                                         }
2697                                                 }
2698                                         }
2699                                         else if (type == COLLADAFW::Transformation::SCALE || type == COLLADAFW::Transformation::TRANSLATE) {
2700                                                 if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3)) {
2701                                                         bool animated = true;
2702                                                         bool scale = (type == COLLADAFW::Transformation::SCALE);
2703
2704                                                         float vec[3] = {0.0f, 0.0f, 0.0f};
2705                                                         if (scale)
2706                                                                 vec[0] = vec[1] = vec[2] = 1.0f;
2707
2708                                                         switch (animclass) {
2709                                                         case COLLADAFW::AnimationList::POSITION_X:
2710                                                                 vec[0] = evaluate_fcurve(curves[0], fra);
2711                                                                 break;
2712                                                         case COLLADAFW::AnimationList::POSITION_Y:
2713                                                                 vec[1] = evaluate_fcurve(curves[0], fra);
2714                                                                 break;
2715                                                         case COLLADAFW::AnimationList::POSITION_Z:
2716                                                                 vec[2] = evaluate_fcurve(curves[0], fra);
2717                                                                 break;
2718                                                         case COLLADAFW::AnimationList::POSITION_XYZ:
2719                                                                 vec[0] = evaluate_fcurve(curves[0], fra);
2720                                                                 vec[1] = evaluate_fcurve(curves[1], fra);
2721                                                                 vec[2] = evaluate_fcurve(curves[2], fra);
2722                                                                 break;
2723                                                         default:
2724                                                                 fprintf(stderr, "<%s> animclass %d is not supported yet\n", scale ? "scale" : "translate", animclass);
2725                                                                 animated = false;
2726                                                                 break;
2727                                                         }
2728
2729                                                         if (animated) {
2730                                                                 if (scale)
2731                                                                         size_to_mat4(mat, vec);
2732                                                                 else