From 49a5141cded6db36642461dc24064e6b695609af Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Thu, 7 Jun 2012 17:55:26 +0000 Subject: [#31739] Collada: New Export selections 'Include Armatures' --- source/blender/collada/ArmatureExporter.cpp | 58 ++++++++++++---------- source/blender/collada/ArmatureExporter.h | 4 +- source/blender/collada/DocumentExporter.cpp | 6 ++- source/blender/collada/ExportSettings.h | 1 + source/blender/collada/GeometryExporter.cpp | 29 ++++------- source/blender/collada/GeometryExporter.h | 2 +- source/blender/collada/SceneExporter.cpp | 52 ++++++++++++++++--- source/blender/collada/collada.cpp | 6 ++- source/blender/collada/collada.h | 6 ++- source/blender/collada/collada_utils.cpp | 39 +++++++++++++++ source/blender/collada/collada_utils.h | 3 ++ source/blender/makesrna/intern/rna_scene_api.c | 6 ++- source/blender/windowmanager/intern/wm_operators.c | 11 +++- 13 files changed, 160 insertions(+), 63 deletions(-) (limited to 'source') diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 9d59be39f33..107a3fc5796 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -37,6 +37,14 @@ #include "BKE_action.h" #include "BKE_armature.h" + +extern "C" { +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +} + #include "ED_armature.h" #include "BLI_listbase.h" @@ -45,6 +53,8 @@ #include "ArmatureExporter.h" #include "SceneExporter.h" +#include "collada_utils.h" + // XXX exporter writes wrong data for shared armatures. A separate // controller should be written for each armature-mesh binding how do // we make controller ids then? @@ -66,12 +76,12 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene* sce, bool ArmatureExporter::is_skinned_mesh(Object *ob) { - return get_assigned_armature(ob) != NULL; + return bc_get_assigned_armature(ob) != NULL; } -void ArmatureExporter::add_instance_controller(Object *ob) +bool ArmatureExporter::add_instance_controller(Object *ob) { - Object *ob_arm = get_assigned_armature(ob); + Object *ob_arm = bc_get_assigned_armature(ob); bArmature *arm = (bArmature*)ob_arm->data; const std::string& controller_id = get_controller_id(ob_arm, ob); @@ -79,6 +89,9 @@ void ArmatureExporter::add_instance_controller(Object *ob) COLLADASW::InstanceController ins(mSW); ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); + Mesh *me = (Mesh *)ob->data; + if (!me->dvert) return false; + // write root bone URLs Bone *bone; for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) { @@ -89,6 +102,7 @@ void ArmatureExporter::add_instance_controller(Object *ob) InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob); ins.add(); + return true; } void ArmatureExporter::export_controllers(Scene *sce) @@ -105,7 +119,7 @@ void ArmatureExporter::export_controllers(Scene *sce) void ArmatureExporter::operator()(Object *ob) { - Object *ob_arm = get_assigned_armature(ob); + Object *ob_arm = bc_get_assigned_armature(ob); if (ob_arm /*&& !already_written(ob_arm)*/) export_controller(ob, ob_arm); @@ -139,27 +153,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vectorparent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { - ob_arm = ob->parent; - } - else { - ModifierData *mod = (ModifierData*)ob->modifiers.first; - while (mod) { - if (mod->type == eModifierType_Armature) { - ob_arm = ((ArmatureModifierData*)mod)->object; - } - - mod = mod->next; - } - } - - return ob_arm; -} - std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm) { return get_joint_id(bone, ob_arm); @@ -325,7 +318,16 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm) */ bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me = (Mesh*)ob->data; + Mesh *me; + + if ( this->export_settings->apply_modifiers ) { + me = bc_to_mesh_apply_modifiers(scene, ob); + } + else { + me = (Mesh*)ob->data; + } + BKE_mesh_tessface_ensure(me); + if (!me->dvert) return; std::string controller_name = id_name(ob_arm); @@ -393,6 +395,10 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm) add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); + if (this->export_settings->apply_modifiers) + { + BKE_libblock_free_us(&(G.main->mesh), me); + } closeSkin(); closeController(); } diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index e9ee38d36cf..beef77af767 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -64,7 +64,7 @@ public: bool is_skinned_mesh(Object *ob); - void add_instance_controller(Object *ob); + bool add_instance_controller(Object *ob); void export_controllers(Scene *sce); @@ -85,8 +85,6 @@ private: void find_objects_using_armature(Object *ob_arm, std::vector& objects, Scene *sce); #endif - Object *get_assigned_armature(Object *ob); - std::string get_joint_sid(Bone *bone, Object *ob_arm); // Scene, SceneExporter and the list of child_objects diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 19fc30a2790..69f302eaec7 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -262,8 +262,10 @@ void DocumentExporter::exportCurrentScene(Scene *sce) // ArmatureExporter arm_exporter(&sw, this->export_settings); - if (has_object_type(sce, OB_ARMATURE)) { - arm_exporter.export_controllers(sce); + if (this->export_settings->include_armatures) { + if (has_object_type(sce, OB_ARMATURE)) { + arm_exporter.export_controllers(sce); + } } // diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index f0d3f810831..a6ae29bf2b2 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -32,6 +32,7 @@ struct ExportSettings public: bool selected; bool apply_modifiers; + bool include_armatures; bool include_bone_children; bool use_object_instantiation; bool second_life; diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 6df16165e4b..53d7f1e6449 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -49,6 +49,7 @@ extern "C" { #include "BKE_material.h" #include "BKE_mesh.h" #include "collada_internal.h" +#include "collada_utils.h" // TODO: optimize UV sets by making indexed list with duplicates removed GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) {} @@ -65,25 +66,6 @@ void GeometryExporter::exportGeom(Scene *sce) closeLibrary(); } -Mesh * GeometryExporter::get_mesh(Object *ob, int apply_modifiers) -{ - Mesh *tmpmesh; - if (!apply_modifiers) - { - tmpmesh = (Mesh*)ob->data; - } - else - { - CustomDataMask mask = CD_MASK_MESH; - DerivedMesh *dm = mesh_create_derived_view(mScene, ob, mask); - tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here - DM_to_mesh(dm, tmpmesh, ob); - dm->release(dm); - } - BKE_mesh_tessface_ensure(tmpmesh); - return tmpmesh; -} - void GeometryExporter::operator()(Object *ob) { // XXX don't use DerivedMesh, Mesh instead? @@ -93,7 +75,14 @@ void GeometryExporter::operator()(Object *ob) #endif bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me = get_mesh(ob, this->export_settings->apply_modifiers); + Mesh *me; + if ( this->export_settings->apply_modifiers ) { + me = bc_to_mesh_apply_modifiers(mScene, ob); + } + else { + me = (Mesh*)ob->data; + } + BKE_mesh_tessface_ensure(me); std::string geom_id = get_geometry_id(ob, use_instantiation); std::vector nor; diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index aae095e819e..23cdcc0a5ba 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -105,7 +105,7 @@ private: const ExportSettings *export_settings; - Mesh * get_mesh(Object *ob, int apply_modifiers); + Mesh * get_mesh(Scene *sce, Object *ob, int apply_modifiers); }; struct GeometryFunctor { diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index d258f4ef5e1..510107272cd 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -25,6 +25,7 @@ */ #include "SceneExporter.h" +#include "collada_utils.h" SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings) : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings) @@ -40,19 +41,36 @@ void SceneExporter::exportScene(Scene *sce) closeLibrary(); } +// Returns true if the parent chain does not contain any selected object +// Otherwise return false (ob has selected predecessor) +bool is_exported_base_node(Object *ob, bool selection_only) { + + if (selection_only && ob->flag & SELECT) { + // Move up towards root object, + // stop at first selected predecessor's child, + // or at root, if no parent was selected + while (ob->parent && (ob->parent->type==OB_ARMATURE || !(ob->parent->flag & SELECT))) + { + ob = ob->parent; + } + } + + return !ob->parent; +} + void SceneExporter::exportHierarchy(Scene *sce) { Base *base= (Base*) sce->base.first; while (base) { Object *ob = base->object; - if (!ob->parent) { + bool is_export_base_node = is_exported_base_node(ob, this->export_settings->selected); + if (is_export_base_node) { if (sce->lay & ob->lay) { switch (ob->type) { case OB_MESH: case OB_CAMERA: case OB_LAMP: - case OB_ARMATURE: case OB_EMPTY: if (this->export_settings->selected && !(ob->flag & SELECT)) { break; @@ -70,6 +88,14 @@ void SceneExporter::exportHierarchy(Scene *sce) void SceneExporter::writeNodes(Object *ob, Scene *sce) { + + // Add associated armature first if available + if (this->export_settings->include_armatures) { + Object *ob_arm = bc_get_assigned_armature(ob); + if(ob_arm != NULL) + writeNodes(ob_arm, sce); + } + COLLADASW::Node node(mSW); node.setNodeId(translate_id(id_name(ob))); node.setNodeName(translate_id(id_name(ob))); @@ -80,8 +106,19 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob); std::list child_objects; + // XXX Not sure about this. + // For me this looks more like a very special case for a very special purpose. + // Wouldn't it be better to have only one option here ? + // + // - include children + // + // Instead of "include_bone_children" ? + // then we could just ask: + // if (this->export_settings->include_children) + // ... + if (this->export_settings->include_armatures + && this->export_settings->include_bone_children) { - if (this->export_settings->include_bone_children) { // list child objects Base *b = (Base*) sce->base.first; while (b) { @@ -105,7 +142,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) } - if (ob->type == OB_MESH && is_skinned_mesh) + if (ob->type == OB_MESH && this->export_settings->include_armatures && is_skinned_mesh) // for skinned mesh we write obmat in TransformWriter::add_node_transform_identity(node); else @@ -113,10 +150,11 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) // if (ob->type == OB_MESH) { - if (is_skinned_mesh) { - arm_exporter->add_instance_controller(ob); + bool instance_controller_created = false; + if (this->export_settings->include_armatures && is_skinned_mesh) { + instance_controller_created = arm_exporter->add_instance_controller(ob); } - else { + if (!instance_controller_created){ COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 951fecec049..e880082c9ec 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -54,14 +54,18 @@ extern "C" const char *filepath, int selected, int apply_modifiers, + + int include_armatures, int include_bone_children, + int use_object_instantiation, - int second_life) + int second_life ) { ExportSettings export_settings; export_settings.selected = selected != 0; export_settings.apply_modifiers = apply_modifiers != 0; + export_settings.include_armatures = include_armatures != 0; export_settings.include_bone_children = include_bone_children != 0; export_settings.second_life = second_life != 0; export_settings.use_object_instantiation = use_object_instantiation != 0; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 67aaf1ff6c7..646c8469e6b 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -38,13 +38,17 @@ extern "C" { */ int collada_import(bContext *C, const char *filepath); int collada_export( - Scene *sce, + Scene *sce, const char *filepath, int selected, int apply_modifiers, + + int include_armatures, int include_bone_children, + int use_object_instantiation, int second_life); + #ifdef __cplusplus } #endif diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 8b7a28e5fbe..8693441d7c8 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -32,8 +32,10 @@ #include "COLLADAFWMeshPrimitive.h" #include "COLLADAFWMeshVertexData.h" +#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 "BLI_math.h" @@ -42,8 +44,13 @@ #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_object.h" +#include "BKE_mesh.h" #include "BKE_scene.h" +extern "C" { +#include "BKE_DerivedMesh.h" +} + #include "WM_api.h" // XXX hrm, see if we can do without this #include "WM_types.h" @@ -125,3 +132,35 @@ Object *bc_add_object(Scene *scene, int type, const char *name) return ob; } +Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob) +{ + Mesh *tmpmesh; + CustomDataMask mask = CD_MASK_MESH; + DerivedMesh *dm = mesh_create_derived_view(scene, ob, mask); + tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here + DM_to_mesh(dm, tmpmesh, ob); + dm->release(dm); + return tmpmesh; +} + +Object *bc_get_assigned_armature(Object *ob) +{ + Object *ob_arm = NULL; + + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod = (ModifierData*)ob->modifiers.first; + while (mod) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData*)mod)->object; + } + + mod = mod->next; + } + } + + return ob_arm; +} + diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 1f5d2b1d8da..9882b44d94c 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -36,6 +36,7 @@ #include #include "DNA_object_types.h" +#include "DNA_mesh_types.h" #include "DNA_customdata_types.h" #include "DNA_texture_types.h" #include "BKE_context.h" @@ -50,5 +51,7 @@ extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_sp extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); extern Object *bc_add_object(Scene *scene, int type, const char *name); +extern Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob); +extern Object *bc_get_assigned_armature(Object *ob); #endif diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 09e0428058a..b2ff36285e6 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -90,11 +90,14 @@ static void rna_Scene_collada_export( const char *filepath, int selected, int apply_modifiers, + int include_armatures, int include_bone_children, int use_object_instantiation, int second_life) { - collada_export(scene, filepath, selected, apply_modifiers, include_bone_children, use_object_instantiation, second_life); + collada_export(scene, filepath, selected, apply_modifiers, + include_armatures, include_bone_children, + use_object_instantiation, second_life); } #endif @@ -124,6 +127,7 @@ void RNA_api_scene(StructRNA *srna) 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_bone_children", 0, "Include Bone Children", "Include all objects attached to bones of selected Armature(s)"); parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instantiation", "Instantiate multiple Objects from same Data"); parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life"); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1cf58b4345b..ed023e42ea3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2162,7 +2162,11 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED static int wm_collada_export_exec(bContext *C, wmOperator *op) { char filename[FILE_MAX]; - int selected, second_life, apply_modifiers, include_bone_children, use_object_instantiation; + int selected, second_life, + include_armatures, + apply_modifiers, + include_bone_children, + use_object_instantiation; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -2174,6 +2178,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* 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"); include_bone_children = RNA_boolean_get(op->ptr, "include_bone_children"); use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); second_life = RNA_boolean_get(op->ptr, "second_life"); @@ -2186,6 +2191,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) filename, selected, apply_modifiers, + include_armatures, include_bone_children, use_object_instantiation, second_life)) { @@ -2216,6 +2222,9 @@ static void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers (Preview Resolution)"); + RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures", + "Include armature(s) used by the exported objects"); + RNA_def_boolean(ot->srna, "include_bone_children", 0, "Include Bone Children", "Include all objects attached to bones of selected Armature(s)"); -- cgit v1.2.3