Blender V2.61 - r43446

DocumentImporter.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00027 // TODO:
00028 // * name imported objects
00029 // * import object rotation as euler
00030 
00031 #include <string>
00032 #include <map>
00033 #include <algorithm> // sort()
00034 
00035 #include "COLLADAFWRoot.h"
00036 #include "COLLADAFWStableHeaders.h"
00037 #include "COLLADAFWColorOrTexture.h"
00038 #include "COLLADAFWIndexList.h"
00039 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
00040 #include "COLLADAFWPolygons.h"
00041 #include "COLLADAFWSampler.h"
00042 #include "COLLADAFWTypes.h"
00043 #include "COLLADAFWVisualScene.h"
00044 #include "COLLADAFWArrayPrimitiveType.h"
00045 #include "COLLADAFWLibraryNodes.h"
00046 #include "COLLADAFWCamera.h"
00047 #include "COLLADAFWLight.h"
00048 
00049 #include "COLLADASaxFWLLoader.h"
00050 #include "COLLADASaxFWLIExtraDataCallbackHandler.h"
00051 
00052 #include "BLI_listbase.h"
00053 #include "BLI_math.h"
00054 #include "BLI_string.h"
00055 #include "BLI_utildefines.h"
00056 
00057 #include "BKE_camera.h"
00058 #include "BKE_main.h"
00059 #include "BKE_lamp.h"
00060 #include "BKE_library.h"
00061 #include "BKE_texture.h"
00062 #include "BKE_fcurve.h"
00063 #include "BKE_depsgraph.h"
00064 #include "BLI_path_util.h"
00065 #include "BKE_scene.h"
00066 #include "BKE_global.h"
00067 #include "BKE_material.h"
00068 #include "BKE_utildefines.h"
00069 #include "BKE_image.h"
00070 
00071 #include "DNA_camera_types.h"
00072 #include "DNA_lamp_types.h"
00073 
00074 #include "RNA_access.h"
00075 
00076 #include "MEM_guardedalloc.h"
00077 
00078 #include "ExtraHandler.h"
00079 #include "ErrorHandler.h"
00080 #include "DocumentImporter.h"
00081 #include "TransformReader.h"
00082 
00083 #include "collada_internal.h"
00084 #include "collada_utils.h"
00085 
00086 
00087 /*
00088   COLLADA Importer limitations:
00089   - no multiple scene import, all objects are added to active scene
00090  */
00091 
00092 // #define COLLADA_DEBUG
00093 // creates empties for each imported bone on layer 2, for debugging
00094 // #define ARMATURE_TEST
00095 
00096 DocumentImporter::DocumentImporter(bContext *C, const char *filename) :
00097     mImportStage(General),
00098     mFilename(filename),
00099     mContext(C),
00100     armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
00101     mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
00102     anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
00103 {}
00104 
00105 DocumentImporter::~DocumentImporter()
00106 {
00107     TagsMap::iterator etit;
00108     etit = uid_tags_map.begin();
00109     while(etit!=uid_tags_map.end()) {
00110         delete etit->second;
00111         etit++;
00112     }
00113 }
00114 
00115 bool DocumentImporter::import()
00116 {
00117     ErrorHandler errorHandler;
00118     COLLADASaxFWL::Loader loader(&errorHandler);
00119     COLLADAFW::Root root(&loader, this);
00120     ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
00121     
00122     loader.registerExtraDataCallbackHandler(ehandler);
00123 
00124     if (!root.loadDocument(mFilename))
00125         return false;
00126     
00127     if(errorHandler.hasError())
00128         return false;
00129     
00132     mImportStage = Controller;
00133     
00134     COLLADASaxFWL::Loader loader2;
00135     COLLADAFW::Root root2(&loader2, this);
00136     
00137     if (!root2.loadDocument(mFilename))
00138         return false;
00139     
00140     
00141     delete ehandler;
00142 
00143     return true;
00144 }
00145 
00146 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
00147 {
00148     // TODO: if possible show error info
00149     //
00150     // Should we get rid of invisible Meshes that were created so far
00151     // or maybe create objects at coordinate space origin?
00152     //
00153     // The latter sounds better.
00154 }
00155 
00156 void DocumentImporter::start(){}
00157 
00158 void DocumentImporter::finish()
00159 {
00160     if(mImportStage!=General)
00161         return;
00162         
00164     std::vector<const COLLADAFW::VisualScene*>::iterator it;
00165     for (it = vscenes.begin(); it != vscenes.end(); it++) {
00166         PointerRNA sceneptr, unit_settings;
00167         PropertyRNA *system, *scale;
00168         // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
00169         Scene *sce = CTX_data_scene(mContext);
00170         
00171         // for scene unit settings: system, scale_length
00172         RNA_id_pointer_create(&sce->id, &sceneptr);
00173         unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
00174         system = RNA_struct_find_property(&unit_settings, "system");
00175         scale = RNA_struct_find_property(&unit_settings, "scale_length");
00176         
00177         switch(unit_converter.isMetricSystem()) {
00178             case UnitConverter::Metric:
00179                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
00180                 break;
00181             case UnitConverter::Imperial:
00182                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
00183                 break;
00184             default:
00185                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
00186                 break;
00187         }
00188         RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter());
00189         
00190         const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
00191 
00192         for (unsigned int i = 0; i < roots.getCount(); i++) {
00193             write_node(roots[i], NULL, sce, NULL, false);
00194         }
00195     }
00196     armature_importer.set_tags_map(this->uid_tags_map);
00197     armature_importer.make_armatures(mContext);
00198 
00199 #if 0
00200     armature_importer.fix_animation();
00201 #endif
00202 
00203     for (std::vector<const COLLADAFW::VisualScene*>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
00204         const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
00205 
00206         for (unsigned int i = 0; i < roots.getCount(); i++)
00207             translate_anim_recursive(roots[i],NULL,NULL);
00208     }
00209 
00210     if (libnode_ob.size()) {
00211         Scene *sce = CTX_data_scene(mContext);
00212 
00213         fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
00214         // free all library_nodes
00215         std::vector<Object*>::iterator it;
00216         for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
00217             Object *ob = *it;
00218 
00219             Base *base = object_in_scene(ob, sce);
00220             if (base) {
00221                 BLI_remlink(&sce->base, base);
00222                 free_libblock_us(&G.main->object, base->object);
00223                 if (sce->basact==base)
00224                     sce->basact= NULL;
00225                 MEM_freeN(base);
00226             }
00227         }
00228         libnode_ob.clear();
00229 
00230         DAG_scene_sort(CTX_data_main(mContext), sce);
00231         DAG_ids_flush_update(CTX_data_main(mContext), 0);
00232     }
00233 }
00234 
00235 
00236 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
00237 {
00238     if (par && par->getType() == COLLADAFW::Node::JOINT) {
00239         // par is root if there's no corresp. key in root_map
00240         if (root_map.find(par->getUniqueId()) == root_map.end())
00241             root_map[node->getUniqueId()] = par;
00242         else
00243             root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
00244     }
00245 
00246     /*COLLADAFW::Transformation::TransformationType types[] = {
00247         COLLADAFW::Transformation::ROTATE,
00248         COLLADAFW::Transformation::SCALE,
00249         COLLADAFW::Transformation::TRANSLATE,
00250         COLLADAFW::Transformation::MATRIX
00251     };
00252 
00253     Object *ob;*/
00254     unsigned int i;
00255 
00256     //for (i = 0; i < 4; i++)
00257         //ob = 
00258     anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
00259 
00260     COLLADAFW::NodePointerArray &children = node->getChildNodes();
00261     for (i = 0; i < children.getCount(); i++) {
00262         translate_anim_recursive(children[i], node, NULL);
00263     }
00264 }
00265 
00268 bool DocumentImporter::writeGlobalAsset ( const COLLADAFW::FileInfo* asset ) 
00269 {
00270     unit_converter.read_asset(asset);
00271 
00272     return true;
00273 }
00274 
00277 bool DocumentImporter::writeScene ( const COLLADAFW::Scene* scene ) 
00278 {
00279     // XXX could store the scene id, but do nothing for now
00280     return true;
00281 }
00282 Object* DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
00283 {
00284     const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
00285     if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { 
00286         fprintf(stderr, "Couldn't find camera by UID.\n");
00287         return NULL;
00288     }
00289     Object *ob = add_object(sce, OB_CAMERA);
00290     Camera *cam = uid_camera_map[cam_uid];
00291     Camera *old_cam = (Camera*)ob->data;
00292     ob->data = cam;
00293     old_cam->id.us--;
00294     if (old_cam->id.us == 0)
00295         free_libblock(&G.main->camera, old_cam);
00296     return ob;
00297 }
00298 
00299 Object* DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
00300 {
00301     const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
00302     if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {    
00303         fprintf(stderr, "Couldn't find lamp by UID. \n");
00304         return NULL;
00305     }
00306     Object *ob = add_object(sce, OB_LAMP);
00307     Lamp *la = uid_lamp_map[lamp_uid];
00308     Lamp *old_lamp = (Lamp*)ob->data;
00309     ob->data = la;
00310     old_lamp->id.us--;
00311     if (old_lamp->id.us == 0)
00312         free_libblock(&G.main->lamp, old_lamp);
00313     return ob;
00314 }
00315 
00316 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)
00317 {
00318     Object *obn = copy_object(source_ob);
00319     obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
00320     scene_add_base(sce, obn);
00321 
00322     if (instance_node) {
00323         anim_importer.read_node_transform(instance_node, obn);
00324         // if we also have a source_node (always ;), take its
00325         // transformation matrix and apply it to the newly instantiated
00326         // object to account for node hierarchy transforms in
00327         // .dae
00328         if(source_node) {
00329             COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
00330             COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
00331             float mat[4][4];
00332             for (int i = 0; i < 4; i++) {
00333                 for (int j = 0; j < 4; j++) {
00334                     mat[i][j] = bmat4[i][j];
00335                 }
00336             }
00337             // calc new matrix and apply
00338             mult_m4_m4m4(obn->obmat, obn->obmat, mat);
00339             object_apply_mat4(obn, obn->obmat, 0, 0);
00340         }
00341     }
00342     else {
00343         anim_importer.read_node_transform(source_node, obn);
00344     }
00345 
00346     DAG_scene_sort(CTX_data_main(mContext), sce);
00347     DAG_ids_flush_update(CTX_data_main(mContext), 0);
00348 
00349     COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
00350     if (children.getCount()) {
00351         for (unsigned int i = 0; i < children.getCount(); i++) {
00352             COLLADAFW::Node *child_node = children[i];
00353             const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
00354             if (object_map.find(child_id) == object_map.end())
00355                 continue;
00356             COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
00357             Object *new_child = NULL;
00358             if (inodes.getCount()) { // \todo loop through instance nodes
00359                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
00360                 new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, NULL, is_library_node);
00361             }
00362             else {
00363                 new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, NULL, is_library_node);
00364             }
00365             bc_set_parent(new_child, obn, mContext, true);
00366 
00367             if (is_library_node)
00368                 libnode_ob.push_back(new_child);
00369         }
00370     }
00371 
00372     // when we have an instance_node, don't return the object, because otherwise
00373     // its correct location gets overwritten in write_node(). Fixes bug #26012.
00374     if(instance_node) {
00375         if (par_ob && obn)
00376             bc_set_parent(obn, par_ob, mContext);
00377         return NULL;
00378     }
00379 
00380     else return obn;
00381 }
00382 
00383 void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
00384 {
00385     Object *ob = NULL;
00386     bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
00387 
00388     if (is_joint) {
00389         if ( par ) {
00390         Object * empty = par;
00391         par = add_object(sce, OB_ARMATURE);
00392         bc_set_parent(par,empty->parent, mContext);
00393         //remove empty : todo
00394         object_map[parent_node->getUniqueId()] = par;
00395         }
00396         armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
00397     }
00398     else {
00399         COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
00400         COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
00401         COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
00402         COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
00403         COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
00404         size_t geom_done = 0;
00405         size_t camera_done = 0;
00406         size_t lamp_done = 0;
00407         size_t controller_done = 0;
00408         size_t inst_done = 0;
00409 
00410         // XXX linking object with the first <instance_geometry>, though a node may have more of them...
00411         // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
00412         // <instance_geometry>
00413         while (geom_done < geom.getCount()) {
00414             ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
00415                                                   material_texture_mapping_map);
00416             ++geom_done;
00417         }
00418         while (camera_done < camera.getCount()) {
00419             ob = create_camera_object(camera[camera_done], sce);
00420             ++camera_done;
00421         }
00422         while (lamp_done < lamp.getCount()) {
00423             ob = create_lamp_object(lamp[lamp_done], sce);
00424             ++lamp_done;
00425         }
00426         while (controller_done < controller.getCount()) {
00427             COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry*)controller[controller_done];
00428             ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
00429             ++controller_done;
00430         }
00431         // XXX instance_node is not supported yet
00432         while (inst_done < inst_node.getCount()) {
00433             const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
00434             if (object_map.find(node_id) == object_map.end()) {
00435                 fprintf(stderr, "Cannot find node to instanciate.\n");
00436                 ob = NULL;
00437             }
00438             else {
00439                 Object *source_ob = object_map[node_id];
00440                 COLLADAFW::Node *source_node = node_map[node_id];
00441 
00442                 ob = create_instance_node(source_ob, source_node, node, sce, par, is_library_node);
00443             }
00444             ++inst_done;
00445         }
00446         // if node is empty - create empty object
00447         // XXX empty node may not mean it is empty object, not sure about this
00448         if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
00449             ob = add_object(sce, OB_EMPTY);
00450         }
00451         
00452         // check if object is not NULL
00453         if (!ob) return;
00454         
00455         std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
00456         rename_id(&ob->id, (char*)nodename.c_str());
00457 
00458         object_map[node->getUniqueId()] = ob;
00459         node_map[node->getUniqueId()] = node;
00460 
00461         if (is_library_node)
00462             libnode_ob.push_back(ob);
00463     }
00464 
00465     anim_importer.read_node_transform(node, ob); // overwrites location set earlier
00466 
00467     if (!is_joint) {
00468         // if par was given make this object child of the previous 
00469         if (par && ob)
00470             bc_set_parent(ob, par, mContext);
00471     }
00472 
00473     // if node has child nodes write them
00474     COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
00475     for (unsigned int i = 0; i < child_nodes.getCount(); i++) { 
00476         write_node(child_nodes[i], node, sce, ob, is_library_node);
00477     }
00478 }
00479 
00482 bool DocumentImporter::writeVisualScene ( const COLLADAFW::VisualScene* visualScene ) 
00483 {
00484     if(mImportStage!=General)
00485         return true;
00486         
00487     // this method called on post process after writeGeometry, writeMaterial, etc.
00488 
00489     // for each <node> in <visual_scene>:
00490     // create an Object
00491     // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
00492 
00493     // update: since we cannot link a Mesh with Object in
00494     // writeGeometry because <geometry> does not reference <node>,
00495     // we link Objects with Meshes here
00496 
00497     vscenes.push_back(visualScene);
00498     
00499     return true;
00500 }
00501 
00505 bool DocumentImporter::writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes ) 
00506 {
00507     if(mImportStage!=General)
00508         return true;
00509         
00510     Scene *sce = CTX_data_scene(mContext);
00511 
00512     const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
00513 
00514     for (unsigned int i = 0; i < nodes.getCount(); i++) {
00515         write_node(nodes[i], NULL, sce, NULL, true);
00516     }
00517 
00518     return true;
00519 }
00520 
00523 bool DocumentImporter::writeGeometry ( const COLLADAFW::Geometry* geom ) 
00524 {
00525     if(mImportStage!=General)
00526         return true;
00527         
00528     return mesh_importer.write_geometry(geom);
00529 }
00530 
00533 bool DocumentImporter::writeMaterial( const COLLADAFW::Material* cmat ) 
00534 {
00535     if(mImportStage!=General)
00536         return true;
00537         
00538     const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
00539     Material *ma = add_material((char*)str_mat_id.c_str());
00540     
00541     this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
00542     this->uid_material_map[cmat->getUniqueId()] = ma;
00543     
00544     return true;
00545 }
00546 
00547 // create mtex, create texture, set texture image
00548 MTex* DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
00549                      int i, TexIndexTextureArrayMap &texindex_texarray_map)
00550 {
00551     COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
00552     COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
00553         
00554     const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
00555     
00556     if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
00557         fprintf(stderr, "Couldn't find an image by UID.\n");
00558         return NULL;
00559     }
00560     
00561     ma->mtex[i] = add_mtex();
00562     ma->mtex[i]->texco = TEXCO_UV;
00563     ma->mtex[i]->tex = add_texture("Texture");
00564     ma->mtex[i]->tex->type = TEX_IMAGE;
00565     ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
00566     ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
00567     
00568     texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
00569     
00570     return ma->mtex[i];
00571 }
00572 
00573 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
00574 {
00575     COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
00576     
00577     // blinn
00578     if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
00579         ma->spec_shader = MA_SPEC_BLINN;
00580         ma->spec = ef->getShininess().getFloatValue();
00581     }
00582     // phong
00583     else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
00584         ma->spec_shader = MA_SPEC_PHONG;
00585         ma->har = ef->getShininess().getFloatValue();
00586     }
00587     // lambert
00588     else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
00589         ma->diff_shader = MA_DIFF_LAMBERT;
00590     }
00591     // default - lambert
00592     else {
00593         ma->diff_shader = MA_DIFF_LAMBERT;
00594         fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
00595     }
00596     // reflectivity
00597     ma->ray_mirror = ef->getReflectivity().getFloatValue();
00598     // index of refraction
00599     ma->ang = ef->getIndexOfRefraction().getFloatValue();
00600     
00601     int i = 0;
00602     COLLADAFW::Color col;
00603     MTex *mtex = NULL;
00604     TexIndexTextureArrayMap texindex_texarray_map;
00605     
00606     // DIFFUSE
00607     // color
00608     if (ef->getDiffuse().isColor()) {
00609         col = ef->getDiffuse().getColor();
00610         ma->r = col.getRed();
00611         ma->g = col.getGreen();
00612         ma->b = col.getBlue();
00613     }
00614     // texture
00615     else if (ef->getDiffuse().isTexture()) {
00616         COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
00617         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00618         if (mtex != NULL) {
00619             mtex->mapto = MAP_COL;
00620             ma->texact = (int)i;
00621             i++;
00622         }
00623     }
00624     // AMBIENT
00625     // color
00626     if (ef->getAmbient().isColor()) {
00627         col = ef->getAmbient().getColor();
00628         ma->ambr = col.getRed();
00629         ma->ambg = col.getGreen();
00630         ma->ambb = col.getBlue();
00631     }
00632     // texture
00633     else if (ef->getAmbient().isTexture()) {
00634         COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
00635         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00636         if (mtex != NULL) {
00637             mtex->mapto = MAP_AMB; 
00638             i++;
00639         }
00640     }
00641     // SPECULAR
00642     // color
00643     if (ef->getSpecular().isColor()) {
00644         col = ef->getSpecular().getColor();
00645         ma->specr = col.getRed();
00646         ma->specg = col.getGreen();
00647         ma->specb = col.getBlue();
00648     }
00649     // texture
00650     else if (ef->getSpecular().isTexture()) {
00651         COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
00652         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00653         if (mtex != NULL) {
00654             mtex->mapto = MAP_SPEC; 
00655             i++;
00656         }
00657     }
00658     // REFLECTIVE
00659     // color
00660     if (ef->getReflective().isColor()) {
00661         col = ef->getReflective().getColor();
00662         ma->mirr = col.getRed();
00663         ma->mirg = col.getGreen();
00664         ma->mirb = col.getBlue();
00665     }
00666     // texture
00667     else if (ef->getReflective().isTexture()) {
00668         COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
00669         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00670         if (mtex != NULL) {
00671             mtex->mapto = MAP_REF; 
00672             i++;
00673         }
00674     }
00675     // EMISSION
00676     // color
00677     if (ef->getEmission().isColor()) {
00678         // XXX there is no emission color in blender
00679         // but I am not sure
00680     }
00681     // texture
00682     else if (ef->getEmission().isTexture()) {
00683         COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
00684         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00685         if (mtex != NULL) {
00686             mtex->mapto = MAP_EMIT; 
00687             i++;
00688         }
00689     }
00690     
00691     if(ef->getOpacity().isTexture()) {
00692         COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
00693         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00694         if(mtex != NULL) {
00695             mtex->mapto = MAP_ALPHA;
00696             mtex->tex->imaflag |= TEX_USEALPHA;
00697             i++;
00698             ma->spectra = ma->alpha = 0;
00699             ma->mode |= MA_ZTRANSP|MA_TRANSP;
00700         }
00701     }
00702     // TRANSPARENT
00703     // color
00704 //  if (ef->getOpacity().isColor()) {
00705 //          // XXX don't know what to do here
00706 //      }
00707 //      // texture
00708 //      else if (ef->getOpacity().isTexture()) {
00709 //          ctex = ef->getOpacity().getTexture();
00710 //          if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
00711 //          else {
00712 //              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
00713 //              if (mtex != NULL) mtex->mapto = MAP_ALPHA;
00714 //          }
00715 //      }
00716     material_texture_mapping_map[ma] = texindex_texarray_map;
00717 }
00718 
00722 bool DocumentImporter::writeEffect( const COLLADAFW::Effect* effect ) 
00723 {
00724     if(mImportStage!=General)
00725         return true;
00726     
00727     const COLLADAFW::UniqueId& uid = effect->getUniqueId();
00728     
00729     if (uid_effect_map.find(uid) == uid_effect_map.end()) {
00730         fprintf(stderr, "Couldn't find a material by UID.\n");
00731         return true;
00732     }
00733     
00734     Material *ma = uid_effect_map[uid];
00735     std::map<COLLADAFW::UniqueId, Material*>::iterator  iter;
00736     for(iter = uid_material_map.begin(); iter != uid_material_map.end() ; iter++ )
00737     {
00738         if ( iter->second == ma ) {
00739             this->FW_object_map[iter->first] = effect;
00740             break;
00741         }
00742     }
00743     COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
00744     if (common_efs.getCount() < 1) {
00745         fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
00746         return true;
00747     }
00748     // XXX TODO: Take all <profile_common>s
00749     // Currently only first <profile_common> is supported
00750     COLLADAFW::EffectCommon *ef = common_efs[0];
00751     write_profile_COMMON(ef, ma);
00752     this->FW_object_map[effect->getUniqueId()] = effect;
00753         
00754     return true;
00755 }
00756 
00757 
00760 bool DocumentImporter::writeCamera( const COLLADAFW::Camera* camera ) 
00761 {
00762     if(mImportStage!=General)
00763         return true;
00764         
00765     Camera *cam = NULL;
00766     std::string cam_id, cam_name;
00767     
00768     cam_id = camera->getOriginalId();
00769     cam_name = camera->getName();
00770     if (cam_name.size()) cam = (Camera*)add_camera((char*)cam_name.c_str());
00771     else cam = (Camera*)add_camera((char*)cam_id.c_str());
00772     
00773     if (!cam) {
00774         fprintf(stderr, "Cannot create camera. \n");
00775         return true;
00776     }
00777     cam->clipsta = camera->getNearClippingPlane().getValue();
00778     cam->clipend = camera->getFarClippingPlane().getValue();
00779     
00780     COLLADAFW::Camera::CameraType type = camera->getCameraType();
00781     switch(type) {
00782     case COLLADAFW::Camera::ORTHOGRAPHIC:
00783         {
00784             cam->type = CAM_ORTHO;
00785         }
00786         break;
00787     case COLLADAFW::Camera::PERSPECTIVE:
00788         {
00789             cam->type = CAM_PERSP;
00790         }
00791         break;
00792     case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
00793         {
00794             fprintf(stderr, "Current camera type is not supported. \n");
00795             cam->type = CAM_PERSP;
00796         }
00797         break;
00798     }
00799     
00800     switch(camera->getDescriptionType()) {
00801     case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
00802         {
00803             switch(cam->type) {
00804                 case CAM_ORTHO:
00805                     {
00806                         double ymag = camera->getYMag().getValue();
00807                         double aspect = camera->getAspectRatio().getValue();
00808                         double xmag = aspect*ymag;
00809                         cam->ortho_scale = (float)xmag;
00810                     }
00811                     break;
00812                 case CAM_PERSP:
00813                 default:
00814                     {
00815                         double yfov = camera->getYFov().getValue();
00816                         double aspect = camera->getAspectRatio().getValue();
00817                         double xfov = aspect*yfov;
00818                         // xfov is in degrees, cam->lens is in millimiters
00819                         cam->lens = fov_to_focallength(DEG2RADF(xfov), cam->sensor_x);
00820                     }
00821                     break;
00822             }
00823         }
00824         break;
00825     /* XXX correct way to do following four is probably to get also render
00826        size and determine proper settings from that somehow */
00827     case COLLADAFW::Camera::ASPECTRATIO_AND_X:
00828     case COLLADAFW::Camera::SINGLE_X:
00829     case COLLADAFW::Camera::X_AND_Y:
00830         {
00831             switch(cam->type) {
00832                 case CAM_ORTHO:
00833                     cam->ortho_scale = (float)camera->getXMag().getValue();
00834                     break;
00835                 case CAM_PERSP:
00836                 default:
00837                     {
00838                         double x = camera->getXFov().getValue();
00839                         // x is in degrees, cam->lens is in millimiters
00840                         cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
00841                     }
00842                     break;
00843             }
00844         }
00845         break;
00846     case COLLADAFW::Camera::SINGLE_Y:
00847         {
00848             switch(cam->type) {
00849                 case CAM_ORTHO:
00850                     cam->ortho_scale = (float)camera->getYMag().getValue();
00851                     break;
00852                 case CAM_PERSP:
00853                 default:
00854                     {
00855                     double yfov = camera->getYFov().getValue();
00856                     // yfov is in degrees, cam->lens is in millimiters
00857                     cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
00858                     }
00859                     break;
00860             }
00861         }
00862         break;
00863     case COLLADAFW::Camera::UNDEFINED:
00864         // read nothing, use blender defaults.
00865         break;
00866     }
00867     
00868     this->uid_camera_map[camera->getUniqueId()] = cam;
00869     this->FW_object_map[camera->getUniqueId()] = camera;
00870     // XXX import camera options
00871     return true;
00872 }
00873 
00876 bool DocumentImporter::writeImage( const COLLADAFW::Image* image ) 
00877 {
00878     if(mImportStage!=General)
00879         return true;
00880         
00881     // XXX maybe it is necessary to check if the path is absolute or relative
00882     const std::string& filepath = image->getImageURI().toNativePath();
00883     const char *filename = (const char*)mFilename.c_str();
00884     char dir[FILE_MAX];
00885     char full_path[FILE_MAX];
00886     
00887     BLI_split_dir_part(filename, dir, sizeof(dir));
00888     BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
00889     Image *ima = BKE_add_image_file(full_path);
00890     if (!ima) {
00891         fprintf(stderr, "Cannot create image. \n");
00892         return true;
00893     }
00894     this->uid_image_map[image->getUniqueId()] = ima;
00895     
00896     return true;
00897 }
00898 
00901 bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) 
00902 {
00903     if(mImportStage!=General)
00904         return true;
00905 
00906     Lamp *lamp = NULL;
00907     std::string la_id, la_name;
00908 
00909     TagsMap::iterator etit;
00910     ExtraTags *et = 0;
00911     etit = uid_tags_map.find(light->getUniqueId().toAscii());
00912     if(etit != uid_tags_map.end())
00913         et = etit->second;
00914 
00915     la_id = light->getOriginalId();
00916     la_name = light->getName();
00917     if (la_name.size()) lamp = (Lamp*)add_lamp((char*)la_name.c_str());
00918     else lamp = (Lamp*)add_lamp((char*)la_id.c_str());
00919 
00920     if (!lamp) {
00921         fprintf(stderr, "Cannot create lamp. \n");
00922         return true;
00923     }
00924 
00925     // if we find an ExtraTags for this, use that instead.
00926     if(et && et->isProfile("blender")) {
00927         et->setData("type", &(lamp->type));
00928         et->setData("flag", &(lamp->flag));
00929         et->setData("mode", &(lamp->mode));
00930         et->setData("gamma", &(lamp->k));
00931         et->setData("red", &(lamp->r));
00932         et->setData("green", &(lamp->g));
00933         et->setData("blue", &(lamp->b));
00934         et->setData("shadow_r", &(lamp->shdwr));
00935         et->setData("shadow_g", &(lamp->shdwg));
00936         et->setData("shadow_b", &(lamp->shdwb));
00937         et->setData("energy", &(lamp->energy));
00938         et->setData("dist", &(lamp->dist));
00939         et->setData("spotsize", &(lamp->spotsize));
00940         et->setData("spotblend", &(lamp->spotblend));
00941         et->setData("halo_intensity", &(lamp->haint));
00942         et->setData("att1", &(lamp->att1));
00943         et->setData("att2", &(lamp->att2));
00944         et->setData("falloff_type", &(lamp->falloff_type));
00945         et->setData("clipsta", &(lamp->clipsta));
00946         et->setData("clipend", &(lamp->clipend));
00947         et->setData("shadspotsize", &(lamp->shadspotsize));
00948         et->setData("bias", &(lamp->bias));
00949         et->setData("soft", &(lamp->soft));
00950         et->setData("compressthresh", &(lamp->compressthresh));
00951         et->setData("bufsize", &(lamp->bufsize));
00952         et->setData("samp", &(lamp->samp));
00953         et->setData("buffers", &(lamp->buffers));
00954         et->setData("filtertype", &(lamp->filtertype));
00955         et->setData("bufflag", &(lamp->bufflag));
00956         et->setData("buftype", &(lamp->buftype));
00957         et->setData("ray_samp", &(lamp->ray_samp));
00958         et->setData("ray_sampy", &(lamp->ray_sampy));
00959         et->setData("ray_sampz", &(lamp->ray_sampz));
00960         et->setData("ray_samp_type", &(lamp->ray_samp_type));
00961         et->setData("area_shape", &(lamp->area_shape));
00962         et->setData("area_size", &(lamp->area_size));
00963         et->setData("area_sizey", &(lamp->area_sizey));
00964         et->setData("area_sizez", &(lamp->area_sizez));
00965         et->setData("adapt_thresh", &(lamp->adapt_thresh));
00966         et->setData("ray_samp_method", &(lamp->ray_samp_method));
00967         et->setData("shadhalostep", &(lamp->shadhalostep));
00968         et->setData("sun_effect_type", &(lamp->shadhalostep));
00969         et->setData("skyblendtype", &(lamp->skyblendtype));
00970         et->setData("horizon_brightness", &(lamp->horizon_brightness));
00971         et->setData("spread", &(lamp->spread));
00972         et->setData("sun_brightness", &(lamp->sun_brightness));
00973         et->setData("sun_size", &(lamp->sun_size));
00974         et->setData("backscattered_light", &(lamp->backscattered_light));
00975         et->setData("sun_intensity", &(lamp->sun_intensity));
00976         et->setData("atm_turbidity", &(lamp->atm_turbidity));
00977         et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
00978         et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
00979         et->setData("skyblendfac", &(lamp->skyblendfac));
00980         et->setData("sky_exposure", &(lamp->sky_exposure));
00981         et->setData("sky_colorspace", &(lamp->sky_colorspace));
00982     }
00983     else {
00984         float constatt = light->getConstantAttenuation().getValue();
00985         float linatt = light->getLinearAttenuation().getValue();
00986         float quadatt = light->getQuadraticAttenuation().getValue();
00987         float d = 25.0f;
00988         float att1 = 0.0f;
00989         float att2 = 0.0f;
00990         float e = 1.0f;
00991 
00992         if (light->getColor().isValid()) {
00993             COLLADAFW::Color col = light->getColor();
00994             lamp->r = col.getRed();
00995             lamp->g = col.getGreen();
00996             lamp->b = col.getBlue();
00997         }
00998 
00999         if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
01000             att2 = quadatt;
01001             d = sqrt(1.0f/quadatt);
01002         }
01003         // linear light
01004         else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
01005             att1 = linatt;
01006             d = (1.0f/linatt);
01007         } else if (IS_EQ(constatt, 1.0f)) {
01008             att1 = 1.0f;
01009         } else {
01010             // assuming point light (const att = 1.0);
01011             att1 = 1.0f;
01012         }
01013         
01014         d *= ( 1.0f / unit_converter.getLinearMeter());
01015 
01016         lamp->energy = e;
01017         lamp->dist = d;
01018 
01019         COLLADAFW::Light::LightType type = light->getLightType();
01020         switch(type) {
01021             case COLLADAFW::Light::AMBIENT_LIGHT:
01022                 {
01023                     lamp->type = LA_HEMI;
01024                 }
01025                 break;
01026             case COLLADAFW::Light::SPOT_LIGHT:
01027                 {
01028                     lamp->type = LA_SPOT;
01029                     lamp->att1 = att1;
01030                     lamp->att2 = att2;
01031                     if(IS_EQ(att1, 0.0f) && att2 > 0)
01032                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
01033                     if(IS_EQ(att2, 0.0f) && att1 > 0)
01034                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
01035                     lamp->spotsize = light->getFallOffAngle().getValue();
01036                     lamp->spotblend = light->getFallOffExponent().getValue();
01037                 }
01038                 break;
01039             case COLLADAFW::Light::DIRECTIONAL_LIGHT:
01040                 {
01041                     /* our sun is very strong, so pick a smaller energy level */
01042                     lamp->type = LA_SUN;
01043                     lamp->mode |= LA_NO_SPEC;
01044                 }
01045                 break;
01046             case COLLADAFW::Light::POINT_LIGHT:
01047                 {
01048                     lamp->type = LA_LOCAL;
01049                     lamp->att1 = att1;
01050                     lamp->att2 = att2;
01051                     if(IS_EQ(att1, 0.0f) && att2 > 0)
01052                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
01053                     if(IS_EQ(att2, 0.0f) && att1 > 0)
01054                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
01055                 }
01056                 break;
01057             case COLLADAFW::Light::UNDEFINED:
01058                 {
01059                     fprintf(stderr, "Current lamp type is not supported. \n");
01060                     lamp->type = LA_LOCAL;
01061                 }
01062                 break;
01063         }
01064     }
01065 
01066     this->uid_lamp_map[light->getUniqueId()] = lamp;
01067     this->FW_object_map[light->getUniqueId()] = light;
01068     return true;
01069 }
01070 
01071 // this function is called only for animations that pass COLLADAFW::validate
01072 bool DocumentImporter::writeAnimation( const COLLADAFW::Animation* anim ) 
01073 {
01074     if(mImportStage!=General)
01075         return true;
01076         
01077     // return true;
01078     return anim_importer.write_animation(anim);
01079 }
01080 
01081 // called on post-process stage after writeVisualScenes
01082 bool DocumentImporter::writeAnimationList( const COLLADAFW::AnimationList* animationList ) 
01083 {
01084     if(mImportStage!=General)
01085         return true;
01086         
01087     // return true;
01088     return anim_importer.write_animation_list(animationList);
01089 }
01090 
01093 bool DocumentImporter::writeSkinControllerData( const COLLADAFW::SkinControllerData* skin ) 
01094 {
01095     return armature_importer.write_skin_controller_data(skin);
01096 }
01097 
01098 // this is called on postprocess, before writeVisualScenes
01099 bool DocumentImporter::writeController( const COLLADAFW::Controller* controller ) 
01100 {
01101     if(mImportStage!=General)
01102         return true;
01103         
01104     return armature_importer.write_controller(controller);
01105 }
01106 
01107 bool DocumentImporter::writeFormulas( const COLLADAFW::Formulas* formulas )
01108 {
01109     return true;
01110 }
01111 
01112 bool DocumentImporter::writeKinematicsScene( const COLLADAFW::KinematicsScene* kinematicsScene )
01113 {
01114     return true;
01115 }
01116 
01117 ExtraTags* DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
01118 {
01119     if(uid_tags_map.find(uid.toAscii())==uid_tags_map.end()) {
01120         return NULL;
01121     }
01122     return uid_tags_map[uid.toAscii()];
01123 }
01124 
01125 bool DocumentImporter::addExtraTags( const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
01126 {
01127     uid_tags_map[uid.toAscii()] = extra_tags;
01128     return true;
01129 }
01130