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