[#31739] Collada: New Export selections 'Include Armatures'

This commit is contained in:
Gaia Clary 2012-06-07 17:55:26 +00:00
parent 64c45caff9
commit 49a5141cde
13 changed files with 160 additions and 63 deletions

View File

@ -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::vector<O
}
#endif
Object *ArmatureExporter::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;
}
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();
}

View File

@ -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<Object *>& 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

View File

@ -262,8 +262,10 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
// <library_controllers>
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);
}
}
// <library_visual_scenes>

View File

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

View File

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

View File

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

View File

@ -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<Object*> 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 <bind_shape_matrix>
TransformWriter::add_node_transform_identity(node);
else
@ -113,10 +150,11 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
// <instance_geometry>
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)));

View File

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

View File

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

View File

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

View File

@ -36,6 +36,7 @@
#include <map>
#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

View File

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

View File

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