From f3bef40b0cf2a10bcffedae6c5235e3f5537670f Mon Sep 17 00:00:00 2001 From: Arystanbek Dyussenov Date: Sat, 18 Feb 2012 06:22:20 +0000 Subject: #collada animation import, bugfix #29082 Fix skeletal animation import for , and transform types. Tested for correctness visually using Seymouranim2.dae from http://collada.org/owl and animated creatures from DKGamesModels folder (from private section of the same site). The results match the results in FXComposer-2.5. Since this is a fix towards correct reading of collada, it shouldn't break existing compatibility with Second Life. --- source/blender/collada/AnimationImporter.cpp | 182 +++++++++++++++++++++++---- source/blender/collada/AnimationImporter.h | 2 + 2 files changed, 157 insertions(+), 27 deletions(-) (limited to 'source/blender/collada') diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index c47e024aba4..b889dd21177 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -834,34 +834,33 @@ void AnimationImporter::translate_Animations ( COLLADAFW::Node * node , std::vector animcurves; for (unsigned int j = 0; j < bindings.getCount(); j++) { animcurves = curve_map[bindings[j].animation]; - if ( is_matrix ) + if ( is_matrix ) { apply_matrix_curves(ob, animcurves, root , node, transform ); + } else { - //calculate rnapaths and array index of fcurves according to transformation and animation class - Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path ); - - std::vector::iterator iter; - //Add the curves of the current animation to the object - for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { - FCurve * fcu = *iter; - if ((ob->type == OB_ARMATURE)) - add_bone_fcurve( ob, node , fcu ); - else - BLI_addtail(AnimCurves, fcu); + + if (is_joint) { + + add_bone_animation_sampled(ob, animcurves, root, node, transform); + } + else { + //calculate rnapaths and array index of fcurves according to transformation and animation class + Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path ); + + std::vector::iterator iter; + //Add the curves of the current animation to the object + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve * fcu = *iter; + + BLI_addtail(AnimCurves, fcu); + } } + } } } - if (is_rotation) { - if (is_joint) - { - bPoseChannel *chan = get_pose_channel(ob->pose, bone_name); - chan->rotmode = ROT_MODE_EUL; - } - else - { - ob->rotmode = ROT_MODE_EUL; - } + if (is_rotation && !is_joint) { + ob->rotmode = ROT_MODE_EUL; } } } @@ -992,6 +991,136 @@ void AnimationImporter::translate_Animations ( COLLADAFW::Node * node , } } +void AnimationImporter::add_bone_animation_sampled(Object * ob, std::vector& animcurves, COLLADAFW::Node* root, COLLADAFW::Node* node, COLLADAFW::Transformation * tm) +{ + const char *bone_name = bc_get_joint_name(node); + char joint_path[200]; + armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); + + std::vector frames; + find_frames(&frames, &animcurves); + + // convert degrees to radians + if (tm->getTransformationType() == COLLADAFW::Transformation::ROTATE) { + + std::vector::iterator iter; + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve* fcu = *iter; + + fcurve_deg_to_rad(fcu); + } + } + + + float irest_dae[4][4]; + float rest[4][4], irest[4][4]; + + get_joint_rest_mat(irest_dae, root, node); + invert_m4(irest_dae); + + Bone *bone = get_named_bone((bArmature*)ob->data, bone_name); + if (!bone) { + fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); + return; + } + + unit_m4(rest); + copy_m4_m4(rest, bone->arm_mat); + invert_m4_m4(irest, rest); + + // new curves to assign matrix transform animation + FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale + unsigned int totcu = 10 ; + const char *tm_str = NULL; + char rna_path[200]; + for (int i = 0; i < totcu; i++) { + + int axis = i; + + if (i < 4) { + tm_str = "rotation_quaternion"; + axis = i; + } + else if (i < 7) { + tm_str = "location"; + axis = i - 4; + } + else { + tm_str = "scale"; + axis = i - 7; + } + + + BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); + + newcu[i] = create_fcurve(axis, rna_path); + newcu[i]->totvert = frames.size(); + } + + if (frames.size() == 0) + return; + + std::sort(frames.begin(), frames.end()); + + std::vector::iterator it; + + // sample values at each frame + for (it = frames.begin(); it != frames.end(); it++) { + float fra = *it; + + float mat[4][4]; + float matfra[4][4]; + + unit_m4(matfra); + + // calc object-space mat + evaluate_transform_at_frame(matfra, node, fra); + + + // for joints, we need a special matrix + // special matrix: iR * M * iR_dae * R + // where R, iR are bone rest and inverse rest mats in world space (Blender bones), + // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) + float temp[4][4], par[4][4]; + + + // calc M + calc_joint_parent_mat_rest(par, NULL, root, node); + mult_m4_m4m4(temp, par, matfra); + + // evaluate_joint_world_transform_at_frame(temp, NULL, , node, fra); + + // calc special matrix + mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL); + + float rot[4], loc[3], scale[3]; + + mat4_to_quat(rot, mat); + copy_v3_v3(loc, mat[3]); + mat4_to_size(scale, mat); + + // add keys + for (int i = 0; i < totcu; i++) { + if (i < 4) + add_bezt(newcu[i], fra, rot[i]); + else if (i < 7) + add_bezt(newcu[i], fra, loc[i - 4]); + else + add_bezt(newcu[i], fra, scale[i - 7]); + } + } + verify_adt_action((ID*)&ob->id, 1); + + // add curves + for (int i= 0; i < totcu; i++) { + add_bone_fcurve(ob, node, newcu[i]); + } + + bPoseChannel *chan = get_pose_channel(ob->pose, bone_name); + chan->rotmode = ROT_MODE_QUAT; + +} + //Check if object is animated by checking if animlist_map holds the animlist_id of node transforms AnimationImporter::AnimMix* AnimationImporter::get_animation_type ( const COLLADAFW::Node * node , @@ -1406,12 +1535,10 @@ void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW:: float m[4][4]; unit_m4(m); - if ( type != COLLADAFW::Transformation::MATRIX ) - continue; std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); if (!evaluate_animation(tm, m, fra, nodename.c_str())) { - /*switch (type) { + switch (type) { case COLLADAFW::Transformation::ROTATE: dae_rotate_to_mat4(tm, m); break; @@ -1426,8 +1553,8 @@ void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW:: break; default: fprintf(stderr, "unsupported transformation type %d\n", type); - }*/ - dae_matrix_to_mat4(tm, m); + } + // dae_matrix_to_mat4(tm, m); } @@ -1510,6 +1637,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float } COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis(); + float ax[3] = {axis[0], axis[1], axis[2]}; float angle = evaluate_fcurve(curves[0], fra); axis_angle_to_mat4(mat, ax, angle); diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h index 118a50b0480..5fb96017dee 100644 --- a/source/blender/collada/AnimationImporter.h +++ b/source/blender/collada/AnimationImporter.h @@ -153,6 +153,8 @@ public: void apply_matrix_curves( Object * ob, std::vector& animcurves, COLLADAFW::Node* root ,COLLADAFW::Node* node, COLLADAFW::Transformation * tm ); + void add_bone_animation_sampled(Object * ob, std::vector& animcurves, COLLADAFW::Node* root ,COLLADAFW::Node* node, COLLADAFW::Transformation * tm); + void Assign_transform_animations(COLLADAFW::Transformation* transform , const COLLADAFW::AnimationList::AnimationBinding * binding, std::vector* curves, bool is_joint, char * joint_path); -- cgit v1.2.3 From e6b708b36bb77ff2287439f20fc79097c275c822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juha=20M=C3=A4ki-Kanto?= Date: Sat, 18 Feb 2012 15:41:09 +0000 Subject: Minor change collada export; don't even run the parentinv-test when ob->parent is NULL --- source/blender/collada/TransformWriter.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'source/blender/collada') diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index c806cd48587..0cf26a03107 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -95,20 +95,24 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) */ /* Using parentinv should allow use of existing curves */ - // If parentinv is identity don't add it. - bool add_parinv = false; - for(int i = 0; i < 16; ++i) + if(ob->parent) { - float f = (i%4 == i/4) ? 1.0f : 0.0f ; - if(ob->parentinv[i%4][i/4] != f) add_parinv = true; - } - - if(add_parinv && ob->parent) - { - double dmat[4][4]; - UnitConverter converter; - converter.mat4_to_dae_double(dmat, ob->parentinv); - node.addMatrix("parentinverse", dmat); + // If parentinv is identity don't add it. + bool add_parinv = false; + + for(int i = 0; i < 16; ++i) + { + float f = (i%4 == i/4) ? 1.0f : 0.0f ; + add_parinv |= (ob->parentinv[i%4][i/4] != f); + } + + if(add_parinv) + { + double dmat[4][4]; + UnitConverter converter; + converter.mat4_to_dae_double(dmat, ob->parentinv); + node.addMatrix("parentinverse", dmat); + } } add_transform(node, ob->loc, ob->rot, ob->size); -- cgit v1.2.3 From 7beddb750610982ebccfd64d87759baa91e011a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juha=20M=C3=A4ki-Kanto?= Date: Sat, 18 Feb 2012 16:20:24 +0000 Subject: Collada export: changes to joints/weights in skincontroller - Collecting joints/weights in one place, it's easier to exclude zero weights or vertexgroups with no matching bone than trying to match same logic in multiple places. - Still not exporting -1 joints for vertices without weights, but also not outputting -1 joint + weight for each vertexgroup without a matching bone. - The exported weights are now normalized. Last I tested this patch stopped 3ds Max crashing on import of file from #29465 (opencollada / internal .dae). --- source/blender/collada/ArmatureExporter.cpp | 124 +++++++++++++++++----------- source/blender/collada/ArmatureExporter.h | 7 +- 2 files changed, 80 insertions(+), 51 deletions(-) (limited to 'source/blender/collada') diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 0e89f2db74b..277b1896397 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -296,10 +296,64 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm) std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id); - std::string weights_source_id = add_weights_source(me, controller_id); + std::list vcounts; + std::list joints; + std::list weights; + + { + int i, j; + + // def group index -> joint index + std::vector joint_index_by_def_index; + bDeformGroup *def; + + for (def = (bDeformGroup*)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) { + if (is_bone_defgroup(ob_arm, def)) + joint_index_by_def_index.push_back(j++); + else + joint_index_by_def_index.push_back(-1); + } + + for (i = 0; i < me->totvert; i++) { + MDeformVert *vert = &me->dvert[i]; + std::map jw; + + // We're normalizing the weights later + float sumw = 0.0f; + + for (j = 0; j < vert->totweight; j++) { + int joint_index = joint_index_by_def_index[vert->dw[j].def_nr]; + if(joint_index != -1 && vert->dw[j].weight > 0.0f) + { + jw[joint_index] += vert->dw[j].weight; + sumw += vert->dw[j].weight; + } + } + + if(sumw > 0.0f) + { + float invsumw = 1.0f/sumw; + vcounts.push_back(jw.size()); + for(std::map::iterator m = jw.begin(); m != jw.end(); ++m) + { + joints.push_back((*m).first); + weights.push_back(invsumw*(*m).second); + } + } + else + { + vcounts.push_back(0); + /*vcounts.push_back(1); + joints.push_back(-1); + weights.push_back(1.0f);*/ + } + } + } + + std::string weights_source_id = add_weights_source(me, controller_id, weights); add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); - add_vertex_weights_element(weights_source_id, joints_source_id, me, ob_arm, &ob->defbase); + add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); closeSkin(); closeController(); @@ -445,21 +499,14 @@ bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup* def) return get_bone_from_defgroup(ob_arm, def) != NULL; } -std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id) +std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list& weights) { std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX; - int i; - int totweight = 0; - - for (i = 0; i < me->totvert; i++) { - totweight += me->dvert[i].totweight; - } - COLLADASW::FloatSourceF source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totweight); + source.setAccessorCount(weights.size()); source.setAccessorStride(1); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); @@ -467,13 +514,8 @@ std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& co source.prepareToAppendValues(); - // NOTE: COLLADA spec says weights should be normalized - - for (i = 0; i < me->totvert; i++) { - MDeformVert *vert = &me->dvert[i]; - for (int j = 0; j < vert->totweight; j++) { - source.appendValues(vert->dw[j].weight); - } + for(std::list::const_iterator i = weights.begin(); i != weights.end(); ++i) { + source.appendValues(*i); } source.finish(); @@ -481,11 +523,12 @@ std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& co return source_id; } -void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me, - Object *ob_arm, ListBase *defbase) +void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, + const std::list& vcounts, + const std::list& joints) { - COLLADASW::VertexWeightsElement weights(mSW); - COLLADASW::InputList &input = weights.getInputList(); + COLLADASW::VertexWeightsElement weightselem(mSW); + COLLADASW::InputList &input = weightselem.getInputList(); int offset = 0; input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h @@ -493,40 +536,25 @@ void ArmatureExporter::add_vertex_weights_element(const std::string& weights_sou input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++)); - weights.setCount(me->totvert); + weightselem.setCount(vcounts.size()); // write number of deformers per vertex - COLLADASW::PrimitivesBase::VCountList vcount; - int i; - for (i = 0; i < me->totvert; i++) { - vcount.push_back(me->dvert[i].totweight); - } + COLLADASW::PrimitivesBase::VCountList vcountlist; - weights.prepareToAppendVCountValues(); - weights.appendVertexCount(vcount); + vcountlist.resize(vcounts.size()); + std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin()); - // def group index -> joint index - std::map joint_index_by_def_index; - bDeformGroup *def; - int j; - for (def = (bDeformGroup*)defbase->first, i = 0, j = 0; def; def = def->next, i++) { - if (is_bone_defgroup(ob_arm, def)) - joint_index_by_def_index[i] = j++; - else - joint_index_by_def_index[i] = -1; - } + weightselem.prepareToAppendVCountValues(); + weightselem.appendVertexCount(vcountlist); - weights.CloseVCountAndOpenVElement(); + weightselem.CloseVCountAndOpenVElement(); // write deformer index - weight index pairs int weight_index = 0; - for (i = 0; i < me->totvert; i++) { - MDeformVert *dvert = &me->dvert[i]; - for (int j = 0; j < dvert->totweight; j++) { - weights.appendValues(joint_index_by_def_index[dvert->dw[j].def_nr]); - weights.appendValues(weight_index++); - } + for(std::list::const_iterator i = joints.begin(); i != joints.end(); ++i) + { + weightselem.appendValues(*i, weight_index++); } - weights.finish(); + weightselem.finish(); } diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 925e65c9b69..9d64664fa63 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -111,10 +111,11 @@ private: bool is_bone_defgroup(Object *ob_arm, bDeformGroup* def); - std::string add_weights_source(Mesh *me, const std::string& controller_id); + std::string add_weights_source(Mesh *me, const std::string& controller_id, + const std::list& weights); - void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, Mesh *me, - Object *ob_arm, ListBase *defbase); + void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, + const std::list& vcount, const std::list& joints); }; #endif -- cgit v1.2.3 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(-) (limited to 'source/blender/collada') 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