From f75bf20c817d9e09b23513d007bc8cc69ff00d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juha=20M=C3=A4ki-Kanto?= Date: Sat, 18 Feb 2012 16:55:41 +0000 Subject: Fix rest of #27022, collada export: add bone parenting of objects - SceneExporter collects a list of child-objects for armature-object and passes it onto ArmatureExporter - SceneExporter's writeNodes is then called from ArmatureExporter for matching child-objects for bone. - ArmatureExporter removes written child-objects from list, objects not exported as being bone parented are exported as direct children of the armature-node. - Should play nice with current Second Life-compatibility. A nicer implementation would require some design changes, will have to wait. --- source/blender/collada/ArmatureExporter.cpp | 59 +++++++++++++++++++++++++---- source/blender/collada/ArmatureExporter.h | 12 ++++-- source/blender/collada/SceneExporter.cpp | 49 ++++++++++++++---------- source/blender/collada/SceneExporter.h | 2 + 4 files changed, 91 insertions(+), 31 deletions(-) diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 277b1896397..9399ce6771d 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -43,6 +43,7 @@ #include "GeometryExporter.h" #include "ArmatureExporter.h" +#include "SceneExporter.h" // XXX exporter writes wrong data for shared armatures. A separate // controller should be written for each armature-mesh binding how do @@ -50,14 +51,16 @@ ArmatureExporter::ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) {} // write bone nodes -void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce) +void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene* sce, + SceneExporter* se, + std::list& child_objects) { // write bone nodes bArmature *arm = (bArmature*)ob_arm->data; for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) { // start from root bones if (!bone->parent) - add_bone_node(bone, ob_arm); + add_bone_node(bone, ob_arm, sce, se, child_objects); } } @@ -163,7 +166,9 @@ std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm) } // parent_mat is armature-space -void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm) +void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene* sce, + SceneExporter* se, + std::list& child_objects) { std::string node_id = get_joint_id(bone, ob_arm); std::string node_name = std::string(bone->name); @@ -183,14 +188,54 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm) add_bone_transform(ob_arm, bone, node); + // Write nodes of childobjects, remove written objects from list + std::list::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]; + + // SECOND_LIFE_COMPATIBILITY + // crude, temporary change to parentinv + // so transform gets exported correctly. + // TODO: when such objects are animated as + // single matrix the tweak must be applied + // to the result. + if(export_settings->second_life) + { + copy_m4_m4(backup_parinv, (*i)->parentinv); + // tweak objects parentinverse to match + // the second life- compatibility + float temp[4][4]; + + copy_m4_m4(temp, bone->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + + mult_m4_m4m4((*i)->parentinv, temp, backup_parinv); + } + + se->writeNodes(*i, sce); + + // restore original parentinv + if(export_settings->second_life) + { + copy_m4_m4((*i)->parentinv, backup_parinv); + } + child_objects.erase(i++); + } + else i++; + } + for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm); + add_bone_node(child, ob_arm, sce, se, child_objects); } node.end(); //} } -void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node) +/*void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node) { node.start(); @@ -201,11 +246,11 @@ void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADA 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); + add_bone_node(child, ob_arm, sce, se, child_objects); } node.end(); -} +}*/ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) { bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 9d64664fa63..e9ee38d36cf 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -28,6 +28,7 @@ #ifndef __ARMATUREEXPORTER_H__ #define __ARMATUREEXPORTER_H__ +#include #include //#include @@ -47,6 +48,8 @@ #include "ExportSettings.h" +class SceneExporter; + // 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? @@ -56,7 +59,8 @@ public: ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); // write bone nodes - void add_armature_bones(Object *ob_arm, Scene *sce); + void add_armature_bones(Object *ob_arm, Scene* sce, SceneExporter* se, + std::list& child_objects); bool is_skinned_mesh(Object *ob); @@ -85,8 +89,10 @@ private: std::string get_joint_sid(Bone *bone, Object *ob_arm); - // parent_mat is armature-space - void add_bone_node(Bone *bone, Object *ob_arm); + // Scene, SceneExporter and the list of child_objects + // are required for writing bone parented objects + void add_bone_node(Bone *bone, Object *ob_arm, Scene* sce, SceneExporter* se, + std::list& child_objects); void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node); diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 5dd452faa41..b6be8a57f7a 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -77,6 +77,29 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) node.start(); bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob); + std::list child_objects; + + // list child objects + Base *b = (Base*) sce->base.first; + while(b) { + // cob - child object + Object *cob = b->object; + + if (cob->parent == ob) { + switch(cob->type) { + case OB_MESH: + case OB_CAMERA: + case OB_LAMP: + case OB_EMPTY: + case OB_ARMATURE: + child_objects.push_back(cob); + break; + } + } + + b = b->next; + } + if (ob->type == OB_MESH && is_skinned_mesh) // for skinned mesh we write obmat in @@ -101,7 +124,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) // else if (ob->type == OB_ARMATURE) { - arm_exporter->add_armature_bones(ob, sce); + arm_exporter->add_armature_bones(ob, sce, this, child_objects); // XXX this looks unstable... node.end(); @@ -131,28 +154,12 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) } } - // write nodes for child objects - Base *b = (Base*) sce->base.first; - while(b) { - // cob - child object - Object *cob = b->object; - - if (cob->parent == ob) { - switch(cob->type) { - case OB_MESH: - case OB_CAMERA: - case OB_LAMP: - case OB_EMPTY: - case OB_ARMATURE: - // write node... - writeNodes(cob, sce); - break; - } - } - - b = b->next; + for(std::list::iterator i= child_objects.begin(); i != child_objects.end(); ++i) + { + writeNodes(*i, sce); } + if (ob->type != OB_ARMATURE) node.end(); } diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index de01eb6e459..31b471a3e4c 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -97,6 +97,8 @@ public: void exportScene(Scene *sce); private: + // required for writeNodes() for bone-parented objects + friend class ArmatureExporter; void exportHierarchy(Scene *sce); void writeNodes(Object *ob, Scene *sce); -- cgit v1.2.3