diff options
Diffstat (limited to 'source/blender/collada/DocumentImporter.cpp')
-rw-r--r-- | source/blender/collada/DocumentImporter.cpp | 252 |
1 files changed, 186 insertions, 66 deletions
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 084f71e0afc..49db6f033d9 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -54,6 +54,7 @@ extern "C" { #include "BLI_math.h" #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BLI_fileops.h" #include "BKE_camera.h" #include "BKE_main.h" @@ -76,6 +77,9 @@ extern "C" { #include "MEM_guardedalloc.h" +#include "WM_api.h" +#include "WM_types.h" + } #include "ExtraHandler.h" @@ -96,11 +100,11 @@ extern "C" { // creates empties for each imported bone on layer 2, for debugging // #define ARMATURE_TEST -DocumentImporter::DocumentImporter(bContext *C, const char *filename) : +DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) : + import_settings(import_settings), mImportStage(General), - mFilename(filename), mContext(C), - armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)), + armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C)), mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)), anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C)) { @@ -128,7 +132,9 @@ bool DocumentImporter::import() // deselect all to select new objects BKE_scene_base_deselect_all(CTX_data_scene(mContext)); - if (!root.loadDocument(mFilename)) { + std::string mFilename = std::string(this->import_settings->filepath); + const std::string encodedFilename = bc_url_encode(mFilename); + if (!root.loadDocument(encodedFilename)) { fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n"); return false; } @@ -143,7 +149,7 @@ bool DocumentImporter::import() COLLADASaxFWL::Loader loader2; COLLADAFW::Root root2(&loader2, this); - if (!root2.loadDocument(mFilename)) { + if (!root2.loadDocument(encodedFilename)) { fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n"); return false; } @@ -151,7 +157,8 @@ bool DocumentImporter::import() delete ehandler; - mesh_importer.bmeshConversion(); + //XXX No longer needed (geometries are now created as bmesh) + //mesh_importer.bmeshConversion(); return true; } @@ -174,46 +181,68 @@ void DocumentImporter::finish() { if (mImportStage != General) return; - + + Main *bmain = CTX_data_main(mContext); + // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it + Scene *sce = CTX_data_scene(mContext); + /** TODO Break up and put into 2-pass parsing of DAE */ std::vector<const COLLADAFW::VisualScene *>::iterator it; for (it = vscenes.begin(); it != vscenes.end(); it++) { PointerRNA sceneptr, unit_settings; PropertyRNA *system, *scale; - // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it - Scene *sce = CTX_data_scene(mContext); // for scene unit settings: system, scale_length + RNA_id_pointer_create(&sce->id, &sceneptr); unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); system = RNA_struct_find_property(&unit_settings, "system"); scale = RNA_struct_find_property(&unit_settings, "scale_length"); - - switch (unit_converter.isMetricSystem()) { - case UnitConverter::Metric: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC); - break; - case UnitConverter::Imperial: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL); - break; - default: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE); - break; + + if (this->import_settings->import_units) { + + switch (unit_converter.isMetricSystem()) { + case UnitConverter::Metric: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC); + break; + case UnitConverter::Imperial: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL); + break; + default: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE); + break; + } + float unit_factor = unit_converter.getLinearMeter(); + RNA_property_float_set(&unit_settings, scale, unit_factor); + fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor); + } - RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter()); - - const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); + // Write nodes to scene + const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); for (unsigned int i = 0; i < roots.getCount(); i++) { - write_node(roots[i], NULL, sce, NULL, false); + std::vector<Object *> *objects_done; + objects_done = write_node(roots[i], NULL, sce, NULL, false); + + if (!this->import_settings->import_units) { + // Match incoming scene with current unit settings + bc_match_scale(objects_done, *sce, unit_converter); + } } + + // update scene + DAG_relations_tag_update(bmain); + WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL); + } - mesh_importer.optimize_material_assignments(); + mesh_importer.optimize_material_assignements(); armature_importer.set_tags_map(this->uid_tags_map); armature_importer.make_armatures(mContext); + armature_importer.make_shape_keys(); + DAG_relations_tag_update(bmain); #if 0 armature_importer.fix_animation(); @@ -222,8 +251,9 @@ void DocumentImporter::finish() for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) { const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); - for (unsigned int i = 0; i < roots.getCount(); i++) + for (unsigned int i = 0; i < roots.getCount(); i++) { translate_anim_recursive(roots[i], NULL, NULL); + } } if (libnode_ob.size()) { @@ -246,8 +276,7 @@ void DocumentImporter::finish() } libnode_ob.clear(); - DAG_scene_sort(CTX_data_main(mContext), sce); - DAG_ids_flush_update(CTX_data_main(mContext), 0); + DAG_relations_tag_update(bmain); } } @@ -256,7 +285,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW { // The split in #29246, rootmap must point at actual root when - // calculating bones in apply_curves_as_matrix. + // calculating bones in apply_curves_as_matrix. - actual root is the root node. // This has to do with inverse bind poses being world space // (the sources for skinned bones' restposes) and the way // non-skinning nodes have their "restpose" recursively calculated. @@ -265,7 +294,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW if (par) { // && par->getType() == COLLADAFW::Node::JOINT) { // par is root if there's no corresp. key in root_map if (root_map.find(par->getUniqueId()) == root_map.end()) - root_map[node->getUniqueId()] = par; + root_map[node->getUniqueId()] = node; else root_map[node->getUniqueId()] = root_map[par->getUniqueId()]; } @@ -282,13 +311,22 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW #endif unsigned int i; + //for (i = 0; i < 4; i++) // ob = anim_importer.translate_Animations(node, root_map, object_map, FW_object_map); - COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (i = 0; i < children.getCount(); i++) { - translate_anim_recursive(children[i], node, NULL); + if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) { + // For Skeletons without root node we have to simulate the + // root node here and recursively enter the same function + // XXX: maybe this can be made more elegant. + translate_anim_recursive(node, node, parob); + } + else { + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + for (i = 0; i < children.getCount(); i++) { + translate_anim_recursive(children[i], node, NULL); + } } } @@ -349,7 +387,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL); Object *obn = BKE_object_copy(source_ob); - obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); BKE_scene_base_add(sce, obn); if (instance_node) { @@ -376,8 +414,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod anim_importer.read_node_transform(source_node, obn); } - DAG_scene_sort(CTX_data_main(mContext), sce); - DAG_ids_flush_update(CTX_data_main(mContext), 0); + /*DAG_relations_tag_update(CTX_data_main(mContext));*/ COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); if (children.getCount()) { @@ -406,23 +443,50 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod return obn; } -void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) +// to create constraints off node <extra> tags. Assumes only constraint data in +// current <extra> with blender profile. +void DocumentImporter::create_constraints(ExtraTags *et, Object *ob) +{ + if (et && et->isProfile("blender")) { + std::string name; + short* type = 0; + et->setData("type", type); + BKE_add_ob_constraint(ob, "Test_con", *type); + + } +} + +std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) { Object *ob = NULL; bool is_joint = node->getType() == COLLADAFW::Node::JOINT; bool read_transform = true; + std::string id = node->getOriginalId(); + std::string name = node->getName(); std::vector<Object *> *objects_done = new std::vector<Object *>(); + fprintf(stderr, + "Writing node id='%s', name='%s'\n", + id.c_str(), + name.c_str()); + if (is_joint) { - if (par) { - Object *empty = par; - par = bc_add_object(sce, OB_ARMATURE, NULL); - bc_set_parent(par, empty->parent, mContext); - //remove empty : todo - object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(parent_node->getUniqueId(), par)); + if (parent_node == NULL) { + // A Joint on root level is a skeleton without root node. + // Here we add the armature "on the fly": + par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str()); + objects_done->push_back(par); + object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par)); + node_map[node->getUniqueId()] = node; } armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce); + + if (parent_node == NULL) { + // for skeletons without root node all has been done above. + // Skeletons with root node are handled further down. + return objects_done; + } } else { COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); @@ -442,13 +506,21 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent while (geom_done < geom.getCount()) { ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map, material_texture_mapping_map); - objects_done->push_back(ob); + if (ob == NULL) { + fprintf(stderr, + "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n", + id.c_str(), + name.c_str()); + } + else { + objects_done->push_back(ob); + } ++geom_done; } while (camera_done < camera.getCount()) { ob = create_camera_object(camera[camera_done], sce); if (ob == NULL) { - std::string id = node->getOriginalId(); + std::string id = node->getOriginalId(); std::string name = node->getName(); fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str()); } @@ -487,16 +559,25 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent read_transform = false; } + // if node is empty - create empty object // XXX empty node may not mean it is empty object, not sure about this if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { - ob = bc_add_object(sce, OB_EMPTY, NULL); + //Check if Object is armature, by checking if immediate child is a JOINT node. + if (is_armature(node)) { + ob = bc_add_object(sce, OB_ARMATURE, name.c_str()); + } + else { + ob = bc_add_object(sce, OB_EMPTY, NULL); + } objects_done->push_back(ob); + } // XXX: if there're multiple instances, only one is stored - if (!ob) return; + if (!ob) return objects_done; + for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { ob = *it; std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); @@ -508,6 +589,9 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent libnode_ob.push_back(ob); } + + //create_constraints(et,ob); + } for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { @@ -524,9 +608,19 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent } // if node has child nodes write them COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); + + if (objects_done->size() > 0) { + ob = *objects_done->begin(); + } + else { + ob = NULL; + } + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { write_node(child_nodes[i], node, sce, ob, is_library_node); } + + return objects_done; } /** When this method is called, the writer must write the entire visual scene. @@ -588,7 +682,7 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat) return true; const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId(); - Material *ma = BKE_material_add((char *)str_mat_id.c_str()); + Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str()); this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; this->uid_material_map[cmat->getUniqueId()] = ma; @@ -612,9 +706,8 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T ma->mtex[i] = add_mtex(); ma->mtex[i]->texco = TEXCO_UV; - ma->mtex[i]->tex = add_texture("Texture"); + ma->mtex[i]->tex = add_texture(G.main, "Texture"); ma->mtex[i]->tex->type = TEX_IMAGE; - ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA; ma->mtex[i]->tex->ima = uid_image_map[ima_uid]; texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]); @@ -745,7 +838,6 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); if (mtex != NULL) { mtex->mapto = MAP_ALPHA; - mtex->tex->imaflag |= TEX_USEALPHA; i++; ma->spectra = ma->alpha = 0; ma->mode |= MA_ZTRANSP | MA_TRANSP; @@ -820,8 +912,8 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) cam_id = camera->getOriginalId(); cam_name = camera->getName(); - if (cam_name.size()) cam = (Camera *)BKE_camera_add((char *)cam_name.c_str()); - else cam = (Camera *)BKE_camera_add((char *)cam_id.c_str()); + if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str()); + else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str()); if (!cam) { fprintf(stderr, "Cannot create camera.\n"); @@ -933,17 +1025,29 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image) if (mImportStage != General) return true; - // XXX maybe it is necessary to check if the path is absolute or relative - const std::string& filepath = image->getImageURI().toNativePath(); - const char *filename = (const char *)mFilename.c_str(); + const std::string& imagepath = image->getImageURI().toNativePath(); + char dir[FILE_MAX]; - char full_path[FILE_MAX]; - - BLI_split_dir_part(filename, dir, sizeof(dir)); - BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str()); - Image *ima = BKE_image_load_exists(full_path); + char absolute_path[FILE_MAX]; + const char *workpath; + + BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir)); + BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str()); + if (BLI_exists(absolute_path)) { + workpath = absolute_path; + } + else { + // Maybe imagepath was already absolute ? + if (!BLI_exists(imagepath.c_str())) { + fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() ); + return true; + } + workpath = imagepath.c_str(); + } + + Image *ima = BKE_image_load_exists(workpath); if (!ima) { - fprintf(stderr, "Cannot create image.\n"); + fprintf(stderr, "Cannot create image: %s\n", workpath); return true; } this->uid_image_map[image->getUniqueId()] = ima; @@ -961,16 +1065,17 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light) Lamp *lamp = NULL; std::string la_id, la_name; - TagsMap::iterator etit; + ExtraTags *et = getExtraTags(light->getUniqueId()); + /*TagsMap::iterator etit; ExtraTags *et = 0; etit = uid_tags_map.find(light->getUniqueId().toAscii()); if (etit != uid_tags_map.end()) - et = etit->second; + et = etit->second;*/ la_id = light->getOriginalId(); la_name = light->getName(); - if (la_name.size()) lamp = (Lamp *)BKE_lamp_add((char *)la_name.c_str()); - else lamp = (Lamp *)BKE_lamp_add((char *)la_id.c_str()); + if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str()); + else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str()); if (!lamp) { fprintf(stderr, "Cannot create lamp.\n"); @@ -1185,3 +1290,18 @@ bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *e return true; } +bool DocumentImporter::is_armature(COLLADAFW::Node *node) +{ + COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) { + return true; + } + else { + continue; + } + } + + //no child is JOINT + return false; +} |