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