Collada: (Exporter) Add new option 'deform bones only'

This commit is contained in:
Gaia Clary 2012-06-15 22:00:25 +00:00
parent a2d4fddfd3
commit 9f6a66d5f9
10 changed files with 158 additions and 94 deletions

@ -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

@ -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);
copy_m4_m4((*i)->parentinv, backup_parinv);
child_objects.erase(i++);
}
se->writeNodes(*i, sce);
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

@ -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

@ -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;

@ -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;

@ -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,

@ -34,11 +34,14 @@
#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"
@ -49,13 +52,13 @@
#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);
}

@ -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

@ -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");

@ -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;
@ -2224,14 +2228,16 @@ void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, 0);
uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, 0);
uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
row = uiLayoutRow(box, 0);
uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
row = uiLayoutRow(box, 0);
uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
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_armatures", 0, "Include Armatures",
"Include armature(s) even if not selected");
RNA_def_boolean(ot->srna, "include_children", 0, "Include Children",
"Include all children even if not selected");
"Export all children of selected objects (even if not selected)");
RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures",
"Export related armatures (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");