Added export skinned animation.
authorChingiz Dyussenov <chingiz.ds@gmail.com>
Fri, 28 Aug 2009 04:50:35 +0000 (04:50 +0000)
committerChingiz Dyussenov <chingiz.ds@gmail.com>
Fri, 28 Aug 2009 04:50:35 +0000 (04:50 +0000)
source/blender/blenkernel/BKE_fcurve.h
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/editors/include/ED_keyframing.h

index cda64c6b2416a7470d36032c408310e5dbad1e13..580750fd4b2bc0841f58bdc3420399d8b983f9f4 100644 (file)
@@ -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). 
index 5c69183d77864ddde6824de73cfb138af10ea687..9bdd9bf17856f5e37e43452c522ff6a22f829411 100644 (file)
 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<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map;
+       std::map<bActionGroup*, std::vector<FCurve*> > 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();
        }
-
-       // called for each exported object
-       void operator() (Object *ob) 
+       
+       void add_bone_animation(FCurve *fcu, std::string ob_name, std::string bone_name)
        {
-               if (!ob->adt || !ob->adt->action) return;
+               const char *axis_names[] = {"X", "Y", "Z"};
+               const char *axis_name = NULL;
+               char c_anim_id[100]; // careful!
 
-               // XXX this needs to be handled differently?
-               if (ob->type == OB_ARMATURE) return;
+               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);
 
-               FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
-               while (fcu) {
+               // check rna_path is one of: rotation, scale, location
 
-                       if (!strcmp(fcu->rna_path, "location") ||
-                               !strcmp(fcu->rna_path, "scale") ||
-                               !strcmp(fcu->rna_path, "rotation")) {
+               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));
 
-                               add_animation(fcu, id_name(ob)/*ob->id.name*/);
+               // 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<FCurve*> &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]);
+               }
+       }
 
-                       fcu = fcu->next;
+       // called for each exported object
+       void operator() (Object *ob) 
+       {
+               if (!ob->adt || !ob->adt->action) return;
+               
+               FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
+               
+               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<FCurve*> &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<FCurve*> &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;
+                       }
                }
        }
 };
index afaba19e2bcef78d763e341f588f4ce28fca5272..f6c40d2e058c9f0da82fe656e9032afad7941769 100644 (file)
@@ -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];
index 64672e3502b1ffa5e5e2ed0999a24e292c57da46..c4d5934b180b8e56fe751bcee08ac2a557b6f897 100644 (file)
@@ -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 */