fix T58568 build errors when using collada 1.6.68 or newer
[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_main(C), CTX_data_scene(C), import_settings),
108         mesh_importer(&unit_converter, &armature_importer, CTX_data_main(C), 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 sit;
194         for (sit = vscenes.begin(); sit != vscenes.end(); sit++) {
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 = (*sit)->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(mContext);
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 vsit = vscenes.begin(); vsit != vscenes.end(); vsit++) {
251                 const COLLADAFW::NodePointerArray& roots = (*vsit)->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
260                 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
261                 // free all library_nodes
262                 std::vector<Object *>::iterator lit;
263                 for (lit = libnode_ob.begin(); lit != libnode_ob.end(); lit++) {
264                         Object *ob = *lit;
265
266                         Base *base = BKE_scene_base_find(sce, ob);
267                         if (base) {
268                                 BLI_remlink(&sce->base, base);
269                                 BKE_libblock_free_us(bmain, base->object);
270                                 if (sce->basact == base)
271                                         sce->basact = NULL;
272                                 MEM_freeN(base);
273                         }
274                 }
275                 libnode_ob.clear();
276
277                 DAG_relations_tag_update(bmain);
278         }
279
280         bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
281
282         delete objects_to_scale;
283 }
284
285
286 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
287 {
288         Main *bmain = CTX_data_main(mContext);
289         // The split in #29246, rootmap must point at actual root when
290         // calculating bones in apply_curves_as_matrix. - actual root is the root node.
291         // This has to do with inverse bind poses being world space
292         // (the sources for skinned bones' restposes) and the way
293         // non-skinning nodes have their "restpose" recursively calculated.
294         // XXX TODO: design issue, how to support unrelated joints taking
295         // part in skinning.
296         if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
297                 // par is root if there's no corresp. key in root_map
298                 if (root_map.find(par->getUniqueId()) == root_map.end())
299                         root_map[node->getUniqueId()] = node;
300                 else
301                         root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
302         }
303
304 #if 0
305         COLLADAFW::Transformation::TransformationType types[] = {
306                 COLLADAFW::Transformation::ROTATE,
307                 COLLADAFW::Transformation::SCALE,
308                 COLLADAFW::Transformation::TRANSLATE,
309                 COLLADAFW::Transformation::MATRIX
310         };
311
312         Object *ob;
313 #endif
314         unsigned int i;
315
316         if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) {
317                 // For Skeletons without root node we have to simulate the
318                 // root node here and recursively enter the same function
319                 // XXX: maybe this can be made more elegant.
320                 translate_anim_recursive(node, node, parob);
321         }
322         else {
323                 anim_importer.translate_Animations(bmain, node, root_map, object_map, FW_object_map, uid_material_map);
324                 COLLADAFW::NodePointerArray &children = node->getChildNodes();
325                 for (i = 0; i < children.getCount(); i++) {
326                         translate_anim_recursive(children[i], node, NULL);
327                 }
328         }
329 }
330
331 /**
332  * If the imported file was made with Blender, return the Blender version used,
333  * otherwise return an empty std::string
334  */
335 std::string DocumentImporter::get_import_version(const COLLADAFW::FileInfo *asset)
336 {
337         const char AUTORING_TOOL[] = "authoring_tool";
338         const std::string BLENDER("Blender ");
339         const COLLADAFW::FileInfo::ValuePairPointerArray &valuePairs = asset->getValuePairArray();
340         for ( size_t i = 0, count = valuePairs.getCount(); i < count; ++i)
341         {
342                 const COLLADAFW::FileInfo::ValuePair* valuePair = valuePairs[i];
343                 const COLLADAFW::String& key = valuePair->first;
344                 const COLLADAFW::String& value = valuePair->second;
345                 if ( key == AUTORING_TOOL )
346                 {
347                         if (value.compare(0, BLENDER.length(), BLENDER) == 0)
348                         {
349                                 // Was made with Blender, now get version string
350                                 std::string v            = value.substr(BLENDER.length());
351                                 std::string::size_type n = v.find(" ");
352                                 if (n > 0) {
353                                         return v.substr(0,n);
354                                 }
355                         }
356                 }
357         }
358         return "";
359 }
360
361 /** When this method is called, the writer must write the global document asset.
362  * \return The writer should return true, if writing succeeded, false otherwise.*/
363 bool DocumentImporter::writeGlobalAsset(const COLLADAFW::FileInfo *asset)
364 {
365         unit_converter.read_asset(asset);
366         import_from_version = get_import_version(asset);
367         anim_importer.set_import_from_version(import_from_version);
368         return true;
369 }
370
371 /** When this method is called, the writer must write the scene.
372  * \return The writer should return true, if writing succeeded, false otherwise.*/
373 bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene)
374 {
375         // XXX could store the scene id, but do nothing for now
376         return true;
377 }
378 Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
379 {
380         const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
381         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {
382                 // fprintf(stderr, "Couldn't find camera by UID.\n");
383                 return NULL;
384         }
385
386         Main *bmain = CTX_data_main(mContext);
387         Object *ob = bc_add_object(bmain, 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(bmain, 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         Main *bmain = CTX_data_main(mContext);
404         Object *ob = bc_add_object(bmain, sce, OB_LAMP, NULL);
405         Lamp *la = uid_lamp_map[lamp_uid];
406         Lamp *old_lamp = (Lamp *)ob->data;
407         ob->data = la;
408         BKE_libblock_free_us(bmain, old_lamp);
409         return ob;
410 }
411
412 Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
413 {
414         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);
415
416         Main *bmain = CTX_data_main(mContext);
417         Object *obn = BKE_object_copy(bmain, source_ob);
418         DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
419         BKE_scene_base_add(sce, obn);
420
421         if (instance_node) {
422                 anim_importer.read_node_transform(instance_node, obn);
423                 // if we also have a source_node (always ;), take its
424                 // transformation matrix and apply it to the newly instantiated
425                 // object to account for node hierarchy transforms in
426                 // .dae
427                 if (source_node) {
428                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
429                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
430                         float mat[4][4];
431                         for (int i = 0; i < 4; i++) {
432                                 for (int j = 0; j < 4; j++) {
433                                         mat[i][j] = bmat4[i][j];
434                                 }
435                         }
436                         // calc new matrix and apply
437                         mul_m4_m4m4(obn->obmat, obn->obmat, mat);
438                         BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
439                 }
440         }
441         else {
442                 anim_importer.read_node_transform(source_node, obn);
443         }
444
445         /*DAG_relations_tag_update(CTX_data_main(mContext));*/
446
447         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
448         if (children.getCount()) {
449                 for (unsigned int i = 0; i < children.getCount(); i++) {
450                         COLLADAFW::Node *child_node = children[i];
451                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
452                         if (object_map.find(child_id) == object_map.end())
453                                 continue;
454                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
455                         Object *new_child = NULL;
456                         if (inodes.getCount()) { // \todo loop through instance nodes
457                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
458                                 fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
459                                 new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
460                         }
461                         else {
462                                 new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
463                         }
464                         bc_set_parent(new_child, obn, mContext, true);
465
466                         if (is_library_node)
467                                 libnode_ob.push_back(new_child);
468                 }
469         }
470
471         return obn;
472 }
473
474 // to create constraints off node <extra> tags. Assumes only constraint data in
475 // current <extra> with blender profile.
476 void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
477 {
478         if (et && et->isProfile("blender")) {
479                 std::string name;
480                 short type = 0;
481                 et->setData("type", &type);
482                 BKE_constraint_add_for_object(ob, "Test_con", type);
483
484         }
485 }
486
487 void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type)
488 {
489         std::string id = node.getOriginalId();
490         std::string name = node.getName();
491         fprintf(stderr,
492                 "error: node id=\"%s\", name=\"%s\" refers to an undefined %s.\n",
493                 id.c_str(),
494                 name.c_str(),
495                 object_type.c_str());
496 }
497
498 std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
499 {
500         Main *bmain = CTX_data_main(mContext);
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(bmain, 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 *geometry = (COLLADAFW::InstanceGeometry *)controller[controller_done];
595                         ob = mesh_importer.create_mesh_object(node, geometry, 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(bmain, sce, OB_ARMATURE, name.c_str());
637                         }
638                         else {
639                                 ob = bc_add_object(bmain, 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(bmain, &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 /**
707  * When this method is called, the writer must write the entire visual scene.
708  * Return The writer should return true, if writing succeeded, false otherwise.
709  */
710 bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
711 {
712         if (mImportStage != General)
713                 return true;
714
715         // this method called on post process after writeGeometry, writeMaterial, etc.
716
717         // for each <node> in <visual_scene>:
718         // create an Object
719         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
720
721         // update: since we cannot link a Mesh with Object in
722         // writeGeometry because <geometry> does not reference <node>,
723         // we link Objects with Meshes here
724
725         vscenes.push_back(visualScene);
726
727         return true;
728 }
729
730 /** When this method is called, the writer must handle all nodes contained in the
731  * library nodes.
732  * \return The writer should return true, if writing succeeded, false otherwise.*/
733 bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
734 {
735         if (mImportStage != General)
736                 return true;
737
738         Scene *sce = CTX_data_scene(mContext);
739
740         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
741
742         for (unsigned int i = 0; i < nodes.getCount(); i++) {
743                 std::vector<Object *> *child_objects;
744                 child_objects = write_node(nodes[i], NULL, sce, NULL, true);
745                 delete child_objects;
746         }
747
748         return true;
749 }
750
751 /** When this method is called, the writer must write the geometry.
752  * \return The writer should return true, if writing succeeded, false otherwise.*/
753 bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
754 {
755         if (mImportStage != General)
756                 return true;
757
758         return mesh_importer.write_geometry(geom);
759 }
760
761 /** When this method is called, the writer must write the material.
762  * \return The writer should return true, if writing succeeded, false otherwise.*/
763 bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
764 {
765         if (mImportStage != General)
766                 return true;
767
768         Main *bmain = CTX_data_main(mContext);
769         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
770         Material *ma = BKE_material_add(bmain, (char *)str_mat_id.c_str());
771
772         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
773         this->uid_material_map[cmat->getUniqueId()] = ma;
774
775         return true;
776 }
777
778 // create mtex, create texture, set texture image
779 MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
780                                        int i, TexIndexTextureArrayMap &texindex_texarray_map)
781 {
782         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
783         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
784
785         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
786
787         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
788                 fprintf(stderr, "Couldn't find an image by UID.\n");
789                 return NULL;
790         }
791
792         Main *bmain = CTX_data_main(mContext);
793         ma->mtex[i] = BKE_texture_mtex_add();
794         ma->mtex[i]->texco = TEXCO_UV;
795         ma->mtex[i]->tex = BKE_texture_add(bmain, "Texture");
796         ma->mtex[i]->tex->type = TEX_IMAGE;
797         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
798
799         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
800
801         return ma->mtex[i];
802 }
803
804 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
805 {
806         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
807
808         // blinn
809         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
810                 ma->spec_shader = MA_SPEC_BLINN;
811                 ma->spec = ef->getShininess().getFloatValue();
812         }
813         // phong
814         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
815                 ma->spec_shader = MA_SPEC_PHONG;
816                 ma->har = ef->getShininess().getFloatValue();
817         }
818         // lambert
819         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
820                 ma->diff_shader = MA_DIFF_LAMBERT;
821         }
822         // default - lambert
823         else {
824                 ma->diff_shader = MA_DIFF_LAMBERT;
825                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
826         }
827         // reflectivity
828         ma->ray_mirror = ef->getReflectivity().getFloatValue();
829         // index of refraction
830         ma->ang = ef->getIndexOfRefraction().getFloatValue();
831
832         int i = 0;
833         COLLADAFW::Color col;
834         MTex *mtex = NULL;
835         TexIndexTextureArrayMap texindex_texarray_map;
836
837         // DIFFUSE
838         // color
839         if (ef->getDiffuse().isColor()) {
840                 /* too high intensity can create artefacts (fireflies)
841                    So here we take care that intensity is set to 0.8 wherever possible
842                 */
843                 col = ef->getDiffuse().getColor();
844                 ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
845                 ma->r = col.getRed()   / ma->ref;
846                 ma->g = col.getGreen() / ma->ref;
847                 ma->b = col.getBlue()  / ma->ref;
848         }
849         // texture
850         else if (ef->getDiffuse().isTexture()) {
851                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture();
852                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
853                 if (mtex != NULL) {
854                         mtex->mapto = MAP_COL;
855                         ma->texact = (int)i;
856                         i++;
857                 }
858         }
859         // AMBIENT
860         // color
861         if (ef->getAmbient().isColor()) {
862                 col = ef->getAmbient().getColor();
863                 ma->ambr = col.getRed();
864                 ma->ambg = col.getGreen();
865                 ma->ambb = col.getBlue();
866         }
867         // texture
868         else if (ef->getAmbient().isTexture()) {
869                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture();
870                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
871                 if (mtex != NULL) {
872                         mtex->mapto = MAP_AMB;
873                         i++;
874                 }
875         }
876         // SPECULAR
877         // color
878         if (ef->getSpecular().isColor()) {
879                 col = ef->getSpecular().getColor();
880                 ma->specr = col.getRed();
881                 ma->specg = col.getGreen();
882                 ma->specb = col.getBlue();
883         }
884         // texture
885         else if (ef->getSpecular().isTexture()) {
886                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture();
887                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
888                 if (mtex != NULL) {
889                         mtex->mapto = MAP_SPEC;
890                         i++;
891                 }
892         }
893         // REFLECTIVE
894         // color
895         if (ef->getReflective().isColor()) {
896                 col = ef->getReflective().getColor();
897                 ma->mirr = col.getRed();
898                 ma->mirg = col.getGreen();
899                 ma->mirb = col.getBlue();
900         }
901         // texture
902         else if (ef->getReflective().isTexture()) {
903                 COLLADAFW::Texture ctex = ef->getReflective().getTexture();
904                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
905                 if (mtex != NULL) {
906                         mtex->mapto = MAP_REF;
907                         i++;
908                 }
909         }
910
911         // EMISSION
912         // color
913         if (ef->getEmission().isColor()) {
914                 // XXX there is no emission color in blender
915                 // but I am not sure
916         }
917         // texture
918         else if (ef->getEmission().isTexture()) {
919                 COLLADAFW::Texture ctex = ef->getEmission().getTexture();
920                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
921                 if (mtex != NULL) {
922                         mtex->mapto = MAP_EMIT;
923                         i++;
924                 }
925         }
926
927         // TRANSPARENT
928         // color
929         if (ef->getOpacity().isColor()) {
930                 col = ef->getTransparent().getColor();
931                 float alpha = ef->getTransparency().getFloatValue();
932                 if (col.isValid()) {
933                         alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
934                 }
935                 if (col.isValid() || alpha < 1.0) {
936                         ma->alpha = alpha;
937                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
938                 }
939         }
940         // texture
941         else if (ef->getOpacity().isTexture()) {
942                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
943                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
944                 if (mtex != NULL) {
945                         mtex->mapto = MAP_ALPHA;
946                         i++;
947                         ma->spectra = ma->alpha = 0;
948                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
949                 }
950         }
951
952         material_texture_mapping_map[ma] = texindex_texarray_map;
953 }
954
955 /** When this method is called, the writer must write the effect.
956  * \return The writer should return true, if writing succeeded, false otherwise.*/
957
958 bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
959 {
960         if (mImportStage != General)
961                 return true;
962
963         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
964
965         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
966                 fprintf(stderr, "Couldn't find a material by UID.\n");
967                 return true;
968         }
969
970         Material *ma = uid_effect_map[uid];
971         std::map<COLLADAFW::UniqueId, Material *>::iterator iter;
972         for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) {
973                 if (iter->second == ma) {
974                         this->FW_object_map[iter->first] = effect;
975                         break;
976                 }
977         }
978         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
979         if (common_efs.getCount() < 1) {
980                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
981                 return true;
982         }
983         // XXX TODO: Take all <profile_common>s
984         // Currently only first <profile_common> is supported
985         COLLADAFW::EffectCommon *ef = common_efs[0];
986         write_profile_COMMON(ef, ma);
987         this->FW_object_map[effect->getUniqueId()] = effect;
988
989         return true;
990 }
991
992
993 /** When this method is called, the writer must write the camera.
994  * \return The writer should return true, if writing succeeded, false otherwise.*/
995 bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
996 {
997         if (mImportStage != General)
998                 return true;
999
1000         Main *bmain = CTX_data_main(mContext);
1001         Camera *cam = NULL;
1002         std::string cam_id, cam_name;
1003
1004         ExtraTags *et=getExtraTags(camera->getUniqueId());
1005         cam_id = camera->getOriginalId();
1006         cam_name = camera->getName();
1007         if (cam_name.size()) cam = (Camera *)BKE_camera_add(bmain, (char *)cam_name.c_str());
1008         else cam = (Camera *)BKE_camera_add(bmain, (char *)cam_id.c_str());
1009
1010         if (!cam) {
1011                 fprintf(stderr, "Cannot create camera.\n");
1012                 return true;
1013         }
1014
1015         if (et && et->isProfile("blender")) {
1016                 et->setData("shiftx",&(cam->shiftx));
1017                 et->setData("shifty",&(cam->shifty));
1018                 et->setData("YF_dofdist",&(cam->YF_dofdist));
1019         }
1020         cam->clipsta = camera->getNearClippingPlane().getValue();
1021         cam->clipend = camera->getFarClippingPlane().getValue();
1022
1023         COLLADAFW::Camera::CameraType type = camera->getCameraType();
1024         switch (type) {
1025                 case COLLADAFW::Camera::ORTHOGRAPHIC:
1026                 {
1027                         cam->type = CAM_ORTHO;
1028                 }
1029                 break;
1030                 case COLLADAFW::Camera::PERSPECTIVE:
1031                 {
1032                         cam->type = CAM_PERSP;
1033                 }
1034                 break;
1035                 case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
1036                 {
1037                         fprintf(stderr, "Current camera type is not supported.\n");
1038                         cam->type = CAM_PERSP;
1039                 }
1040                 break;
1041         }
1042
1043         switch (camera->getDescriptionType()) {
1044                 case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
1045                 {
1046                         switch (cam->type) {
1047                                 case CAM_ORTHO:
1048                                 {
1049                                         double ymag = 2 * camera->getYMag().getValue();
1050                                         double aspect = camera->getAspectRatio().getValue();
1051                                         double xmag = aspect * ymag;
1052                                         cam->ortho_scale = (float)xmag;
1053                                 }
1054                                 break;
1055                                 case CAM_PERSP:
1056                                 default:
1057                                 {
1058                                         double yfov = camera->getYFov().getValue();
1059                                         double aspect = camera->getAspectRatio().getValue();
1060
1061                                         // NOTE: Needs more testing (As we curretnly have no official test data for this)
1062
1063                                         double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f));
1064                                         cam->lens = fov_to_focallength(xfov, cam->sensor_x);
1065                                 }
1066                                 break;
1067                         }
1068                 }
1069                 break;
1070                 /* XXX correct way to do following four is probably to get also render
1071                  * size and determine proper settings from that somehow */
1072                 case COLLADAFW::Camera::ASPECTRATIO_AND_X:
1073                 case COLLADAFW::Camera::SINGLE_X:
1074                 case COLLADAFW::Camera::X_AND_Y:
1075                 {
1076                         switch (cam->type) {
1077                                 case CAM_ORTHO:
1078                                         cam->ortho_scale = (float)camera->getXMag().getValue() * 2;
1079                                         break;
1080                                 case CAM_PERSP:
1081                                 default:
1082                                 {
1083                                         double x = camera->getXFov().getValue();
1084                                         // x is in degrees, cam->lens is in millimiters
1085                                         cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
1086                                 }
1087                                 break;
1088                         }
1089                 }
1090                 break;
1091                 case COLLADAFW::Camera::SINGLE_Y:
1092                 {
1093                         switch (cam->type) {
1094                                 case CAM_ORTHO:
1095                                         cam->ortho_scale = (float)camera->getYMag().getValue();
1096                                         break;
1097                                 case CAM_PERSP:
1098                                 default:
1099                                 {
1100                                         double yfov = camera->getYFov().getValue();
1101                                         // yfov is in degrees, cam->lens is in millimiters
1102                                         cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
1103                                 }
1104                                 break;
1105                         }
1106                 }
1107                 break;
1108                 case COLLADAFW::Camera::UNDEFINED:
1109                         // read nothing, use blender defaults.
1110                         break;
1111         }
1112
1113         this->uid_camera_map[camera->getUniqueId()] = cam;
1114         this->FW_object_map[camera->getUniqueId()] = camera;
1115         // XXX import camera options
1116         return true;
1117 }
1118
1119 /** When this method is called, the writer must write the image.
1120  * \return The writer should return true, if writing succeeded, false otherwise.*/
1121 bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
1122 {
1123         if (mImportStage != General)
1124                 return true;
1125
1126         const std::string& imagepath = image->getImageURI().toNativePath();
1127
1128         char dir[FILE_MAX];
1129         char absolute_path[FILE_MAX];
1130         const char *workpath;
1131
1132         BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir));
1133         BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str());
1134         if (BLI_exists(absolute_path)) {
1135                 workpath = absolute_path;
1136         }
1137         else {
1138                 // Maybe imagepath was already absolute ?
1139                 if (!BLI_exists(imagepath.c_str())) {
1140                         fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
1141                         return true;
1142                 }
1143                 workpath = imagepath.c_str();
1144         }
1145
1146         Image *ima = BKE_image_load_exists(CTX_data_main(mContext), workpath);
1147         if (!ima) {
1148                 fprintf(stderr, "Cannot create image: %s\n", workpath);
1149                 return true;
1150         }
1151         this->uid_image_map[image->getUniqueId()] = ima;
1152
1153         return true;
1154 }
1155
1156 /** When this method is called, the writer must write the light.
1157  * \return The writer should return true, if writing succeeded, false otherwise.*/
1158 bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
1159 {
1160         if (mImportStage != General)
1161                 return true;
1162
1163         Main *bmain = CTX_data_main(mContext);
1164         Lamp *lamp = NULL;
1165         std::string la_id, la_name;
1166
1167         ExtraTags *et = getExtraTags(light->getUniqueId());
1168         /*TagsMap::iterator etit;
1169         ExtraTags *et = 0;
1170         etit = uid_tags_map.find(light->getUniqueId().toAscii());
1171         if (etit != uid_tags_map.end())
1172                 et = etit->second;*/
1173
1174         la_id = light->getOriginalId();
1175         la_name = light->getName();
1176         if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(bmain, (char *)la_name.c_str());
1177         else lamp = (Lamp *)BKE_lamp_add(bmain, (char *)la_id.c_str());
1178
1179         if (!lamp) {
1180                 fprintf(stderr, "Cannot create lamp.\n");
1181                 return true;
1182         }
1183
1184         // if we find an ExtraTags for this, use that instead.
1185         if (et && et->isProfile("blender")) {
1186                 et->setData("type", &(lamp->type));
1187                 et->setData("flag", &(lamp->flag));
1188                 et->setData("mode", &(lamp->mode));
1189                 et->setData("gamma", &(lamp->k));
1190                 et->setData("red", &(lamp->r));
1191                 et->setData("green", &(lamp->g));
1192                 et->setData("blue", &(lamp->b));
1193                 et->setData("shadow_r", &(lamp->shdwr));
1194                 et->setData("shadow_g", &(lamp->shdwg));
1195                 et->setData("shadow_b", &(lamp->shdwb));
1196                 et->setData("energy", &(lamp->energy));
1197                 et->setData("dist", &(lamp->dist));
1198                 et->setData("spotsize", &(lamp->spotsize));
1199                 lamp->spotsize = DEG2RADF(lamp->spotsize);
1200                 et->setData("spotblend", &(lamp->spotblend));
1201                 et->setData("halo_intensity", &(lamp->haint));
1202                 et->setData("att1", &(lamp->att1));
1203                 et->setData("att2", &(lamp->att2));
1204                 et->setData("falloff_type", &(lamp->falloff_type));
1205                 et->setData("clipsta", &(lamp->clipsta));
1206                 et->setData("clipend", &(lamp->clipend));
1207                 et->setData("bias", &(lamp->bias));
1208                 et->setData("soft", &(lamp->soft));
1209                 et->setData("compressthresh", &(lamp->compressthresh));
1210                 et->setData("bufsize", &(lamp->bufsize));
1211                 et->setData("samp", &(lamp->samp));
1212                 et->setData("buffers", &(lamp->buffers));
1213                 et->setData("filtertype", &(lamp->filtertype));
1214                 et->setData("bufflag", &(lamp->bufflag));
1215                 et->setData("buftype", &(lamp->buftype));
1216                 et->setData("ray_samp", &(lamp->ray_samp));
1217                 et->setData("ray_sampy", &(lamp->ray_sampy));
1218                 et->setData("ray_sampz", &(lamp->ray_sampz));
1219                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
1220                 et->setData("area_shape", &(lamp->area_shape));
1221                 et->setData("area_size", &(lamp->area_size));
1222                 et->setData("area_sizey", &(lamp->area_sizey));
1223                 et->setData("area_sizez", &(lamp->area_sizez));
1224                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
1225                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
1226                 et->setData("shadhalostep", &(lamp->shadhalostep));
1227                 et->setData("sun_effect_type", &(lamp->shadhalostep));
1228                 et->setData("skyblendtype", &(lamp->skyblendtype));
1229                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
1230                 et->setData("spread", &(lamp->spread));
1231                 et->setData("sun_brightness", &(lamp->sun_brightness));
1232                 et->setData("sun_size", &(lamp->sun_size));
1233                 et->setData("backscattered_light", &(lamp->backscattered_light));
1234                 et->setData("sun_intensity", &(lamp->sun_intensity));
1235                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
1236                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
1237                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
1238                 et->setData("skyblendfac", &(lamp->skyblendfac));
1239                 et->setData("sky_exposure", &(lamp->sky_exposure));
1240                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
1241         }
1242         else {
1243                 float constatt = light->getConstantAttenuation().getValue();
1244                 float linatt = light->getLinearAttenuation().getValue();
1245                 float quadatt = light->getQuadraticAttenuation().getValue();
1246                 float d = 25.0f;
1247                 float att1 = 0.0f;
1248                 float att2 = 0.0f;
1249                 float e = 1.0f;
1250
1251                 if (light->getColor().isValid()) {
1252                         COLLADAFW::Color col = light->getColor();
1253                         lamp->r = col.getRed();
1254                         lamp->g = col.getGreen();
1255                         lamp->b = col.getBlue();
1256                 }
1257
1258                 if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1259                         att2 = quadatt;
1260                         d = sqrt(1.0f / quadatt);
1261                 }
1262                 // linear light
1263                 else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1264                         att1 = linatt;
1265                         d = (1.0f / linatt);
1266                 }
1267                 else if (IS_EQ(constatt, 1.0f)) {
1268                         att1 = 1.0f;
1269                 }
1270                 else {
1271                         // assuming point light (const att = 1.0);
1272                         att1 = 1.0f;
1273                 }
1274
1275                 d *= (1.0f / unit_converter.getLinearMeter());
1276
1277                 lamp->energy = e;
1278                 lamp->dist = d;
1279
1280                 COLLADAFW::Light::LightType type = light->getLightType();
1281                 switch (type) {
1282                         case COLLADAFW::Light::AMBIENT_LIGHT:
1283                         {
1284                                 lamp->type = LA_HEMI;
1285                         }
1286                         break;
1287                         case COLLADAFW::Light::SPOT_LIGHT:
1288                         {
1289                                 lamp->type = LA_SPOT;
1290                                 lamp->att1 = att1;
1291                                 lamp->att2 = att2;
1292                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1293                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1294                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1295                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1296                                 lamp->spotsize = DEG2RADF(light->getFallOffAngle().getValue());
1297                                 lamp->spotblend = light->getFallOffExponent().getValue();
1298                         }
1299                         break;
1300                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1301                         {
1302                                 /* our sun is very strong, so pick a smaller energy level */
1303                                 lamp->type = LA_SUN;
1304                                 lamp->mode |= LA_NO_SPEC;
1305                         }
1306                         break;
1307                         case COLLADAFW::Light::POINT_LIGHT:
1308                         {
1309                                 lamp->type = LA_LOCAL;
1310                                 lamp->att1 = att1;
1311                                 lamp->att2 = att2;
1312                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1313                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1314                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1315                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1316                         }
1317                         break;
1318                         case COLLADAFW::Light::UNDEFINED:
1319                         {
1320                                 fprintf(stderr, "Current lamp type is not supported.\n");
1321                                 lamp->type = LA_LOCAL;
1322                         }
1323                         break;
1324                 }
1325         }
1326
1327         this->uid_lamp_map[light->getUniqueId()] = lamp;
1328         this->FW_object_map[light->getUniqueId()] = light;
1329         return true;
1330 }
1331
1332 // this function is called only for animations that pass COLLADAFW::validate
1333 bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
1334 {
1335         if (mImportStage != General)
1336                 return true;
1337
1338         // return true;
1339         return anim_importer.write_animation(anim);
1340 }
1341
1342 // called on post-process stage after writeVisualScenes
1343 bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
1344 {
1345         if (mImportStage != General)
1346                 return true;
1347
1348         // return true;
1349         return anim_importer.write_animation_list(animationList);
1350 }
1351
1352 #if OPENCOLLADA_WITH_ANIMATION_CLIP
1353 // Since opencollada 1.6.68
1354 // called on post-process stage after writeVisualScenes
1355 bool DocumentImporter::writeAnimationClip(const COLLADAFW::AnimationClip *AnimationClip)
1356 {
1357         if (mImportStage != General)
1358                 return true;
1359
1360         return true;
1361         //return animation_clip_importer.write_animation_clip(animationClip); // TODO: implement import of AnimationClips
1362 }
1363 #endif
1364
1365 /** When this method is called, the writer must write the skin controller data.
1366  * \return The writer should return true, if writing succeeded, false otherwise.*/
1367 bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin)
1368 {
1369         return armature_importer.write_skin_controller_data(skin);
1370 }
1371
1372 // this is called on postprocess, before writeVisualScenes
1373 bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
1374 {
1375         if (mImportStage != General)
1376                 return true;
1377
1378         return armature_importer.write_controller(controller);
1379 }
1380
1381 bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas)
1382 {
1383         return true;
1384 }
1385
1386 bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene)
1387 {
1388         return true;
1389 }
1390
1391 ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1392 {
1393         if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) {
1394                 return NULL;
1395         }
1396         return uid_tags_map[uid.toAscii()];
1397 }
1398
1399 bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1400 {
1401         uid_tags_map[uid.toAscii()] = extra_tags;
1402         return true;
1403 }
1404
1405 bool DocumentImporter::is_armature(COLLADAFW::Node *node)
1406 {
1407         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
1408         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
1409                 if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) {
1410                         return true;
1411                 }
1412                 else {
1413                         continue;
1414                 }
1415         }
1416
1417         //no child is JOINT
1418         return false;
1419 }