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