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