|
Blender
V2.59
|
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