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.
This commit is contained in:
@@ -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<Object*>& 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<Object*>& 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<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];
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#ifndef __ARMATUREEXPORTER_H__
|
||||
#define __ARMATUREEXPORTER_H__
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
//#include <vector>
|
||||
|
||||
@@ -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<Object*>& 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<Object*>& child_objects);
|
||||
|
||||
void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node);
|
||||
|
||||
|
||||
@@ -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<Object*> 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 <bind_shape_matrix>
|
||||
@@ -101,7 +124,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
|
||||
|
||||
// <instance_controller>
|
||||
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<Object*>::iterator i= child_objects.begin(); i != child_objects.end(); ++i)
|
||||
{
|
||||
writeNodes(*i, sce);
|
||||
}
|
||||
|
||||
|
||||
if (ob->type != OB_ARMATURE)
|
||||
node.end();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user