Base refactor 3/4
[blender.git] / source / blender / collada / DocumentImporter.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/DocumentImporter.cpp
24  *  \ingroup collada
25  */
26
27 // TODO:
28 // * name imported objects
29 // * import object rotation as euler
30
31 #include <string>
32 #include <map>
33 #include <algorithm> // sort()
34
35 #include "COLLADAFWRoot.h"
36 #include "COLLADAFWStableHeaders.h"
37 #include "COLLADAFWColorOrTexture.h"
38 #include "COLLADAFWIndexList.h"
39 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
40 #include "COLLADAFWPolygons.h"
41 #include "COLLADAFWSampler.h"
42 #include "COLLADAFWTypes.h"
43 #include "COLLADAFWVisualScene.h"
44 #include "COLLADAFWArrayPrimitiveType.h"
45 #include "COLLADAFWLibraryNodes.h"
46 #include "COLLADAFWCamera.h"
47 #include "COLLADAFWLight.h"
48
49 #include "COLLADASaxFWLLoader.h"
50 #include "COLLADASaxFWLIExtraDataCallbackHandler.h"
51
52 extern "C" {
53 #include "BLI_listbase.h"
54 #include "BLI_math.h"
55 #include "BLI_string.h"
56 #include "BLI_utildefines.h"
57 #include "BLI_fileops.h"
58
59 #include "BKE_camera.h"
60 #include "BKE_collection.h"
61 #include "BKE_main.h"
62 #include "BKE_lamp.h"
63 #include "BKE_library.h"
64 #include "BKE_texture.h"
65 #include "BKE_fcurve.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_scene.h"
68 #include "BKE_global.h"
69 #include "BKE_material.h"
70 #include "BKE_image.h"
71
72 #include "BLI_path_util.h"
73
74 #include "DNA_camera_types.h"
75 #include "DNA_lamp_types.h"
76
77 #include "RNA_access.h"
78
79 #include "MEM_guardedalloc.h"
80
81 #include "WM_api.h"
82 #include "WM_types.h"
83
84 }
85
86 #include "ExtraHandler.h"
87 #include "ErrorHandler.h"
88 #include "DocumentImporter.h"
89 #include "TransformReader.h"
90
91 #include "collada_internal.h"
92 #include "collada_utils.h"
93
94
95 /*
96  * COLLADA Importer limitations:
97  * - no multiple scene import, all objects are added to active scene
98  */
99
100 // #define COLLADA_DEBUG
101 // creates empties for each imported bone on layer 2, for debugging
102 // #define ARMATURE_TEST
103
104 DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
105         import_settings(import_settings),
106         mImportStage(General),
107         mContext(C),
108         armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C), import_settings),
109         mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
110         anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
111 {
112 }
113
114 DocumentImporter::~DocumentImporter()
115 {
116         TagsMap::iterator etit;
117         etit = uid_tags_map.begin();
118         while (etit != uid_tags_map.end()) {
119                 delete etit->second;
120                 etit++;
121         }
122 }
123
124 bool DocumentImporter::import()
125 {
126         ErrorHandler errorHandler;
127         COLLADASaxFWL::Loader loader(&errorHandler);
128         COLLADAFW::Root root(&loader, this);
129         ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
130         
131         loader.registerExtraDataCallbackHandler(ehandler);
132
133         // deselect all to select new objects
134         BKE_scene_base_deselect_all(CTX_data_scene(mContext));
135
136         std::string mFilename = std::string(this->import_settings->filepath);
137         const std::string encodedFilename = bc_url_encode(mFilename);
138         if (!root.loadDocument(encodedFilename)) {
139                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
140                 delete ehandler;
141                 return false;
142         }
143         
144         if (errorHandler.hasError()) {
145                 delete ehandler;
146                 return false;
147         }
148         
149         /** TODO set up scene graph and such here */
150         
151         mImportStage = Controller;
152         
153         COLLADASaxFWL::Loader loader2;
154         COLLADAFW::Root root2(&loader2, this);
155         
156         if (!root2.loadDocument(encodedFilename)) {
157                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
158                 delete ehandler;
159                 return false;
160         }
161
162         delete ehandler;
163
164         return true;
165 }
166
167 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
168 {
169         // TODO: if possible show error info
170         //
171         // Should we get rid of invisible Meshes that were created so far
172         // or maybe create objects at coordinate space origin?
173         //
174         // The latter sounds better.
175 }
176
177 void DocumentImporter::start()
178 {
179 }
180
181 void DocumentImporter::finish()
182 {
183         if (mImportStage != General)
184                 return;
185
186         Main *bmain = CTX_data_main(mContext);
187         // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
188         Scene *sce = CTX_data_scene(mContext);
189         unit_converter.calculate_scale(*sce);
190
191         std::vector<Object *> *objects_to_scale = new std::vector<Object *>();
192
193         /** TODO Break up and put into 2-pass parsing of DAE */
194         std::vector<const COLLADAFW::VisualScene *>::iterator it;
195         for (it = vscenes.begin(); it != vscenes.end(); it++) {
196                 PointerRNA sceneptr, unit_settings;
197                 PropertyRNA *system, *scale;
198                 
199                 // for scene unit settings: system, scale_length
200
201                 RNA_id_pointer_create(&sce->id, &sceneptr);
202                 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
203                 system = RNA_struct_find_property(&unit_settings, "system");
204                 scale = RNA_struct_find_property(&unit_settings, "scale_length");
205
206                 if (this->import_settings->import_units) {
207                         
208                         switch (unit_converter.isMetricSystem()) {
209                                 case UnitConverter::Metric:
210                                         RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
211                                         break;
212                                 case UnitConverter::Imperial:
213                                         RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
214                                         break;
215                                 default:
216                                         RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
217                                         break;
218                         }
219                         float unit_factor = unit_converter.getLinearMeter();
220                         RNA_property_float_set(&unit_settings, scale, unit_factor);
221                         fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor);
222
223                 }
224
225                 // Write nodes to scene
226                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
227                 for (unsigned int i = 0; i < roots.getCount(); i++) {
228                         std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false);
229                         objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end());
230                         delete objects_done;
231                 }
232
233                 // update scene
234                 DAG_relations_tag_update(bmain);
235                 WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
236
237         }
238
239
240         mesh_importer.optimize_material_assignements();
241
242         armature_importer.set_tags_map(this->uid_tags_map);
243         armature_importer.make_armatures(mContext, *objects_to_scale);
244         armature_importer.make_shape_keys();
245         DAG_relations_tag_update(bmain);
246
247 #if 0
248         armature_importer.fix_animation();
249 #endif
250
251         for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
252                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
253
254                 for (unsigned int i = 0; i < roots.getCount(); i++) {
255                         translate_anim_recursive(roots[i], NULL, NULL);
256                 }
257         }
258
259         if (libnode_ob.size()) {
260                 Scene *sce = CTX_data_scene(mContext);
261
262                 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
263                 // free all library_nodes
264                 std::vector<Object *>::iterator it;
265                 for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
266                         Object *ob = *it;
267
268                         BaseLegacy *base = BKE_scene_base_find(sce, ob);
269                         if (base) {
270                                 BLI_remlink(&sce->base, base);
271                                 BKE_libblock_free_us(G.main, base->object);
272                                 if (sce->basact == base)
273                                         sce->basact = NULL;
274                                 MEM_freeN(base);
275                         }
276                 }
277                 libnode_ob.clear();
278
279                 DAG_relations_tag_update(bmain);
280         }
281         
282         bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
283
284         delete objects_to_scale;
285 }
286
287
288 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
289 {
290
291         // The split in #29246, rootmap must point at actual root when
292         // calculating bones in apply_curves_as_matrix. - actual root is the root node.
293         // This has to do with inverse bind poses being world space
294         // (the sources for skinned bones' restposes) and the way
295         // non-skinning nodes have their "restpose" recursively calculated.
296         // XXX TODO: design issue, how to support unrelated joints taking
297         // part in skinning.
298         if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
299                 // par is root if there's no corresp. key in root_map
300                 if (root_map.find(par->getUniqueId()) == root_map.end())
301                         root_map[node->getUniqueId()] = node;
302                 else
303                         root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
304         }
305
306 #if 0
307         COLLADAFW::Transformation::TransformationType types[] = {
308                 COLLADAFW::Transformation::ROTATE,
309                 COLLADAFW::Transformation::SCALE,
310                 COLLADAFW::Transformation::TRANSLATE,
311                 COLLADAFW::Transformation::MATRIX
312         };
313
314         Object *ob;
315 #endif
316         unsigned int i;
317
318         if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) {
319                 // For Skeletons without root node we have to simulate the
320                 // root node here and recursively enter the same function
321                 // XXX: maybe this can be made more elegant.
322                 translate_anim_recursive(node, node, parob);
323         }
324         else {
325                 anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
326                 COLLADAFW::NodePointerArray &children = node->getChildNodes();
327                 for (i = 0; i < children.getCount(); i++) {
328                         translate_anim_recursive(children[i], node, NULL);
329                 }
330         }
331 }
332
333 /**
334  * If the imported file was made with Blender, return the Blender version used,
335  * otherwise return an empty std::string
336  */
337 std::string DocumentImporter::get_import_version(const COLLADAFW::FileInfo *asset)
338 {
339         const char AUTORING_TOOL[] = "authoring_tool";
340         const std::string BLENDER("Blender ");
341         const COLLADAFW::FileInfo::ValuePairPointerArray &valuePairs = asset->getValuePairArray();
342         for ( size_t i = 0, count = valuePairs.getCount(); i < count; ++i)
343         {
344                 const COLLADAFW::FileInfo::ValuePair* valuePair = valuePairs[i];
345                 const COLLADAFW::String& key = valuePair->first;
346                 const COLLADAFW::String& value = valuePair->second;
347                 if ( key == AUTORING_TOOL )
348                 {
349                         if (value.compare(0, BLENDER.length(), BLENDER) == 0)
350                         {
351                                 // Was made with Blender, now get version string
352                                 std::string v            = value.substr(BLENDER.length());
353                                 std::string::size_type n = v.find(" ");
354                                 if (n > 0) {
355                                         return v.substr(0,n);
356                                 }
357                         }
358                 }
359         }
360         return "";
361 }
362
363 /** When this method is called, the writer must write the global document asset.
364  * \return The writer should return true, if writing succeeded, false otherwise.*/
365 bool DocumentImporter::writeGlobalAsset(const COLLADAFW::FileInfo *asset)
366 {
367         unit_converter.read_asset(asset);
368         import_from_version = get_import_version(asset);
369         anim_importer.set_import_from_version(import_from_version);
370         return true;
371 }
372
373 /** When this method is called, the writer must write the scene.
374  * \return The writer should return true, if writing succeeded, false otherwise.*/
375 bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene)
376 {
377         // XXX could store the scene id, but do nothing for now
378         return true;
379 }
380 Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
381 {
382         const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
383         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {
384                 // fprintf(stderr, "Couldn't find camera by UID.\n");
385                 return NULL;
386         }
387
388         Object *ob = bc_add_object(sce, OB_CAMERA, NULL);
389         Camera *cam = uid_camera_map[cam_uid];
390         Camera *old_cam = (Camera *)ob->data;
391         ob->data = cam;
392         id_us_min(&old_cam->id);
393         if (old_cam->id.us == 0)
394                 BKE_libblock_free(G.main, old_cam);
395         return ob;
396 }
397
398 Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
399 {
400         const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
401         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {
402                 fprintf(stderr, "Couldn't find lamp by UID.\n");
403                 return NULL;
404         }
405
406         Object *ob = bc_add_object(sce, OB_LAMP, NULL);
407         Lamp *la = uid_lamp_map[lamp_uid];
408         Lamp *old_lamp = (Lamp *)ob->data;
409         ob->data = la;
410         id_us_min(&old_lamp->id);
411         if (old_lamp->id.us == 0)
412                 BKE_libblock_free(G.main, old_lamp);
413         return ob;
414 }
415
416 Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
417 {
418         fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
419
420         Object *obn = BKE_object_copy(G.main, source_ob);
421         DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
422         BKE_collection_object_add_from(sce, source_ob, obn);
423
424         if (instance_node) {
425                 anim_importer.read_node_transform(instance_node, obn);
426                 // if we also have a source_node (always ;), take its
427                 // transformation matrix and apply it to the newly instantiated
428                 // object to account for node hierarchy transforms in
429                 // .dae
430                 if (source_node) {
431                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
432                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
433                         float mat[4][4];
434                         for (int i = 0; i < 4; i++) {
435                                 for (int j = 0; j < 4; j++) {
436                                         mat[i][j] = bmat4[i][j];
437                                 }
438                         }
439                         // calc new matrix and apply
440                         mul_m4_m4m4(obn->obmat, obn->obmat, mat);
441                         BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
442                 }
443         }
444         else {
445                 anim_importer.read_node_transform(source_node, obn);
446         }
447
448         /*DAG_relations_tag_update(CTX_data_main(mContext));*/
449
450         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
451         if (children.getCount()) {
452                 for (unsigned int i = 0; i < children.getCount(); i++) {
453                         COLLADAFW::Node *child_node = children[i];
454                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
455                         if (object_map.find(child_id) == object_map.end())
456                                 continue;
457                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
458                         Object *new_child = NULL;
459                         if (inodes.getCount()) { // \todo loop through instance nodes
460                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
461                                 fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
462                                 new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
463                         }
464                         else {
465                                 new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
466                         }
467                         bc_set_parent(new_child, obn, mContext, true);
468
469                         if (is_library_node)
470                                 libnode_ob.push_back(new_child);
471                 }
472         }
473
474         return obn;
475 }
476
477 // to create constraints off node <extra> tags. Assumes only constraint data in
478 // current <extra> with blender profile.
479 void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
480 {
481         if (et && et->isProfile("blender")) {
482                 std::string name;
483                 short* type = 0;
484                 et->setData("type", type);
485                 BKE_constraint_add_for_object(ob, "Test_con", *type);
486                 
487         }
488 }
489
490 void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type)
491 {
492         std::string id = node.getOriginalId();
493         std::string name = node.getName();
494         fprintf(stderr,
495                 "error: node id=\"%s\", name=\"%s\" refers to an undefined %s.\n",
496                 id.c_str(),
497                 name.c_str(),
498                 object_type.c_str());
499 }
500
501 std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
502 {
503         Object *ob = NULL;
504         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
505         bool read_transform = true;
506         std::string id   = node->getOriginalId();
507         std::string name = node->getName();
508
509         // if node has child nodes write them
510         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
511
512         std::vector<Object *> *objects_done = new std::vector<Object *>();
513         std::vector<Object *> *root_objects = new std::vector<Object *>();
514
515         fprintf(stderr,
516                         "Writing node id='%s', name='%s'\n",
517                         id.c_str(),
518                         name.c_str());
519
520         if (is_joint) {
521                 if (parent_node == NULL && !is_library_node) {
522                         // A Joint on root level is a skeleton without root node.
523                         // Here we add the armature "on the fly":
524                         par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
525                         objects_done->push_back(par);
526                         root_objects->push_back(par);
527                         object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
528                         node_map[node->getUniqueId()] = node;
529                 }
530                 if (parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT) {
531                         armature_importer.add_root_joint(node, par);
532                 }
533
534                 if (parent_node == NULL) {
535                         // for skeletons without root node all has been done above.
536                         // Skeletons with root node are handled further down.
537                         goto finally;
538                 }
539         }
540         else {
541                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
542                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
543                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
544                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
545                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
546                 size_t geom_done = 0;
547                 size_t camera_done = 0;
548                 size_t lamp_done = 0;
549                 size_t controller_done = 0;
550                 size_t inst_done = 0;
551
552                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
553                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
554                 // <instance_geometry>
555                 while (geom_done < geom.getCount()) {
556                         ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
557                                                               material_texture_mapping_map);
558                         if (ob == NULL) {
559                                 report_unknown_reference(*node, "instance_mesh");
560                         }
561                         else {
562                                 objects_done->push_back(ob);
563                                 if (parent_node == NULL) {
564                                         root_objects->push_back(ob);
565                                 }
566                         }
567                         ++geom_done;
568                 }
569                 while (camera_done < camera.getCount()) {
570                         ob = create_camera_object(camera[camera_done], sce);
571                         if (ob == NULL) {
572                                 report_unknown_reference(*node, "instance_camera");
573                         }
574                         else {
575                                 objects_done->push_back(ob);
576                                 if (parent_node == NULL) {
577                                         root_objects->push_back(ob);
578                                 }
579                         }
580                         ++camera_done;
581                 }
582                 while (lamp_done < lamp.getCount()) {
583                         ob = create_lamp_object(lamp[lamp_done], sce);
584                         if (ob == NULL) {
585                                 report_unknown_reference(*node, "instance_lamp");
586                         }
587                         else {
588                                 objects_done->push_back(ob);
589                                 if (parent_node == NULL) {
590                                         root_objects->push_back(ob);
591                                 }
592                         }
593                         ++lamp_done;
594                 }
595                 while (controller_done < controller.getCount()) {
596                         COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done];
597                         ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
598                         if (ob == NULL) {
599                                 report_unknown_reference(*node, "instance_controller");
600                         }
601                         else {
602                                 objects_done->push_back(ob);
603                                 if (parent_node == NULL) {
604                                         root_objects->push_back(ob);
605                                 }
606                         }
607                         ++controller_done;
608                 }
609                 // XXX instance_node is not supported yet
610                 while (inst_done < inst_node.getCount()) {
611                         const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
612                         if (object_map.find(node_id) == object_map.end()) {
613                                 fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str());
614                                 ob = NULL;
615                         }
616                         else {
617                                 std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, std::multimap<COLLADAFW::UniqueId, Object *>::iterator> pair_iter = object_map.equal_range(node_id);
618                                 for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; it2 != pair_iter.second; it2++) {
619                                         Object *source_ob = (Object *)it2->second;
620                                         COLLADAFW::Node *source_node = node_map[node_id];
621                                         ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
622                                         objects_done->push_back(ob);
623                                         if (parent_node == NULL) {
624                                                 root_objects->push_back(ob);
625                                         }
626                                 }
627                         }
628                         ++inst_done;
629
630                         read_transform = false;
631                 }
632
633                 // if node is empty - create empty object
634                 // XXX empty node may not mean it is empty object, not sure about this
635                 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
636                         //Check if Object is armature, by checking if immediate child is a JOINT node.
637                         if (is_armature(node)) {
638                                 ob = bc_add_object(sce, OB_ARMATURE, name.c_str());
639                         }
640                         else {
641                                 ob = bc_add_object(sce, OB_EMPTY, NULL);
642                         }
643                         objects_done->push_back(ob);
644                         if (parent_node == NULL) {
645                                 root_objects->push_back(ob);
646                         }
647                 }
648                 
649                 // XXX: if there're multiple instances, only one is stored
650
651                 if (!ob) {
652                         goto finally;
653                 }
654
655                 for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
656                         ob = *it;
657                         std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
658                         BKE_libblock_rename(G.main, &ob->id, (char *)nodename.c_str());
659                         object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob));
660                         node_map[node->getUniqueId()] = node;
661
662                         if (is_library_node)
663                                 libnode_ob.push_back(ob);
664                 }
665
666
667                 //create_constraints(et,ob);
668
669         }
670
671         for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
672                 ob = *it;
673
674                 if (read_transform)
675                         anim_importer.read_node_transform(node, ob);  // overwrites location set earlier
676
677                 if (!is_joint) {
678                         if (par && ob) {
679                                 ob->parent = par;
680                                 ob->partype = PAROBJECT;
681                                 ob->parsubstr[0] = 0;
682
683                                 //bc_set_parent(ob, par, mContext, false);
684                         }
685                 }
686         }
687
688         if (objects_done->size() > 0) {
689                 ob = *objects_done->begin();
690         }
691         else {
692                 ob = NULL;
693         }
694
695         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
696                 std::vector<Object *> *child_objects;
697                 child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node);
698                 delete child_objects;
699         }
700
701
702 finally:
703         delete objects_done;
704
705         return root_objects;
706 }
707
708 /** When this method is called, the writer must write the entire visual scene.
709  *  Return The writer should return true, if writing succeeded, false otherwise. */
710 bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
711 {
712         if (mImportStage != General)
713                 return true;
714                 
715         // this method called on post process after writeGeometry, writeMaterial, etc.
716
717         // for each <node> in <visual_scene>:
718         // create an Object
719         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
720
721         // update: since we cannot link a Mesh with Object in
722         // writeGeometry because <geometry> does not reference <node>,
723         // we link Objects with Meshes here
724
725         vscenes.push_back(visualScene);
726         
727         return true;
728 }
729
730 /** When this method is called, the writer must handle all nodes contained in the 
731  * library nodes.
732  * \return The writer should return true, if writing succeeded, false otherwise.*/
733 bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
734 {
735         if (mImportStage != General)
736                 return true;
737                 
738         Scene *sce = CTX_data_scene(mContext);
739
740         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
741
742         for (unsigned int i = 0; i < nodes.getCount(); i++) {
743                 std::vector<Object *> *child_objects;
744                 child_objects = write_node(nodes[i], NULL, sce, NULL, true);
745                 delete child_objects;
746         }
747
748         return true;
749 }
750
751 /** When this method is called, the writer must write the geometry.
752  * \return The writer should return true, if writing succeeded, false otherwise.*/
753 bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
754 {
755         if (mImportStage != General)
756                 return true;
757                 
758         return mesh_importer.write_geometry(geom);
759 }
760
761 /** When this method is called, the writer must write the material.
762  * \return The writer should return true, if writing succeeded, false otherwise.*/
763 bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
764 {
765         if (mImportStage != General)
766                 return true;
767                 
768         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
769         Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
770         
771         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
772         this->uid_material_map[cmat->getUniqueId()] = ma;
773         
774         return true;
775 }
776
777 // create mtex, create texture, set texture image
778 MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
779                                        int i, TexIndexTextureArrayMap &texindex_texarray_map)
780 {
781         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
782         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
783                 
784         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
785         
786         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
787                 fprintf(stderr, "Couldn't find an image by UID.\n");
788                 return NULL;
789         }
790         
791         ma->mtex[i] = BKE_texture_mtex_add();
792         ma->mtex[i]->texco = TEXCO_UV;
793         ma->mtex[i]->tex = BKE_texture_add(G.main, "Texture");
794         ma->mtex[i]->tex->type = TEX_IMAGE;
795         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
796         
797         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
798         
799         return ma->mtex[i];
800 }
801
802 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
803 {
804         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
805         
806         // blinn
807         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
808                 ma->spec_shader = MA_SPEC_BLINN;
809                 ma->spec = ef->getShininess().getFloatValue();
810         }
811         // phong
812         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
813                 ma->spec_shader = MA_SPEC_PHONG;
814                 ma->har = ef->getShininess().getFloatValue();
815         }
816         // lambert
817         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
818                 ma->diff_shader = MA_DIFF_LAMBERT;
819         }
820         // default - lambert
821         else {
822                 ma->diff_shader = MA_DIFF_LAMBERT;
823                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
824         }
825         // reflectivity
826         ma->ray_mirror = ef->getReflectivity().getFloatValue();
827         // index of refraction
828         ma->ang = ef->getIndexOfRefraction().getFloatValue();
829         
830         int i = 0;
831         COLLADAFW::Color col;
832         MTex *mtex = NULL;
833         TexIndexTextureArrayMap texindex_texarray_map;
834         
835         // DIFFUSE
836         // color
837         if (ef->getDiffuse().isColor()) {
838                 /* too high intensity can create artefacts (fireflies)
839                    So here we take care that intensity is set to 0.8 wherever possible
840                 */
841                 col = ef->getDiffuse().getColor();
842                 ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
843                 ma->r = col.getRed()   / ma->ref;
844                 ma->g = col.getGreen() / ma->ref;
845                 ma->b = col.getBlue()  / ma->ref;
846         }
847         // texture
848         else if (ef->getDiffuse().isTexture()) {
849                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
850                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
851                 if (mtex != NULL) {
852                         mtex->mapto = MAP_COL;
853                         ma->texact = (int)i;
854                         i++;
855                 }
856         }
857         // AMBIENT
858         // color
859         if (ef->getAmbient().isColor()) {
860                 col = ef->getAmbient().getColor();
861                 ma->ambr = col.getRed();
862                 ma->ambg = col.getGreen();
863                 ma->ambb = col.getBlue();
864         }
865         // texture
866         else if (ef->getAmbient().isTexture()) {
867                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
868                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
869                 if (mtex != NULL) {
870                         mtex->mapto = MAP_AMB; 
871                         i++;
872                 }
873         }
874         // SPECULAR
875         // color
876         if (ef->getSpecular().isColor()) {
877                 col = ef->getSpecular().getColor();
878                 ma->specr = col.getRed();
879                 ma->specg = col.getGreen();
880                 ma->specb = col.getBlue();
881         }
882         // texture
883         else if (ef->getSpecular().isTexture()) {
884                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
885                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
886                 if (mtex != NULL) {
887                         mtex->mapto = MAP_SPEC; 
888                         i++;
889                 }
890         }
891         // REFLECTIVE
892         // color
893         if (ef->getReflective().isColor()) {
894                 col = ef->getReflective().getColor();
895                 ma->mirr = col.getRed();
896                 ma->mirg = col.getGreen();
897                 ma->mirb = col.getBlue();
898         }
899         // texture
900         else if (ef->getReflective().isTexture()) {
901                 COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
902                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
903                 if (mtex != NULL) {
904                         mtex->mapto = MAP_REF; 
905                         i++;
906                 }
907         }
908
909         // EMISSION
910         // color
911         if (ef->getEmission().isColor()) {
912                 // XXX there is no emission color in blender
913                 // but I am not sure
914         }
915         // texture
916         else if (ef->getEmission().isTexture()) {
917                 COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
918                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
919                 if (mtex != NULL) {
920                         mtex->mapto = MAP_EMIT; 
921                         i++;
922                 }
923         }
924
925         // TRANSPARENT
926         // color
927         if (ef->getOpacity().isColor()) {
928                 col = ef->getTransparent().getColor();
929                 float alpha = ef->getTransparency().getFloatValue();
930                 if (col.isValid()) {
931                         alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
932                 }
933                 if (col.isValid() || alpha < 1.0) {
934                         ma->alpha = alpha;
935                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
936                 }
937         }
938         // texture
939         else if (ef->getOpacity().isTexture()) {
940                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
941                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
942                 if (mtex != NULL) {
943                         mtex->mapto = MAP_ALPHA;
944                         i++;
945                         ma->spectra = ma->alpha = 0;
946                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
947                 }
948         }
949
950         material_texture_mapping_map[ma] = texindex_texarray_map;
951 }
952
953 /** When this method is called, the writer must write the effect.
954  * \return The writer should return true, if writing succeeded, false otherwise.*/
955
956 bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
957 {
958         if (mImportStage != General)
959                 return true;
960         
961         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
962         
963         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
964                 fprintf(stderr, "Couldn't find a material by UID.\n");
965                 return true;
966         }
967         
968         Material *ma = uid_effect_map[uid];
969         std::map<COLLADAFW::UniqueId, Material *>::iterator iter;
970         for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) {
971                 if (iter->second == ma) {
972                         this->FW_object_map[iter->first] = effect;
973                         break;
974                 }
975         }
976         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
977         if (common_efs.getCount() < 1) {
978                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
979                 return true;
980         }
981         // XXX TODO: Take all <profile_common>s
982         // Currently only first <profile_common> is supported
983         COLLADAFW::EffectCommon *ef = common_efs[0];
984         write_profile_COMMON(ef, ma);
985         this->FW_object_map[effect->getUniqueId()] = effect;
986                 
987         return true;
988 }
989
990
991 /** When this method is called, the writer must write the camera.
992  * \return The writer should return true, if writing succeeded, false otherwise.*/
993 bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
994 {
995         if (mImportStage != General)
996                 return true;
997                 
998         Camera *cam = NULL;
999         std::string cam_id, cam_name;
1000         
1001         ExtraTags *et=getExtraTags(camera->getUniqueId());
1002         cam_id = camera->getOriginalId();
1003         cam_name = camera->getName();
1004         if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
1005         else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
1006         
1007         if (!cam) {
1008                 fprintf(stderr, "Cannot create camera.\n");
1009                 return true;
1010         }
1011
1012         if (et && et->isProfile("blender")) {
1013                 et->setData("shiftx",&(cam->shiftx));
1014                 et->setData("shifty",&(cam->shifty));
1015                 et->setData("YF_dofdist",&(cam->YF_dofdist));
1016         }
1017         cam->clipsta = camera->getNearClippingPlane().getValue();
1018         cam->clipend = camera->getFarClippingPlane().getValue();
1019         
1020         COLLADAFW::Camera::CameraType type = camera->getCameraType();
1021         switch (type) {
1022                 case COLLADAFW::Camera::ORTHOGRAPHIC:
1023                 {
1024                         cam->type = CAM_ORTHO;
1025                 }
1026                 break;
1027                 case COLLADAFW::Camera::PERSPECTIVE:
1028                 {
1029                         cam->type = CAM_PERSP;
1030                 }
1031                 break;
1032                 case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
1033                 {
1034                         fprintf(stderr, "Current camera type is not supported.\n");
1035                         cam->type = CAM_PERSP;
1036                 }
1037                 break;
1038         }
1039         
1040         switch (camera->getDescriptionType()) {
1041                 case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
1042                 {
1043                         switch (cam->type) {
1044                                 case CAM_ORTHO:
1045                                 {
1046                                         double ymag = 2 * camera->getYMag().getValue();
1047                                         double aspect = camera->getAspectRatio().getValue();
1048                                         double xmag = aspect * ymag;
1049                                         cam->ortho_scale = (float)xmag;
1050                                 }
1051                                 break;
1052                                 case CAM_PERSP:
1053                                 default:
1054                                 {
1055                                         double yfov = camera->getYFov().getValue();
1056                                         double aspect = camera->getAspectRatio().getValue();
1057
1058                                         // NOTE: Needs more testing (As we curretnly have no official test data for this)
1059
1060                                         double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f));
1061                                         cam->lens = fov_to_focallength(xfov, cam->sensor_x);
1062                                 }
1063                                 break;
1064                         }
1065                 }
1066                 break;
1067                 /* XXX correct way to do following four is probably to get also render
1068                  * size and determine proper settings from that somehow */
1069                 case COLLADAFW::Camera::ASPECTRATIO_AND_X:
1070                 case COLLADAFW::Camera::SINGLE_X:
1071                 case COLLADAFW::Camera::X_AND_Y:
1072                 {
1073                         switch (cam->type) {
1074                                 case CAM_ORTHO:
1075                                         cam->ortho_scale = (float)camera->getXMag().getValue() * 2;
1076                                         break;
1077                                 case CAM_PERSP:
1078                                 default:
1079                                 {
1080                                         double x = camera->getXFov().getValue();
1081                                         // x is in degrees, cam->lens is in millimiters
1082                                         cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
1083                                 }
1084                                 break;
1085                         }
1086                 }
1087                 break;
1088                 case COLLADAFW::Camera::SINGLE_Y:
1089                 {
1090                         switch (cam->type) {
1091                                 case CAM_ORTHO:
1092                                         cam->ortho_scale = (float)camera->getYMag().getValue();
1093                                         break;
1094                                 case CAM_PERSP:
1095                                 default:
1096                                 {
1097                                         double yfov = camera->getYFov().getValue();
1098                                         // yfov is in degrees, cam->lens is in millimiters
1099                                         cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
1100                                 }
1101                                 break;
1102                         }
1103                 }
1104                 break;
1105                 case COLLADAFW::Camera::UNDEFINED:
1106                         // read nothing, use blender defaults.
1107                         break;
1108         }
1109         
1110         this->uid_camera_map[camera->getUniqueId()] = cam;
1111         this->FW_object_map[camera->getUniqueId()] = camera;
1112         // XXX import camera options
1113         return true;
1114 }
1115
1116 /** When this method is called, the writer must write the image.
1117  * \return The writer should return true, if writing succeeded, false otherwise.*/
1118 bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
1119 {
1120         if (mImportStage != General)
1121                 return true;
1122                 
1123         const std::string& imagepath = image->getImageURI().toNativePath();
1124
1125         char dir[FILE_MAX];
1126         char absolute_path[FILE_MAX];
1127         const char *workpath;
1128
1129         BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir));
1130         BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str());
1131         if (BLI_exists(absolute_path)) {
1132                 workpath = absolute_path;
1133         } 
1134         else {
1135                 // Maybe imagepath was already absolute ?
1136                 if (!BLI_exists(imagepath.c_str())) {
1137                         fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
1138                         return true;
1139                 }
1140                 workpath = imagepath.c_str();
1141         }
1142
1143         Image *ima = BKE_image_load_exists(workpath);
1144         if (!ima) {
1145                 fprintf(stderr, "Cannot create image: %s\n", workpath);
1146                 return true;
1147         }
1148         this->uid_image_map[image->getUniqueId()] = ima;
1149         
1150         return true;
1151 }
1152
1153 /** When this method is called, the writer must write the light.
1154  * \return The writer should return true, if writing succeeded, false otherwise.*/
1155 bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
1156 {
1157         if (mImportStage != General)
1158                 return true;
1159
1160         Lamp *lamp = NULL;
1161         std::string la_id, la_name;
1162
1163         ExtraTags *et = getExtraTags(light->getUniqueId());
1164         /*TagsMap::iterator etit;
1165         ExtraTags *et = 0;
1166         etit = uid_tags_map.find(light->getUniqueId().toAscii());
1167         if (etit != uid_tags_map.end())
1168                 et = etit->second;*/
1169
1170         la_id = light->getOriginalId();
1171         la_name = light->getName();
1172         if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
1173         else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
1174
1175         if (!lamp) {
1176                 fprintf(stderr, "Cannot create lamp.\n");
1177                 return true;
1178         }
1179
1180         // if we find an ExtraTags for this, use that instead.
1181         if (et && et->isProfile("blender")) {
1182                 et->setData("type", &(lamp->type));
1183                 et->setData("flag", &(lamp->flag));
1184                 et->setData("mode", &(lamp->mode));
1185                 et->setData("gamma", &(lamp->k));
1186                 et->setData("red", &(lamp->r));
1187                 et->setData("green", &(lamp->g));
1188                 et->setData("blue", &(lamp->b));
1189                 et->setData("shadow_r", &(lamp->shdwr));
1190                 et->setData("shadow_g", &(lamp->shdwg));
1191                 et->setData("shadow_b", &(lamp->shdwb));
1192                 et->setData("energy", &(lamp->energy));
1193                 et->setData("dist", &(lamp->dist));
1194                 et->setData("spotsize", &(lamp->spotsize));
1195                 lamp->spotsize = DEG2RADF(lamp->spotsize);
1196                 et->setData("spotblend", &(lamp->spotblend));
1197                 et->setData("halo_intensity", &(lamp->haint));
1198                 et->setData("att1", &(lamp->att1));
1199                 et->setData("att2", &(lamp->att2));
1200                 et->setData("falloff_type", &(lamp->falloff_type));
1201                 et->setData("clipsta", &(lamp->clipsta));
1202                 et->setData("clipend", &(lamp->clipend));
1203                 et->setData("bias", &(lamp->bias));
1204                 et->setData("soft", &(lamp->soft));
1205                 et->setData("compressthresh", &(lamp->compressthresh));
1206                 et->setData("bufsize", &(lamp->bufsize));
1207                 et->setData("samp", &(lamp->samp));
1208                 et->setData("buffers", &(lamp->buffers));
1209                 et->setData("filtertype", &(lamp->filtertype));
1210                 et->setData("bufflag", &(lamp->bufflag));
1211                 et->setData("buftype", &(lamp->buftype));
1212                 et->setData("ray_samp", &(lamp->ray_samp));
1213                 et->setData("ray_sampy", &(lamp->ray_sampy));
1214                 et->setData("ray_sampz", &(lamp->ray_sampz));
1215                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
1216                 et->setData("area_shape", &(lamp->area_shape));
1217                 et->setData("area_size", &(lamp->area_size));
1218                 et->setData("area_sizey", &(lamp->area_sizey));
1219                 et->setData("area_sizez", &(lamp->area_sizez));
1220                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
1221                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
1222                 et->setData("shadhalostep", &(lamp->shadhalostep));
1223                 et->setData("sun_effect_type", &(lamp->shadhalostep));
1224                 et->setData("skyblendtype", &(lamp->skyblendtype));
1225                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
1226                 et->setData("spread", &(lamp->spread));
1227                 et->setData("sun_brightness", &(lamp->sun_brightness));
1228                 et->setData("sun_size", &(lamp->sun_size));
1229                 et->setData("backscattered_light", &(lamp->backscattered_light));
1230                 et->setData("sun_intensity", &(lamp->sun_intensity));
1231                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
1232                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
1233                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
1234                 et->setData("skyblendfac", &(lamp->skyblendfac));
1235                 et->setData("sky_exposure", &(lamp->sky_exposure));
1236                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
1237         }
1238         else {
1239                 float constatt = light->getConstantAttenuation().getValue();
1240                 float linatt = light->getLinearAttenuation().getValue();
1241                 float quadatt = light->getQuadraticAttenuation().getValue();
1242                 float d = 25.0f;
1243                 float att1 = 0.0f;
1244                 float att2 = 0.0f;
1245                 float e = 1.0f;
1246
1247                 if (light->getColor().isValid()) {
1248                         COLLADAFW::Color col = light->getColor();
1249                         lamp->r = col.getRed();
1250                         lamp->g = col.getGreen();
1251                         lamp->b = col.getBlue();
1252                 }
1253
1254                 if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1255                         att2 = quadatt;
1256                         d = sqrt(1.0f / quadatt);
1257                 }
1258                 // linear light
1259                 else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1260                         att1 = linatt;
1261                         d = (1.0f / linatt);
1262                 }
1263                 else if (IS_EQ(constatt, 1.0f)) {
1264                         att1 = 1.0f;
1265                 }
1266                 else {
1267                         // assuming point light (const att = 1.0);
1268                         att1 = 1.0f;
1269                 }
1270                 
1271                 d *= (1.0f / unit_converter.getLinearMeter());
1272
1273                 lamp->energy = e;
1274                 lamp->dist = d;
1275
1276                 COLLADAFW::Light::LightType type = light->getLightType();
1277                 switch (type) {
1278                         case COLLADAFW::Light::AMBIENT_LIGHT:
1279                         {
1280                                 lamp->type = LA_HEMI;
1281                         }
1282                         break;
1283                         case COLLADAFW::Light::SPOT_LIGHT:
1284                         {
1285                                 lamp->type = LA_SPOT;
1286                                 lamp->att1 = att1;
1287                                 lamp->att2 = att2;
1288                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1289                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1290                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1291                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1292                                 lamp->spotsize = DEG2RADF(light->getFallOffAngle().getValue());
1293                                 lamp->spotblend = light->getFallOffExponent().getValue();
1294                         }
1295                         break;
1296                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1297                         {
1298                                 /* our sun is very strong, so pick a smaller energy level */
1299                                 lamp->type = LA_SUN;
1300                                 lamp->mode |= LA_NO_SPEC;
1301                         }
1302                         break;
1303                         case COLLADAFW::Light::POINT_LIGHT:
1304                         {
1305                                 lamp->type = LA_LOCAL;
1306                                 lamp->att1 = att1;
1307                                 lamp->att2 = att2;
1308                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1309                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1310                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1311                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1312                         }
1313                         break;
1314                         case COLLADAFW::Light::UNDEFINED:
1315                         {
1316                                 fprintf(stderr, "Current lamp type is not supported.\n");
1317                                 lamp->type = LA_LOCAL;
1318                         }
1319                         break;
1320                 }
1321         }
1322
1323         this->uid_lamp_map[light->getUniqueId()] = lamp;
1324         this->FW_object_map[light->getUniqueId()] = light;
1325         return true;
1326 }
1327
1328 // this function is called only for animations that pass COLLADAFW::validate
1329 bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
1330 {
1331         if (mImportStage != General)
1332                 return true;
1333                 
1334         // return true;
1335         return anim_importer.write_animation(anim);
1336 }
1337
1338 // called on post-process stage after writeVisualScenes
1339 bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
1340 {
1341         if (mImportStage != General)
1342                 return true;
1343                 
1344         // return true;
1345         return anim_importer.write_animation_list(animationList);
1346 }
1347
1348 /** When this method is called, the writer must write the skin controller data.
1349  * \return The writer should return true, if writing succeeded, false otherwise.*/
1350 bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin)
1351 {
1352         return armature_importer.write_skin_controller_data(skin);
1353 }
1354
1355 // this is called on postprocess, before writeVisualScenes
1356 bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
1357 {
1358         if (mImportStage != General)
1359                 return true;
1360                 
1361         return armature_importer.write_controller(controller);
1362 }
1363
1364 bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas)
1365 {
1366         return true;
1367 }
1368
1369 bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene)
1370 {
1371         return true;
1372 }
1373
1374 ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1375 {
1376         if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) {
1377                 return NULL;
1378         }
1379         return uid_tags_map[uid.toAscii()];
1380 }
1381
1382 bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1383 {
1384         uid_tags_map[uid.toAscii()] = extra_tags;
1385         return true;
1386 }
1387
1388 bool DocumentImporter::is_armature(COLLADAFW::Node *node)
1389 {
1390         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
1391         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
1392                 if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) {
1393                         return true;
1394                 }
1395                 else {
1396                         continue;
1397                 }
1398         }
1399
1400         //no child is JOINT
1401         return false;
1402 }