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