Camera tracking integration
[blender.git] / source / blender / collada / DocumentImporter.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/collada/DocumentImporter.cpp
26  *  \ingroup collada
27  */
28
29 // TODO:
30 // * name imported objects
31 // * import object rotation as euler
32
33 #include <string>
34 #include <map>
35 #include <algorithm> // sort()
36
37 #include "COLLADAFWRoot.h"
38 #include "COLLADAFWStableHeaders.h"
39 #include "COLLADAFWColorOrTexture.h"
40 #include "COLLADAFWIndexList.h"
41 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
42 #include "COLLADAFWPolygons.h"
43 #include "COLLADAFWSampler.h"
44 #include "COLLADAFWTypes.h"
45 #include "COLLADAFWVisualScene.h"
46 #include "COLLADAFWArrayPrimitiveType.h"
47 #include "COLLADAFWLibraryNodes.h"
48 #include "COLLADAFWCamera.h"
49 #include "COLLADAFWLight.h"
50
51 #include "COLLADASaxFWLLoader.h"
52 #include "COLLADASaxFWLIExtraDataCallbackHandler.h"
53
54 #include "BLI_listbase.h"
55 #include "BLI_math.h"
56 #include "BLI_string.h"
57 #include "BLI_utildefines.h"
58
59 #include "BKE_main.h"
60 #include "BKE_library.h"
61 #include "BKE_texture.h"
62 #include "BKE_fcurve.h"
63 #include "BKE_depsgraph.h"
64 #include "BLI_path_util.h"
65 #include "BKE_scene.h"
66 #include "BKE_global.h"
67 #include "BKE_material.h"
68 #include "BKE_utildefines.h"
69 #include "BKE_image.h"
70
71 #include "DNA_camera_types.h"
72 #include "DNA_lamp_types.h"
73
74 #include "RNA_access.h"
75
76 #include "MEM_guardedalloc.h"
77
78 #include "ExtraHandler.h"
79 #include "ErrorHandler.h"
80 #include "DocumentImporter.h"
81 #include "TransformReader.h"
82
83 #include "collada_internal.h"
84 #include "collada_utils.h"
85
86
87 /*
88   COLLADA Importer limitations:
89   - no multiple scene import, all objects are added to active scene
90  */
91
92 // #define COLLADA_DEBUG
93 // creates empties for each imported bone on layer 2, for debugging
94 // #define ARMATURE_TEST
95
96 DocumentImporter::DocumentImporter(bContext *C, const char *filename) :
97         mImportStage(General),
98         mFilename(filename),
99         mContext(C),
100         armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
101         mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
102         anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
103 {}
104
105 DocumentImporter::~DocumentImporter()
106 {
107         TagsMap::iterator etit;
108         etit = uid_tags_map.begin();
109         while(etit!=uid_tags_map.end()) {
110                 delete etit->second;
111                 etit++;
112         }
113 }
114
115 bool DocumentImporter::import()
116 {
117         ErrorHandler errorHandler;
118         COLLADASaxFWL::Loader loader(&errorHandler);
119         COLLADAFW::Root root(&loader, this);
120         ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
121         
122         loader.registerExtraDataCallbackHandler(ehandler);
123
124         if (!root.loadDocument(mFilename))
125                 return false;
126         
127         if(errorHandler.hasError())
128                 return false;
129         
130         /** TODO set up scene graph and such here */
131         
132         mImportStage = Controller;
133         
134         COLLADASaxFWL::Loader loader2;
135         COLLADAFW::Root root2(&loader2, this);
136         
137         if (!root2.loadDocument(mFilename))
138                 return false;
139         
140         
141         delete ehandler;
142
143         return true;
144 }
145
146 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
147 {
148         // TODO: if possible show error info
149         //
150         // Should we get rid of invisible Meshes that were created so far
151         // or maybe create objects at coordinate space origin?
152         //
153         // The latter sounds better.
154 }
155
156 void DocumentImporter::start(){}
157
158 void DocumentImporter::finish()
159 {
160         if(mImportStage!=General)
161                 return;
162                 
163         /** TODO Break up and put into 2-pass parsing of DAE */
164         std::vector<const COLLADAFW::VisualScene*>::iterator it;
165         for (it = vscenes.begin(); it != vscenes.end(); it++) {
166                 PointerRNA sceneptr, unit_settings;
167                 PropertyRNA *system, *scale;
168                 // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
169                 Scene *sce = CTX_data_scene(mContext);
170                 
171                 // for scene unit settings: system, scale_length
172                 RNA_id_pointer_create(&sce->id, &sceneptr);
173                 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
174                 system = RNA_struct_find_property(&unit_settings, "system");
175                 scale = RNA_struct_find_property(&unit_settings, "scale_length");
176                 
177                 switch(unit_converter.isMetricSystem()) {
178                         case UnitConverter::Metric:
179                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
180                                 break;
181                         case UnitConverter::Imperial:
182                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
183                                 break;
184                         default:
185                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
186                                 break;
187                 }
188                 RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter());
189                 
190                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
191
192                 for (unsigned int i = 0; i < roots.getCount(); i++) {
193                         write_node(roots[i], NULL, sce, NULL, false);
194                 }
195         }
196         armature_importer.set_tags_map(this->uid_tags_map);
197         armature_importer.make_armatures(mContext);
198
199 #if 0
200         armature_importer.fix_animation();
201 #endif
202
203         for (std::vector<const COLLADAFW::VisualScene*>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
204                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
205
206                 for (unsigned int i = 0; i < roots.getCount(); i++)
207                         translate_anim_recursive(roots[i],NULL,NULL);
208         }
209
210         if (libnode_ob.size()) {
211                 Scene *sce = CTX_data_scene(mContext);
212
213                 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
214                 // free all library_nodes
215                 std::vector<Object*>::iterator it;
216                 for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
217                         Object *ob = *it;
218
219                         Base *base = object_in_scene(ob, sce);
220                         if (base) {
221                                 BLI_remlink(&sce->base, base);
222                                 free_libblock_us(&G.main->object, base->object);
223                                 if (sce->basact==base)
224                                         sce->basact= NULL;
225                                 MEM_freeN(base);
226                         }
227                 }
228                 libnode_ob.clear();
229
230                 DAG_scene_sort(CTX_data_main(mContext), sce);
231                 DAG_ids_flush_update(CTX_data_main(mContext), 0);
232         }
233 }
234
235
236 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
237 {
238         if (par && par->getType() == COLLADAFW::Node::JOINT) {
239                 // par is root if there's no corresp. key in root_map
240                 if (root_map.find(par->getUniqueId()) == root_map.end())
241                         root_map[node->getUniqueId()] = par;
242                 else
243                         root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
244         }
245
246         /*COLLADAFW::Transformation::TransformationType types[] = {
247                 COLLADAFW::Transformation::ROTATE,
248                 COLLADAFW::Transformation::SCALE,
249                 COLLADAFW::Transformation::TRANSLATE,
250                 COLLADAFW::Transformation::MATRIX
251         };
252
253         Object *ob;*/
254         unsigned int i;
255
256         //for (i = 0; i < 4; i++)
257                 //ob = 
258         anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
259
260         COLLADAFW::NodePointerArray &children = node->getChildNodes();
261         for (i = 0; i < children.getCount(); i++) {
262                 translate_anim_recursive(children[i], node, NULL);
263         }
264 }
265
266 /** When this method is called, the writer must write the global document asset.
267         @return The writer should return true, if writing succeeded, false otherwise.*/
268 bool DocumentImporter::writeGlobalAsset ( const COLLADAFW::FileInfo* asset ) 
269 {
270         unit_converter.read_asset(asset);
271
272         return true;
273 }
274
275 /** When this method is called, the writer must write the scene.
276         @return The writer should return true, if writing succeeded, false otherwise.*/
277 bool DocumentImporter::writeScene ( const COLLADAFW::Scene* scene ) 
278 {
279         // XXX could store the scene id, but do nothing for now
280         return true;
281 }
282 Object* DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
283 {
284         const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
285         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {     
286                 fprintf(stderr, "Couldn't find camera by UID.\n");
287                 return NULL;
288         }
289         Object *ob = add_object(sce, OB_CAMERA);
290         Camera *cam = uid_camera_map[cam_uid];
291         Camera *old_cam = (Camera*)ob->data;
292         ob->data = cam;
293         old_cam->id.us--;
294         if (old_cam->id.us == 0)
295                 free_libblock(&G.main->camera, old_cam);
296         return ob;
297 }
298
299 Object* DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
300 {
301         const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
302         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {        
303                 fprintf(stderr, "Couldn't find lamp by UID. \n");
304                 return NULL;
305         }
306         Object *ob = add_object(sce, OB_LAMP);
307         Lamp *la = uid_lamp_map[lamp_uid];
308         Lamp *old_lamp = (Lamp*)ob->data;
309         ob->data = la;
310         old_lamp->id.us--;
311         if (old_lamp->id.us == 0)
312                 free_libblock(&G.main->lamp, old_lamp);
313         return ob;
314 }
315
316 Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, Object *par_ob, bool is_library_node)
317 {
318         Object *obn = copy_object(source_ob);
319         obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
320         scene_add_base(sce, obn);
321
322         if (instance_node) {
323                 anim_importer.read_node_transform(instance_node, obn);
324                 // if we also have a source_node (always ;), take its
325                 // transformation matrix and apply it to the newly instantiated
326                 // object to account for node hierarchy transforms in
327                 // .dae
328                 if(source_node) {
329                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
330                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
331                         float mat[4][4];
332                         for (int i = 0; i < 4; i++) {
333                                 for (int j = 0; j < 4; j++) {
334                                         mat[i][j] = bmat4[i][j];
335                                 }
336                         }
337                         // calc new matrix and apply
338                         mul_m4_m4m4(obn->obmat, mat, obn->obmat);
339                         object_apply_mat4(obn, obn->obmat, 0, 0);
340                 }
341         }
342         else {
343                 anim_importer.read_node_transform(source_node, obn);
344         }
345
346         DAG_scene_sort(CTX_data_main(mContext), sce);
347         DAG_ids_flush_update(CTX_data_main(mContext), 0);
348
349         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
350         if (children.getCount()) {
351                 for (unsigned int i = 0; i < children.getCount(); i++) {
352                         COLLADAFW::Node *child_node = children[i];
353                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
354                         if (object_map.find(child_id) == object_map.end())
355                                 continue;
356                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
357                         Object *new_child = NULL;
358                         if (inodes.getCount()) { // \todo loop through instance nodes
359                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
360                                 new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, NULL, is_library_node);
361                         }
362                         else {
363                                 new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, NULL, is_library_node);
364                         }
365                         bc_set_parent(new_child, obn, mContext, true);
366
367                         if (is_library_node)
368                                 libnode_ob.push_back(new_child);
369                 }
370         }
371
372         // when we have an instance_node, don't return the object, because otherwise
373         // its correct location gets overwritten in write_node(). Fixes bug #26012.
374         if(instance_node) {
375                 if (par_ob && obn)
376                         bc_set_parent(obn, par_ob, mContext);
377                 return NULL;
378         }
379
380         else return obn;
381 }
382
383 void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
384 {
385         Object *ob = NULL;
386         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
387
388         if (is_joint) {
389                 if ( par ) {
390                 Object * empty = par;
391                 par = add_object(sce, OB_ARMATURE);
392                 bc_set_parent(par,empty->parent, mContext);
393                 //remove empty : todo
394                 object_map[parent_node->getUniqueId()] = par;
395                 }
396                 armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
397         }
398         else {
399                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
400                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
401                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
402                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
403                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
404                 size_t geom_done = 0;
405                 size_t camera_done = 0;
406                 size_t lamp_done = 0;
407                 size_t controller_done = 0;
408                 size_t inst_done = 0;
409
410                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
411                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
412                 // <instance_geometry>
413                 while (geom_done < geom.getCount()) {
414                         ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
415                                                                                                   material_texture_mapping_map);
416                         ++geom_done;
417                 }
418                 while (camera_done < camera.getCount()) {
419                         ob = create_camera_object(camera[camera_done], sce);
420                         ++camera_done;
421                 }
422                 while (lamp_done < lamp.getCount()) {
423                         ob = create_lamp_object(lamp[lamp_done], sce);
424                         ++lamp_done;
425                 }
426                 while (controller_done < controller.getCount()) {
427                         COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry*)controller[controller_done];
428                         ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
429                         ++controller_done;
430                 }
431                 // XXX instance_node is not supported yet
432                 while (inst_done < inst_node.getCount()) {
433                         const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
434                         if (object_map.find(node_id) == object_map.end()) {
435                                 fprintf(stderr, "Cannot find node to instanciate.\n");
436                                 ob = NULL;
437                         }
438                         else {
439                                 Object *source_ob = object_map[node_id];
440                                 COLLADAFW::Node *source_node = node_map[node_id];
441
442                                 ob = create_instance_node(source_ob, source_node, node, sce, par, is_library_node);
443                         }
444                         ++inst_done;
445                 }
446                 // if node is empty - create empty object
447                 // XXX empty node may not mean it is empty object, not sure about this
448                 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
449                         ob = add_object(sce, OB_EMPTY);
450                 }
451                 
452                 // check if object is not NULL
453                 if (!ob) return;
454                 
455                 std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
456                 rename_id(&ob->id, (char*)nodename.c_str());
457
458                 object_map[node->getUniqueId()] = ob;
459                 node_map[node->getUniqueId()] = node;
460
461                 if (is_library_node)
462                         libnode_ob.push_back(ob);
463         }
464
465         anim_importer.read_node_transform(node, ob); // overwrites location set earlier
466
467         if (!is_joint) {
468                 // if par was given make this object child of the previous 
469                 if (par && ob)
470                         bc_set_parent(ob, par, mContext);
471         }
472
473         // if node has child nodes write them
474         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
475         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {     
476                 write_node(child_nodes[i], node, sce, ob, is_library_node);
477         }
478 }
479
480 /** When this method is called, the writer must write the entire visual scene.
481         @return The writer should return true, if writing succeeded, false otherwise.*/
482 bool DocumentImporter::writeVisualScene ( const COLLADAFW::VisualScene* visualScene ) 
483 {
484         if(mImportStage!=General)
485                 return true;
486                 
487         // this method called on post process after writeGeometry, writeMaterial, etc.
488
489         // for each <node> in <visual_scene>:
490         // create an Object
491         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
492
493         // update: since we cannot link a Mesh with Object in
494         // writeGeometry because <geometry> does not reference <node>,
495         // we link Objects with Meshes here
496
497         vscenes.push_back(visualScene);
498         
499         return true;
500 }
501
502 /** When this method is called, the writer must handle all nodes contained in the 
503         library nodes.
504         @return The writer should return true, if writing succeeded, false otherwise.*/
505 bool DocumentImporter::writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes ) 
506 {
507         if(mImportStage!=General)
508                 return true;
509                 
510         Scene *sce = CTX_data_scene(mContext);
511
512         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
513
514         for (unsigned int i = 0; i < nodes.getCount(); i++) {
515                 write_node(nodes[i], NULL, sce, NULL, true);
516         }
517
518         return true;
519 }
520
521 /** When this method is called, the writer must write the geometry.
522         @return The writer should return true, if writing succeeded, false otherwise.*/
523 bool DocumentImporter::writeGeometry ( const COLLADAFW::Geometry* geom ) 
524 {
525         if(mImportStage!=General)
526                 return true;
527                 
528         return mesh_importer.write_geometry(geom);
529 }
530
531 /** When this method is called, the writer must write the material.
532         @return The writer should return true, if writing succeeded, false otherwise.*/
533 bool DocumentImporter::writeMaterial( const COLLADAFW::Material* cmat ) 
534 {
535         if(mImportStage!=General)
536                 return true;
537                 
538         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
539         Material *ma = add_material((char*)str_mat_id.c_str());
540         
541         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
542         this->uid_material_map[cmat->getUniqueId()] = ma;
543         
544         return true;
545 }
546
547 // create mtex, create texture, set texture image
548 MTex* DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
549                                          int i, TexIndexTextureArrayMap &texindex_texarray_map)
550 {
551         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
552         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
553                 
554         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
555         
556         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
557                 fprintf(stderr, "Couldn't find an image by UID.\n");
558                 return NULL;
559         }
560         
561         ma->mtex[i] = add_mtex();
562         ma->mtex[i]->texco = TEXCO_UV;
563         ma->mtex[i]->tex = add_texture("Texture");
564         ma->mtex[i]->tex->type = TEX_IMAGE;
565         ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
566         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
567         
568         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
569         
570         return ma->mtex[i];
571 }
572
573 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
574 {
575         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
576         
577         // blinn
578         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
579                 ma->spec_shader = MA_SPEC_BLINN;
580                 ma->spec = ef->getShininess().getFloatValue();
581         }
582         // phong
583         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
584                 ma->spec_shader = MA_SPEC_PHONG;
585                 ma->har = ef->getShininess().getFloatValue();
586         }
587         // lambert
588         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
589                 ma->diff_shader = MA_DIFF_LAMBERT;
590         }
591         // default - lambert
592         else {
593                 ma->diff_shader = MA_DIFF_LAMBERT;
594                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
595         }
596         // reflectivity
597         ma->ray_mirror = ef->getReflectivity().getFloatValue();
598         // index of refraction
599         ma->ang = ef->getIndexOfRefraction().getFloatValue();
600         
601         int i = 0;
602         COLLADAFW::Color col;
603         MTex *mtex = NULL;
604         TexIndexTextureArrayMap texindex_texarray_map;
605         
606         // DIFFUSE
607         // color
608         if (ef->getDiffuse().isColor()) {
609                 col = ef->getDiffuse().getColor();
610                 ma->r = col.getRed();
611                 ma->g = col.getGreen();
612                 ma->b = col.getBlue();
613         }
614         // texture
615         else if (ef->getDiffuse().isTexture()) {
616                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
617                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
618                 if (mtex != NULL) {
619                         mtex->mapto = MAP_COL;
620                         ma->texact = (int)i;
621                         i++;
622                 }
623         }
624         // AMBIENT
625         // color
626         if (ef->getAmbient().isColor()) {
627                 col = ef->getAmbient().getColor();
628                 ma->ambr = col.getRed();
629                 ma->ambg = col.getGreen();
630                 ma->ambb = col.getBlue();
631         }
632         // texture
633         else if (ef->getAmbient().isTexture()) {
634                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
635                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
636                 if (mtex != NULL) {
637                         mtex->mapto = MAP_AMB; 
638                         i++;
639                 }
640         }
641         // SPECULAR
642         // color
643         if (ef->getSpecular().isColor()) {
644                 col = ef->getSpecular().getColor();
645                 ma->specr = col.getRed();
646                 ma->specg = col.getGreen();
647                 ma->specb = col.getBlue();
648         }
649         // texture
650         else if (ef->getSpecular().isTexture()) {
651                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
652                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
653                 if (mtex != NULL) {
654                         mtex->mapto = MAP_SPEC; 
655                         i++;
656                 }
657         }
658         // REFLECTIVE
659         // color
660         if (ef->getReflective().isColor()) {
661                 col = ef->getReflective().getColor();
662                 ma->mirr = col.getRed();
663                 ma->mirg = col.getGreen();
664                 ma->mirb = col.getBlue();
665         }
666         // texture
667         else if (ef->getReflective().isTexture()) {
668                 COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
669                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
670                 if (mtex != NULL) {
671                         mtex->mapto = MAP_REF; 
672                         i++;
673                 }
674         }
675         // EMISSION
676         // color
677         if (ef->getEmission().isColor()) {
678                 // XXX there is no emission color in blender
679                 // but I am not sure
680         }
681         // texture
682         else if (ef->getEmission().isTexture()) {
683                 COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
684                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
685                 if (mtex != NULL) {
686                         mtex->mapto = MAP_EMIT; 
687                         i++;
688                 }
689         }
690         
691         if(ef->getOpacity().isTexture()) {
692                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
693                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
694                 if(mtex != NULL) {
695                         mtex->mapto = MAP_ALPHA;
696                         mtex->tex->imaflag |= TEX_USEALPHA;
697                         i++;
698                         ma->spectra = ma->alpha = 0;
699                         ma->mode |= MA_ZTRANSP|MA_TRANSP;
700                 }
701         }
702         // TRANSPARENT
703         // color
704 //      if (ef->getOpacity().isColor()) {
705 //                      // XXX don't know what to do here
706 //              }
707 //              // texture
708 //              else if (ef->getOpacity().isTexture()) {
709 //                      ctex = ef->getOpacity().getTexture();
710 //                      if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
711 //                      else {
712 //                              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
713 //                              if (mtex != NULL) mtex->mapto = MAP_ALPHA;
714 //                      }
715 //              }
716         material_texture_mapping_map[ma] = texindex_texarray_map;
717 }
718
719 /** When this method is called, the writer must write the effect.
720         @return The writer should return true, if writing succeeded, false otherwise.*/
721
722 bool DocumentImporter::writeEffect( const COLLADAFW::Effect* effect ) 
723 {
724         if(mImportStage!=General)
725                 return true;
726         
727         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
728         
729         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
730                 fprintf(stderr, "Couldn't find a material by UID.\n");
731                 return true;
732         }
733         
734         Material *ma = uid_effect_map[uid];
735         std::map<COLLADAFW::UniqueId, Material*>::iterator  iter;
736         for(iter = uid_material_map.begin(); iter != uid_material_map.end() ; iter++ )
737         {
738                 if ( iter->second == ma ) {
739                         this->FW_object_map[iter->first] = effect;
740                         break;
741                 }
742         }
743         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
744         if (common_efs.getCount() < 1) {
745                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
746                 return true;
747         }
748         // XXX TODO: Take all <profile_common>s
749         // Currently only first <profile_common> is supported
750         COLLADAFW::EffectCommon *ef = common_efs[0];
751         write_profile_COMMON(ef, ma);
752         this->FW_object_map[effect->getUniqueId()] = effect;
753                 
754         return true;
755 }
756
757
758 /** When this method is called, the writer must write the camera.
759         @return The writer should return true, if writing succeeded, false otherwise.*/
760 bool DocumentImporter::writeCamera( const COLLADAFW::Camera* camera ) 
761 {
762         if(mImportStage!=General)
763                 return true;
764                 
765         Camera *cam = NULL;
766         std::string cam_id, cam_name;
767         
768         cam_id = camera->getOriginalId();
769         cam_name = camera->getName();
770         if (cam_name.size()) cam = (Camera*)add_camera((char*)cam_name.c_str());
771         else cam = (Camera*)add_camera((char*)cam_id.c_str());
772         
773         if (!cam) {
774                 fprintf(stderr, "Cannot create camera. \n");
775                 return true;
776         }
777         cam->clipsta = camera->getNearClippingPlane().getValue();
778         cam->clipend = camera->getFarClippingPlane().getValue();
779         
780         COLLADAFW::Camera::CameraType type = camera->getCameraType();
781         switch(type) {
782         case COLLADAFW::Camera::ORTHOGRAPHIC:
783                 {
784                         cam->type = CAM_ORTHO;
785                 }
786                 break;
787         case COLLADAFW::Camera::PERSPECTIVE:
788                 {
789                         cam->type = CAM_PERSP;
790                 }
791                 break;
792         case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
793                 {
794                         fprintf(stderr, "Current camera type is not supported. \n");
795                         cam->type = CAM_PERSP;
796                 }
797                 break;
798         }
799         
800         switch(camera->getDescriptionType()) {
801         case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
802                 {
803                         switch(cam->type) {
804                                 case CAM_ORTHO:
805                                         {
806                                                 double ymag = camera->getYMag().getValue();
807                                                 double aspect = camera->getAspectRatio().getValue();
808                                                 double xmag = aspect*ymag;
809                                                 cam->ortho_scale = (float)xmag;
810                                         }
811                                         break;
812                                 case CAM_PERSP:
813                                 default:
814                                         {
815                                                 double yfov = camera->getYFov().getValue();
816                                                 double aspect = camera->getAspectRatio().getValue();
817                                                 double xfov = aspect*yfov;
818                                                 // xfov is in degrees, cam->lens is in millimiters
819                                                 cam->lens = hfov_to_focallength((float)xfov*(M_PI/180.0f), cam->sensor_x);
820                                         }
821                                         break;
822                         }
823                 }
824                 break;
825         /* XXX correct way to do following four is probably to get also render
826            size and determine proper settings from that somehow */
827         case COLLADAFW::Camera::ASPECTRATIO_AND_X:
828         case COLLADAFW::Camera::SINGLE_X:
829         case COLLADAFW::Camera::X_AND_Y:
830                 {
831                         switch(cam->type) {
832                                 case CAM_ORTHO:
833                                         cam->ortho_scale = (float)camera->getXMag().getValue();
834                                         break;
835                                 case CAM_PERSP:
836                                 default:
837                                         {
838                                                 double x = camera->getXFov().getValue();
839                                                 // x is in degrees, cam->lens is in millimiters
840                                                 cam->lens = hfov_to_focallength((float)x*(M_PI/180.0f), cam->sensor_x);
841                                         }
842                                         break;
843                         }
844                 }
845                 break;
846         case COLLADAFW::Camera::SINGLE_Y:
847                 {
848                         switch(cam->type) {
849                                 case CAM_ORTHO:
850                                         cam->ortho_scale = (float)camera->getYMag().getValue();
851                                         break;
852                                 case CAM_PERSP:
853                                 default:
854                                         {
855                                         double yfov = camera->getYFov().getValue();
856                                         // yfov is in degrees, cam->lens is in millimiters
857                                         cam->lens = hfov_to_focallength((float)yfov*(M_PI/180.0f), cam->sensor_x);
858                                         }
859                                         break;
860                         }
861                 }
862                 break;
863         case COLLADAFW::Camera::UNDEFINED:
864                 // read nothing, use blender defaults.
865                 break;
866         }
867         
868         this->uid_camera_map[camera->getUniqueId()] = cam;
869         this->FW_object_map[camera->getUniqueId()] = camera;
870         // XXX import camera options
871         return true;
872 }
873
874 /** When this method is called, the writer must write the image.
875         @return The writer should return true, if writing succeeded, false otherwise.*/
876 bool DocumentImporter::writeImage( const COLLADAFW::Image* image ) 
877 {
878         if(mImportStage!=General)
879                 return true;
880                 
881         // XXX maybe it is necessary to check if the path is absolute or relative
882         const std::string& filepath = image->getImageURI().toNativePath();
883         const char *filename = (const char*)mFilename.c_str();
884         char dir[FILE_MAX];
885         char full_path[FILE_MAX];
886         
887         BLI_split_dirfile(filename, dir, NULL);
888         BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
889         Image *ima = BKE_add_image_file(full_path);
890         if (!ima) {
891                 fprintf(stderr, "Cannot create image. \n");
892                 return true;
893         }
894         this->uid_image_map[image->getUniqueId()] = ima;
895         
896         return true;
897 }
898
899 /** When this method is called, the writer must write the light.
900         @return The writer should return true, if writing succeeded, false otherwise.*/
901 bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) 
902 {
903         if(mImportStage!=General)
904                 return true;
905
906         Lamp *lamp = NULL;
907         std::string la_id, la_name;
908
909         TagsMap::iterator etit;
910         ExtraTags *et = 0;
911         etit = uid_tags_map.find(light->getUniqueId().toAscii());
912         if(etit != uid_tags_map.end())
913                 et = etit->second;
914
915         la_id = light->getOriginalId();
916         la_name = light->getName();
917         if (la_name.size()) lamp = (Lamp*)add_lamp((char*)la_name.c_str());
918         else lamp = (Lamp*)add_lamp((char*)la_id.c_str());
919
920         if (!lamp) {
921                 fprintf(stderr, "Cannot create lamp. \n");
922                 return true;
923         }
924
925         // if we find an ExtraTags for this, use that instead.
926         if(et && et->isProfile("blender")) {
927                 et->setData("type", &(lamp->type));
928                 et->setData("flag", &(lamp->flag));
929                 et->setData("mode", &(lamp->mode));
930                 et->setData("gamma", &(lamp->k));
931                 et->setData("red", &(lamp->r));
932                 et->setData("green", &(lamp->g));
933                 et->setData("blue", &(lamp->b));
934                 et->setData("shadow_r", &(lamp->shdwr));
935                 et->setData("shadow_g", &(lamp->shdwg));
936                 et->setData("shadow_b", &(lamp->shdwb));
937                 et->setData("energy", &(lamp->energy));
938                 et->setData("dist", &(lamp->dist));
939                 et->setData("spotsize", &(lamp->spotsize));
940                 et->setData("spotblend", &(lamp->spotblend));
941                 et->setData("halo_intensity", &(lamp->haint));
942                 et->setData("att1", &(lamp->att1));
943                 et->setData("att2", &(lamp->att2));
944                 et->setData("falloff_type", &(lamp->falloff_type));
945                 et->setData("clipsta", &(lamp->clipsta));
946                 et->setData("clipend", &(lamp->clipend));
947                 et->setData("shadspotsize", &(lamp->shadspotsize));
948                 et->setData("bias", &(lamp->bias));
949                 et->setData("soft", &(lamp->soft));
950                 et->setData("compressthresh", &(lamp->compressthresh));
951                 et->setData("bufsize", &(lamp->bufsize));
952                 et->setData("samp", &(lamp->samp));
953                 et->setData("buffers", &(lamp->buffers));
954                 et->setData("filtertype", &(lamp->filtertype));
955                 et->setData("bufflag", &(lamp->bufflag));
956                 et->setData("buftype", &(lamp->buftype));
957                 et->setData("ray_samp", &(lamp->ray_samp));
958                 et->setData("ray_sampy", &(lamp->ray_sampy));
959                 et->setData("ray_sampz", &(lamp->ray_sampz));
960                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
961                 et->setData("area_shape", &(lamp->area_shape));
962                 et->setData("area_size", &(lamp->area_size));
963                 et->setData("area_sizey", &(lamp->area_sizey));
964                 et->setData("area_sizez", &(lamp->area_sizez));
965                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
966                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
967                 et->setData("shadhalostep", &(lamp->shadhalostep));
968                 et->setData("sun_effect_type", &(lamp->shadhalostep));
969                 et->setData("skyblendtype", &(lamp->skyblendtype));
970                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
971                 et->setData("spread", &(lamp->spread));
972                 et->setData("sun_brightness", &(lamp->sun_brightness));
973                 et->setData("sun_size", &(lamp->sun_size));
974                 et->setData("backscattered_light", &(lamp->backscattered_light));
975                 et->setData("sun_intensity", &(lamp->sun_intensity));
976                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
977                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
978                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
979                 et->setData("skyblendfac", &(lamp->skyblendfac));
980                 et->setData("sky_exposure", &(lamp->sky_exposure));
981                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
982         }
983         else {
984                 float constatt = light->getConstantAttenuation().getValue();
985                 float linatt = light->getLinearAttenuation().getValue();
986                 float quadatt = light->getQuadraticAttenuation().getValue();
987                 float d = 25.0f;
988                 float att1 = 0.0f;
989                 float att2 = 0.0f;
990                 float e = 1.0f;
991
992                 if (light->getColor().isValid()) {
993                         COLLADAFW::Color col = light->getColor();
994                         lamp->r = col.getRed();
995                         lamp->g = col.getGreen();
996                         lamp->b = col.getBlue();
997                 }
998
999                 if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1000                         att2 = quadatt;
1001                         d = sqrt(1.0f/quadatt);
1002                 }
1003                 // linear light
1004                 else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1005                         att1 = linatt;
1006                         d = (1.0f/linatt);
1007                 } else if (IS_EQ(constatt, 1.0f)) {
1008                         att1 = 1.0f;
1009                 } else {
1010                         // assuming point light (const att = 1.0);
1011                         att1 = 1.0f;
1012                 }
1013                 
1014                 d *= ( 1.0f / unit_converter.getLinearMeter());
1015
1016                 lamp->energy = e;
1017                 lamp->dist = d;
1018
1019                 COLLADAFW::Light::LightType type = light->getLightType();
1020                 switch(type) {
1021                         case COLLADAFW::Light::AMBIENT_LIGHT:
1022                                 {
1023                                         lamp->type = LA_HEMI;
1024                                 }
1025                                 break;
1026                         case COLLADAFW::Light::SPOT_LIGHT:
1027                                 {
1028                                         lamp->type = LA_SPOT;
1029                                         lamp->att1 = att1;
1030                                         lamp->att2 = att2;
1031                                         if(IS_EQ(att1, 0.0f) && att2 > 0)
1032                                                 lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1033                                         if(IS_EQ(att2, 0.0f) && att1 > 0)
1034                                                 lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1035                                         lamp->spotsize = light->getFallOffAngle().getValue();
1036                                         lamp->spotblend = light->getFallOffExponent().getValue();
1037                                 }
1038                                 break;
1039                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1040                                 {
1041                                         /* our sun is very strong, so pick a smaller energy level */
1042                                         lamp->type = LA_SUN;
1043                                         lamp->mode |= LA_NO_SPEC;
1044                                 }
1045                                 break;
1046                         case COLLADAFW::Light::POINT_LIGHT:
1047                                 {
1048                                         lamp->type = LA_LOCAL;
1049                                         lamp->att1 = att1;
1050                                         lamp->att2 = att2;
1051                                         if(IS_EQ(att1, 0.0f) && att2 > 0)
1052                                                 lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1053                                         if(IS_EQ(att2, 0.0f) && att1 > 0)
1054                                                 lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1055                                 }
1056                                 break;
1057                         case COLLADAFW::Light::UNDEFINED:
1058                                 {
1059                                         fprintf(stderr, "Current lamp type is not supported. \n");
1060                                         lamp->type = LA_LOCAL;
1061                                 }
1062                                 break;
1063                 }
1064         }
1065
1066         this->uid_lamp_map[light->getUniqueId()] = lamp;
1067         this->FW_object_map[light->getUniqueId()] = light;
1068         return true;
1069 }
1070
1071 // this function is called only for animations that pass COLLADAFW::validate
1072 bool DocumentImporter::writeAnimation( const COLLADAFW::Animation* anim ) 
1073 {
1074         if(mImportStage!=General)
1075                 return true;
1076                 
1077         // return true;
1078         return anim_importer.write_animation(anim);
1079 }
1080
1081 // called on post-process stage after writeVisualScenes
1082 bool DocumentImporter::writeAnimationList( const COLLADAFW::AnimationList* animationList ) 
1083 {
1084         if(mImportStage!=General)
1085                 return true;
1086                 
1087         // return true;
1088         return anim_importer.write_animation_list(animationList);
1089 }
1090
1091 /** When this method is called, the writer must write the skin controller data.
1092         @return The writer should return true, if writing succeeded, false otherwise.*/
1093 bool DocumentImporter::writeSkinControllerData( const COLLADAFW::SkinControllerData* skin ) 
1094 {
1095         return armature_importer.write_skin_controller_data(skin);
1096 }
1097
1098 // this is called on postprocess, before writeVisualScenes
1099 bool DocumentImporter::writeController( const COLLADAFW::Controller* controller ) 
1100 {
1101         if(mImportStage!=General)
1102                 return true;
1103                 
1104         return armature_importer.write_controller(controller);
1105 }
1106
1107 bool DocumentImporter::writeFormulas( const COLLADAFW::Formulas* formulas )
1108 {
1109         return true;
1110 }
1111
1112 bool DocumentImporter::writeKinematicsScene( const COLLADAFW::KinematicsScene* kinematicsScene )
1113 {
1114         return true;
1115 }
1116
1117 ExtraTags* DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1118 {
1119         if(uid_tags_map.find(uid.toAscii())==uid_tags_map.end()) {
1120                 return NULL;
1121         }
1122         return uid_tags_map[uid.toAscii()];
1123 }
1124
1125 bool DocumentImporter::addExtraTags( const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1126 {
1127         uid_tags_map[uid.toAscii()] = extra_tags;
1128         return true;
1129 }
1130