Adding support for Matrix Transformation export
authorGaia Clary <gaia.clary@machinimatrix.org>
Mon, 26 Feb 2018 15:34:45 +0000 (16:34 +0100)
committerGaia Clary <gaia.clary@machinimatrix.org>
Mon, 26 Feb 2018 16:16:56 +0000 (17:16 +0100)
The exporter does export matrix data (4*4 Transformation matrix) only for Skeletal animation. For object animation only exporting to trans/rot/loc is implemented.

This task implements Matrix export also for simple Object animation.

Differential Revision: https://developer.blender.org/D3082

12 files changed:
source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationExporter.h
source/blender/collada/ControllerExporter.cpp
source/blender/collada/DocumentExporter.cpp
source/blender/collada/ExportSettings.h
source/blender/collada/SceneExporter.cpp
source/blender/collada/SceneExporter.h
source/blender/collada/collada.cpp
source/blender/collada/collada.h
source/blender/collada/collada_utils.cpp
source/blender/collada/collada_utils.h
source/blender/editors/io/io_collada.c

index cf689a4a3eb6a35318d86d5f4b6c0b983a80de95..8c0733374a189e5aff21a427d2510bd0af5b7a82 100644 (file)
@@ -49,7 +49,16 @@ bool AnimationExporter::exportAnimations(Scene *sce)
        return has_animations;
 }
 
-
+bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
+{
+       for (int i = 0; i < values.size(); i += channel_count) {
+               for (int j = 0; j < channel_count; j++) {
+                       if (!bc_in_range(values[j], values[i+j], 0.000001))
+                               return false;
+               }
+       }
+       return true;
+}
 /*
  *  This function creates a complete LINEAR Collada <Animation> Entry with all needed 
  *  <source>, <sampler>, and <channel> entries.
@@ -83,9 +92,11 @@ void AnimationExporter::create_sampled_animation(int channel_count,
        std::string axis_name,
        bool is_rot)
 {
-
        char anim_id[200];
 
+       if (is_flat_line(values, channel_count))
+               return;
+
        BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
 
        openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
@@ -97,8 +108,10 @@ void AnimationExporter::create_sampled_animation(int channel_count,
        std::string output_id;
        if (channel_count == 1)
                output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
-       else if(channel_count == 3)
+       else if (channel_count == 3)
                output_id = create_xyz_source(&values[0], times.size(), anim_id);
+       else if (channel_count == 16)
+               output_id = create_4x4_source(times, values, anim_id);
 
        std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
        COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
@@ -135,26 +148,38 @@ void AnimationExporter::create_sampled_animation(int channel_count,
 void AnimationExporter::export_keyframed_animation_set(Object *ob)
 {
        FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
+       if (!fcu) {
+               return; /* object has no animation */
+       }
 
-       char *transformName;
-       while (fcu) {
-               //for armature animations as objects
-               if (ob->type == OB_ARMATURE)
-                       transformName = fcu->rna_path;
-               else
-                       transformName = extract_transform_name(fcu->rna_path);
+       if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
 
-               if (
-                       STREQ(transformName, "location") ||
-                       STREQ(transformName, "scale") ||
-                       (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
-                       STREQ(transformName, "rotation_quaternion"))
-               {
-                       create_keyframed_animation(ob, fcu, transformName, false);
-               }
-               fcu = fcu->next;
+               std::vector<float> ctimes;
+               std::vector<float[4][4]> values;
+               find_keyframes(ob, ctimes);
+               if (ctimes.size() > 0)
+                       export_sampled_matrix_animation(ob, ctimes);
        }
+       else {
+               char *transformName;
+               while (fcu) {
+                       //for armature animations as objects
+                       if (ob->type == OB_ARMATURE)
+                               transformName = fcu->rna_path;
+                       else
+                               transformName = extract_transform_name(fcu->rna_path);
 
+                       if (
+                               STREQ(transformName, "location") ||
+                               STREQ(transformName, "scale") ||
+                               (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
+                               STREQ(transformName, "rotation_quaternion"))
+                       {
+                               create_keyframed_animation(ob, fcu, transformName, false);
+                       }
+                       fcu = fcu->next;
+               }
+       }
 }
 
 /*
@@ -170,20 +195,53 @@ void AnimationExporter::export_keyframed_animation_set(Object *ob)
  * Also keyframed animation exports tend to break when negative scales are involved.
  */
 void AnimationExporter::export_sampled_animation_set(Object *ob)
+{
+       std::vector<float>ctimes;
+       find_sampleframes(ob, ctimes);
+       if (ctimes.size() > 0) {
+               if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
+                       export_sampled_matrix_animation(ob, ctimes);
+               else
+                       export_sampled_transrotloc_animation(ob, ctimes);
+       }
+}
+
+void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
+{
+       UnitConverter converter;
+
+       std::vector<float> values;
+
+       for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
+               float fmat[4][4];
+               float outmat[4][4];
+
+               bc_update_scene(scene, *ctime);
+               BKE_object_matrix_local_get(ob, fmat);
+               converter.mat4_to_dae(outmat, fmat);
+
+               if (this->export_settings->limit_precision)
+                       bc_sanitize_mat(outmat, 6);
+
+               for (int i = 0; i < 4; i++)
+                       for (int j = 0; j < 4; j++)
+                               values.push_back(outmat[j][i]);
+       }
+
+       std::string ob_name = id_name(ob);
+
+       create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
+}
+
+void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
 {
        static int LOC   = 0;
        static int EULX  = 1;
        static int EULY  = 2;
        static int EULZ  = 3;
        static int SCALE = 4;
-       static int TIME  = 5;
-
-       if (this->export_settings->sampling_rate < 1)
-               return; // to avoid infinite loop
 
-       std::vector<float> baked_curves[6];
-       std::vector<float> &ctimes = baked_curves[TIME];
-       find_sampleframes(ob, ctimes);
+       std::vector<float> baked_curves[5];
 
        for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
                float fmat[4][4];
@@ -192,7 +250,7 @@ void AnimationExporter::export_sampled_animation_set(Object *ob)
                float fsize[3];
                float feul[3];
 
-               evaluate_anim_with_constraints(ob, *ctime); // set object transforms to the frame
+               bc_update_scene(scene, *ctime);
 
                BKE_object_matrix_local_get(ob, fmat);
                mat4_decompose(floc, fquat, fsize, fmat);
@@ -214,16 +272,16 @@ void AnimationExporter::export_sampled_animation_set(Object *ob)
 
        std::string ob_name = id_name(ob);
 
-       create_sampled_animation(3, baked_curves[TIME], baked_curves[SCALE], ob_name, "scale",   "", false);
-       create_sampled_animation(3, baked_curves[TIME], baked_curves[LOC],  ob_name, "location", "", false);
+       create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale",   "", false);
+       create_sampled_animation(3, ctimes, baked_curves[LOC],  ob_name, "location", "", false);
 
        /* Not sure how to export rotation as a 3channel animation, 
         * so separate into 3 single animations for now:
         */
 
-       create_sampled_animation(1, baked_curves[TIME], baked_curves[EULX], ob_name, "rotation", "X", true);
-       create_sampled_animation(1, baked_curves[TIME], baked_curves[EULY], ob_name, "rotation", "Y", true);
-       create_sampled_animation(1, baked_curves[TIME], baked_curves[EULZ], ob_name, "rotation", "Z", true);
+       create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
+       create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
+       create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
 
        fprintf(stdout, "Animation Export: Baked %zd frames for %s (sampling rate: %d)\n",
                baked_curves[0].size(),
@@ -242,19 +300,19 @@ void AnimationExporter::operator()(Object *ob)
        if (ob->adt && ob->adt->action) {
 
                if (ob->type == OB_ARMATURE) {
+                       /* Export skeletal animation (if any)*/
                        bArmature *arm = (bArmature *)ob->data;
                        for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
                                write_bone_animation_matrix(ob, bone);
                }
+
+               /* Armatures can have object animation and skeletal animation*/
+               if (this->export_settings->sampling_rate < 1) {
+                       export_keyframed_animation_set(ob);
+               }
                else {
-                       if (this->export_settings->sampling_rate == -1) {
-                               export_keyframed_animation_set(ob);
-                       }
-                       else {
-                               export_sampled_animation_set(ob);
-                       }
+                       export_sampled_animation_set(ob);
                }
-
        }
 
        export_object_constraint_animation(ob);
@@ -1186,9 +1244,51 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti
        return source_id;
 }
 
+std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
+{
+       COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
+       std::string source_id = anim_id + get_semantic_suffix(semantic);
+
+       COLLADASW::Float4x4Source source(mSW);
+       source.setId(source_id);
+       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+       source.setAccessorCount(ctimes.size());
+       source.setAccessorStride(16);
+
+       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+       add_source_parameters(param, semantic, false, NULL, true);
+
+       source.prepareToAppendValues();
+
+       bPoseChannel *parchan = NULL;
+       bPoseChannel *pchan = NULL;
+
+
+       std::vector<float>::iterator it;
+
+       for (it = values.begin(); it != values.end(); it+=16) {
+               float mat[4][4];
+
+               bc_copy_m4_farray(mat, &*it);
+
+               UnitConverter converter;
+               double outmat[4][4];
+               converter.mat4_to_dae_double(outmat, mat);
+
+               if (this->export_settings->limit_precision)
+                       bc_sanitize_mat(outmat, 6);
+
+               source.appendValues(outmat);
+       }
+
+       source.finish();
+       return source_id;
+}
 
 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
 {
+       bool is_bone_animation = ob->type == OB_ARMATURE && bone;
+
        COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
        std::string source_id = anim_id + get_semantic_suffix(semantic);
 
@@ -1206,7 +1306,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
        bPoseChannel *parchan = NULL;
        bPoseChannel *pchan = NULL;
 
-       if (ob->type == OB_ARMATURE && bone) {
+       if (is_bone_animation) {
                bPose *pose = ob->pose;
                pchan = BKE_pose_channel_find_name(pose, bone->name);
                if (!pchan)
@@ -1224,11 +1324,8 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
                float frame = *it;
 
                float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
-               CFRA = BKE_scene_frame_get_from_ctime(scene, frame);
-               //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene,scene->lay);
-               BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
-                               
-               if (bone) {
+               bc_update_scene(scene, ctime);
+               if (is_bone_animation) {
                        if (pchan->flag & POSE_CHAIN) {
                                enable_fcurves(ob->adt->action, NULL);
                                BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
@@ -1268,10 +1365,6 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
 
                }
                else {
-                       BKE_scene_frame_set(scene, ctime);
-                       Main *bmain = bc_get_main();
-                       EvaluationContext *ev_context = bc_get_evaluation_context();
-                       BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
                        copy_m4_m4(mat, ob->obmat);
                }
                
index b26b0427f33665de6ae69c61948990044e3bd0d7..52b463535281cb8a5ebae5dadbac593b6f0a617b 100644 (file)
@@ -144,9 +144,12 @@ protected:
        
        float* get_eul_source_for_quat(Object *ob );
 
+       bool is_flat_line(std::vector<float> &values, int channel_count);
        void export_keyframed_animation_set(Object *ob);
        void create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
        void export_sampled_animation_set(Object *ob);
+       void export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes);
+       void export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes);
        void create_sampled_animation(int channel_count, std::vector<float> &times, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot);
 
        void evaluate_anim_with_constraints(Object *ob, float ctime);
@@ -161,7 +164,7 @@ protected:
        std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name);
 
        std::string create_xyz_source(float *v, int tot, const std::string& anim_id);
-
+       std::string create_4x4_source(std::vector<float> &times, std::vector<float> &values, const std::string& anim_id);
        std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id);
 
        std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
index 5cd5e6d271a6d48f4ac6577245c3b75cb7691e74..4afe71f47ba8a51828095402e84541449749eb5d 100644 (file)
@@ -282,7 +282,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
                }
 
                if (oob_counter > 0) {
-                       fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %lu.\n",
+                       fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n",
                                oob_counter, joint_index_by_def_index.size());
                }
        }
index 957fec50e4ba0173bfe2936700e657bd7a6ffb24..7ed5d8ff69345823d023fd0db8777f657516dafe 100644 (file)
@@ -302,29 +302,11 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
 
        SceneExporter se(writer, &arm_exporter, this->export_settings);
 
-       // <library_animations>
-       AnimationExporter ae(writer, this->export_settings);
-
-#if 0
-       bool has_animations = ae.exportAnimations(sce);
-       /* The following code seems to be an obsolete workaround
-       Comment out until it proofs correct that we no longer need it.
-       */
-       if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
-               // channels adressing <matrix> objects is not (yet) supported
-               // So we force usage of <location>, <translation> and <scale>
-               fprintf(stdout, 
-                       "For animated Ojects we must use decomposed <matrix> elements,\n" \
-                       "Forcing usage of TransLocRot transformation type.");
-               se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC);
+       if (this->export_settings->include_animations) {
+               // <library_animations>
+               AnimationExporter ae(writer, this->export_settings);
+               ae.exportAnimations(sce);
        }
-       else {
-               se.setExportTransformationType(this->export_settings->export_transformation_type);
-       }
-#else
-       ae.exportAnimations(sce);
-       se.setExportTransformationType(this->export_settings->export_transformation_type);
-#endif
        se.exportScene(sce);
        
        // <scene>
index 3b0b5708c7ce291370ad8961d7c43142f5948d95..73a101108a9d0423cf665a5b835f364fd5dfc64e 100644 (file)
@@ -39,6 +39,7 @@ public:
        bool include_armatures;
        bool include_shapekeys;
        bool deform_bones_only;
+       bool include_animations;
        int sampling_rate;
 
        bool active_uv_only;
index 739455399313f92477be693a0893b80d7efb0fb0..5a0badf8d3a96aa35899ff3e3bb3d28ca4fb1dff 100644 (file)
@@ -38,11 +38,6 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm,
 {
 }
 
-void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type)
-{
-       this->transformation_type = transformation_type;
-}
-
 void SceneExporter::exportScene(Scene *sce)
 {
        // <library_visual_scenes> <visual_scene>
@@ -138,7 +133,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
                // for skinned mesh we write obmat in <bind_shape_matrix>
                TransformWriter::add_node_transform_identity(colladaNode);
        else {
-               TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type);
+               TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type);
        }
 
        // <instance_geometry>
index c7c15dba2cbb59d038872aac3063c2a1b761c7ad..b896b9abd8d28b83f2b08d9d6d7bd4fd892c57ec 100644 (file)
@@ -97,11 +97,8 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter,
 public:
        SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
        void exportScene(Scene *sce);
-       void setExportTransformationType(BC_export_transformation_type transformation_type);
 
 private:
-       BC_export_transformation_type transformation_type;
-       // required for writeNodes() for bone-parented objects
        friend class ArmatureExporter;
        void exportHierarchy(Scene *sce);
        void writeNodes(Object *ob, Scene *sce);
index 79f50888150026d98ef64369ca343fe450f4fe40..9605dae275bc611a2511b57af85dfca89bdea5a7 100644 (file)
@@ -78,6 +78,7 @@ int collada_export(Scene *sce,
                    int include_armatures,
                                   int include_shapekeys,
                    int deform_bones_only,
+                                  int include_animations,
                    int sampling_rate,
 
                                   int active_uv_only,
@@ -104,7 +105,8 @@ int collada_export(Scene *sce,
        export_settings.include_armatures        = include_armatures != 0;
        export_settings.include_shapekeys        = include_shapekeys != 0;
        export_settings.deform_bones_only        = deform_bones_only != 0;
-       export_settings.sampling_rate            = sampling_rate;
+       export_settings.include_animations       = include_animations;
+       export_settings.sampling_rate = sampling_rate;
 
        export_settings.active_uv_only           = active_uv_only != 0;
        export_settings.export_texture_type      = export_texture_type;
index a8f082f630c8f8c0061f08d6f8c959df776c5bb8..99f601b7db712be83dd553bde446b5212717e0bb 100644 (file)
@@ -77,6 +77,7 @@ int collada_export(struct Scene *sce,
                    int include_armatures,
                    int include_shapekeys,
                    int deform_bones_only,
+                                  int include_animations,
                    int sampling_rate,
 
                    int active_uv_only,
index 9f984a33ed12502f605fa0cf1c766c228d36b15a..fcd92e220c0ab3bcd80270c248b91251e483d2b1 100644 (file)
@@ -144,6 +144,14 @@ EvaluationContext *bc_get_evaluation_context()
        return bmain->eval_ctx;
 }
 
+void bc_update_scene(Scene *scene, float ctime)
+{
+       BKE_scene_frame_set(scene, ctime);
+       Main *bmain = bc_get_main();
+       EvaluationContext *ev_context = bc_get_evaluation_context();
+       BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
+}
+
 Object *bc_add_object(Scene *scene, int type, const char *name)
 {
        Object *ob = BKE_object_add_only_object(G.main, type, name);
@@ -883,6 +891,21 @@ void bc_sanitize_mat(double mat[4][4], int precision)
                        mat[i][j] = double_round(mat[i][j], precision);
 }
 
+void bc_copy_m4_farray(float r[4][4], float *a)
+{
+       for (int i = 0; i < 4; i++)
+               for (int j = 0; j < 4; j++)
+                       r[i][j] = *a++;
+}
+
+void bc_copy_farray_m4(float *r, float a[4][4])
+{
+       for (int i = 0; i < 4; i++)
+               for (int j = 0; j < 4; j++)
+                       *r++ = a[i][j];
+
+}
+
 /*
 * Returns name of Active UV Layer or empty String if no active UV Layer defined.
 * Assuming the Object is of type MESH
index 8b5903b9746c78b7fe34ca27537403e8146bcfd7..bbe36f2999c66f60b48f99aeaf8f6b44a3a1c993 100644 (file)
@@ -65,6 +65,7 @@ typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureA
 
 extern Main *bc_get_main();
 extern EvaluationContext *bc_get_evaluation_context();
+extern void bc_update_scene(Scene *scene, float ctime);
 
 extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index);
 extern int bc_test_parent_loop(Object *par, Object *ob);
@@ -102,6 +103,13 @@ extern bool bc_is_leaf_bone(Bone *bone);
 extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
 extern int bc_set_layer(int bitfield, int layer, bool enable);
 extern int bc_set_layer(int bitfield, int layer);
+
+inline bool bc_in_range(float a, float b, float range) {
+       return abs(a - b) < range;
+}
+void bc_copy_m4_farray(float r[4][4], float *a);
+void bc_copy_farray_m4(float *r, float a[4][4]);
+
 extern void bc_sanitize_mat(float mat[4][4], int precision);
 extern void bc_sanitize_mat(double mat[4][4], int precision);
 
index 3746ba3b64a9c0d5157a268ea82a9331f03160d8..35b73065843b615d926d42d9d2e4877a74fb456a 100644 (file)
@@ -86,6 +86,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
        int include_armatures;
        int include_shapekeys;
        int deform_bones_only;
+
+       int include_animations;
+       int sample_animations;
        int sampling_rate;
 
        int export_texture_type;
@@ -137,7 +140,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
        include_children         = RNA_boolean_get(op->ptr, "include_children");
        include_armatures        = RNA_boolean_get(op->ptr, "include_armatures");
        include_shapekeys        = RNA_boolean_get(op->ptr, "include_shapekeys");
-       sampling_rate             = RNA_int_get(op->ptr,     "sampling_rate");
+
+       include_animations       = RNA_boolean_get(op->ptr, "include_animations");
+       sample_animations        = RNA_boolean_get(op->ptr, "sample_animations");
+       sampling_rate            = (sample_animations)? RNA_int_get(op->ptr, "sampling_rate") : 0;
+
        deform_bones_only        = RNA_boolean_get(op->ptr, "deform_bones_only");
 
        export_texture_type      = RNA_enum_get(op->ptr, "export_texture_type_selection");
@@ -167,6 +174,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
                include_armatures,
                include_shapekeys,
                deform_bones_only,
+               include_animations,
                sampling_rate,
 
                active_uv_only,
@@ -203,6 +211,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
 static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
 {
        uiLayout *box, *row, *col, *split;
+       bool include_animations = RNA_boolean_get(imfptr, "include_animations");
 
        /* Export Options: */
        box = uiLayoutBox(layout);
@@ -233,9 +242,15 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
        uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
 
        row = uiLayoutRow(box, false);
-       uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
+       uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
+       row = uiLayoutRow(box, false);
+       if (include_animations) {
+               uiItemR(row, imfptr, "sample_animations", 0, NULL, ICON_NONE);
+               row = uiLayoutColumn(box, false);
+               uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
+               uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "sample_animations"));
+       }
 
-       
        /* Texture options */
        box = uiLayoutBox(layout);
        row = uiLayoutRow(box, false);
@@ -278,7 +293,6 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
        split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
        uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
        uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
-
        row = uiLayoutRow(box, false);
        uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
 
@@ -376,8 +390,14 @@ void WM_OT_collada_export(wmOperatorType *ot)
        RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
                        "Only export deforming bones with armatures");
 
-       RNA_def_int(func, "sampling_rate", 0, -1, INT_MAX,
-               "Samplintg Rate", "The maximum distance of frames between 2 keyframes. Disabled when value is -1", -1, INT_MAX);
+       RNA_def_boolean(func, "include_animations", false,
+               "Include Animations", "Export Animations if available.\nExporting Animations will enforce the decomposition of node transforms\ninto  <translation> <rotation> and <scale> components");
+
+       RNA_def_boolean(func, "sample_animations", 0,
+               "Sample Animations", "Auto-generate keyframes with a frame distance set by 'Sampling Rate'.\nWhen disabled, export only the keyframes defined in the animation f-curves (may be less accurate)");
+
+       RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX,
+               "Sampling Rate", "The distance between 2 keyframes. 1 means: Every frame is keyed", 1, INT_MAX);
 
        RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
                        "Export only the selected UV Map");