fix: Import of meshes with holes is now reported as WARNING (unsupported)
authorGaia Clary <gaia.clary@machinimatrix.org>
Thu, 26 May 2016 15:40:56 +0000 (17:40 +0200)
committerGaia Clary <gaia.clary@machinimatrix.org>
Thu, 26 May 2016 15:53:25 +0000 (17:53 +0200)
improved: add support for bone tail export/import using Blender Collada profile

Differential Revision: https://developer.blender.org/D2031

source/blender/collada/ArmatureExporter.cpp
source/blender/collada/ArmatureExporter.h
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/ArmatureImporter.h
source/blender/collada/ExportSettings.h
source/blender/collada/collada.cpp
source/blender/collada/collada.h
source/blender/editors/io/io_collada.c
source/blender/makesrna/intern/rna_scene_api.c

index 36ab85b9b5b096e2126762c206d7463455a8acd8..cf02293886ca7eacec998063fe805580dbdc5f38 100644 (file)
@@ -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);
index 931cc5d29880b29e12fe1c79722c5b81448b21e1..883a6aca8476014b2266fed6b1541c36271fbb32 100644 (file)
@@ -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);
index fd08e1ebfabf789ce02d6a7cc35dfb8a2fd9a1d1..df60b213d161c0210ad94de12cd99d2c2d581ff9 100644 (file)
@@ -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;
 }
index 732fda80ff164eebd86e0ed47804b8ea677b807c..407fa83f84b3a057f9ca19c2040b8b1f0a566c0e 100644 (file)
@@ -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]);
index 3dc7e74379e88c54439ac0f31736a1b9c2b2a775..9451cac9dae2d410d26094028e81079acf26789e 100644 (file)
@@ -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;
index b64b10e08339c4523ad6f36561f925c1a2016455..e1b8a2dd30aab6f66839c70c51a4ae04ece91ff0 100644 (file)
@@ -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;
index 6819a62fdf04582eb5ce24d0dc4b7c778d3775b5..db8ea8842228ecc8fecf4a7ec9b9252c1723ee2e 100644 (file)
@@ -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);
index d4c976fb5449d598793f354f908664b3f129c111..acb8e8e75127aded8d3be2279a128d1022afed0c 100644 (file)
@@ -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");
index 74fb4a08eda733d9d3c912b899f8440317a68476..e1216e3c85f9e0763e7ba62ff10046c4613e1d43 100644 (file)
@@ -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");