Importer: fix parenting.
[blender.git] / source / blender / collada / DocumentImporter.cpp
1 #include "COLLADAFWRoot.h"
2 #include "COLLADAFWIWriter.h"
3 #include "COLLADAFWStableHeaders.h"
4 #include "COLLADAFWAnimationCurve.h"
5 #include "COLLADAFWAnimationList.h"
6 #include "COLLADAFWCamera.h"
7 #include "COLLADAFWColorOrTexture.h"
8 #include "COLLADAFWEffect.h"
9 #include "COLLADAFWFloatOrDoubleArray.h"
10 #include "COLLADAFWGeometry.h"
11 #include "COLLADAFWImage.h"
12 #include "COLLADAFWIndexList.h"
13 #include "COLLADAFWInstanceGeometry.h"
14 #include "COLLADAFWLight.h"
15 #include "COLLADAFWMaterial.h"
16 #include "COLLADAFWMesh.h"
17 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
18 #include "COLLADAFWNode.h"
19 #include "COLLADAFWPolygons.h"
20 #include "COLLADAFWRotate.h"
21 #include "COLLADAFWSampler.h"
22 #include "COLLADAFWScale.h"
23 #include "COLLADAFWSkinController.h"
24 #include "COLLADAFWTransformation.h"
25 #include "COLLADAFWTranslate.h"
26 #include "COLLADAFWTypes.h"
27 #include "COLLADAFWVisualScene.h"
28 #include "COLLADAFWFileInfo.h"
29 #include "COLLADAFWArrayPrimitiveType.h"
30
31 #include "COLLADASaxFWLLoader.h"
32
33 // TODO move "extern C" into header files
34 extern "C" 
35 {
36 #include "BKE_main.h"
37 #include "BKE_customdata.h"
38 #include "BKE_library.h"
39 #include "BKE_texture.h"
40 #include "ED_keyframing.h"
41 #include "BKE_fcurve.h"
42 #include "BKE_depsgraph.h"
43 }
44 #include "DNA_lamp_types.h"
45 #include "BKE_mesh.h"
46 #include "BKE_global.h"
47 #include "BKE_context.h"
48 #include "BKE_object.h"
49 #include "BKE_image.h"
50 #include "BKE_material.h"
51
52 #include "BLI_arithb.h"
53 #include "BLI_listbase.h"
54 #include "BLI_string.h"
55
56 #include "DNA_anim_types.h"
57 #include "DNA_curve_types.h"
58 #include "DNA_texture_types.h"
59 #include "DNA_camera_types.h"
60 #include "DNA_object_types.h"
61 #include "DNA_meshdata_types.h"
62 #include "DNA_mesh_types.h"
63 #include "DNA_material_types.h"
64 #include "DNA_scene_types.h"
65
66 #include "MEM_guardedalloc.h"
67
68 #include "DocumentImporter.h"
69
70 #include <string>
71 #include <map>
72
73
74 // #define COLLADA_DEBUG
75
76 char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
77
78 const char *primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
79 {
80         using namespace COLLADAFW;
81         
82         switch (type) {
83         case MeshPrimitive::LINES:
84                 return "LINES";
85         case MeshPrimitive::LINE_STRIPS:
86                 return "LINESTRIPS";
87         case MeshPrimitive::POLYGONS:
88                 return "POLYGONS";
89         case MeshPrimitive::POLYLIST:
90                 return "POLYLIST";
91         case MeshPrimitive::TRIANGLES:
92                 return "TRIANGLES";
93         case MeshPrimitive::TRIANGLE_FANS:
94                 return "TRIANGLE_FANS";
95         case MeshPrimitive::TRIANGLE_STRIPS:
96                 return "TRIANGLE_FANS";
97         case MeshPrimitive::POINTS:
98                 return "POINTS";
99         case MeshPrimitive::UNDEFINED_PRIMITIVE_TYPE:
100                 return "UNDEFINED_PRIMITIVE_TYPE";
101         }
102         return "UNKNOWN";
103 }
104 const char *geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
105 {
106         switch (type) {
107         case COLLADAFW::Geometry::GEO_TYPE_MESH:
108                 return "MESH";
109         case COLLADAFW::Geometry::GEO_TYPE_SPLINE:
110                 return "SPLINE";
111         case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
112                 return "CONVEX_MESH";
113         }
114         return "UNKNOWN";
115 }
116
117 /*
118
119   COLLADA Importer limitations:
120
121   - no multiple scene import, all objects are added to active scene
122
123  */
124 /** Class that needs to be implemented by a writer. 
125         IMPORTANT: The write functions are called in arbitrary order.*/
126 class Writer: public COLLADAFW::IWriter
127 {
128 private:
129         std::string mFilename;
130         
131         std::vector<COLLADAFW::VisualScene> mVisualScenes;
132
133         bContext *mContext;
134
135         std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map
136         std::map<COLLADAFW::UniqueId, Image*> uid_image_map;
137         std::map<COLLADAFW::UniqueId, Material*> uid_material_map;
138         std::map<COLLADAFW::UniqueId, Material*> uid_effect_map;
139         std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map;
140         std::map<COLLADAFW::UniqueId, Lamp*> uid_lamp_map;
141         // maps for assigning textures to uv layers
142         std::map<COLLADAFW::TextureMapId, char*> set_layername_map;
143         std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > index_mtex_map;
144         // this structure is used to assign material indices to faces
145         // when materials are assigned to an object
146         struct Primitive {
147                 MFace *mface;
148                 int totface;
149         };
150         typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap;
151         // amazing name!
152         std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map;
153         // maps for animation
154         std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > uid_fcurve_map;
155         struct AnimatedTransform {
156                 Object *ob;
157                 // COLLADAFW::Node *node;
158                 COLLADAFW::Transformation *tm; // which transform is animated by an AnimationList->id
159         };
160         // Nodes don't share AnimationLists (Arystan)
161         std::map<COLLADAFW::UniqueId, AnimatedTransform> uid_animated_map; // AnimationList->uniqueId to AnimatedObject map
162
163         class UnitConverter
164         {
165         private:
166                 COLLADAFW::FileInfo::Unit mUnit;
167                 COLLADAFW::FileInfo::UpAxisType mUpAxis;
168         public:
169                 UnitConverter(COLLADAFW::FileInfo::UpAxisType upAxis, COLLADAFW::FileInfo::Unit& unit) :
170                         mUpAxis(upAxis), mUnit(unit)
171                 {
172                 }
173
174                 // TODO
175                 // convert vector vec from COLLADA format to Blender
176                 void convertVec3(float *vec)
177                 {
178                 }
179                 
180                 // TODO need also for angle conversion, time conversion...
181         };
182
183         class UVDataWrapper
184         {
185                 COLLADAFW::MeshVertexData *mVData;
186         public:
187                 UVDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata)
188                 {}
189
190 #ifdef COLLADA_DEBUG
191                 void print()
192                 {
193                         fprintf(stderr, "UVs:\n");
194                         COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
195                         for (int i = 0; i < values->getCount(); i += 2) {
196                                 fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i+1]);
197                         }
198                         fprintf(stderr, "\n");
199                 }
200 #endif
201
202                 void getUV(int uv_set_index, int uv_index[2], float *uv)
203                 {
204                         switch(mVData->getType()) {
205                         case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
206                                 {
207                                         COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
208                                         uv[0] = (*values)[uv_index[0]];
209                                         uv[1] = (*values)[uv_index[1]];
210                                         
211                                         break;
212                                 }
213                         case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
214                                 {
215                                         COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
216                                         
217                                         uv[0] = (float)(*values)[uv_index[0]];
218                                         uv[1] = (float)(*values)[uv_index[1]];
219                                         
220                                         break;
221                                 }
222                         }
223                 }
224         };
225
226 public:
227
228         /** Constructor. */
229         Writer(bContext *C, const char *filename) : mContext(C), mFilename(filename) {};
230
231         /** Destructor. */
232         ~Writer() {};
233
234         bool write()
235         {
236                 COLLADASaxFWL::Loader loader;
237                 COLLADAFW::Root root(&loader, this);
238
239                 // XXX report error
240                 if (!root.loadDocument(mFilename))
241                         return false;
242
243                 return true;
244         }
245
246         /** This method will be called if an error in the loading process occurred and the loader cannot
247                 continue to to load. The writer should undo all operations that have been performed.
248                 @param errorMessage A message containing informations about the error that occurred.
249         */
250         virtual void cancel(const COLLADAFW::String& errorMessage)
251         {
252                 // TODO: if possible show error info
253                 //
254                 // Should we get rid of invisible Meshes that were created so far
255                 // or maybe create objects at coordinate space origin?
256                 //
257                 // The latter sounds better.
258         }
259
260         /** This is the method called. The writer hast to prepare to receive data.*/
261         virtual void start()
262         {
263         }
264
265         /** This method is called after the last write* method. No other methods will be called after this.*/
266         virtual void finish()
267         {
268                 // using mVisualScenes, do:
269                 // - write <node> data to Objects: materials, transforms, etc.
270
271                 // TODO: import materials (<instance_material> inside <instance_geometry>) and textures
272
273                 std::vector<COLLADAFW::VisualScene>::iterator it = mVisualScenes.begin();
274                 for (; it != mVisualScenes.end(); it++) {
275                         COLLADAFW::VisualScene &visscene = *it;
276
277                         // create new blender scene
278
279                         // create Objects from <node>s inside this <visual_scene>
280
281                         // link each Object with a Mesh
282                         // for each Object's <instance_geometry> there should already exist a Mesh
283                 }
284         }
285
286         /** When this method is called, the writer must write the global document asset.
287                 @return The writer should return true, if writing succeeded, false otherwise.*/
288         virtual bool writeGlobalAsset ( const COLLADAFW::FileInfo* asset ) 
289         {
290                 // XXX take up_axis, unit into account
291                 // COLLADAFW::FileInfo::Unit unit = asset->getUnit();
292                 // COLLADAFW::FileInfo::UpAxisType upAxis = asset->getUpAxisType();
293
294                 return true;
295         }
296
297         /** When this method is called, the writer must write the scene.
298                 @return The writer should return true, if writing succeeded, false otherwise.*/
299         virtual bool writeScene ( const COLLADAFW::Scene* scene ) 
300         {
301                 // XXX could store the scene id, but do nothing for now
302                 return true;
303         }
304         
305         // bind early created mesh to object, assign materials and textures
306         Object *create_mesh_object(Object *ob, Scene *sce, COLLADAFW::Node *node,
307                                                            COLLADAFW::InstanceGeometry *geom)
308         {
309                 ob = add_object(sce, OB_MESH);
310                 
311                 const std::string& id = node->getOriginalId();
312                 if (id.length())
313                         rename_id(&ob->id, (char*)id.c_str());
314                 
315                 const COLLADAFW::UniqueId& geom_uid = geom->getInstanciatedObjectId();
316                 if (uid_mesh_map.find(geom_uid) == uid_mesh_map.end()) {
317                         // XXX report to user
318                         // this could happen if a mesh was not created
319                         // (e.g. if it contains unsupported geometry)
320                         fprintf(stderr, "Couldn't find a mesh by UID.\n");
321                         return NULL;
322                 }
323                 // replace ob->data freeing the old one
324                 Mesh *old_mesh = (Mesh*)ob->data;
325                 set_mesh(ob, uid_mesh_map[geom_uid]);
326                 if (old_mesh->id.us == 0) free_libblock(&G.main->mesh, old_mesh);
327                 
328                 // assign materials to object
329                 // assign material indices to mesh faces
330                 Mesh *me = (Mesh*)ob->data;
331                 MTex *mtex = NULL;
332                 MTFace *tface = NULL;
333                 char *layername = CustomData_get_layer_name(&me->fdata, CD_MTFACE, 0);
334                 
335                 for (int k = 0; k < geom->getMaterialBindings().getCount(); k++) {
336                         
337                         const COLLADAFW::UniqueId& ma_uid = geom->getMaterialBindings()[k].getReferencedMaterial();
338                         // check if material was properly written to map
339                         if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
340                                 fprintf(stderr, "Cannot find material by UID.\n");
341                                 continue;
342                         }
343                         Material *ma = uid_material_map[ma_uid];
344                         int l;
345                         
346                         // assign textures to uv layers
347                         // bvi_array "bind_vertex_input array"
348                         COLLADAFW::InstanceGeometry::TextureCoordinateBindingArray& bvi_array = 
349                                 geom->getMaterialBindings()[k].getTextureCoordinateBindingArray();
350                         
351                         for (l = 0; l < bvi_array.getCount(); l++) {
352                                 
353                                 COLLADAFW::TextureMapId tex_index = bvi_array[l].textureMapId;
354                                 size_t set_index = bvi_array[l].setIndex;
355                                 char *uvname = set_layername_map[set_index];
356                                 
357                                 // check if mtexes were properly added to vector
358                                 if (index_mtex_map.find(tex_index) == index_mtex_map.end()) {
359                                         fprintf(stderr, "Cannot find mtexes by texmap id.\n");
360                                         continue;
361                                 }
362                                 std::vector<MTex*> mtexes = index_mtex_map[tex_index];
363                                 std::vector<MTex*>::iterator it;
364                                 for (it = mtexes.begin(); it != mtexes.end(); it++) {
365                                         mtex = *it;
366                                         strcpy(mtex->uvname, uvname);
367                                         
368                                 }       
369                         }
370                         mtex = NULL;
371                         // find and save texture mapped to diffuse
372                         for (l = 0; l < 18; l++) {
373                                 if (ma->mtex[l] != NULL && ma->mtex[l]->mapto == MAP_COL)
374                                         mtex = ma->mtex[l];
375                         }
376                         // get mtface for first uv layer
377                         if (tface == NULL && mtex != NULL)
378                                 tface = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE, mtex->uvname);
379                         // get mtface for next uv layer
380                         else if(layername != NULL && mtex != NULL && strcmp(layername, mtex->uvname) != 0) {
381                                 tface = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE, mtex->uvname);
382                                 layername = mtex->uvname;
383                         }
384                         
385                         assign_material(ob, ma, ob->totcol + 1);
386                         
387                         MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[geom_uid];
388                         COLLADAFW::MaterialId mat_id = geom->getMaterialBindings()[k].getMaterialId();
389                         
390                         // if there's geometry that uses this material,
391                         // set mface->mat_nr=k for each face in that geometry
392                         if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
393                                 
394                                 std::vector<Primitive>& prims = mat_prim_map[mat_id];
395                                 
396                                 std::vector<Primitive>::iterator it;
397                                 
398                                 for (it = prims.begin(); it != prims.end(); it++) {
399                                         Primitive& prim = *it;
400                                         l = 0;
401                                         while (l++ < prim.totface) {
402                                                 prim.mface->mat_nr = k;
403                                                 prim.mface++;
404                                                 if (mtex != NULL && tface != NULL) {
405                                                         tface->tpage = (Image*)mtex->tex->ima;
406                                                         tface->mode = TF_TEX;
407                                                         tface++;
408                                                 }
409                                         }
410                                 }
411                         }
412                 }
413                 return ob;
414         }
415         
416         void write_node (COLLADAFW::Node *node, Scene *sce, Object *par = NULL)
417         {
418                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
419                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
420                 if (node->getType() != COLLADAFW::Node::NODE) return;
421                 
422                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
423                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
424                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
425                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
426                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
427                 Object *ob = NULL;
428                 int k;
429                 
430                 // if node has <instance_geometries> - connect mesh with object
431                 // XXX currently only one <instance_geometry> in a node is supported
432                 if (geom.getCount() != 0) {
433                         ob = create_mesh_object(ob, sce, node, geom[0]);
434                 }
435                 // checking all other possible instances
436                 // <instance_camera>
437                 else if (camera.getCount() != 0) {
438                         const COLLADAFW::UniqueId& cam_uid = camera[0]->getInstanciatedObjectId();
439                         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {     
440                                 fprintf(stderr, "Couldn't find camera by UID. \n");
441                                 return;
442                         }
443                         ob = add_object(sce, OB_CAMERA);
444                         Camera *cam = uid_camera_map[cam_uid];
445                         Camera *old_cam = (Camera*)ob->data;
446                         old_cam->id.us--;
447                         ob->data = cam;
448                         if (old_cam->id.us == 0) free_libblock(&G.main->camera, old_cam);
449                 }
450                 // <instance_light>
451                 else if (lamp.getCount() != 0) {
452                         const COLLADAFW::UniqueId& lamp_uid = lamp[0]->getInstanciatedObjectId();
453                         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {        
454                                 fprintf(stderr, "Couldn't find lamp by UID. \n");
455                                 return;
456                         }
457                         ob = add_object(sce, OB_LAMP);
458                         Lamp *la = uid_lamp_map[lamp_uid];
459                         Lamp *old_lamp = (Lamp*)ob->data;
460                         old_lamp->id.us--;
461                         ob->data = la;
462                         if (old_lamp->id.us == 0) free_libblock(&G.main->lamp, old_lamp);
463                 }
464                 else if (controller.getCount() != 0) {
465                         //ob = create_mesh_object(ob, sce, node, controller[0]);
466                         return;
467                 }
468                 else if (inst_node.getCount() != 0) {
469                         return;
470                 }
471                 // if node has no instances - create empty object
472                 else {
473                         ob = add_object(sce, OB_EMPTY);
474                 }
475                 // just checking if object wasn't created
476                 if (ob == NULL) return;
477                 // if par was given make this object child of the previous 
478                 if (par != NULL) {
479                         Object workob;
480
481                         ob->parent = par;
482
483                         // doing what 'set parent' operator does
484                         par->recalc |= OB_RECALC_OB;
485                         ob->parsubstr[0] = 0;
486
487                         // since ob->obmat is identity, this is not needed?
488                         what_does_parent(sce, ob, &workob);
489                         Mat4Invert(ob->parentinv, workob.obmat);
490
491                         ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
492                         ob->partype = PAROBJECT;
493                         DAG_scene_sort(sce);
494                 }
495                 // transform Object
496                 float rot[3][3];
497                 Mat3One(rot);
498                 
499                 // transform Object and store animation linking info
500                 for (k = 0; k < node->getTransformations().getCount(); k ++) {
501                         
502                         COLLADAFW::Transformation *tm = node->getTransformations()[k];
503                         COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
504
505                         switch(type) {
506                         case COLLADAFW::Transformation::TRANSLATE:
507                                 {
508                                         COLLADAFW::Translate *tra = (COLLADAFW::Translate*)tm;
509                                         COLLADABU::Math::Vector3& t = tra->getTranslation();
510                                         ob->loc[0] = (float)t[0];
511                                         ob->loc[1] = (float)t[1];
512                                         ob->loc[2] = (float)t[2];
513                                 }
514                                 break;
515                         case COLLADAFW::Transformation::ROTATE:
516                                 {
517                                         COLLADAFW::Rotate *ro = (COLLADAFW::Rotate*)tm;
518                                         COLLADABU::Math::Vector3& raxis = ro->getRotationAxis();
519                                         float angle = (float)(ro->getRotationAngle() * M_PI / 180.0f);
520                                         float axis[] = {raxis[0], raxis[1], raxis[2]};
521                                         float quat[4];
522                                         float rot_copy[3][3];
523                                         float mat[3][3];
524                                         AxisAngleToQuat(quat, axis, angle);
525                                         
526                                         QuatToMat3(quat, mat);
527                                         Mat3CpyMat3(rot_copy, rot);
528                                         Mat3MulMat3(rot, rot_copy, mat);
529                                 }
530                                 break;
531                         case COLLADAFW::Transformation::SCALE:
532                                 {
533                                         COLLADABU::Math::Vector3& s = ((COLLADAFW::Scale*)tm)->getScale();
534                                         ob->size[0] = (float)s[0];
535                                         ob->size[1] = (float)s[1];
536                                         ob->size[2] = (float)s[2];
537                                 }
538                                 break;
539                         case COLLADAFW::Transformation::MATRIX:
540                         case COLLADAFW::Transformation::LOOKAT:
541                         case COLLADAFW::Transformation::SKEW:
542                                 fprintf(stderr, "MATRIX, LOOKAT and SKEW transformations are not supported yet.\n");
543                                 break;
544                         }
545                         
546                         // AnimationList that drives this Transformation
547                         const COLLADAFW::UniqueId& anim_list_id = tm->getAnimationList();
548                         
549                         // store this so later we can link animation data with ob
550                         AnimatedTransform anim = {ob, tm};
551                         this->uid_animated_map[anim_list_id] = anim;
552                 }
553                 Mat3ToEul(rot, ob->rot);
554                 
555                 // if node has child nodes write them
556                 COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
557                 for (k = 0; k < child_nodes.getCount(); k++) {  
558                         
559                         COLLADAFW::Node *child_node = child_nodes[k];
560                         write_node(child_node, sce, ob);
561                 }
562         }
563
564         /** When this method is called, the writer must write the entire visual scene.
565                 @return The writer should return true, if writing succeeded, false otherwise.*/
566         virtual bool writeVisualScene ( const COLLADAFW::VisualScene* visualScene ) 
567         {
568                 // This method is guaranteed to be called _after_ writeGeometry, writeMaterial, etc.
569
570                 // for each <node> in <visual_scene>:
571                 // create an Object
572                 // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
573
574                 // update: since we cannot link a Mesh with Object in
575                 // writeGeometry because <geometry> does not reference <node>,
576                 // we link Objects with Meshes here
577
578                 // TODO: create a new scene except the selected <visual_scene> - use current blender
579                 // scene for it
580                 Scene *sce = CTX_data_scene(mContext);
581
582                 for (int i = 0; i < visualScene->getRootNodes().getCount(); i++) {
583                         COLLADAFW::Node *node = visualScene->getRootNodes()[i];
584                         
585                         if (node->getType() != COLLADAFW::Node::NODE) {
586                                 continue;
587                         }
588                         
589                         write_node(node, sce);
590                 }
591                 
592                 mVisualScenes.push_back(*visualScene);
593
594                 return true;
595         }
596
597         /** When this method is called, the writer must handle all nodes contained in the 
598                 library nodes.
599                 @return The writer should return true, if writing succeeded, false otherwise.*/
600         virtual bool writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes ) 
601         {
602                 return true;
603         }
604
605         // utility functions
606
607         void set_face_indices(MFace *mface, unsigned int *indices, bool quad)
608         {
609                 mface->v1 = indices[0];
610                 mface->v2 = indices[1];
611                 mface->v3 = indices[2];
612                 if (quad) mface->v4 = indices[3];
613         }
614
615         // change face indices order so that v4 is not 0
616         void rotate_face_indices(MFace *mface) {
617                 mface->v4 = mface->v1;
618                 mface->v1 = mface->v2;
619                 mface->v2 = mface->v3;
620                 mface->v3 = 0;
621         }
622
623         void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, int uv_set_index,
624                                         COLLADAFW::IndexList& index_list, int index, bool quad)
625         {
626                 int uv_indices[4][2];
627
628                 // per face vertex indices, this means for quad we have 4 indices, not 8
629                 COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
630
631                 // make indices into FloatOrDoubleArray
632                 for (int i = 0; i < (quad ? 4 : 3); i++) {
633                         int uv_index = indices[index + i];
634                         uv_indices[i][0] = uv_index * 2;
635                         uv_indices[i][1] = uv_index * 2 + 1;
636                 }
637
638                 uvs.getUV(uv_set_index, uv_indices[0], mtface->uv[0]);
639                 uvs.getUV(uv_set_index, uv_indices[1], mtface->uv[1]);
640                 uvs.getUV(uv_set_index, uv_indices[2], mtface->uv[2]);
641
642                 if (quad) uvs.getUV(uv_set_index, uv_indices[3], mtface->uv[3]);
643
644 #ifdef COLLADA_DEBUG
645                 if (quad) {
646                         fprintf(stderr, "face uv:\n"
647                                         "((%d, %d), (%d, %d), (%d, %d), (%d, %d))\n"
648                                         "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
649
650                                         uv_indices[0][0], uv_indices[0][1],
651                                         uv_indices[1][0], uv_indices[1][1],
652                                         uv_indices[2][0], uv_indices[2][1],
653                                         uv_indices[3][0], uv_indices[3][1],
654
655                                         mtface->uv[0][0], mtface->uv[0][1],
656                                         mtface->uv[1][0], mtface->uv[1][1],
657                                         mtface->uv[2][0], mtface->uv[2][1],
658                                         mtface->uv[3][0], mtface->uv[3][1]);
659                 }
660                 else {
661                         fprintf(stderr, "face uv:\n"
662                                         "((%d, %d), (%d, %d), (%d, %d))\n"
663                                         "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
664
665                                         uv_indices[0][0], uv_indices[0][1],
666                                         uv_indices[1][0], uv_indices[1][1],
667                                         uv_indices[2][0], uv_indices[2][1],
668
669                                         mtface->uv[0][0], mtface->uv[0][1],
670                                         mtface->uv[1][0], mtface->uv[1][1],
671                                         mtface->uv[2][0], mtface->uv[2][1]);
672                 }
673 #endif
674         }
675
676 #ifdef COLLADA_DEBUG
677         void print_index_list(COLLADAFW::IndexList& index_list)
678         {
679                 fprintf(stderr, "Index list for \"%s\":\n", index_list.getName().c_str());
680                 for (int i = 0; i < index_list.getIndicesCount(); i += 2) {
681                         fprintf(stderr, "%u, %u\n", index_list.getIndex(i), index_list.getIndex(i + 1));
682                 }
683                 fprintf(stderr, "\n");
684         }
685 #endif
686
687         /** When this method is called, the writer must write the geometry.
688                 @return The writer should return true, if writing succeeded, false otherwise.*/
689         virtual bool writeGeometry ( const COLLADAFW::Geometry* cgeom ) 
690         {
691                 // - create a mesh object
692                 // - write geometry
693
694                 // - ignore usupported primitive types
695                 
696                 // TODO: import also uvs, normals
697                 // XXX what to do with normal indices?
698                 // XXX num_normals may be != num verts, then what to do?
699
700                 // check geometry->getType() first
701                 if (cgeom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
702                         // TODO: report warning
703                         fprintf(stderr, "Mesh type %s is not supported\n", geomTypeToStr(cgeom->getType()));
704                         return true;
705                 }
706                 
707                 COLLADAFW::Mesh *cmesh = (COLLADAFW::Mesh*)cgeom;
708                 
709                 // first check if we can import this mesh
710                 COLLADAFW::MeshPrimitiveArray& prim_arr = cmesh->getMeshPrimitives();
711                 int i;
712                 
713                 for (i = 0; i < prim_arr.getCount(); i++) {
714                         
715                         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
716                         COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
717
718                         const char *type_str = primTypeToStr(type);
719                         
720                         // OpenCollada passes POLYGONS type for <polylist>
721                         if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
722
723                                 COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons*)mp;
724                                 COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
725                                 
726                                 for(int j = 0; j < vca.getCount(); j++){
727                                         int count = vca[j];
728                                         if (count != 3 && count != 4) {
729                                                 fprintf(stderr, "%s has at least one face with vertex count > 4 or < 3\n",
730                                                                 type_str);
731                                                 return true;
732                                         }
733                                 }
734                                         
735                         }
736                         else if(type != COLLADAFW::MeshPrimitive::TRIANGLES) {
737                                 fprintf(stderr, "Primitive type %s is not supported.\n", type_str);
738                                 return true;
739                         }
740                 }
741                 
742                 size_t totvert = cmesh->getPositions().getFloatValues()->getCount() / 3;
743                 
744                 const std::string& str_geom_id = cgeom->getOriginalId();
745                 Mesh *me = add_mesh((char*)str_geom_id.c_str());
746
747                 // store mesh ptr
748                 // to link it later with Object
749                 this->uid_mesh_map[cgeom->getUniqueId()] = me;
750                 
751                 // vertices     
752                 me->mvert = (MVert*)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
753                 me->totvert = totvert;
754                 
755                 float *pos_float_array = cmesh->getPositions().getFloatValues()->getData();
756                 
757                 MVert *mvert = me->mvert;
758                 i = 0;
759                 while (i < totvert) {
760                         // fill mvert
761                         mvert->co[0] = pos_float_array[0];
762                         mvert->co[1] = pos_float_array[1];
763                         mvert->co[2] = pos_float_array[2];
764
765                         pos_float_array += 3;
766                         mvert++;
767                         i++;
768                 }
769
770                 // count totface
771                 int totface = cmesh->getFacesCount();
772
773                 // allocate faces
774                 me->mface = (MFace*)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, totface);
775                 me->totface = totface;
776                 
777                 // UVs
778                 int totuvset = cmesh->getUVCoords().getInputInfosArray().getCount();
779                 
780                 for (i = 0; i < totuvset; i++) {
781                         // add new CustomData layer
782                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, totface);
783                         this->set_layername_map[i] = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
784                         
785                 }
786
787                 // activate the first uv layer if any
788                 if (totuvset) me->mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, 0);
789
790                 UVDataWrapper uvs(cmesh->getUVCoords());
791
792 #ifdef COLLADA_DEBUG
793                 uvs.print();
794 #endif
795
796                 // read faces
797                 MFace *mface = me->mface;
798
799                 MaterialIdPrimitiveArrayMap mat_prim_map;
800
801                 // TODO: import uv set names
802                 int face_index = 0;
803
804                 for (i = 0; i < prim_arr.getCount(); i++) {
805                         
806                         COLLADAFW::MeshPrimitive *mp = prim_arr[i];
807
808                         // faces
809                         size_t prim_totface = mp->getFaceCount();
810                         unsigned int *indices = mp->getPositionIndices().getData();
811                         int j, k;
812                         int type = mp->getPrimitiveType();
813                         int index = 0;
814                         
815                         // since we cannot set mface->mat_nr here, we store a portion of me->mface in Primitive
816                         Primitive prim = {mface, 0};
817                         COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray();
818
819 #ifdef COLLADA_DEBUG
820                         fprintf(stderr, "Primitive %d:\n", i);
821                         for (int j = 0; j < totuvset; j++) {
822                                 print_index_list(*index_list_array[j]);
823                         }
824 #endif
825                         
826                         if (type == COLLADAFW::MeshPrimitive::TRIANGLES) {
827                                 for (j = 0; j < prim_totface; j++){
828                                         
829                                         set_face_indices(mface, indices, false);
830                                         indices += 3;
831
832                                         for (k = 0; k < totuvset; k++) {
833                                                 // get mtface by face index and uv set index
834                                                 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
835                                                 set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false);
836                                         }
837                                         
838                                         index += 3;
839                                         mface++;
840                                         face_index++;
841                                         prim.totface++;
842                                 }
843                         }
844                         else if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
845                                 COLLADAFW::Polygons *mpvc =     (COLLADAFW::Polygons*)mp;
846                                 COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
847
848                                 for (j = 0; j < prim_totface; j++) {
849
850                                         // face
851                                         int vcount = vcounta[j];
852
853                                         set_face_indices(mface, indices, vcount == 4);
854                                         indices += vcount;
855                                         
856                                         // do the trick if needed
857                                         if (vcount == 4 && mface->v4 == 0)
858                                                 rotate_face_indices(mface);
859
860                                         // set mtface for each uv set
861                                         // it is assumed that all primitives have equal number of UV sets
862
863                                         for (k = 0; k < totuvset; k++) {
864                                                 // get mtface by face index and uv set index
865                                                 MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
866                                                 set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0);
867                                         }
868
869                                         index += mface->v4 ? 4 : 3;
870                                         mface++;
871                                         face_index++;
872                                         prim.totface++;
873                                 }
874                         }
875                         
876                         mat_prim_map[mp->getMaterialId()].push_back(prim);
877                         
878                 }
879                 
880                 geom_uid_mat_mapping_map[cgeom->getUniqueId()] = mat_prim_map;
881                 
882                 mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
883                 make_edges(me, 0);
884
885                 return true;
886         }
887
888         /** When this method is called, the writer must write the material.
889                 @return The writer should return true, if writing succeeded, false otherwise.*/
890         virtual bool writeMaterial( const COLLADAFW::Material* cmat ) 
891         {
892                 const std::string& str_mat_id = cmat->getOriginalId();
893                 Material *ma = add_material((char*)str_mat_id.c_str());
894                 
895                 this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
896                 this->uid_material_map[cmat->getUniqueId()] = ma;
897                 
898                 return true;
899         }
900         
901         // create mtex, create texture, set texture image
902         MTex *create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture ctex, Material *ma, int i)
903         {
904                 COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
905                 COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
906                 
907                 if (sampler->getSamplerType() == COLLADAFW::Sampler::SAMPLER_TYPE_2D) {
908                         
909                         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
910                         
911                         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
912                                 fprintf(stderr, "Couldn't find an image by UID.\n");
913                                 return NULL;
914                         }
915                         
916                     ma->mtex[i] = add_mtex();
917                         ma->mtex[i]->texco = TEXCO_UV;
918                         ma->mtex[i]->tex = add_texture("texture");
919                         ma->mtex[i]->tex->type = TEX_IMAGE;
920                         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
921                         index_mtex_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
922                         return ma->mtex[i];
923                 }
924         }
925
926         /** When this method is called, the writer must write the effect.
927                 @return The writer should return true, if writing succeeded, false otherwise.*/
928         virtual bool writeEffect( const COLLADAFW::Effect* effect ) 
929         {
930                 
931                 const COLLADAFW::UniqueId& uid = effect->getUniqueId();
932                 if (uid_effect_map.find(uid) == uid_effect_map.end()) {
933                         fprintf(stderr, "Couldn't find a material by UID.\n");
934                         return true;
935                 }
936                 
937                 Material *ma = uid_effect_map[uid];
938                 
939                 COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
940                 if (common_efs.getCount() < 1) {
941                         fprintf(stderr, "<effect> hasn't got <profile_COMMON>s.\n Currently we support only them. \n");
942                         return true;
943                 }
944                 // XXX TODO: Take all <profile_common>s
945                 // Currently only first <profile_common> is supported
946                 COLLADAFW::EffectCommon *ef = common_efs[0];
947                 COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
948                 
949                 // blinn
950                 if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
951                         ma->spec_shader = MA_SPEC_BLINN;
952                         ma->spec = ef->getShininess().getFloatValue();
953                 }
954                 // phong
955                 else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
956                         ma->spec_shader = MA_SPEC_PHONG;
957                         ma->spec = ef->getShininess().getFloatValue();
958                 }
959                 // lambert
960                 else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
961                         ma->diff_shader = MA_DIFF_LAMBERT;
962                 }
963                 // default - lambert
964                 else {
965                         ma->diff_shader = MA_DIFF_LAMBERT;
966                         fprintf(stderr, "Current shader type is not supported.\n");
967                 }
968                 // reflectivity
969                 ma->ray_mirror = ef->getReflectivity().getFloatValue();
970                 // index of refraction
971                 ma->ang = ef->getIndexOfRefraction().getFloatValue();
972                 
973                 int i = 0;
974                 COLLADAFW::Color col;
975                 COLLADAFW::Texture ctex;
976                 MTex *mtex = NULL;
977                 
978                 // DIFFUSE
979                 // color
980                 if (ef->getDiffuse().isColor()) {
981                         col = ef->getDiffuse().getColor();
982                         ma->r = col.getRed();
983                         ma->g = col.getGreen();
984                         ma->b = col.getBlue();
985                 }
986                 // texture
987                 else if (ef->getDiffuse().isTexture()) {
988                         ctex = ef->getDiffuse().getTexture(); 
989                         mtex = create_texture(ef, ctex, ma, i);
990                         if (mtex != NULL) {
991                                 mtex->mapto = MAP_COL;
992                                 ma->texact = (int)i;
993                                 i++;
994                         }
995                 }
996                 // AMBIENT
997                 // color
998                 if (ef->getAmbient().isColor()) {
999                         col = ef->getAmbient().getColor();
1000                         ma->ambr = col.getRed();
1001                         ma->ambg = col.getGreen();
1002                         ma->ambb = col.getBlue();
1003                 }
1004                 // texture
1005                 else if (ef->getAmbient().isTexture()) {
1006                         ctex = ef->getAmbient().getTexture(); 
1007                         mtex = create_texture(ef, ctex, ma, i);
1008                         if (mtex != NULL) {
1009                                 mtex->mapto = MAP_AMB; 
1010                                 i++;
1011                         }
1012                 }
1013                 // SPECULAR
1014                 // color
1015                 if (ef->getSpecular().isColor()) {
1016                         col = ef->getSpecular().getColor();
1017                         ma->specr = col.getRed();
1018                         ma->specg = col.getGreen();
1019                         ma->specb = col.getBlue();
1020                 }
1021                 // texture
1022                 else if (ef->getSpecular().isTexture()) {
1023                         ctex = ef->getSpecular().getTexture(); 
1024                         mtex = create_texture(ef, ctex, ma, i);
1025                         if (mtex != NULL) {
1026                                 mtex->mapto = MAP_SPEC; 
1027                                 i++;
1028                         }
1029                 }
1030                 // REFLECTIVE
1031                 // color
1032                 if (ef->getReflective().isColor()) {
1033                         col = ef->getReflective().getColor();
1034                         ma->mirr = col.getRed();
1035                         ma->mirg = col.getGreen();
1036                         ma->mirb = col.getBlue();
1037                 }
1038                 // texture
1039                 else if (ef->getReflective().isTexture()) {
1040                         ctex = ef->getReflective().getTexture(); 
1041                         mtex = create_texture(ef, ctex, ma, i);
1042                         if (mtex != NULL) {
1043                                 mtex->mapto = MAP_REF; 
1044                                 i++;
1045                         }
1046                 }
1047                 // EMISSION
1048                 // color
1049                 if (ef->getEmission().isColor()) {
1050                         // XXX there is no emission color in blender
1051                         // but I am not sure
1052                 }
1053                 // texture
1054                 else if (ef->getEmission().isTexture()) {
1055                         ctex = ef->getEmission().getTexture(); 
1056                         mtex = create_texture(ef, ctex, ma, i);
1057                         if (mtex != NULL) {
1058                                 mtex->mapto = MAP_EMIT; 
1059                                 i++;
1060                         }
1061                 }
1062                 return true;
1063         }
1064
1065         /** When this method is called, the writer must write the camera.
1066                 @return The writer should return true, if writing succeeded, false otherwise.*/
1067         virtual bool writeCamera( const COLLADAFW::Camera* camera ) 
1068         {
1069                 std::string name = camera->getOriginalId();
1070                 Camera *cam = (Camera*)add_camera((char*)name.c_str());
1071                 if (cam != NULL)
1072                         this->uid_camera_map[camera->getUniqueId()] = cam;
1073                 else fprintf(stderr, "Cannot create camera. \n");
1074                 // XXX import camera options
1075                 return true;
1076         }
1077
1078         /** When this method is called, the writer must write the image.
1079                 @return The writer should return true, if writing succeeded, false otherwise.*/
1080         virtual bool writeImage( const COLLADAFW::Image* image ) 
1081         {
1082             const std::string& filepath = image->getImageURI().toNativePath();
1083                 Image *ima = BKE_add_image_file((char*)filepath.c_str(), 0);
1084                 if (ima == NULL)
1085                         fprintf(stderr, "Cannot create image. \n");
1086                 else
1087                         this->uid_image_map[image->getUniqueId()] = ima;
1088                 
1089                 return true;
1090         }
1091
1092         /** When this method is called, the writer must write the light.
1093                 @return The writer should return true, if writing succeeded, false otherwise.*/
1094         virtual bool writeLight( const COLLADAFW::Light* light ) 
1095         {
1096                 std::string name = light->getOriginalId();
1097                 Lamp *lamp = (Lamp*)add_lamp((char*)name.c_str());
1098                 COLLADAFW::Light::LightType type = light->getLightType();
1099                 switch(type) {
1100                 case COLLADAFW::Light::AMBIENT_LIGHT:
1101                         {
1102                                 lamp->type = LA_HEMI;
1103                         }
1104                         break;
1105                 case COLLADAFW::Light::SPOT_LIGHT:
1106                         {
1107                                 lamp->type = LA_SPOT;
1108                         }
1109                         break;
1110                 case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1111                         {
1112                                 lamp->type = LA_SUN;
1113                         }
1114                         break;
1115                 case COLLADAFW::Light::POINT_LIGHT:
1116                         {
1117                                 lamp->type = LA_AREA;
1118                         }
1119                         break;
1120                 case COLLADAFW::Light::UNDEFINED:
1121                         {
1122                                 fprintf(stderr, "Current lamp type is not supported. \n");
1123                                 lamp->type = LA_LOCAL;
1124                         }
1125                         break;
1126                 }
1127                         
1128                 if (lamp != NULL)
1129                         this->uid_lamp_map[light->getUniqueId()] = lamp;
1130                 else fprintf(stderr, "Cannot create lamp. \n");
1131                 // XXX import light options*/
1132                 return true;
1133         }
1134         
1135         float get_float(COLLADAFW::FloatOrDoubleArray array, int i)
1136         {
1137                 switch(array.getType()) {
1138                 case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
1139                         {
1140                                 COLLADAFW::ArrayPrimitiveType<float> *values = array.getFloatValues();
1141                                 return (*values)[i];
1142                         }
1143                 case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
1144                         {
1145                                 COLLADAFW::ArrayPrimitiveType<double> *values = array.getDoubleValues();
1146                                 return (float)(*values)[i];
1147                         }
1148                 }
1149         }
1150         
1151         void write_curves(const COLLADAFW::Animation* anim,
1152                                           COLLADAFW::AnimationCurve *curve,
1153                                           COLLADAFW::FloatOrDoubleArray input,
1154                                           COLLADAFW::FloatOrDoubleArray output,
1155                                           COLLADAFW::FloatOrDoubleArray intan,
1156                                           COLLADAFW::FloatOrDoubleArray outtan, size_t dim, float fps)
1157         {
1158                 int i;
1159                 if (dim == 1) {
1160                         // create fcurve
1161                         FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1162                         if (!fcu) {
1163                                 fprintf(stderr, "Cannot create fcurve. \n");
1164                                 return;
1165                         }
1166                         char *path = "location";
1167                         fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1168                         fcu->rna_path = BLI_strdupn(path, strlen(path));
1169                         fcu->array_index = 0;
1170                         fcu->totvert = curve->getKeyCount();
1171                         
1172                         // create beztriple for each key
1173                         for (i = 0; i < curve->getKeyCount(); i++) {
1174                                 BezTriple bez;
1175                                 memset(&bez, 0, sizeof(BezTriple));
1176                                 // intangent
1177                                 bez.vec[0][0] = get_float(intan, i + i) * fps;
1178                                 bez.vec[0][1] = get_float(intan, i + i + 1);
1179                                 // input, output
1180                                 bez.vec[1][0] = get_float(input, i) * fps;
1181                                 bez.vec[1][1] = get_float(output, i);
1182                                 // outtangent
1183                                 bez.vec[2][0] = get_float(outtan, i + i) * fps;
1184                                 bez.vec[2][1] = get_float(outtan, i + i + 1);
1185                                 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1186                                 bez.f1 = bez.f2 = bez.f3 = SELECT;
1187                                 bez.h1 = bez.h2 = HD_AUTO;
1188                                 insert_bezt_fcurve(fcu, &bez);
1189                                 calchandles_fcurve(fcu);
1190                         }
1191                         // map fcurve to animation's UID
1192                         this->uid_fcurve_map[anim->getUniqueId()].push_back(fcu);
1193                 }
1194                 else if(dim == 3) {
1195                         for (i = 0; i < dim; i++ ) {
1196                                 // create fcurve
1197                                 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
1198                                 if (!fcu) {
1199                                         fprintf(stderr, "Cannot create fcurve. \n");
1200                                         continue;
1201                                 }
1202                                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
1203                                 fcu->rna_path = "location";
1204                                 fcu->array_index = 0;
1205                                 fcu->totvert = curve->getKeyCount();
1206                                 
1207                                 // create beztriple for each key
1208                                 for (int j = 0; j < curve->getKeyCount(); j++) {
1209                                         BezTriple bez;
1210                                         memset(&bez, 0, sizeof(BezTriple));
1211                                         // intangent
1212                                         bez.vec[0][0] = get_float(intan, j * 6 + i + i) * fps;
1213                                         bez.vec[0][1] = get_float(intan, j * 6 + i + i + 1);
1214                                         // input, output
1215                                         bez.vec[1][0] = get_float(input, j) * fps; 
1216                                         bez.vec[1][1] = get_float(output, j * 3 + i);
1217                                         // outtangent
1218                                         bez.vec[2][0] = get_float(outtan, j * 6 + i + i) * fps;
1219                                         bez.vec[2][1] = get_float(outtan, j * 6 + i + i + 1);
1220                                         bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1221                                         bez.f1 = bez.f2 = bez.f3 = SELECT;
1222                                         bez.h1 = bez.h2 = HD_AUTO;
1223                                         insert_bezt_fcurve(fcu, &bez);
1224                                         calchandles_fcurve(fcu);
1225                                 }
1226                                 // map fcurve to animation's UID
1227                                 this->uid_fcurve_map[anim->getUniqueId()].push_back(fcu);
1228                                 
1229                         }
1230                 }
1231         }
1232         
1233         // this function is called only for animations that pass COLLADAFW::validate
1234         virtual bool writeAnimation( const COLLADAFW::Animation* anim ) 
1235         {
1236                 if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
1237                         COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve*)anim;
1238                         Scene *scene = CTX_data_scene(mContext);
1239                         float fps = (float)FPS;
1240                         // I wonder how do we use this (Arystan)
1241                         size_t dim = curve->getOutDimension();
1242                         
1243                         // XXX Don't know if it's necessary
1244                         // Should we check outPhysicalDimension?
1245                         if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) {
1246                                 fprintf(stderr, "Inputs physical dimension is not time. \n");
1247                                 return true;
1248                         }
1249                         COLLADAFW::FloatOrDoubleArray input = curve->getInputValues();
1250                         COLLADAFW::FloatOrDoubleArray output = curve->getOutputValues();
1251                         COLLADAFW::FloatOrDoubleArray intan = curve->getInTangentValues();
1252                         COLLADAFW::FloatOrDoubleArray outtan = curve->getOutTangentValues();
1253                         // a curve can have mixed interpolation type,
1254                         // in this case curve->getInterpolationTypes returns a list of interpolation types per key
1255                         COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
1256                         
1257                         if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
1258                                 switch (interp) {
1259                                 case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
1260                                         // support this
1261                                         write_curves(anim, curve, input, output, intan, outtan, dim, fps);
1262                                         break;
1263                                 case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
1264                                         // and this
1265                                         write_curves(anim, curve, input, output, intan, outtan, dim, fps);
1266                                         break;
1267                                 case COLLADAFW::AnimationCurve::INTERPOLATION_CARDINAL:
1268                                 case COLLADAFW::AnimationCurve::INTERPOLATION_HERMITE:
1269                                 case COLLADAFW::AnimationCurve::INTERPOLATION_BSPLINE:
1270                                 case COLLADAFW::AnimationCurve::INTERPOLATION_STEP:
1271                                         fprintf(stderr, "CARDINAL, HERMITE, BSPLINE and STEP anim interpolation types not supported yet.\n");
1272                                         break;
1273                                 }
1274                         }
1275                         else {
1276                                 // not supported yet
1277                                 fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n");
1278                         }
1279                 }
1280                 else {
1281                         fprintf(stderr, "FORMULA animation type is not supported yet.\n");
1282                 }
1283                 
1284                 return true;
1285         }
1286         
1287         void change_fcurve(Object *ob, const COLLADAFW::UniqueId& anim_id, char *rna_path, int array_index)
1288         {
1289                 if (uid_fcurve_map.find(anim_id) == uid_fcurve_map.end()) {
1290                         fprintf(stderr, "Cannot find fcurves by UID.\n");
1291                         return;
1292                 }
1293                 ID *id = &ob->id;
1294                 bAction *act;
1295                 if (!ob->adt || !ob->adt->action)
1296                         act = verify_adt_action(id, 1);
1297                 else 
1298                         act = verify_adt_action(id, 0);
1299                 if (!ob->adt || !ob->adt->action) {
1300                         fprintf(stderr, "Cannot create anim data or action for this object. \n");
1301                         return;
1302                 }
1303                 FCurve *fcu;
1304                 std::vector<FCurve*> fcurves = uid_fcurve_map[anim_id];
1305                 std::vector<FCurve*>::iterator it;
1306                 int i = 0;
1307                 for (it = fcurves.begin(); it != fcurves.end(); it++) {
1308                         fcu = *it;
1309                         strcpy(fcu->rna_path, rna_path);
1310                         if (array_index == -1)
1311                                 fcu->array_index = i;
1312                         else
1313                                 fcu->array_index = array_index;
1314                         // convert degrees to radians for rotation
1315                         if (strcmp(rna_path, "rotation") == 0) {
1316                                 for(int j = 0; j < fcu->totvert; j++) {
1317                                         float rot_intan = fcu->bezt[j].vec[0][1];
1318                                         float rot_output = fcu->bezt[j].vec[1][1];
1319                                         float rot_outtan = fcu->bezt[j].vec[2][1];
1320                                     fcu->bezt[j].vec[0][1] = rot_intan * M_PI / 180.0f;
1321                                         fcu->bezt[j].vec[1][1] = rot_output * M_PI / 180.0f;
1322                                         fcu->bezt[j].vec[2][1] = rot_outtan * M_PI / 180.0f;
1323                                 }
1324                         }
1325                         i++;
1326                         BLI_addtail(&act->curves, fcu);
1327                 }
1328         }
1329         
1330         // called on post-process stage after writeVisualScenes
1331         virtual bool writeAnimationList( const COLLADAFW::AnimationList* animationList ) 
1332         {
1333                 const COLLADAFW::UniqueId& anim_list_id = animationList->getUniqueId();
1334
1335                 // possible in case we cannot interpret some transform
1336                 if (uid_animated_map.find(anim_list_id) == uid_animated_map.end()) {
1337                         return true;
1338                 }
1339                 
1340                 // what does this AnimationList animate?
1341                 AnimatedTransform& animated = uid_animated_map[anim_list_id];
1342                 char *loc = "location";
1343                 char *rotate = "rotation";
1344                 char *scale = "scale";
1345                 Object *ob = animated.ob;
1346                 
1347                 const COLLADAFW::AnimationList::AnimationBindings& bindings = animationList->getAnimationBindings();
1348                 switch (animated.tm->getTransformationType()) {
1349                 case COLLADAFW::Transformation::TRANSLATE:
1350                         {
1351                                 for (int i = 0; i < bindings.getCount(); i++) {
1352                                         const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
1353                                         COLLADAFW::UniqueId anim_uid = binding.animation;
1354                                         
1355                                         switch (binding.animationClass) {
1356                                         case COLLADAFW::AnimationList::POSITION_X:
1357                                                 change_fcurve(ob, anim_uid, loc, 0);
1358                                                 break;
1359                                         case COLLADAFW::AnimationList::POSITION_Y:
1360                                                 change_fcurve(ob, anim_uid, loc, 1);
1361                                                 break;
1362                                         case COLLADAFW::AnimationList::POSITION_Z:
1363                                                 change_fcurve(ob, anim_uid, loc, 2);
1364                                                 break;
1365                                         case COLLADAFW::AnimationList::POSITION_XYZ:
1366                                                 change_fcurve(ob, anim_uid, loc, -1);
1367                                                 break;
1368                                         default:
1369                                                 fprintf(stderr, "AnimationClass %d is not supported for TRANSLATE transformation.\n", binding.animationClass);
1370                                         }
1371                                 }
1372                         }
1373                         break;
1374                 case COLLADAFW::Transformation::ROTATE:
1375                         {
1376                                 COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)animated.tm;
1377                                 COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
1378                                 
1379                                 for (int i = 0; i < bindings.getCount(); i++) {
1380                                         const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
1381                                         COLLADAFW::UniqueId anim_uid = binding.animation;
1382                                         
1383                                         switch (binding.animationClass) {
1384                                         case COLLADAFW::AnimationList::ANGLE:
1385                                                 if (COLLADABU::Math::Vector3::UNIT_X == axis) {
1386                                                         change_fcurve(ob, anim_uid, rotate, 0);
1387                                                 }
1388                                                 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
1389                                                         change_fcurve(ob, anim_uid, rotate, 1);
1390                                                 }
1391                                                 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
1392                                                         change_fcurve(ob, anim_uid, rotate, 2);
1393                                                 }
1394                                                 break;
1395                                         case COLLADAFW::AnimationList::AXISANGLE:
1396                                                 // convert axis-angle to quat? or XYZ?
1397                                                 break;
1398                                         default:
1399                                                 fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
1400                                                                 binding.animationClass);
1401                                         }
1402                                 }
1403                         }
1404                         break;
1405                 case COLLADAFW::Transformation::SCALE:
1406                         {
1407                                 // same as for TRANSLATE
1408                                 for (int i = 0; i < bindings.getCount(); i++) {
1409                                         const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
1410                                         COLLADAFW::UniqueId anim_uid = binding.animation;
1411                                         
1412                                         switch (binding.animationClass) {
1413                                         case COLLADAFW::AnimationList::POSITION_X:
1414                                                 change_fcurve(ob, anim_uid, scale, 0);
1415                                                 break;
1416                                         case COLLADAFW::AnimationList::POSITION_Y:
1417                                                 change_fcurve(ob, anim_uid, scale, 1);
1418                                                 break;
1419                                         case COLLADAFW::AnimationList::POSITION_Z:
1420                                                 change_fcurve(ob, anim_uid, scale, 2);
1421                                                 break;
1422                                         case COLLADAFW::AnimationList::POSITION_XYZ:
1423                                                 change_fcurve(ob, anim_uid, scale, -1);
1424                                                 break;
1425                                         default:
1426                                                 fprintf(stderr, "AnimationClass %d is not supported for TRANSLATE transformation.\n", binding.animationClass);
1427                                         }
1428                                 }
1429                         }
1430                         break;
1431                 case COLLADAFW::Transformation::MATRIX:
1432                 case COLLADAFW::Transformation::SKEW:
1433                 case COLLADAFW::Transformation::LOOKAT:
1434                         fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
1435                         break;
1436                 }
1437                 
1438                 return true;
1439         }
1440         
1441         /** When this method is called, the writer must write the skin controller data.
1442                 @return The writer should return true, if writing succeeded, false otherwise.*/
1443         virtual bool writeSkinControllerData( const COLLADAFW::SkinControllerData* skinControllerData ) 
1444         {
1445                 // see COLLADAFW::validate for an example of how to use SkinControllerData
1446                 return true;
1447         }
1448
1449         /** When this method is called, the writer must write the controller.
1450                 @return The writer should return true, if writing succeeded, false otherwise.*/
1451         virtual bool writeController( const COLLADAFW::Controller* controller ) 
1452         {
1453                 // if skin controller
1454                 if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
1455                         return true;
1456                 }
1457                 // if morph controller
1458                 else {
1459                         return true;
1460                 }
1461         }
1462 };
1463
1464 void DocumentImporter::import(bContext *C, const char *filename)
1465 {
1466         Writer w(C, filename);
1467         w.write();
1468 }