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