From 29aa13cfa284182ee47818a477a3b8b7297a12c8 Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 26 May 2016 17:40:56 +0200 Subject: fix: Import of meshes with holes is now reported as WARNING (unsupported) improved: add support for bone tail export/import using Blender Collada profile Differential Revision: https://developer.blender.org/D2031 --- source/blender/collada/ArmatureExporter.cpp | 49 ++++---- source/blender/collada/ArmatureExporter.h | 2 - source/blender/collada/ArmatureImporter.cpp | 161 ++++++++++++++++++------- source/blender/collada/ArmatureImporter.h | 15 ++- source/blender/collada/ExportSettings.h | 1 + source/blender/collada/collada.cpp | 6 +- source/blender/collada/collada.h | 1 + source/blender/editors/io/io_collada.c | 10 +- source/blender/makesrna/intern/rna_scene_api.c | 4 +- 9 files changed, 175 insertions(+), 74 deletions(-) (limited to 'source') diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 36ab85b9b5b..cf02293886c 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -150,6 +150,16 @@ std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm) return get_joint_id(bone, ob_arm); } +static bool is_leaf_bone(Bone *bone) +{ + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + if (child->flag & BONE_CONNECTED) { + return false; + } + } + return true; +} + // parent_mat is armature-space void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se, @@ -167,12 +177,22 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, node.setNodeName(node_name); node.setNodeSid(node_sid); -#if 0 - if (BLI_listbase_is_empty(&bone->childbase) || BLI_listbase_count_ex(&bone->childbase, 2) == 2) { - add_blender_leaf_bone( bone, ob_arm, node); + if (this->export_settings->use_blender_profile) + { + if (bone->parent) { + if (bone->flag & BONE_CONNECTED) { + node.addExtraTechniqueParameter("blender", "connect", true); + } + } + + if (is_leaf_bone(bone)) + { + node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]); + node.addExtraTechniqueParameter("blender", "tip_y", bone->arm_tail[1] - bone->arm_head[1]); + node.addExtraTechniqueParameter("blender", "tip_z", bone->arm_tail[2] - bone->arm_head[2]); + } } - else { -#endif + node.start(); add_bone_transform(ob_arm, bone, node); @@ -227,25 +247,6 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, } } -//#if 1 -void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node) -{ - node.start(); - - add_bone_transform(ob_arm, bone, node); - - node.addExtraTechniqueParameter("blender", "tip_x", bone->tail[0]); - node.addExtraTechniqueParameter("blender", "tip_y", bone->tail[1]); - node.addExtraTechniqueParameter("blender", "tip_z", bone->tail[2]); - - /*for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm, sce, se, child_objects); - }*/ - node.end(); - -} -//#endif - void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) { //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 931cc5d2988..883a6aca847 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -92,8 +92,6 @@ private: void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node); - void add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node); - std::string get_controller_id(Object *ob_arm, Object *ob); void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index fd08e1ebfab..df60b213d16 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -158,21 +158,33 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon float loc[3], size[3], rot[3][3]; float angle; - float vec[3] = {0.0f, 0.5f, 0.0f}; + + BoneExtended &be = add_bone_extended(bone, node); + + float *tail = be.get_tail(); + int use_connect = be.get_use_connect(); + + switch (use_connect) { + case 1: bone->flag |= BONE_CONNECTED; + break; + case 0: bone->flag &= ~BONE_CONNECTED; + case -1: break; // not defined + } + mat4_to_loc_rot_size(loc, rot, size, mat); - //copy_m3_m4(bonemat,mat); - mat3_to_vec_roll(rot, vec, &angle); + mat3_to_vec_roll(rot, NULL, &angle); bone->roll = angle; - // set head copy_v3_v3(bone->head, mat[3]); - - // set tail, don't set it to head because 0-length bones are not allowed - add_v3_v3v3(bone->tail, bone->head, vec); + add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero /* find smallest bone length in armature (used later for leaf bone length) */ if (parent) { + if (use_connect == 1) { + copy_v3_v3(parent->tail, bone->head); + } + /* guess reasonable leaf bone length */ float length = len_v3v3(parent->head, bone->head); if ((length < leaf_bone_length || totbone == 0) && length > MINIMUM_BONE_LENGTH) { @@ -182,9 +194,6 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon COLLADAFW::NodePointerArray& children = node->getChildNodes(); - BoneExtended &be = add_bone_extended(bone, node); - be.set_leaf_bone(true); - for (unsigned int i = 0; i < children.getCount(); i++) { int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm); if (cl > chain_length) @@ -201,6 +210,18 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon return chain_length + 1; } +/* + * A bone is a leaf when it has no children or all children are not connected. + */ +static bool is_leaf_bone(Bone *bone) +{ + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + if (child->flag & BONE_CONNECTED) + return false; + } + return true; +} + /** * Collada only knows Joints, hence bones at the end of a bone chain * don't have a defined length. This function guesses reasonable @@ -209,33 +230,26 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon **/ void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone) { - /* armature has no bones */ if (bone == NULL) return; - BoneExtended *be = extended_bones[bone->name]; - if (be != NULL && be->is_leaf_bone() ) { + if (is_leaf_bone(bone)) { /* Collada only knows Joints, Here we guess a reasonable leaf bone length */ float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length; EditBone *ebone = get_edit_bone(armature, bone->name); float vec[3]; - if (this->import_settings->fix_orientation) { - if (ebone->parent != NULL) { - EditBone *parent = ebone->parent; - sub_v3_v3v3(vec, ebone->head, parent->tail); - if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH) - { - sub_v3_v3v3(vec, parent->tail, parent->head); - } - } - else { - vec[2] = 0.1f; - sub_v3_v3v3(vec, ebone->tail, ebone->head); + if (ebone->parent != NULL) { + EditBone *parent = ebone->parent; + sub_v3_v3v3(vec, ebone->head, parent->head); + if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH) + { + sub_v3_v3v3(vec, parent->tail, parent->head); } } else { + vec[2] = 0.1f; sub_v3_v3v3(vec, ebone->tail, ebone->head); } @@ -250,6 +264,22 @@ void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone) } +void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone) +{ + /* armature has no bones */ + if (bone == NULL) + return; + + if (bone->parent && bone->flag & BONE_CONNECTED) { + copy_v3_v3(bone->parent->tail, bone->head); + } + + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + fix_parent_connect(armature, child); + } + +} + void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip) { @@ -455,14 +485,23 @@ void ArmatureImporter::create_armature_bones( ) /* and step back to edit mode to fix the leaf nodes */ ED_armature_to_edit(armature); - connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - fix_leaf_bones(armature, (Bone *)armature->bonebase.first); + if (this->import_settings->fix_orientation || this->import_settings->find_chains) { + + if (this->import_settings->find_chains) + connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - // exit armature edit mode - unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm; + if (this->import_settings->fix_orientation) + fix_leaf_bones(armature, (Bone *)armature->bonebase.first); + + // exit armature edit mode + unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm; + } + + fix_parent_connect(armature, (Bone *)armature->bonebase.first); ED_armature_from_edit(armature); ED_armature_edit_free(armature); + DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA); } } @@ -594,8 +633,8 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin) if (armature->bonebase.first) { /* Do this only if Armature has bones */ - connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); - fix_leaf_bones(armature, (Bone *)armature->bonebase.first); + //connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX); + //fix_leaf_bones(armature, (Bone *)armature->bonebase.first); } // exit armature edit mode ED_armature_from_edit(armature); @@ -905,7 +944,11 @@ BoneExtended::BoneExtended(EditBone *aBone) { this->set_name(aBone->name); this->chain_length = 0; - this->is_leaf = false; + this->is_leaf = false; + this->tail[0] = 0.0f; + this->tail[1] = 0.5f; + this->tail[2] = 0.0f; + this->use_connect = -1; } char *BoneExtended::get_name() @@ -928,7 +971,6 @@ void BoneExtended::set_chain_length(const int aLength) chain_length = aLength; } - void BoneExtended::set_leaf_bone(bool state) { is_leaf = state; @@ -939,25 +981,60 @@ bool BoneExtended::is_leaf_bone() return is_leaf; } +void BoneExtended::set_tail(float vec[]) +{ + this->tail[0] = vec[0]; + this->tail[1] = vec[1]; + this->tail[2] = vec[2]; +} + +float *BoneExtended::get_tail() +{ + return this->tail; +} + +void BoneExtended::set_use_connect(int use_connect) +{ + this->use_connect = use_connect; +} + +int BoneExtended::get_use_connect() +{ + return this->use_connect; +} + + BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node) { + BoneExtended *be = new BoneExtended(bone); + extended_bones[bone->name] = be; TagsMap::iterator etit; ExtraTags *et = 0; etit = uid_tags_map.find(node->getUniqueId().toAscii()); if (etit != uid_tags_map.end()) { - float x, y, z; + + float tail[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; + int use_connect = -1; et = etit->second; - et->setData("tip_x", &x); - et->setData("tip_y", &y); - et->setData("tip_z", &z); - float vec[3] = { x, y, z }; - copy_v3_v3(bone->tail, bone->head); - add_v3_v3v3(bone->tail, bone->head, vec); + et->setData("tip_x", &tail[0]); + et->setData("tip_y", &tail[1]); + et->setData("tip_z", &tail[2]); + et->setData("connect", &use_connect); + + if (!(tail[0] == FLT_MAX || tail[1] == FLT_MAX || tail[2] == FLT_MAX)) + { + if (use_connect == -1) + { + use_connect = 0; // got a bone tail definition but no connect info -> bone is not connected + } + } + + be->set_tail(tail); + be->set_use_connect(use_connect); } + be->set_leaf_bone(true); - BoneExtended *be = new BoneExtended(bone); - extended_bones[bone->name] = be; return *be; } diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index 732fda80ff1..407fa83f84b 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -65,17 +65,27 @@ private: char name[MAXBONENAME]; int chain_length; bool is_leaf; + float tail[3]; + bool use_connect; public: BoneExtended(EditBone *aBone); - char *get_name(); - int get_chain_length(); void set_name(char *aName); + char *get_name(); + void set_chain_length(const int aLength); + int get_chain_length(); + void set_leaf_bone(bool state); bool is_leaf_bone(); + + void set_tail(float *vec); + float *get_tail(); + + void set_use_connect(int use_connect); + int get_use_connect(); }; class ArmatureImporter : private TransformReader @@ -131,6 +141,7 @@ private: void clear_extended_boneset(); void fix_leaf_bones(bArmature *armature, Bone *bone); + void fix_parent_connect(bArmature *armature, Bone *bone); void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length); void set_pose( Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]); diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 3dc7e74379e..9451cac9dae 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -48,6 +48,7 @@ public: bool triangulate; bool use_object_instantiation; + bool use_blender_profile; bool sort_by_name; BC_export_transformation_type export_transformation_type; bool open_sim; diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index b64b10e0833..e1b8a2dd30a 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -81,8 +81,9 @@ int collada_export(Scene *sce, int use_texture_copies, int triangulate, - int use_object_instantiation, - int sort_by_name, + int use_object_instantiation, + int use_blender_profile, + int sort_by_name, BC_export_transformation_type export_transformation_type, int open_sim) { @@ -105,6 +106,7 @@ int collada_export(Scene *sce, export_settings.triangulate = triangulate != 0; export_settings.use_object_instantiation = use_object_instantiation != 0; + export_settings.use_blender_profile = use_blender_profile != 0; export_settings.sort_by_name = sort_by_name != 0; export_settings.export_transformation_type = export_transformation_type; export_settings.open_sim = open_sim != 0; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 6819a62fdf0..db8ea884222 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -78,6 +78,7 @@ int collada_export(struct Scene *sce, int triangulate, int use_object_instantiation, + int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, int open_sim); diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index d4c976fb544..acb8e8e7512 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -94,6 +94,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int triangulate; int use_object_instantiation; + int use_blender_profile; int sort_by_name; int export_transformation_type; int open_sim; @@ -142,6 +143,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) triangulate = RNA_boolean_get(op->ptr, "triangulate"); use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); + use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile"); sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); open_sim = RNA_boolean_get(op->ptr, "open_sim"); @@ -167,6 +169,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) triangulate, use_object_instantiation, + use_blender_profile, sort_by_name, export_transformation_type, open_sim); @@ -256,6 +259,8 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "use_blender_profile", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); @@ -349,7 +354,10 @@ void WM_OT_collada_export(wmOperatorType *ot) "Export Polygons (Quads & NGons) as Triangles"); RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances", - "Instantiate multiple Objects from same Data"); + "Instantiate multiple Objects from same Data"); + + RNA_def_boolean(ot->srna, "use_blender_profile", 1, "Use Blender Profile", + "Export additional Blender specific information (for material, shaders, bones, etc.)"); RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 74fb4a08eda..e1216e3c85f 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -196,6 +196,7 @@ static void rna_Scene_collada_export( int use_ngons, int use_object_instantiation, + int use_blender_profile, int sort_by_name, int export_transformation_type, int open_sim) @@ -203,7 +204,7 @@ static void rna_Scene_collada_export( collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, include_shapekeys, deform_bones_only, active_uv_only, include_uv_textures, include_material_textures, - use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, open_sim); + use_texture_copies, use_ngons, use_object_instantiation, use_blender_profile, sort_by_name, export_transformation_type, open_sim); } #endif @@ -286,6 +287,7 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export"); parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data"); + parm = RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", "Export additional Blender specific information (for material, shaders, bones, etc.)"); parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); parm = RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds"); -- cgit v1.2.3