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