From c77f005b14ccd560b7f621a1a0953984894fc058 Mon Sep 17 00:00:00 2001 From: Chingiz Dyussenov Date: Fri, 28 Aug 2009 04:50:35 +0000 Subject: [PATCH] Added export skinned animation. --- source/blender/blenkernel/BKE_fcurve.h | 4 +- source/blender/collada/DocumentExporter.cpp | 226 ++++++++++++++++-- source/blender/collada/DocumentImporter.cpp | 4 +- .../blender/editors/include/ED_keyframing.h | 4 +- 4 files changed, 210 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index cda64c6b241..580750fd4b2 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -96,7 +96,7 @@ typedef struct FModifierTypeInfo { } FModifierTypeInfo; /* Values which describe the behaviour of a FModifier Type */ -enum { +typedef enum { /* modifier only modifies values outside of data range */ FMI_TYPE_EXTRAPOLATION = 0, /* modifier leaves data-points alone, but adjusts the interpolation between and around them */ @@ -108,7 +108,7 @@ enum { } eFMI_Action_Types; /* Flags for the requirements of a FModifier Type */ -enum { +typedef enum { /* modifier requires original data-points (kindof beats the purpose of a modifier stack?) */ FMI_REQUIRES_ORIGINAL_DATA = (1<<0), /* modifier doesn't require on any preceeding data (i.e. it will generate a curve). diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 5c69183d778..9bdd9bf1785 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -20,9 +20,14 @@ extern "C" { #include "BKE_DerivedMesh.h" +#include "BKE_fcurve.h" #include "BLI_util.h" #include "BLI_fileops.h" +#include "ED_keyframing.h" } + +#include "MEM_guardedalloc.h" + #include "BKE_scene.h" #include "BKE_global.h" #include "BKE_main.h" @@ -1659,6 +1664,8 @@ public: class AnimationExporter: COLLADASW::LibraryAnimations { Scene *scene; + std::map > fcurves_actionGroup_map; + std::map > rotfcurves_actionGroup_map; public: AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) {} @@ -1749,8 +1756,11 @@ public: { std::string source_id = anim_id + get_semantic_suffix(semantic); - bool is_rotation = !strcmp(fcu->rna_path, "rotation"); - + //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); + bool is_rotation = false; + + if (strstr(fcu->rna_path, "rotation")) is_rotation = true; + COLLADASW::FloatSourceF source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); @@ -1780,7 +1790,7 @@ public: { std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION); - bool is_rotation = !strcmp(fcu->rna_path, "rotation"); + //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); COLLADASW::NameSource source(mSW); source.setId(source_id); @@ -1805,18 +1815,33 @@ public: std::string get_transform_sid(char *rna_path, const char *axis_name) { - if (!strcmp(rna_path, "rotation")) - return std::string(rna_path) + axis_name; + // if (!strcmp(rna_path, "rotation")) +// return std::string(rna_path) + axis_name; - return std::string(rna_path) + "." + axis_name; +// return std::string(rna_path) + "." + axis_name; + std::string new_rna_path; + + if (strstr(rna_path, "rotation")) { + new_rna_path = strstr(rna_path, "rotation"); + return new_rna_path + axis_name; + } + else if (strstr(rna_path, "location")) { + new_rna_path = strstr(rna_path, "location"); + return new_rna_path + "." + axis_name; + } + else if (strstr(rna_path, "scale")) { + new_rna_path = strstr(rna_path, "scale"); + return new_rna_path + "." + axis_name; + } + return NULL; } - void add_animation(FCurve *fcu, std::string ob_name/*const char *ob_name*/) + void add_animation(FCurve *fcu, std::string ob_name) { const char *axis_names[] = {"X", "Y", "Z"}; const char *axis_name = NULL; char c_anim_id[100]; // careful! - + if (fcu->array_index < 3) axis_name = axis_names[fcu->array_index]; @@ -1847,32 +1872,189 @@ public: addSampler(sampler); - //std::string target = std::string(ob_name) + "/" + get_transform_sid(fcu->rna_path, axis_name); std::string target = ob_name + "/" + get_transform_sid(fcu->rna_path, axis_name); addChannel(COLLADABU::URI(empty, sampler_id), target); closeAnimation(); } + + void add_bone_animation(FCurve *fcu, std::string ob_name, std::string bone_name) + { + const char *axis_names[] = {"X", "Y", "Z"}; + const char *axis_name = NULL; + char c_anim_id[100]; // careful! + + if (fcu->array_index < 3) + axis_name = axis_names[fcu->array_index]; + + std::string transform_sid = get_transform_sid(fcu->rna_path, axis_name); + + BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str()); + std::string anim_id(c_anim_id); + + // check rna_path is one of: rotation, scale, location + + openAnimation(anim_id); + + // create input source + std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name); + + // create output source + std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name); + + std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); + std::string empty; + sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + + // this input is required + sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + addSampler(sampler); + + std::string target = ob_name + "_" + bone_name + "/" + transform_sid; + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + } + + FCurve *create_fcurve(int array_index, char *rna_path) + { + FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); + + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); + fcu->array_index = array_index; + return fcu; + } + + void create_bezt(FCurve *fcu, float frame, float output) + { + BezTriple bez; + memset(&bez, 0, sizeof(BezTriple)); + bez.vec[1][0] = frame; + bez.vec[1][1] = output; + bez.ipo = U.ipo_new; /* use default interpolation mode here... */ + bez.f1 = bez.f2 = bez.f3 = SELECT; + bez.h1 = bez.h2 = HD_AUTO; + insert_bezt_fcurve(fcu, &bez); + calchandles_fcurve(fcu); + } + + void change_quat_to_eul(Object *ob, bActionGroup *grp, char *grpname) + { + std::vector &rot_fcurves = rotfcurves_actionGroup_map[grp]; + + FCurve *quatcu[4] = {NULL, NULL, NULL, NULL}; + int i; + + for (i = 0; i < rot_fcurves.size(); i++) + quatcu[rot_fcurves[i]->array_index] = rot_fcurves[i]; + + char *rna_path = rot_fcurves[0]->rna_path; + + FCurve *eulcu[3] = { + create_fcurve(0, rna_path), + create_fcurve(1, rna_path), + create_fcurve(2, rna_path) + }; + + for (i = 0; i < 4; i++) { + + FCurve *cu = quatcu[i]; + + if (!cu) continue; + + for (int j = 0; j < cu->totvert; j++) { + float frame = cu->bezt[j].vec[1][0]; + + float quat[4] = { + quatcu[0] ? evaluate_fcurve(quatcu[0], frame) : 0.0f, + quatcu[1] ? evaluate_fcurve(quatcu[1], frame) : 0.0f, + quatcu[2] ? evaluate_fcurve(quatcu[2], frame) : 0.0f, + quatcu[3] ? evaluate_fcurve(quatcu[3], frame) : 0.0f + }; + + float eul[3]; + + QuatToEul(quat, eul); + + for (int k = 0; k < 3; k++) + create_bezt(eulcu[k], frame, eul[k]); + } + } + + for (i = 0; i < 3; i++) { + add_bone_animation(eulcu[i], id_name(ob), std::string(grpname)); + free_fcurve(eulcu[i]); + } + } // called for each exported object void operator() (Object *ob) { if (!ob->adt || !ob->adt->action) return; - - // XXX this needs to be handled differently? - if (ob->type == OB_ARMATURE) return; - + FCurve *fcu = (FCurve*)ob->adt->action->curves.first; - while (fcu) { - - if (!strcmp(fcu->rna_path, "location") || - !strcmp(fcu->rna_path, "scale") || - !strcmp(fcu->rna_path, "rotation")) { - - add_animation(fcu, id_name(ob)/*ob->id.name*/); + + if (ob->type == OB_ARMATURE) { + + while (fcu) { + + if (strstr(fcu->rna_path, ".rotation")) + rotfcurves_actionGroup_map[fcu->grp].push_back(fcu); + else fcurves_actionGroup_map[fcu->grp].push_back(fcu); + + fcu = fcu->next; + } + + for (bPoseChannel *pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + int i; + char *grpname = pchan->name; + bActionGroup *grp = action_groups_find_named(ob->adt->action, grpname); + + if (!grp) continue; + + // write animation for location & scaling + if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) continue; + + std::vector &fcurves = fcurves_actionGroup_map[grp]; + for (i = 0; i < fcurves.size(); i++) + add_bone_animation(fcurves[i], id_name(ob), std::string(grpname)); + + // ... for rotation + if (rotfcurves_actionGroup_map.find(grp) == rotfcurves_actionGroup_map.end()) + continue; + + // if rotation mode is euler - no need to convert it + if (pchan->rotmode == PCHAN_ROT_EUL) { + + std::vector &rotfcurves = rotfcurves_actionGroup_map[grp]; + + for (i = 0; i < rotfcurves.size(); i++) + add_bone_animation(rotfcurves[i], id_name(ob), std::string(grpname)); + } + + // convert rotation to euler & write animation + else change_quat_to_eul(ob, grp, grpname); + } + } + else { + while (fcu) { + + if (!strcmp(fcu->rna_path, "location") || + !strcmp(fcu->rna_path, "scale") || + !strcmp(fcu->rna_path, "rotation")) { + + add_animation(fcu, id_name(ob)); + } + + fcu = fcu->next; } - - fcu = fcu->next; } } }; diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index afaba19e2bc..f6c40d2e058 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -2174,7 +2174,7 @@ public: create_fcurve(0, rna_path), create_fcurve(1, rna_path), create_fcurve(2, rna_path), - create_fcurve(3, rna_path), + create_fcurve(3, rna_path) }; for (i = 0; i < 3; i++) { @@ -2189,7 +2189,7 @@ public: float eul[3] = { eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f, eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f, - eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f, + eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f }; float quat[4]; diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 64672e3502b..c4d5934b180 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -135,7 +135,7 @@ typedef struct bCommonKeySrc { /* -------- */ /* mode for modify_keyframes */ -enum { +typedef enum eModifyKey_Modes { MODIFYKEY_MODE_INSERT = 0, MODIFYKEY_MODE_DELETE, } eModifyKey_Modes; @@ -220,7 +220,7 @@ short id_frame_has_keyframe(struct ID *id, float frame, short filter); * WARNING: do not alter order of these, as also stored in files * (for v3d->keyflags) */ -enum { +typedef enum eAnimFilterFlags { /* general */ ANIMFILTER_KEYS_LOCAL = (1<<0), /* only include locally available anim data */ ANIMFILTER_KEYS_MUTED = (1<<1), /* include muted elements */