Cleanup: remove moar ugly G.main usages...
[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 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();
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(G.main, 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         Object *ob = bc_add_object(sce, OB_CAMERA, NULL);
387         Camera *cam = uid_camera_map[cam_uid];
388         Camera *old_cam = (Camera *)ob->data;
389         ob->data = cam;
390         BKE_libblock_free_us(G.main, old_cam);
391         return ob;
392 }
393
394 Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
395 {
396         const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
397         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {
398                 fprintf(stderr, "Couldn't find lamp by UID.\n");
399                 return NULL;
400         }
401
402         Object *ob = bc_add_object(sce, OB_LAMP, NULL);
403         Lamp *la = uid_lamp_map[lamp_uid];
404         Lamp *old_lamp = (Lamp *)ob->data;
405         ob->data = la;
406         BKE_libblock_free_us(G.main, old_lamp);
407         return ob;
408 }
409
410 Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
411 {
412         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);
413
414         Object *obn = BKE_object_copy(G.main, source_ob);
415         DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
416         BKE_scene_base_add(sce, obn);
417
418         if (instance_node) {
419                 anim_importer.read_node_transform(instance_node, obn);
420                 // if we also have a source_node (always ;), take its
421                 // transformation matrix and apply it to the newly instantiated
422                 // object to account for node hierarchy transforms in
423                 // .dae
424                 if (source_node) {
425                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
426                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
427                         float mat[4][4];
428                         for (int i = 0; i < 4; i++) {
429                                 for (int j = 0; j < 4; j++) {
430                                         mat[i][j] = bmat4[i][j];
431                                 }
432                         }
433                         // calc new matrix and apply
434                         mul_m4_m4m4(obn->obmat, obn->obmat, mat);
435                         BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
436                 }
437         }
438         else {
439                 anim_importer.read_node_transform(source_node, obn);
440         }
441
442         /*DAG_relations_tag_update(CTX_data_main(mContext));*/
443
444         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
445         if (children.getCount()) {
446                 for (unsigned int i = 0; i < children.getCount(); i++) {
447                         COLLADAFW::Node *child_node = children[i];
448                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
449                         if (object_map.find(child_id) == object_map.end())
450                                 continue;
451                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
452                         Object *new_child = NULL;
453                         if (inodes.getCount()) { // \todo loop through instance nodes
454                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
455                                 fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
456                                 new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
457                         }
458                         else {
459                                 new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
460                         }
461                         bc_set_parent(new_child, obn, mContext, true);
462
463                         if (is_library_node)
464                                 libnode_ob.push_back(new_child);
465                 }
466         }
467
468         return obn;
469 }
470
471 // to create constraints off node <extra> tags. Assumes only constraint data in
472 // current <extra> with blender profile.
473 void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
474 {
475         if (et && et->isProfile("blender")) {
476                 std::string name;
477                 short type = 0;
478                 et->setData("type", &type);
479                 BKE_constraint_add_for_object(ob, "Test_con", type);
480
481         }
482 }
483
484 void DocumentImporter::report_unknown_reference(const COLLADAFW::Node &node, const std::string object_type)
485 {
486         std::string id = node.getOriginalId();
487         std::string name = node.getName();
488         fprintf(stderr,
489                 "error: node id=\"%s\", name=\"%s\" refers to an undefined %s.\n",
490                 id.c_str(),
491                 name.c_str(),
492                 object_type.c_str());
493 }
494
495 std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
496 {
497         Object *ob = NULL;
498         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
499         bool read_transform = true;
500         std::string id   = node->getOriginalId();
501         std::string name = node->getName();
502
503         // if node has child nodes write them
504         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
505
506         std::vector<Object *> *objects_done = new std::vector<Object *>();
507         std::vector<Object *> *root_objects = new std::vector<Object *>();
508
509         fprintf(stderr,
510                 "Writing node id='%s', name='%s'\n",
511                 id.c_str(),
512                 name.c_str());
513
514         if (is_joint) {
515                 if (parent_node == NULL && !is_library_node) {
516                         // A Joint on root level is a skeleton without root node.
517                         // Here we add the armature "on the fly":
518                         par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
519                         objects_done->push_back(par);
520                         root_objects->push_back(par);
521                         object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
522                         node_map[node->getUniqueId()] = node;
523                 }
524                 if (parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT) {
525                         armature_importer.add_root_joint(node, par);
526                 }
527
528                 if (parent_node == NULL) {
529                         // for skeletons without root node all has been done above.
530                         // Skeletons with root node are handled further down.
531                         goto finally;
532                 }
533         }
534         else {
535                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
536                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
537                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
538                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
539                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
540                 size_t geom_done = 0;
541                 size_t camera_done = 0;
542                 size_t lamp_done = 0;
543                 size_t controller_done = 0;
544                 size_t inst_done = 0;
545
546                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
547                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
548                 // <instance_geometry>
549                 while (geom_done < geom.getCount()) {
550                         ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
551                                                               material_texture_mapping_map);
552                         if (ob == NULL) {
553                                 report_unknown_reference(*node, "instance_mesh");
554                         }
555                         else {
556                                 objects_done->push_back(ob);
557                                 if (parent_node == NULL) {
558                                         root_objects->push_back(ob);
559                                 }
560                         }
561                         ++geom_done;
562                 }
563                 while (camera_done < camera.getCount()) {
564                         ob = create_camera_object(camera[camera_done], sce);
565                         if (ob == NULL) {
566                                 report_unknown_reference(*node, "instance_camera");
567                         }
568                         else {
569                                 objects_done->push_back(ob);
570                                 if (parent_node == NULL) {
571                                         root_objects->push_back(ob);
572                                 }
573                         }
574                         ++camera_done;
575                 }
576                 while (lamp_done < lamp.getCount()) {
577                         ob = create_lamp_object(lamp[lamp_done], sce);
578                         if (ob == NULL) {
579                                 report_unknown_reference(*node, "instance_lamp");
580                         }
581                         else {
582                                 objects_done->push_back(ob);
583                                 if (parent_node == NULL) {
584                                         root_objects->push_back(ob);
585                                 }
586                         }
587                         ++lamp_done;
588                 }
589                 while (controller_done < controller.getCount()) {
590                         COLLADAFW::InstanceGeometry *geometry = (COLLADAFW::InstanceGeometry *)controller[controller_done];
591                         ob = mesh_importer.create_mesh_object(node, geometry, true, uid_material_map, material_texture_mapping_map);
592                         if (ob == NULL) {
593                                 report_unknown_reference(*node, "instance_controller");
594                         }
595                         else {
596                                 objects_done->push_back(ob);
597                                 if (parent_node == NULL) {
598                                         root_objects->push_back(ob);
599                                 }
600                         }
601                         ++controller_done;
602                 }
603                 // XXX instance_node is not supported yet
604                 while (inst_done < inst_node.getCount()) {
605                         const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
606                         if (object_map.find(node_id) == object_map.end()) {
607                                 fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str());
608                                 ob = NULL;
609                         }
610                         else {
611                                 std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, std::multimap<COLLADAFW::UniqueId, Object *>::iterator> pair_iter = object_map.equal_range(node_id);
612                                 for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; it2 != pair_iter.second; it2++) {
613                                         Object *source_ob = (Object *)it2->second;
614                                         COLLADAFW::Node *source_node = node_map[node_id];
615                                         ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
616                                         objects_done->push_back(ob);
617                                         if (parent_node == NULL) {
618                                                 root_objects->push_back(ob);
619                                         }
620                                 }
621                         }
622                         ++inst_done;
623
624                         read_transform = false;
625                 }
626
627                 // if node is empty - create empty object
628                 // XXX empty node may not mean it is empty object, not sure about this
629                 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
630                         //Check if Object is armature, by checking if immediate child is a JOINT node.
631                         if (is_armature(node)) {
632                                 ob = bc_add_object(sce, OB_ARMATURE, name.c_str());
633                         }
634                         else {
635                                 ob = bc_add_object(sce, OB_EMPTY, NULL);
636                         }
637                         objects_done->push_back(ob);
638                         if (parent_node == NULL) {
639                                 root_objects->push_back(ob);
640                         }
641                 }
642
643                 // XXX: if there're multiple instances, only one is stored
644
645                 if (!ob) {
646                         goto finally;
647                 }
648
649                 for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
650                         ob = *it;
651                         std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
652                         BKE_libblock_rename(G.main, &ob->id, (char *)nodename.c_str());
653                         object_map.insert(std::pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob));
654                         node_map[node->getUniqueId()] = node;
655
656                         if (is_library_node)
657                                 libnode_ob.push_back(ob);
658                 }
659
660
661                 //create_constraints(et,ob);
662
663         }
664
665         for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
666                 ob = *it;
667
668                 if (read_transform)
669                         anim_importer.read_node_transform(node, ob);  // overwrites location set earlier
670
671                 if (!is_joint) {
672                         if (par && ob) {
673                                 ob->parent = par;
674                                 ob->partype = PAROBJECT;
675                                 ob->parsubstr[0] = 0;
676
677                                 //bc_set_parent(ob, par, mContext, false);
678                         }
679                 }
680         }
681
682         if (objects_done->size() > 0) {
683                 ob = *objects_done->begin();
684         }
685         else {
686                 ob = NULL;
687         }
688
689         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
690                 std::vector<Object *> *child_objects;
691                 child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node);
692                 delete child_objects;
693         }
694
695
696 finally:
697         delete objects_done;
698
699         return root_objects;
700 }
701
702 /** When this method is called, the writer must write the entire visual scene.
703  *  Return The writer should return true, if writing succeeded, false otherwise. */
704 bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
705 {
706         if (mImportStage != General)
707                 return true;
708
709         // this method called on post process after writeGeometry, writeMaterial, etc.
710
711         // for each <node> in <visual_scene>:
712         // create an Object
713         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
714
715         // update: since we cannot link a Mesh with Object in
716         // writeGeometry because <geometry> does not reference <node>,
717         // we link Objects with Meshes here
718
719         vscenes.push_back(visualScene);
720
721         return true;
722 }
723
724 /** When this method is called, the writer must handle all nodes contained in the
725  * library nodes.
726  * \return The writer should return true, if writing succeeded, false otherwise.*/
727 bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
728 {
729         if (mImportStage != General)
730                 return true;
731
732         Scene *sce = CTX_data_scene(mContext);
733
734         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
735
736         for (unsigned int i = 0; i < nodes.getCount(); i++) {
737                 std::vector<Object *> *child_objects;
738                 child_objects = write_node(nodes[i], NULL, sce, NULL, true);
739                 delete child_objects;
740         }
741
742         return true;
743 }
744
745 /** When this method is called, the writer must write the geometry.
746  * \return The writer should return true, if writing succeeded, false otherwise.*/
747 bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
748 {
749         if (mImportStage != General)
750                 return true;
751
752         return mesh_importer.write_geometry(geom);
753 }
754
755 /** When this method is called, the writer must write the material.
756  * \return The writer should return true, if writing succeeded, false otherwise.*/
757 bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
758 {
759         if (mImportStage != General)
760                 return true;
761
762         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
763         Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
764
765         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
766         this->uid_material_map[cmat->getUniqueId()] = ma;
767
768         return true;
769 }
770
771 // create mtex, create texture, set texture image
772 MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
773                                        int i, TexIndexTextureArrayMap &texindex_texarray_map)
774 {
775         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
776         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
777
778         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
779
780         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
781                 fprintf(stderr, "Couldn't find an image by UID.\n");
782                 return NULL;
783         }
784
785         ma->mtex[i] = BKE_texture_mtex_add();
786         ma->mtex[i]->texco = TEXCO_UV;
787         ma->mtex[i]->tex = BKE_texture_add(G.main, "Texture");
788         ma->mtex[i]->tex->type = TEX_IMAGE;
789         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
790
791         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
792
793         return ma->mtex[i];
794 }
795
796 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
797 {
798         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
799
800         // blinn
801         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
802                 ma->spec_shader = MA_SPEC_BLINN;
803                 ma->spec = ef->getShininess().getFloatValue();
804         }
805         // phong
806         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
807                 ma->spec_shader = MA_SPEC_PHONG;
808                 ma->har = ef->getShininess().getFloatValue();
809         }
810         // lambert
811         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
812                 ma->diff_shader = MA_DIFF_LAMBERT;
813         }
814         // default - lambert
815         else {
816                 ma->diff_shader = MA_DIFF_LAMBERT;
817                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
818         }
819         // reflectivity
820         ma->ray_mirror = ef->getReflectivity().getFloatValue();
821         // index of refraction
822         ma->ang = ef->getIndexOfRefraction().getFloatValue();
823
824         int i = 0;
825         COLLADAFW::Color col;
826         MTex *mtex = NULL;
827         TexIndexTextureArrayMap texindex_texarray_map;
828
829         // DIFFUSE
830         // color
831         if (ef->getDiffuse().isColor()) {
832                 /* too high intensity can create artefacts (fireflies)
833                    So here we take care that intensity is set to 0.8 wherever possible
834                 */
835                 col = ef->getDiffuse().getColor();
836                 ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
837                 ma->r = col.getRed()   / ma->ref;
838                 ma->g = col.getGreen() / ma->ref;
839                 ma->b = col.getBlue()  / ma->ref;
840         }
841         // texture
842         else if (ef->getDiffuse().isTexture()) {
843                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture();
844                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
845                 if (mtex != NULL) {
846                         mtex->mapto = MAP_COL;
847                         ma->texact = (int)i;
848                         i++;
849                 }
850         }
851         // AMBIENT
852         // color
853         if (ef->getAmbient().isColor()) {
854                 col = ef->getAmbient().getColor();
855                 ma->ambr = col.getRed();
856                 ma->ambg = col.getGreen();
857                 ma->ambb = col.getBlue();
858         }
859         // texture
860         else if (ef->getAmbient().isTexture()) {
861                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture();
862                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
863                 if (mtex != NULL) {
864                         mtex->mapto = MAP_AMB;
865                         i++;
866                 }
867         }
868         // SPECULAR
869         // color
870         if (ef->getSpecular().isColor()) {
871                 col = ef->getSpecular().getColor();
872                 ma->specr = col.getRed();
873                 ma->specg = col.getGreen();
874                 ma->specb = col.getBlue();
875         }
876         // texture
877         else if (ef->getSpecular().isTexture()) {
878                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture();
879                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
880                 if (mtex != NULL) {
881                         mtex->mapto = MAP_SPEC;
882                         i++;
883                 }
884         }
885         // REFLECTIVE
886         // color
887         if (ef->getReflective().isColor()) {
888                 col = ef->getReflective().getColor();
889                 ma->mirr = col.getRed();
890                 ma->mirg = col.getGreen();
891                 ma->mirb = col.getBlue();
892         }
893         // texture
894         else if (ef->getReflective().isTexture()) {
895                 COLLADAFW::Texture ctex = ef->getReflective().getTexture();
896                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
897                 if (mtex != NULL) {
898                         mtex->mapto = MAP_REF;
899                         i++;
900                 }
901         }
902
903         // EMISSION
904         // color
905         if (ef->getEmission().isColor()) {
906                 // XXX there is no emission color in blender
907                 // but I am not sure
908         }
909         // texture
910         else if (ef->getEmission().isTexture()) {
911                 COLLADAFW::Texture ctex = ef->getEmission().getTexture();
912                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
913                 if (mtex != NULL) {
914                         mtex->mapto = MAP_EMIT;
915                         i++;
916                 }
917         }
918
919         // TRANSPARENT
920         // color
921         if (ef->getOpacity().isColor()) {
922                 col = ef->getTransparent().getColor();
923                 float alpha = ef->getTransparency().getFloatValue();
924                 if (col.isValid()) {
925                         alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
926                 }
927                 if (col.isValid() || alpha < 1.0) {
928                         ma->alpha = alpha;
929                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
930                 }
931         }
932         // texture
933         else if (ef->getOpacity().isTexture()) {
934                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
935                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
936                 if (mtex != NULL) {
937                         mtex->mapto = MAP_ALPHA;
938                         i++;
939                         ma->spectra = ma->alpha = 0;
940                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
941                 }
942         }
943
944         material_texture_mapping_map[ma] = texindex_texarray_map;
945 }
946
947 /** When this method is called, the writer must write the effect.
948  * \return The writer should return true, if writing succeeded, false otherwise.*/
949
950 bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
951 {
952         if (mImportStage != General)
953                 return true;
954
955         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
956
957         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
958                 fprintf(stderr, "Couldn't find a material by UID.\n");
959                 return true;
960         }
961
962         Material *ma = uid_effect_map[uid];
963         std::map<COLLADAFW::UniqueId, Material *>::iterator iter;
964         for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) {
965                 if (iter->second == ma) {
966                         this->FW_object_map[iter->first] = effect;
967                         break;
968                 }
969         }
970         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
971         if (common_efs.getCount() < 1) {
972                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
973                 return true;
974         }
975         // XXX TODO: Take all <profile_common>s
976         // Currently only first <profile_common> is supported
977         COLLADAFW::EffectCommon *ef = common_efs[0];
978         write_profile_COMMON(ef, ma);
979         this->FW_object_map[effect->getUniqueId()] = effect;
980
981         return true;
982 }
983
984
985 /** When this method is called, the writer must write the camera.
986  * \return The writer should return true, if writing succeeded, false otherwise.*/
987 bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
988 {
989         if (mImportStage != General)
990                 return true;
991
992         Camera *cam = NULL;
993         std::string cam_id, cam_name;
994
995         ExtraTags *et=getExtraTags(camera->getUniqueId());
996         cam_id = camera->getOriginalId();
997         cam_name = camera->getName();
998         if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
999         else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
1000
1001         if (!cam) {
1002                 fprintf(stderr, "Cannot create camera.\n");
1003                 return true;
1004         }
1005
1006         if (et && et->isProfile("blender")) {
1007                 et->setData("shiftx",&(cam->shiftx));
1008                 et->setData("shifty",&(cam->shifty));
1009                 et->setData("YF_dofdist",&(cam->YF_dofdist));
1010         }
1011         cam->clipsta = camera->getNearClippingPlane().getValue();
1012         cam->clipend = camera->getFarClippingPlane().getValue();
1013
1014         COLLADAFW::Camera::CameraType type = camera->getCameraType();
1015         switch (type) {
1016                 case COLLADAFW::Camera::ORTHOGRAPHIC:
1017                 {
1018                         cam->type = CAM_ORTHO;
1019                 }
1020                 break;
1021                 case COLLADAFW::Camera::PERSPECTIVE:
1022                 {
1023                         cam->type = CAM_PERSP;
1024                 }
1025                 break;
1026                 case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
1027                 {
1028                         fprintf(stderr, "Current camera type is not supported.\n");
1029                         cam->type = CAM_PERSP;
1030                 }
1031                 break;
1032         }
1033
1034         switch (camera->getDescriptionType()) {
1035                 case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
1036                 {
1037                         switch (cam->type) {
1038                                 case CAM_ORTHO:
1039                                 {
1040                                         double ymag = 2 * camera->getYMag().getValue();
1041                                         double aspect = camera->getAspectRatio().getValue();
1042                                         double xmag = aspect * ymag;
1043                                         cam->ortho_scale = (float)xmag;
1044                                 }
1045                                 break;
1046                                 case CAM_PERSP:
1047                                 default:
1048                                 {
1049                                         double yfov = camera->getYFov().getValue();
1050                                         double aspect = camera->getAspectRatio().getValue();
1051
1052                                         // NOTE: Needs more testing (As we curretnly have no official test data for this)
1053
1054                                         double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f));
1055                                         cam->lens = fov_to_focallength(xfov, cam->sensor_x);
1056                                 }
1057                                 break;
1058                         }
1059                 }
1060                 break;
1061                 /* XXX correct way to do following four is probably to get also render
1062                  * size and determine proper settings from that somehow */
1063                 case COLLADAFW::Camera::ASPECTRATIO_AND_X:
1064                 case COLLADAFW::Camera::SINGLE_X:
1065                 case COLLADAFW::Camera::X_AND_Y:
1066                 {
1067                         switch (cam->type) {
1068                                 case CAM_ORTHO:
1069                                         cam->ortho_scale = (float)camera->getXMag().getValue() * 2;
1070                                         break;
1071                                 case CAM_PERSP:
1072                                 default:
1073                                 {
1074                                         double x = camera->getXFov().getValue();
1075                                         // x is in degrees, cam->lens is in millimiters
1076                                         cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
1077                                 }
1078                                 break;
1079                         }
1080                 }
1081                 break;
1082                 case COLLADAFW::Camera::SINGLE_Y:
1083                 {
1084                         switch (cam->type) {
1085                                 case CAM_ORTHO:
1086                                         cam->ortho_scale = (float)camera->getYMag().getValue();
1087                                         break;
1088                                 case CAM_PERSP:
1089                                 default:
1090                                 {
1091                                         double yfov = camera->getYFov().getValue();
1092                                         // yfov is in degrees, cam->lens is in millimiters
1093                                         cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
1094                                 }
1095                                 break;
1096                         }
1097                 }
1098                 break;
1099                 case COLLADAFW::Camera::UNDEFINED:
1100                         // read nothing, use blender defaults.
1101                         break;
1102         }
1103
1104         this->uid_camera_map[camera->getUniqueId()] = cam;
1105         this->FW_object_map[camera->getUniqueId()] = camera;
1106         // XXX import camera options
1107         return true;
1108 }
1109
1110 /** When this method is called, the writer must write the image.
1111  * \return The writer should return true, if writing succeeded, false otherwise.*/
1112 bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
1113 {
1114         if (mImportStage != General)
1115                 return true;
1116
1117         const std::string& imagepath = image->getImageURI().toNativePath();
1118
1119         char dir[FILE_MAX];
1120         char absolute_path[FILE_MAX];
1121         const char *workpath;
1122
1123         BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir));
1124         BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str());
1125         if (BLI_exists(absolute_path)) {
1126                 workpath = absolute_path;
1127         }
1128         else {
1129                 // Maybe imagepath was already absolute ?
1130                 if (!BLI_exists(imagepath.c_str())) {
1131                         fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
1132                         return true;
1133                 }
1134                 workpath = imagepath.c_str();
1135         }
1136
1137         Image *ima = BKE_image_load_exists(CTX_data_main(mContext), workpath);
1138         if (!ima) {
1139                 fprintf(stderr, "Cannot create image: %s\n", workpath);
1140                 return true;
1141         }
1142         this->uid_image_map[image->getUniqueId()] = ima;
1143
1144         return true;
1145 }
1146
1147 /** When this method is called, the writer must write the light.
1148  * \return The writer should return true, if writing succeeded, false otherwise.*/
1149 bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
1150 {
1151         if (mImportStage != General)
1152                 return true;
1153
1154         Lamp *lamp = NULL;
1155         std::string la_id, la_name;
1156
1157         ExtraTags *et = getExtraTags(light->getUniqueId());
1158         /*TagsMap::iterator etit;
1159         ExtraTags *et = 0;
1160         etit = uid_tags_map.find(light->getUniqueId().toAscii());
1161         if (etit != uid_tags_map.end())
1162                 et = etit->second;*/
1163
1164         la_id = light->getOriginalId();
1165         la_name = light->getName();
1166         if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
1167         else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
1168
1169         if (!lamp) {
1170                 fprintf(stderr, "Cannot create lamp.\n");
1171                 return true;
1172         }
1173
1174         // if we find an ExtraTags for this, use that instead.
1175         if (et && et->isProfile("blender")) {
1176                 et->setData("type", &(lamp->type));
1177                 et->setData("flag", &(lamp->flag));
1178                 et->setData("mode", &(lamp->mode));
1179                 et->setData("gamma", &(lamp->k));
1180                 et->setData("red", &(lamp->r));
1181                 et->setData("green", &(lamp->g));
1182                 et->setData("blue", &(lamp->b));
1183                 et->setData("shadow_r", &(lamp->shdwr));
1184                 et->setData("shadow_g", &(lamp->shdwg));
1185                 et->setData("shadow_b", &(lamp->shdwb));
1186                 et->setData("energy", &(lamp->energy));
1187                 et->setData("dist", &(lamp->dist));
1188                 et->setData("spotsize", &(lamp->spotsize));
1189                 lamp->spotsize = DEG2RADF(lamp->spotsize);
1190                 et->setData("spotblend", &(lamp->spotblend));
1191                 et->setData("halo_intensity", &(lamp->haint));
1192                 et->setData("att1", &(lamp->att1));
1193                 et->setData("att2", &(lamp->att2));
1194                 et->setData("falloff_type", &(lamp->falloff_type));
1195                 et->setData("clipsta", &(lamp->clipsta));
1196                 et->setData("clipend", &(lamp->clipend));
1197                 et->setData("bias", &(lamp->bias));
1198                 et->setData("soft", &(lamp->soft));
1199                 et->setData("compressthresh", &(lamp->compressthresh));
1200                 et->setData("bufsize", &(lamp->bufsize));
1201                 et->setData("samp", &(lamp->samp));
1202                 et->setData("buffers", &(lamp->buffers));
1203                 et->setData("filtertype", &(lamp->filtertype));
1204                 et->setData("bufflag", &(lamp->bufflag));
1205                 et->setData("buftype", &(lamp->buftype));
1206                 et->setData("ray_samp", &(lamp->ray_samp));
1207                 et->setData("ray_sampy", &(lamp->ray_sampy));
1208                 et->setData("ray_sampz", &(lamp->ray_sampz));
1209                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
1210                 et->setData("area_shape", &(lamp->area_shape));
1211                 et->setData("area_size", &(lamp->area_size));
1212                 et->setData("area_sizey", &(lamp->area_sizey));
1213                 et->setData("area_sizez", &(lamp->area_sizez));
1214                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
1215                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
1216                 et->setData("shadhalostep", &(lamp->shadhalostep));
1217                 et->setData("sun_effect_type", &(lamp->shadhalostep));
1218                 et->setData("skyblendtype", &(lamp->skyblendtype));
1219                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
1220                 et->setData("spread", &(lamp->spread));
1221                 et->setData("sun_brightness", &(lamp->sun_brightness));
1222                 et->setData("sun_size", &(lamp->sun_size));
1223                 et->setData("backscattered_light", &(lamp->backscattered_light));
1224                 et->setData("sun_intensity", &(lamp->sun_intensity));
1225                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
1226                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
1227                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
1228                 et->setData("skyblendfac", &(lamp->skyblendfac));
1229                 et->setData("sky_exposure", &(lamp->sky_exposure));
1230                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
1231         }
1232         else {
1233                 float constatt = light->getConstantAttenuation().getValue();
1234                 float linatt = light->getLinearAttenuation().getValue();
1235                 float quadatt = light->getQuadraticAttenuation().getValue();
1236                 float d = 25.0f;
1237                 float att1 = 0.0f;
1238                 float att2 = 0.0f;
1239                 float e = 1.0f;
1240
1241                 if (light->getColor().isValid()) {
1242                         COLLADAFW::Color col = light->getColor();
1243                         lamp->r = col.getRed();
1244                         lamp->g = col.getGreen();
1245                         lamp->b = col.getBlue();
1246                 }
1247
1248                 if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1249                         att2 = quadatt;
1250                         d = sqrt(1.0f / quadatt);
1251                 }
1252                 // linear light
1253                 else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1254                         att1 = linatt;
1255                         d = (1.0f / linatt);
1256                 }
1257                 else if (IS_EQ(constatt, 1.0f)) {
1258                         att1 = 1.0f;
1259                 }
1260                 else {
1261                         // assuming point light (const att = 1.0);
1262                         att1 = 1.0f;
1263                 }
1264
1265                 d *= (1.0f / unit_converter.getLinearMeter());
1266
1267                 lamp->energy = e;
1268                 lamp->dist = d;
1269
1270                 COLLADAFW::Light::LightType type = light->getLightType();
1271                 switch (type) {
1272                         case COLLADAFW::Light::AMBIENT_LIGHT:
1273                         {
1274                                 lamp->type = LA_HEMI;
1275                         }
1276                         break;
1277                         case COLLADAFW::Light::SPOT_LIGHT:
1278                         {
1279                                 lamp->type = LA_SPOT;
1280                                 lamp->att1 = att1;
1281                                 lamp->att2 = att2;
1282                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1283                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1284                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1285                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1286                                 lamp->spotsize = DEG2RADF(light->getFallOffAngle().getValue());
1287                                 lamp->spotblend = light->getFallOffExponent().getValue();
1288                         }
1289                         break;
1290                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1291                         {
1292                                 /* our sun is very strong, so pick a smaller energy level */
1293                                 lamp->type = LA_SUN;
1294                                 lamp->mode |= LA_NO_SPEC;
1295                         }
1296                         break;
1297                         case COLLADAFW::Light::POINT_LIGHT:
1298                         {
1299                                 lamp->type = LA_LOCAL;
1300                                 lamp->att1 = att1;
1301                                 lamp->att2 = att2;
1302                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1303                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1304                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1305                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1306                         }
1307                         break;
1308                         case COLLADAFW::Light::UNDEFINED:
1309                         {
1310                                 fprintf(stderr, "Current lamp type is not supported.\n");
1311                                 lamp->type = LA_LOCAL;
1312                         }
1313                         break;
1314                 }
1315         }
1316
1317         this->uid_lamp_map[light->getUniqueId()] = lamp;
1318         this->FW_object_map[light->getUniqueId()] = light;
1319         return true;
1320 }
1321
1322 // this function is called only for animations that pass COLLADAFW::validate
1323 bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
1324 {
1325         if (mImportStage != General)
1326                 return true;
1327
1328         // return true;
1329         return anim_importer.write_animation(anim);
1330 }
1331
1332 // called on post-process stage after writeVisualScenes
1333 bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
1334 {
1335         if (mImportStage != General)
1336                 return true;
1337
1338         // return true;
1339         return anim_importer.write_animation_list(animationList);
1340 }
1341
1342 /** When this method is called, the writer must write the skin controller data.
1343  * \return The writer should return true, if writing succeeded, false otherwise.*/
1344 bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin)
1345 {
1346         return armature_importer.write_skin_controller_data(skin);
1347 }
1348
1349 // this is called on postprocess, before writeVisualScenes
1350 bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
1351 {
1352         if (mImportStage != General)
1353                 return true;
1354
1355         return armature_importer.write_controller(controller);
1356 }
1357
1358 bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas)
1359 {
1360         return true;
1361 }
1362
1363 bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene)
1364 {
1365         return true;
1366 }
1367
1368 ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1369 {
1370         if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) {
1371                 return NULL;
1372         }
1373         return uid_tags_map[uid.toAscii()];
1374 }
1375
1376 bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1377 {
1378         uid_tags_map[uid.toAscii()] = extra_tags;
1379         return true;
1380 }
1381
1382 bool DocumentImporter::is_armature(COLLADAFW::Node *node)
1383 {
1384         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
1385         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
1386                 if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) {
1387                         return true;
1388                 }
1389                 else {
1390                         continue;
1391                 }
1392         }
1393
1394         //no child is JOINT
1395         return false;
1396 }