style cleanup: follow style guide for formatting of if/for/while loops, and else...
[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 #include "BLI_listbase.h"
53 #include "BLI_math.h"
54 #include "BLI_string.h"
55 #include "BLI_utildefines.h"
56
57 #include "BKE_camera.h"
58 #include "BKE_main.h"
59 #include "BKE_lamp.h"
60 #include "BKE_library.h"
61 #include "BKE_texture.h"
62 #include "BKE_fcurve.h"
63 #include "BKE_depsgraph.h"
64 #include "BLI_path_util.h"
65 #include "BKE_scene.h"
66 #include "BKE_global.h"
67 #include "BKE_material.h"
68 #include "BKE_utildefines.h"
69 #include "BKE_image.h"
70
71 #include "DNA_camera_types.h"
72 #include "DNA_lamp_types.h"
73
74 #include "RNA_access.h"
75
76 #include "MEM_guardedalloc.h"
77
78 #include "ExtraHandler.h"
79 #include "ErrorHandler.h"
80 #include "DocumentImporter.h"
81 #include "TransformReader.h"
82
83 #include "collada_internal.h"
84 #include "collada_utils.h"
85
86
87 /*
88   COLLADA Importer limitations:
89   - no multiple scene import, all objects are added to active scene
90  */
91
92 // #define COLLADA_DEBUG
93 // creates empties for each imported bone on layer 2, for debugging
94 // #define ARMATURE_TEST
95
96 DocumentImporter::DocumentImporter(bContext *C, const char *filename) :
97         mImportStage(General),
98         mFilename(filename),
99         mContext(C),
100         armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
101         mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
102         anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
103 {}
104
105 DocumentImporter::~DocumentImporter()
106 {
107         TagsMap::iterator etit;
108         etit = uid_tags_map.begin();
109         while(etit!=uid_tags_map.end()) {
110                 delete etit->second;
111                 etit++;
112         }
113 }
114
115 bool DocumentImporter::import()
116 {
117         ErrorHandler errorHandler;
118         COLLADASaxFWL::Loader loader(&errorHandler);
119         COLLADAFW::Root root(&loader, this);
120         ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
121         
122         loader.registerExtraDataCallbackHandler(ehandler);
123
124         if (!root.loadDocument(mFilename)) {
125                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
126                 return false;
127         }
128         
129         if(errorHandler.hasError())
130                 return false;
131         
132         /** TODO set up scene graph and such here */
133         
134         mImportStage = Controller;
135         
136         COLLADASaxFWL::Loader loader2;
137         COLLADAFW::Root root2(&loader2, this);
138         
139         if (!root2.loadDocument(mFilename)) {
140                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
141                 return false;
142         }
143         
144         
145         delete ehandler;
146
147         return true;
148 }
149
150 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
151 {
152         // TODO: if possible show error info
153         //
154         // Should we get rid of invisible Meshes that were created so far
155         // or maybe create objects at coordinate space origin?
156         //
157         // The latter sounds better.
158 }
159
160 void DocumentImporter::start(){}
161
162 void DocumentImporter::finish()
163 {
164         if(mImportStage!=General)
165                 return;
166                 
167         /** TODO Break up and put into 2-pass parsing of DAE */
168         std::vector<const COLLADAFW::VisualScene*>::iterator it;
169         for (it = vscenes.begin(); it != vscenes.end(); it++) {
170                 PointerRNA sceneptr, unit_settings;
171                 PropertyRNA *system, *scale;
172                 // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
173                 Scene *sce = CTX_data_scene(mContext);
174                 
175                 // for scene unit settings: system, scale_length
176                 RNA_id_pointer_create(&sce->id, &sceneptr);
177                 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
178                 system = RNA_struct_find_property(&unit_settings, "system");
179                 scale = RNA_struct_find_property(&unit_settings, "scale_length");
180                 
181                 switch(unit_converter.isMetricSystem()) {
182                         case UnitConverter::Metric:
183                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
184                                 break;
185                         case UnitConverter::Imperial:
186                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
187                                 break;
188                         default:
189                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
190                                 break;
191                 }
192                 RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter());
193                 
194                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
195
196                 for (unsigned int i = 0; i < roots.getCount(); i++) {
197                         write_node(roots[i], NULL, sce, NULL, false);
198                 }
199         }
200         armature_importer.set_tags_map(this->uid_tags_map);
201         armature_importer.make_armatures(mContext);
202
203 #if 0
204         armature_importer.fix_animation();
205 #endif
206
207         for (std::vector<const COLLADAFW::VisualScene*>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
208                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
209
210                 for (unsigned int i = 0; i < roots.getCount(); i++)
211                         translate_anim_recursive(roots[i],NULL,NULL);
212         }
213
214         if (libnode_ob.size()) {
215                 Scene *sce = CTX_data_scene(mContext);
216
217                 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
218                 // free all library_nodes
219                 std::vector<Object*>::iterator it;
220                 for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
221                         Object *ob = *it;
222
223                         Base *base = object_in_scene(ob, sce);
224                         if (base) {
225                                 BLI_remlink(&sce->base, base);
226                                 free_libblock_us(&G.main->object, base->object);
227                                 if (sce->basact==base)
228                                         sce->basact= NULL;
229                                 MEM_freeN(base);
230                         }
231                 }
232                 libnode_ob.clear();
233
234                 DAG_scene_sort(CTX_data_main(mContext), sce);
235                 DAG_ids_flush_update(CTX_data_main(mContext), 0);
236         }
237 }
238
239
240 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
241 {
242
243         // The split in #29246, rootmap must point at actual root when
244         // calculating bones in apply_curves_as_matrix.
245         // This has to do with inverse bind poses being world space
246         // (the sources for skinned bones' restposes) and the way
247         // non-skinning nodes have their "restpose" recursively calculated.
248         // XXX TODO: design issue, how to support unrelated joints taking
249         // part in skinning.
250         if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
251                 // par is root if there's no corresp. key in root_map
252                 if (root_map.find(par->getUniqueId()) == root_map.end())
253                         root_map[node->getUniqueId()] = par;
254                 else
255                         root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
256         }
257
258         /*COLLADAFW::Transformation::TransformationType types[] = {
259                 COLLADAFW::Transformation::ROTATE,
260                 COLLADAFW::Transformation::SCALE,
261                 COLLADAFW::Transformation::TRANSLATE,
262                 COLLADAFW::Transformation::MATRIX
263         };
264
265         Object *ob;*/
266         unsigned int i;
267
268         //for (i = 0; i < 4; i++)
269                 //ob = 
270         anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
271
272         COLLADAFW::NodePointerArray &children = node->getChildNodes();
273         for (i = 0; i < children.getCount(); i++) {
274                 translate_anim_recursive(children[i], node, NULL);
275         }
276 }
277
278 /** When this method is called, the writer must write the global document asset.
279         \return The writer should return true, if writing succeeded, false otherwise.*/
280 bool DocumentImporter::writeGlobalAsset ( const COLLADAFW::FileInfo* asset ) 
281 {
282         unit_converter.read_asset(asset);
283
284         return true;
285 }
286
287 /** When this method is called, the writer must write the scene.
288         \return The writer should return true, if writing succeeded, false otherwise.*/
289 bool DocumentImporter::writeScene ( const COLLADAFW::Scene* scene ) 
290 {
291         // XXX could store the scene id, but do nothing for now
292         return true;
293 }
294 Object* DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
295 {
296         const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
297         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {     
298                 fprintf(stderr, "Couldn't find camera by UID.\n");
299                 return NULL;
300         }
301         Object *ob = add_object(sce, OB_CAMERA);
302         Camera *cam = uid_camera_map[cam_uid];
303         Camera *old_cam = (Camera*)ob->data;
304         ob->data = cam;
305         old_cam->id.us--;
306         if (old_cam->id.us == 0)
307                 free_libblock(&G.main->camera, old_cam);
308         return ob;
309 }
310
311 Object* DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
312 {
313         const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
314         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {        
315                 fprintf(stderr, "Couldn't find lamp by UID. \n");
316                 return NULL;
317         }
318         Object *ob = add_object(sce, OB_LAMP);
319         Lamp *la = uid_lamp_map[lamp_uid];
320         Lamp *old_lamp = (Lamp*)ob->data;
321         ob->data = la;
322         old_lamp->id.us--;
323         if (old_lamp->id.us == 0)
324                 free_libblock(&G.main->lamp, old_lamp);
325         return ob;
326 }
327
328 Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
329 {
330         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);
331
332         Object *obn = copy_object(source_ob);
333         obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
334         scene_add_base(sce, obn);
335
336         if (instance_node) {
337                 anim_importer.read_node_transform(instance_node, obn);
338                 // if we also have a source_node (always ;), take its
339                 // transformation matrix and apply it to the newly instantiated
340                 // object to account for node hierarchy transforms in
341                 // .dae
342                 if(source_node) {
343                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
344                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
345                         float mat[4][4];
346                         for (int i = 0; i < 4; i++) {
347                                 for (int j = 0; j < 4; j++) {
348                                         mat[i][j] = bmat4[i][j];
349                                 }
350                         }
351                         // calc new matrix and apply
352                         mult_m4_m4m4(obn->obmat, obn->obmat, mat);
353                         object_apply_mat4(obn, obn->obmat, 0, 0);
354                 }
355         }
356         else {
357                 anim_importer.read_node_transform(source_node, obn);
358         }
359
360         DAG_scene_sort(CTX_data_main(mContext), sce);
361         DAG_ids_flush_update(CTX_data_main(mContext), 0);
362
363         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
364         if (children.getCount()) {
365                 for (unsigned int i = 0; i < children.getCount(); i++) {
366                         COLLADAFW::Node *child_node = children[i];
367                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
368                         if (object_map.find(child_id) == object_map.end())
369                                 continue;
370                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
371                         Object *new_child = NULL;
372                         if (inodes.getCount()) { // \todo loop through instance nodes
373                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
374                                 new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, is_library_node);
375                         }
376                         else {
377                                 new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, is_library_node);
378                         }
379                         bc_set_parent(new_child, obn, mContext, true);
380
381                         if (is_library_node)
382                                 libnode_ob.push_back(new_child);
383                 }
384         }
385
386         return obn;
387 }
388
389 void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
390 {
391         Object *ob = NULL;
392         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
393         bool read_transform = true;
394
395         if (is_joint) {
396                 if ( par ) {
397                 Object * empty = par;
398                 par = add_object(sce, OB_ARMATURE);
399                 bc_set_parent(par,empty->parent, mContext);
400                 //remove empty : todo
401                 object_map[parent_node->getUniqueId()] = par;
402                 }
403                 armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
404         }
405         else {
406                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
407                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
408                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
409                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
410                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
411                 size_t geom_done = 0;
412                 size_t camera_done = 0;
413                 size_t lamp_done = 0;
414                 size_t controller_done = 0;
415                 size_t inst_done = 0;
416
417                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
418                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
419                 // <instance_geometry>
420                 while (geom_done < geom.getCount()) {
421                         ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
422                                                                                                   material_texture_mapping_map);
423                         ++geom_done;
424                 }
425                 while (camera_done < camera.getCount()) {
426                         ob = create_camera_object(camera[camera_done], sce);
427                         ++camera_done;
428                 }
429                 while (lamp_done < lamp.getCount()) {
430                         ob = create_lamp_object(lamp[lamp_done], sce);
431                         ++lamp_done;
432                 }
433                 while (controller_done < controller.getCount()) {
434                         COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry*)controller[controller_done];
435                         ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
436                         ++controller_done;
437                 }
438                 // XXX instance_node is not supported yet
439                 while (inst_done < inst_node.getCount()) {
440                         const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
441                         if (object_map.find(node_id) == object_map.end()) {
442                                 fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str());
443                                 ob = NULL;
444                         }
445                         else {
446                                 Object *source_ob = object_map[node_id];
447                                 COLLADAFW::Node *source_node = node_map[node_id];
448
449                                 ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
450                         }
451                         ++inst_done;
452
453                         read_transform = false;
454                 }
455                 // if node is empty - create empty object
456                 // XXX empty node may not mean it is empty object, not sure about this
457                 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
458                         ob = add_object(sce, OB_EMPTY);
459                 }
460                 
461                 // XXX: if there're multiple instances, only one is stored
462
463                 if (!ob) return;
464                 
465                 std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
466                 rename_id(&ob->id, (char*)nodename.c_str());
467
468                 object_map[node->getUniqueId()] = ob;
469                 node_map[node->getUniqueId()] = node;
470
471                 if (is_library_node)
472                         libnode_ob.push_back(ob);
473         }
474
475         if (read_transform)
476                 anim_importer.read_node_transform(node, ob); // overwrites location set earlier
477
478         if (!is_joint) {
479                 // if par was given make this object child of the previous 
480                 if (par && ob)
481                         bc_set_parent(ob, par, mContext);
482         }
483
484         // if node has child nodes write them
485         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
486         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {     
487                 write_node(child_nodes[i], node, sce, ob, is_library_node);
488         }
489 }
490
491 /** When this method is called, the writer must write the entire visual scene.
492         \return The writer should return true, if writing succeeded, false otherwise.*/
493 bool DocumentImporter::writeVisualScene ( const COLLADAFW::VisualScene* visualScene ) 
494 {
495         if(mImportStage!=General)
496                 return true;
497                 
498         // this method called on post process after writeGeometry, writeMaterial, etc.
499
500         // for each <node> in <visual_scene>:
501         // create an Object
502         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
503
504         // update: since we cannot link a Mesh with Object in
505         // writeGeometry because <geometry> does not reference <node>,
506         // we link Objects with Meshes here
507
508         vscenes.push_back(visualScene);
509         
510         return true;
511 }
512
513 /** When this method is called, the writer must handle all nodes contained in the 
514         library nodes.
515         \return The writer should return true, if writing succeeded, false otherwise.*/
516 bool DocumentImporter::writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes ) 
517 {
518         if(mImportStage!=General)
519                 return true;
520                 
521         Scene *sce = CTX_data_scene(mContext);
522
523         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
524
525         for (unsigned int i = 0; i < nodes.getCount(); i++) {
526                 write_node(nodes[i], NULL, sce, NULL, true);
527         }
528
529         return true;
530 }
531
532 /** When this method is called, the writer must write the geometry.
533         \return The writer should return true, if writing succeeded, false otherwise.*/
534 bool DocumentImporter::writeGeometry ( const COLLADAFW::Geometry* geom ) 
535 {
536         if(mImportStage!=General)
537                 return true;
538                 
539         return mesh_importer.write_geometry(geom);
540 }
541
542 /** When this method is called, the writer must write the material.
543         \return The writer should return true, if writing succeeded, false otherwise.*/
544 bool DocumentImporter::writeMaterial( const COLLADAFW::Material* cmat ) 
545 {
546         if(mImportStage!=General)
547                 return true;
548                 
549         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
550         Material *ma = add_material((char*)str_mat_id.c_str());
551         
552         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
553         this->uid_material_map[cmat->getUniqueId()] = ma;
554         
555         return true;
556 }
557
558 // create mtex, create texture, set texture image
559 MTex* DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
560                                          int i, TexIndexTextureArrayMap &texindex_texarray_map)
561 {
562         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
563         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
564                 
565         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
566         
567         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
568                 fprintf(stderr, "Couldn't find an image by UID.\n");
569                 return NULL;
570         }
571         
572         ma->mtex[i] = add_mtex();
573         ma->mtex[i]->texco = TEXCO_UV;
574         ma->mtex[i]->tex = add_texture("Texture");
575         ma->mtex[i]->tex->type = TEX_IMAGE;
576         ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
577         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
578         
579         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
580         
581         return ma->mtex[i];
582 }
583
584 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
585 {
586         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
587         
588         // blinn
589         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
590                 ma->spec_shader = MA_SPEC_BLINN;
591                 ma->spec = ef->getShininess().getFloatValue();
592         }
593         // phong
594         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
595                 ma->spec_shader = MA_SPEC_PHONG;
596                 ma->har = ef->getShininess().getFloatValue();
597         }
598         // lambert
599         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
600                 ma->diff_shader = MA_DIFF_LAMBERT;
601         }
602         // default - lambert
603         else {
604                 ma->diff_shader = MA_DIFF_LAMBERT;
605                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
606         }
607         // reflectivity
608         ma->ray_mirror = ef->getReflectivity().getFloatValue();
609         // index of refraction
610         ma->ang = ef->getIndexOfRefraction().getFloatValue();
611         
612         int i = 0;
613         COLLADAFW::Color col;
614         MTex *mtex = NULL;
615         TexIndexTextureArrayMap texindex_texarray_map;
616         
617         // DIFFUSE
618         // color
619         if (ef->getDiffuse().isColor()) {
620                 col = ef->getDiffuse().getColor();
621                 ma->r = col.getRed();
622                 ma->g = col.getGreen();
623                 ma->b = col.getBlue();
624         }
625         // texture
626         else if (ef->getDiffuse().isTexture()) {
627                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
628                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
629                 if (mtex != NULL) {
630                         mtex->mapto = MAP_COL;
631                         ma->texact = (int)i;
632                         i++;
633                 }
634         }
635         // AMBIENT
636         // color
637         if (ef->getAmbient().isColor()) {
638                 col = ef->getAmbient().getColor();
639                 ma->ambr = col.getRed();
640                 ma->ambg = col.getGreen();
641                 ma->ambb = col.getBlue();
642         }
643         // texture
644         else if (ef->getAmbient().isTexture()) {
645                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
646                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
647                 if (mtex != NULL) {
648                         mtex->mapto = MAP_AMB; 
649                         i++;
650                 }
651         }
652         // SPECULAR
653         // color
654         if (ef->getSpecular().isColor()) {
655                 col = ef->getSpecular().getColor();
656                 ma->specr = col.getRed();
657                 ma->specg = col.getGreen();
658                 ma->specb = col.getBlue();
659         }
660         // texture
661         else if (ef->getSpecular().isTexture()) {
662                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
663                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
664                 if (mtex != NULL) {
665                         mtex->mapto = MAP_SPEC; 
666                         i++;
667                 }
668         }
669         // REFLECTIVE
670         // color
671         if (ef->getReflective().isColor()) {
672                 col = ef->getReflective().getColor();
673                 ma->mirr = col.getRed();
674                 ma->mirg = col.getGreen();
675                 ma->mirb = col.getBlue();
676         }
677         // texture
678         else if (ef->getReflective().isTexture()) {
679                 COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
680                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
681                 if (mtex != NULL) {
682                         mtex->mapto = MAP_REF; 
683                         i++;
684                 }
685         }
686         // EMISSION
687         // color
688         if (ef->getEmission().isColor()) {
689                 // XXX there is no emission color in blender
690                 // but I am not sure
691         }
692         // texture
693         else if (ef->getEmission().isTexture()) {
694                 COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
695                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
696                 if (mtex != NULL) {
697                         mtex->mapto = MAP_EMIT; 
698                         i++;
699                 }
700         }
701         
702         if(ef->getOpacity().isTexture()) {
703                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
704                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
705                 if(mtex != NULL) {
706                         mtex->mapto = MAP_ALPHA;
707                         mtex->tex->imaflag |= TEX_USEALPHA;
708                         i++;
709                         ma->spectra = ma->alpha = 0;
710                         ma->mode |= MA_ZTRANSP|MA_TRANSP;
711                 }
712         }
713         // TRANSPARENT
714         // color
715 //      if (ef->getOpacity().isColor()) {
716 //                      // XXX don't know what to do here
717 //              }
718 //              // texture
719 //              else if (ef->getOpacity().isTexture()) {
720 //                      ctex = ef->getOpacity().getTexture();
721 //                      if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
722 //                      else {
723 //                              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
724 //                              if (mtex != NULL) mtex->mapto = MAP_ALPHA;
725 //                      }
726 //              }
727         material_texture_mapping_map[ma] = texindex_texarray_map;
728 }
729
730 /** When this method is called, the writer must write the effect.
731         \return The writer should return true, if writing succeeded, false otherwise.*/
732
733 bool DocumentImporter::writeEffect( const COLLADAFW::Effect* effect ) 
734 {
735         if(mImportStage!=General)
736                 return true;
737         
738         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
739         
740         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
741                 fprintf(stderr, "Couldn't find a material by UID.\n");
742                 return true;
743         }
744         
745         Material *ma = uid_effect_map[uid];
746         std::map<COLLADAFW::UniqueId, Material*>::iterator  iter;
747         for(iter = uid_material_map.begin(); iter != uid_material_map.end() ; iter++ )
748         {
749                 if ( iter->second == ma ) {
750                         this->FW_object_map[iter->first] = effect;
751                         break;
752                 }
753         }
754         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
755         if (common_efs.getCount() < 1) {
756                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
757                 return true;
758         }
759         // XXX TODO: Take all <profile_common>s
760         // Currently only first <profile_common> is supported
761         COLLADAFW::EffectCommon *ef = common_efs[0];
762         write_profile_COMMON(ef, ma);
763         this->FW_object_map[effect->getUniqueId()] = effect;
764                 
765         return true;
766 }
767
768
769 /** When this method is called, the writer must write the camera.
770         \return The writer should return true, if writing succeeded, false otherwise.*/
771 bool DocumentImporter::writeCamera( const COLLADAFW::Camera* camera ) 
772 {
773         if(mImportStage!=General)
774                 return true;
775                 
776         Camera *cam = NULL;
777         std::string cam_id, cam_name;
778         
779         cam_id = camera->getOriginalId();
780         cam_name = camera->getName();
781         if (cam_name.size()) cam = (Camera*)add_camera((char*)cam_name.c_str());
782         else cam = (Camera*)add_camera((char*)cam_id.c_str());
783         
784         if (!cam) {
785                 fprintf(stderr, "Cannot create camera. \n");
786                 return true;
787         }
788         cam->clipsta = camera->getNearClippingPlane().getValue();
789         cam->clipend = camera->getFarClippingPlane().getValue();
790         
791         COLLADAFW::Camera::CameraType type = camera->getCameraType();
792         switch(type) {
793         case COLLADAFW::Camera::ORTHOGRAPHIC:
794                 {
795                         cam->type = CAM_ORTHO;
796                 }
797                 break;
798         case COLLADAFW::Camera::PERSPECTIVE:
799                 {
800                         cam->type = CAM_PERSP;
801                 }
802                 break;
803         case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
804                 {
805                         fprintf(stderr, "Current camera type is not supported. \n");
806                         cam->type = CAM_PERSP;
807                 }
808                 break;
809         }
810         
811         switch(camera->getDescriptionType()) {
812         case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
813                 {
814                         switch(cam->type) {
815                                 case CAM_ORTHO:
816                                         {
817                                                 double ymag = camera->getYMag().getValue();
818                                                 double aspect = camera->getAspectRatio().getValue();
819                                                 double xmag = aspect*ymag;
820                                                 cam->ortho_scale = (float)xmag;
821                                         }
822                                         break;
823                                 case CAM_PERSP:
824                                 default:
825                                         {
826                                                 double yfov = camera->getYFov().getValue();
827                                                 double aspect = camera->getAspectRatio().getValue();
828                                                 double xfov = aspect*yfov;
829                                                 // xfov is in degrees, cam->lens is in millimiters
830                                                 cam->lens = fov_to_focallength(DEG2RADF(xfov), cam->sensor_x);
831                                         }
832                                         break;
833                         }
834                 }
835                 break;
836         /* XXX correct way to do following four is probably to get also render
837            size and determine proper settings from that somehow */
838         case COLLADAFW::Camera::ASPECTRATIO_AND_X:
839         case COLLADAFW::Camera::SINGLE_X:
840         case COLLADAFW::Camera::X_AND_Y:
841                 {
842                         switch(cam->type) {
843                                 case CAM_ORTHO:
844                                         cam->ortho_scale = (float)camera->getXMag().getValue();
845                                         break;
846                                 case CAM_PERSP:
847                                 default:
848                                         {
849                                                 double x = camera->getXFov().getValue();
850                                                 // x is in degrees, cam->lens is in millimiters
851                                                 cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
852                                         }
853                                         break;
854                         }
855                 }
856                 break;
857         case COLLADAFW::Camera::SINGLE_Y:
858                 {
859                         switch(cam->type) {
860                                 case CAM_ORTHO:
861                                         cam->ortho_scale = (float)camera->getYMag().getValue();
862                                         break;
863                                 case CAM_PERSP:
864                                 default:
865                                         {
866                                         double yfov = camera->getYFov().getValue();
867                                         // yfov is in degrees, cam->lens is in millimiters
868                                         cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
869                                         }
870                                         break;
871                         }
872                 }
873                 break;
874         case COLLADAFW::Camera::UNDEFINED:
875                 // read nothing, use blender defaults.
876                 break;
877         }
878         
879         this->uid_camera_map[camera->getUniqueId()] = cam;
880         this->FW_object_map[camera->getUniqueId()] = camera;
881         // XXX import camera options
882         return true;
883 }
884
885 /** When this method is called, the writer must write the image.
886         \return The writer should return true, if writing succeeded, false otherwise.*/
887 bool DocumentImporter::writeImage( const COLLADAFW::Image* image ) 
888 {
889         if(mImportStage!=General)
890                 return true;
891                 
892         // XXX maybe it is necessary to check if the path is absolute or relative
893         const std::string& filepath = image->getImageURI().toNativePath();
894         const char *filename = (const char*)mFilename.c_str();
895         char dir[FILE_MAX];
896         char full_path[FILE_MAX];
897         
898         BLI_split_dir_part(filename, dir, sizeof(dir));
899         BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
900         Image *ima = BKE_add_image_file(full_path);
901         if (!ima) {
902                 fprintf(stderr, "Cannot create image. \n");
903                 return true;
904         }
905         this->uid_image_map[image->getUniqueId()] = ima;
906         
907         return true;
908 }
909
910 /** When this method is called, the writer must write the light.
911         \return The writer should return true, if writing succeeded, false otherwise.*/
912 bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) 
913 {
914         if(mImportStage!=General)
915                 return true;
916
917         Lamp *lamp = NULL;
918         std::string la_id, la_name;
919
920         TagsMap::iterator etit;
921         ExtraTags *et = 0;
922         etit = uid_tags_map.find(light->getUniqueId().toAscii());
923         if(etit != uid_tags_map.end())
924                 et = etit->second;
925
926         la_id = light->getOriginalId();
927         la_name = light->getName();
928         if (la_name.size()) lamp = (Lamp*)add_lamp((char*)la_name.c_str());
929         else lamp = (Lamp*)add_lamp((char*)la_id.c_str());
930
931         if (!lamp) {
932                 fprintf(stderr, "Cannot create lamp. \n");
933                 return true;
934         }
935
936         // if we find an ExtraTags for this, use that instead.
937         if(et && et->isProfile("blender")) {
938                 et->setData("type", &(lamp->type));
939                 et->setData("flag", &(lamp->flag));
940                 et->setData("mode", &(lamp->mode));
941                 et->setData("gamma", &(lamp->k));
942                 et->setData("red", &(lamp->r));
943                 et->setData("green", &(lamp->g));
944                 et->setData("blue", &(lamp->b));
945                 et->setData("shadow_r", &(lamp->shdwr));
946                 et->setData("shadow_g", &(lamp->shdwg));
947                 et->setData("shadow_b", &(lamp->shdwb));
948                 et->setData("energy", &(lamp->energy));
949                 et->setData("dist", &(lamp->dist));
950                 et->setData("spotsize", &(lamp->spotsize));
951                 et->setData("spotblend", &(lamp->spotblend));
952                 et->setData("halo_intensity", &(lamp->haint));
953                 et->setData("att1", &(lamp->att1));
954                 et->setData("att2", &(lamp->att2));
955                 et->setData("falloff_type", &(lamp->falloff_type));
956                 et->setData("clipsta", &(lamp->clipsta));
957                 et->setData("clipend", &(lamp->clipend));
958                 et->setData("shadspotsize", &(lamp->shadspotsize));
959                 et->setData("bias", &(lamp->bias));
960                 et->setData("soft", &(lamp->soft));
961                 et->setData("compressthresh", &(lamp->compressthresh));
962                 et->setData("bufsize", &(lamp->bufsize));
963                 et->setData("samp", &(lamp->samp));
964                 et->setData("buffers", &(lamp->buffers));
965                 et->setData("filtertype", &(lamp->filtertype));
966                 et->setData("bufflag", &(lamp->bufflag));
967                 et->setData("buftype", &(lamp->buftype));
968                 et->setData("ray_samp", &(lamp->ray_samp));
969                 et->setData("ray_sampy", &(lamp->ray_sampy));
970                 et->setData("ray_sampz", &(lamp->ray_sampz));
971                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
972                 et->setData("area_shape", &(lamp->area_shape));
973                 et->setData("area_size", &(lamp->area_size));
974                 et->setData("area_sizey", &(lamp->area_sizey));
975                 et->setData("area_sizez", &(lamp->area_sizez));
976                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
977                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
978                 et->setData("shadhalostep", &(lamp->shadhalostep));
979                 et->setData("sun_effect_type", &(lamp->shadhalostep));
980                 et->setData("skyblendtype", &(lamp->skyblendtype));
981                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
982                 et->setData("spread", &(lamp->spread));
983                 et->setData("sun_brightness", &(lamp->sun_brightness));
984                 et->setData("sun_size", &(lamp->sun_size));
985                 et->setData("backscattered_light", &(lamp->backscattered_light));
986                 et->setData("sun_intensity", &(lamp->sun_intensity));
987                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
988                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
989                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
990                 et->setData("skyblendfac", &(lamp->skyblendfac));
991                 et->setData("sky_exposure", &(lamp->sky_exposure));
992                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
993         }
994         else {
995                 float constatt = light->getConstantAttenuation().getValue();
996                 float linatt = light->getLinearAttenuation().getValue();
997                 float quadatt = light->getQuadraticAttenuation().getValue();
998                 float d = 25.0f;
999                 float att1 = 0.0f;
1000                 float att2 = 0.0f;
1001                 float e = 1.0f;
1002
1003                 if (light->getColor().isValid()) {
1004                         COLLADAFW::Color col = light->getColor();
1005                         lamp->r = col.getRed();
1006                         lamp->g = col.getGreen();
1007                         lamp->b = col.getBlue();
1008                 }
1009
1010                 if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1011                         att2 = quadatt;
1012                         d = sqrt(1.0f/quadatt);
1013                 }
1014                 // linear light
1015                 else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1016                         att1 = linatt;
1017                         d = (1.0f/linatt);
1018                 }
1019                 else if (IS_EQ(constatt, 1.0f)) {
1020                         att1 = 1.0f;
1021                 }
1022                 else {
1023                         // assuming point light (const att = 1.0);
1024                         att1 = 1.0f;
1025                 }
1026                 
1027                 d *= ( 1.0f / unit_converter.getLinearMeter());
1028
1029                 lamp->energy = e;
1030                 lamp->dist = d;
1031
1032                 COLLADAFW::Light::LightType type = light->getLightType();
1033                 switch(type) {
1034                         case COLLADAFW::Light::AMBIENT_LIGHT:
1035                                 {
1036                                         lamp->type = LA_HEMI;
1037                                 }
1038                                 break;
1039                         case COLLADAFW::Light::SPOT_LIGHT:
1040                                 {
1041                                         lamp->type = LA_SPOT;
1042                                         lamp->att1 = att1;
1043                                         lamp->att2 = att2;
1044                                         if(IS_EQ(att1, 0.0f) && att2 > 0)
1045                                                 lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1046                                         if(IS_EQ(att2, 0.0f) && att1 > 0)
1047                                                 lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1048                                         lamp->spotsize = light->getFallOffAngle().getValue();
1049                                         lamp->spotblend = light->getFallOffExponent().getValue();
1050                                 }
1051                                 break;
1052                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1053                                 {
1054                                         /* our sun is very strong, so pick a smaller energy level */
1055                                         lamp->type = LA_SUN;
1056                                         lamp->mode |= LA_NO_SPEC;
1057                                 }
1058                                 break;
1059                         case COLLADAFW::Light::POINT_LIGHT:
1060                                 {
1061                                         lamp->type = LA_LOCAL;
1062                                         lamp->att1 = att1;
1063                                         lamp->att2 = att2;
1064                                         if(IS_EQ(att1, 0.0f) && att2 > 0)
1065                                                 lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1066                                         if(IS_EQ(att2, 0.0f) && att1 > 0)
1067                                                 lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1068                                 }
1069                                 break;
1070                         case COLLADAFW::Light::UNDEFINED:
1071                                 {
1072                                         fprintf(stderr, "Current lamp type is not supported. \n");
1073                                         lamp->type = LA_LOCAL;
1074                                 }
1075                                 break;
1076                 }
1077         }
1078
1079         this->uid_lamp_map[light->getUniqueId()] = lamp;
1080         this->FW_object_map[light->getUniqueId()] = light;
1081         return true;
1082 }
1083
1084 // this function is called only for animations that pass COLLADAFW::validate
1085 bool DocumentImporter::writeAnimation( const COLLADAFW::Animation* anim ) 
1086 {
1087         if(mImportStage!=General)
1088                 return true;
1089                 
1090         // return true;
1091         return anim_importer.write_animation(anim);
1092 }
1093
1094 // called on post-process stage after writeVisualScenes
1095 bool DocumentImporter::writeAnimationList( const COLLADAFW::AnimationList* animationList ) 
1096 {
1097         if(mImportStage!=General)
1098                 return true;
1099                 
1100         // return true;
1101         return anim_importer.write_animation_list(animationList);
1102 }
1103
1104 /** When this method is called, the writer must write the skin controller data.
1105         \return The writer should return true, if writing succeeded, false otherwise.*/
1106 bool DocumentImporter::writeSkinControllerData( const COLLADAFW::SkinControllerData* skin ) 
1107 {
1108         return armature_importer.write_skin_controller_data(skin);
1109 }
1110
1111 // this is called on postprocess, before writeVisualScenes
1112 bool DocumentImporter::writeController( const COLLADAFW::Controller* controller ) 
1113 {
1114         if(mImportStage!=General)
1115                 return true;
1116                 
1117         return armature_importer.write_controller(controller);
1118 }
1119
1120 bool DocumentImporter::writeFormulas( const COLLADAFW::Formulas* formulas )
1121 {
1122         return true;
1123 }
1124
1125 bool DocumentImporter::writeKinematicsScene( const COLLADAFW::KinematicsScene* kinematicsScene )
1126 {
1127         return true;
1128 }
1129
1130 ExtraTags* DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1131 {
1132         if(uid_tags_map.find(uid.toAscii())==uid_tags_map.end()) {
1133                 return NULL;
1134         }
1135         return uid_tags_map[uid.toAscii()];
1136 }
1137
1138 bool DocumentImporter::addExtraTags( const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1139 {
1140         uid_tags_map[uid.toAscii()] = extra_tags;
1141         return true;
1142 }
1143