Collada: (Exporter) Add new option 'deform bones only'
authorGaia Clary <gaia.clary@machinimatrix.org>
Fri, 15 Jun 2012 22:00:25 +0000 (22:00 +0000)
committerGaia Clary <gaia.clary@machinimatrix.org>
Fri, 15 Jun 2012 22:00:25 +0000 (22:00 +0000)
release/scripts/presets/operator/wm.collada_export/second_life.py
source/blender/collada/ArmatureExporter.cpp
source/blender/collada/ArmatureExporter.h
source/blender/collada/ExportSettings.h
source/blender/collada/collada.cpp
source/blender/collada/collada.h
source/blender/collada/collada_utils.cpp
source/blender/collada/collada_utils.h
source/blender/makesrna/intern/rna_scene_api.c
source/blender/windowmanager/intern/wm_operators.c

index be96564..bacf49a 100644 (file)
@@ -1,10 +1,10 @@
 import bpy
 op = bpy.context.active_operator
-
-op.selected = True
 op.apply_modifiers = True
-op.include_armatures = False
+op.selected = True
 op.include_children = False
+op.include_armatures = True
+op.deform_bones_only = True
 op.use_object_instantiation = False
 op.sort_by_name = True
 op.second_life = True
index 98047df..8301066 100644 (file)
@@ -80,6 +80,18 @@ bool ArmatureExporter::is_skinned_mesh(Object *ob)
        return bc_get_assigned_armature(ob) != NULL;
 }
 
+
+void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
+{
+       if ( bc_is_root_bone(bone, this->export_settings->deform_bones_only) )
+               ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
+       else {
+               for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+                       write_bone_URLs(ins, ob_arm, child);
+               }
+       }
+}
+
 bool ArmatureExporter::add_instance_controller(Object *ob)
 {
        Object *ob_arm = bc_get_assigned_armature(ob);
@@ -96,8 +108,7 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
        // write root bone URLs
        Bone *bone;
        for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
-               if (!bone->parent)
-                       ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
+               write_bone_URLs(ins, ob_arm, bone);
        }
 
        InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob);
@@ -164,67 +175,73 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
                                      SceneExporter *se,
                                      std::list<Object *>& child_objects)
 {
-       std::string node_id = get_joint_id(bone, ob_arm);
-       std::string node_name = std::string(bone->name);
-       std::string node_sid = get_joint_sid(bone, ob_arm);
+       if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) {
+               std::string node_id = get_joint_id(bone, ob_arm);
+               std::string node_name = std::string(bone->name);
+               std::string node_sid = get_joint_sid(bone, ob_arm);
 
-       COLLADASW::Node node(mSW);
+               COLLADASW::Node node(mSW);
 
-       node.setType(COLLADASW::Node::JOINT);
-       node.setNodeId(node_id);
-       node.setNodeName(node_name);
-       node.setNodeSid(node_sid);
+               node.setType(COLLADASW::Node::JOINT);
+               node.setNodeId(node_id);
+               node.setNodeName(node_name);
+               node.setNodeSid(node_sid);
 
-       /*if ( bone->childbase.first == NULL || BLI_countlist(&(bone->childbase))>=2)
-           add_blender_leaf_bone( bone, ob_arm , node );
-          else{*/
-       node.start();
+               /*if ( bone->childbase.first == NULL || BLI_countlist(&(bone->childbase))>=2)
+                       add_blender_leaf_bone( bone, ob_arm , node );
+                  else{*/
+               node.start();
 
-       add_bone_transform(ob_arm, bone, node);
+               add_bone_transform(ob_arm, bone, node);
 
-       // Write nodes of childobjects, remove written objects from list
-       std::list<Object *>::iterator i = child_objects.begin();
+               // Write nodes of childobjects, remove written objects from list
+               std::list<Object *>::iterator i = child_objects.begin();
 
-       while (i != child_objects.end()) {
-               if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
-                       float backup_parinv[4][4];
-                       copy_m4_m4(backup_parinv, (*i)->parentinv);
+               while (i != child_objects.end()) {
+                       if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
+                               float backup_parinv[4][4];
+                               copy_m4_m4(backup_parinv, (*i)->parentinv);
 
-                       // crude, temporary change to parentinv
-                       // so transform gets exported correctly.
+                               // crude, temporary change to parentinv
+                               // so transform gets exported correctly.
 
-                       // Add bone tail- translation... don't know why
-                       // bone parenting is against the tail of a bone
-                       // and not it's head, seems arbitrary.
-                       (*i)->parentinv[3][1] += bone->length;
+                               // Add bone tail- translation... don't know why
+                               // bone parenting is against the tail of a bone
+                               // and not it's head, seems arbitrary.
+                               (*i)->parentinv[3][1] += bone->length;
 
-                       // SECOND_LIFE_COMPATIBILITY
-                       // TODO: when such objects are animated as
-                       // single matrix the tweak must be applied
-                       // to the result.
-                       if (export_settings->second_life) {
-                               // tweak objects parentinverse to match compatibility
-                               float temp[4][4];
+                               // SECOND_LIFE_COMPATIBILITY
+                               // TODO: when such objects are animated as
+                               // single matrix the tweak must be applied
+                               // to the result.
+                               if (export_settings->second_life) {
+                                       // tweak objects parentinverse to match compatibility
+                                       float temp[4][4];
 
-                               copy_m4_m4(temp, bone->arm_mat);
-                               temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+                                       copy_m4_m4(temp, bone->arm_mat);
+                                       temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
 
-                               mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
-                       }
+                                       mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
+                               }
 
-                       se->writeNodes(*i, sce);
+                               se->writeNodes(*i, sce);
 
-                       copy_m4_m4((*i)->parentinv, backup_parinv);
-                       child_objects.erase(i++);
+                               copy_m4_m4((*i)->parentinv, backup_parinv);
+                               child_objects.erase(i++);
+                       }
+                       else i++;
                }
-               else i++;
-       }
 
-       for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
-               add_bone_node(child, ob_arm, sce, se, child_objects);
+               for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+                       add_bone_node(child, ob_arm, sce, se, child_objects);
+               }
+               node.end();
+       }
+       else {
+               for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+                       add_bone_node(child, ob_arm, sce, se, child_objects);
+               }
        }
-       node.end();
-       //}
 }
 
 #if 0
index beef77a..a7575e9 100644 (file)
@@ -120,6 +120,8 @@ private:
 
        void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
                                                                        const std::list<int>& vcount, const std::list<int>& joints);
+
+       void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone);
 };
 
 #endif
index e856eef..c93a1b5 100644 (file)
@@ -34,10 +34,11 @@ extern "C" {
 struct ExportSettings
 {
  public:
- bool selected;
  bool apply_modifiers;
- bool include_armatures;
+ bool selected;
  bool include_children;
+ bool include_armatures;
+ bool deform_bones_only;
  bool use_object_instantiation;
  bool sort_by_name;
  bool second_life;
index 9a4fd44..5b970c2 100644 (file)
@@ -50,17 +50,19 @@ int collada_import(bContext *C, const char *filepath)
 }
 
 int collada_export(
-    Scene *sce,
-    const char *filepath,
-    int selected,
-    int apply_modifiers,
+       Scene *sce,
+       const char *filepath,
 
-    int include_armatures,
-    int include_children,
+       int apply_modifiers,
 
-    int use_object_instantiation,
+       int selected,
+       int include_children,
+       int include_armatures,
+       int deform_bones_only,
+
+       int use_object_instantiation,
        int sort_by_name,
-    int second_life)
+       int second_life)
 {
        ExportSettings export_settings;
 
@@ -73,15 +75,19 @@ int collada_export(
        }
        /* end! */
 
+       export_settings.filepath                 = (char *)filepath;
 
-       export_settings.selected                 = selected != 0;
        export_settings.apply_modifiers          = apply_modifiers != 0;
+
+       export_settings.selected                 = selected          != 0;
+       export_settings.include_children         = include_children  != 0;
        export_settings.include_armatures        = include_armatures != 0;
-       export_settings.include_children         = include_children != 0;
-       export_settings.second_life              = second_life != 0;
+       export_settings.deform_bones_only        = deform_bones_only != 0;
+
        export_settings.use_object_instantiation = use_object_instantiation != 0;
        export_settings.sort_by_name             = sort_by_name != 0;
-       export_settings.filepath                 = (char *)filepath;
+       export_settings.second_life              = second_life != 0;
+
 
        int includeFilter = OB_REL_NONE;
        if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
index 8daf2b6..89b0e29 100644 (file)
@@ -40,11 +40,12 @@ extern "C" {
        int collada_export(
                Scene *sce, 
                const char *filepath,
-               int selected,
                int apply_modifiers,
 
-               int include_armatures,
+               int selected,
                int include_children,
+               int include_armatures,
+               int deform_bones_only,
 
                int use_object_instantiation,
                int sort_by_name,
index aa6f0b3..041ffd4 100644 (file)
 
 #include "collada_utils.h"
 
+extern "C" {
+
 #include "DNA_modifier_types.h"
 #include "DNA_customdata_types.h"
 #include "DNA_object_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_armature_types.h"
 
 #include "BLI_math.h"
 
 #include "BKE_mesh.h"
 #include "BKE_scene.h"
 
-extern "C" {
 #include "BKE_DerivedMesh.h"
 #include "BLI_linklist.h"
-}
+
 
 #include "WM_api.h" // XXX hrm, see if we can do without this
 #include "WM_types.h"
+}
 
 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
 {
@@ -181,6 +184,7 @@ Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *o
        return ancestor;
 }
 
+
 bool bc_is_base_node(LinkNode *export_set, Object *ob)
 {
        Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
@@ -253,3 +257,23 @@ void bc_bubble_sort_by_Object_name(LinkNode *export_set)
                }
        }
 }
+
+/* Check if a bone is the top most exportable bone in the bone hierarchy. 
+ * When deform_bones_only == false, then only bones with NO parent 
+ * can be root bones. Otherwise the top most deform bones in the hierarchy
+ * are root bones.
+ */
+bool bc_is_root_bone(Bone *aBone, bool deform_bones_only) {
+       if(deform_bones_only) {
+               Bone *root = NULL;
+               Bone *bone = aBone;
+               while (bone) {
+                       if (!(bone->flag & BONE_NO_DEFORM))
+                               root = bone;
+                       bone = bone->parent;
+               }
+               return aBone==root;
+       }
+       else
+               return !(aBone->parent);
+}
index 139a2cb..6558ad3 100644 (file)
@@ -72,5 +72,6 @@ extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int
 extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
 
 extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
+extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
 
 #endif
index 76366ef..4e4316b 100644 (file)
@@ -88,16 +88,17 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name
 static void rna_Scene_collada_export(
     Scene *scene,
     const char *filepath,
-    int selected,
     int apply_modifiers,
-    int include_armatures,
+    int selected,
     int include_children,
+    int include_armatures,
+       int deform_bones_only,
     int use_object_instantiation,
        int sort_by_name,
     int second_life)
 {
-       collada_export(scene, filepath, selected, apply_modifiers, 
-                      include_armatures, include_children,
+       collada_export(scene, filepath, apply_modifiers, selected,  
+                      include_children, include_armatures, deform_bones_only, 
                       use_object_instantiation, sort_by_name, second_life);
 }
 
@@ -126,11 +127,12 @@ void RNA_api_scene(StructRNA *srna)
        parm = RNA_def_string(func, "filepath", "", FILE_MAX, "File Path", "File path to write Collada file");
        RNA_def_property_flag(parm, PROP_REQUIRED);
        RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
-       parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements");
        parm = RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers (in Preview resolution)");
-       parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Include armature(s) used by the exported objects");
-       parm = RNA_def_boolean(func, "include_children", 0, "Include Children", "Include all children even if not selected");
-       parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instantiation", "Instantiate multiple Objects from same Data");
+       parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements");
+       parm = RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)");
+       parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)");
+       parm = RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures");
+       parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
        parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
        parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life");
        RNA_def_function_ui_description(func, "Export to collada file");
index f39b8f2..35261a8 100644 (file)
@@ -2162,13 +2162,15 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED
 static int wm_collada_export_exec(bContext *C, wmOperator *op)
 {
        char filepath[FILE_MAX];
-       int selected, second_life; 
-       int include_armatures;
        int apply_modifiers;
+       int selected;
        int include_children;
+       int include_armatures;
+       int deform_bones_only;
        int use_object_instantiation;
        int sort_by_name;
-       
+       int second_life; 
+
        if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
                BKE_report(op->reports, RPT_ERROR, "No filename given");
                return OPERATOR_CANCELLED;
@@ -2178,10 +2180,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
        BLI_ensure_extension(filepath, sizeof(filepath), ".dae");
 
        /* Options panel */
-       selected                 = RNA_boolean_get(op->ptr, "selected");
        apply_modifiers          = RNA_boolean_get(op->ptr, "apply_modifiers");
-       include_armatures        = RNA_boolean_get(op->ptr, "include_armatures");
+       selected                 = RNA_boolean_get(op->ptr, "selected");
        include_children         = RNA_boolean_get(op->ptr, "include_children");
+       include_armatures        = RNA_boolean_get(op->ptr, "include_armatures");
+       deform_bones_only        = RNA_boolean_get(op->ptr, "deform_bones_only");
        use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
        sort_by_name             = RNA_boolean_get(op->ptr, "sort_by_name");
        second_life              = RNA_boolean_get(op->ptr, "second_life");
@@ -2192,11 +2195,12 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
        if (collada_export(
                CTX_data_scene(C),
                filepath,
-               selected,
                apply_modifiers,
-               include_armatures,
+               selected,
                include_children,
-               use_object_instantiation,
+               include_armatures,
+                       deform_bones_only,
+                       use_object_instantiation,
                        sort_by_name,
                second_life)) {
                return OPERATOR_FINISHED;
@@ -2225,13 +2229,15 @@ void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
        uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
 
        row = uiLayoutRow(box, 0);
-       uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
+       uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
        uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
 
        row = uiLayoutRow(box, 0);
-       uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
+       uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
        uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
 
+       row = uiLayoutRow(box, 0);
+       uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
 
        // Collada options:
        box = uiLayoutBox(layout);
@@ -2271,18 +2277,22 @@ static void WM_OT_collada_export(wmOperatorType *ot)
        
        WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
 
+       RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers",
+                       "Apply modifiers (Preview Resolution)");
+
 
        RNA_def_boolean(ot->srna, "selected", 0, "Selection Only",
                        "Export only selected elements");
 
+       RNA_def_boolean(ot->srna, "include_children", 0, "Include Children",
+                       "Export all children of selected objects (even if not selected)");
+
        RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures",
-                       "Include armature(s) even if not selected");
+                       "Export related armatures (even if not selected)");
 
-       RNA_def_boolean(ot->srna, "include_children", 0, "Include Children",
-                       "Include all children even if not selected");
+       RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only",
+                       "Only export deforming bones with armatures");
 
-       RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers",
-                       "Apply modifiers (Preview Resolution)");
 
        RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances",
                        "Instantiate multiple Objects from same Data");