diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 0436dd40744..88a67eebe9d 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -213,15 +213,17 @@ void DocumentImporter::finish() fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor); } - else { - // TODO: add automatic scaling for the case when Blender units - // and import units are set to different values. - } // 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 *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 @@ -443,7 +445,7 @@ void DocumentImporter::create_constraints(ExtraTags *et, Object *ob) } } -void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) +std::vector *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; @@ -549,7 +551,8 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent // XXX: if there're multiple instances, only one is stored - if (!ob) return; + if (!ob) return objects_done; + for (std::vector::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { ob = *it; std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); @@ -561,6 +564,7 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent libnode_ob.push_back(ob); } + //create_constraints(et,ob); } @@ -585,6 +589,8 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent 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. diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index 76d16f38a0c..ff0cbd44043 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -77,7 +77,7 @@ public: Object* create_lamp_object(COLLADAFW::InstanceLight*, Scene*); Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool); void create_constraints(ExtraTags *et, Object *ob); - void write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool); + std::vector *write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool); MTex* create_texture(COLLADAFW::EffectCommon*, COLLADAFW::Texture&, Material*, int, TexIndexTextureArrayMap&); void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index ab8491dde01..84bb33929c1 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -295,11 +295,69 @@ std::string bc_url_encode(std::string data) { } std::string bc_replace_string(std::string data, const std::string& pattern, - const std::string& replacement) { + const std::string& replacement) { size_t pos = 0; - while ((pos = data.find(pattern, pos)) != std::string::npos) { + while((pos = data.find(pattern, pos)) != std::string::npos) { data.replace(pos, pattern.length(), replacement); pos += replacement.length(); } return data; } + +/** + Calculate a rescale factor such that the imported scene's scale + is preserved. I.e. 1 meter in the import will also be + 1 meter in the curretn scene. + XXX : I am not sure if it is correct to map 1 Blender Unit + to 1 Meter for unit type NONE. But it looks reasonable to me. +*/ +void bc_match_scale(std::vector *objects_done, + Scene &sce, + UnitConverter &unit_converter) { + + Object *ob = NULL; + + PointerRNA scene_ptr, unit_settings; + PropertyRNA *system_ptr, *scale_ptr; + RNA_id_pointer_create(&sce.id, &scene_ptr); + + unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings"); + system_ptr = RNA_struct_find_property(&unit_settings, "system"); + scale_ptr = RNA_struct_find_property(&unit_settings, "scale_length"); + + int type = RNA_property_enum_get(&unit_settings, system_ptr); + + float bl_scale; + + switch(type) { + case USER_UNIT_NONE : bl_scale = 1.0; // map 1 Blender unit to 1 Meter + break; + case USER_UNIT_METRIC : bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); + break; + default : bl_scale = RNA_property_float_get(&unit_settings, scale_ptr); + // it looks like the conversion to Imperial is done implicitly. + // So nothing to do here. + break; + } + + float size_mat3[3][3]; + float size_mat4[4][4]; + + float scale_conv = unit_converter.getLinearMeter() / bl_scale; + + float rescale[3]; + rescale[0] = rescale[1] = rescale[2] = scale_conv; + + size_to_mat3(size_mat3, rescale); + copy_m4_m3(size_mat4, size_mat3); + + for (std::vector::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { + ob = *it; + mult_m4_m4m4(ob->obmat, ob->obmat, size_mat4); + ob->obmat[3][0] = ob->loc[0] * rescale[0]; + ob->obmat[3][1] = ob->loc[1] * rescale[1]; + ob->obmat[3][2] = ob->loc[2] * rescale[2]; + BKE_object_apply_mat4(ob, ob->obmat, 0, 0); + } + +} diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 90282d9d28f..892b57e6a4a 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -42,15 +42,19 @@ extern "C" { #include "DNA_texture_types.h" #include "DNA_scene_types.h" +#include "RNA_access.h" + #include "BLI_linklist.h" #include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_object.h" #include "BKE_DerivedMesh.h" +#include "BKE_scene.h" } #include "ExportSettings.h" +#include "collada_internal.h" typedef std::map > TexIndexTextureArrayMap; @@ -79,5 +83,5 @@ extern int bc_get_active_UVLayer(Object *ob); extern std::string bc_replace_string(std::string data, const std::string& pattern, const std::string& replacement); extern std::string bc_url_encode(std::string data); - +extern void bc_match_scale(std::vector *objects_done, Scene &sce, UnitConverter &unit_converter); #endif diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index d8bb372b936..52a585dd314 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -319,12 +319,11 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) import_units = RNA_boolean_get(op->ptr, "import_units"); RNA_string_get(op->ptr, "filepath", filename); - if (collada_import(C, filename, import_units)) { + if (collada_import( C, filename, import_units)) { return OPERATOR_FINISHED; } else { - BKE_report(op->reports, RPT_ERROR, - "Errors found during parsing COLLADA document (see console for details)"); + BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document (see console for details)"); return OPERATOR_CANCELLED; } } @@ -367,8 +366,9 @@ void WM_OT_collada_import(wmOperatorType *ot) WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); - RNA_def_boolean(ot->srna, "import_units", 0, "Import Units", - "If enabled use Units as defined in Collada Import, else keep Blender's current Units settings"); + RNA_def_boolean(ot->srna, + "import_units", 0, "Import Units", + "If disabled match import to Blender's current Unit settings. Otherwise use the settings from the Imported scene."); } #endif