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