Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/collada/AnimationCurveCache.cpp')
-rw-r--r--source/blender/collada/AnimationCurveCache.cpp391
1 files changed, 391 insertions, 0 deletions
diff --git a/source/blender/collada/AnimationCurveCache.cpp b/source/blender/collada/AnimationCurveCache.cpp
new file mode 100644
index 00000000000..3ad921baffe
--- /dev/null
+++ b/source/blender/collada/AnimationCurveCache.cpp
@@ -0,0 +1,391 @@
+/*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+#include "AnimationCurveCache.h"
+
+extern "C" {
+#include "BKE_action.h"
+#include "BLI_listbase.h"
+}
+
+AnimationCurveCache::AnimationCurveCache(bContext *C):
+ mContext(C)
+{
+}
+
+AnimationCurveCache::~AnimationCurveCache()
+{
+ clear_cache();
+}
+
+void AnimationCurveCache::clear_cache()
+{
+
+}
+
+void AnimationCurveCache::clear_cache(Object *ob)
+{
+
+}
+
+void AnimationCurveCache::create_curves(Object *ob)
+{
+
+}
+
+void AnimationCurveCache::addObject(Object *ob)
+{
+ cached_objects.push_back(ob);
+}
+
+bool AnimationCurveCache::bone_matrix_local_get(Object *ob, Bone *bone, float(&mat)[4][4], bool for_opensim)
+{
+
+ /* Ok, lets be super cautious and check if the bone exists */
+ bPose *pose = ob->pose;
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ if (!pchan) {
+ return false;
+ }
+
+ bAction *action = bc_getSceneObjectAction(ob);
+ bPoseChannel *parchan = pchan->parent;
+ enable_fcurves(action, bone->name);
+ float ipar[4][4];
+
+ if (bone->parent) {
+ invert_m4_m4(ipar, parchan->pose_mat);
+ mul_m4_m4m4(mat, ipar, pchan->pose_mat);
+ }
+ else
+ copy_m4_m4(mat, pchan->pose_mat);
+
+ /* OPEN_SIM_COMPATIBILITY
+ * AFAIK animation to second life is via BVH, but no
+ * reason to not have the collada-animation be correct
+ */
+ if (for_opensim) {
+ float temp[4][4];
+ copy_m4_m4(temp, bone->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
+
+ mul_m4_m4m4(mat, mat, temp);
+
+ if (bone->parent) {
+ copy_m4_m4(temp, bone->parent->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, temp, mat);
+ }
+ }
+
+ return true;
+}
+
+void AnimationCurveCache::sampleMain(Scene *scene, BC_export_transformation_type atm_type, bool for_opensim)
+{
+ std::map<int, std::vector<SamplePoint>>::iterator frame;
+ for (frame = sample_frames.begin(); frame != sample_frames.end(); frame++) {
+ int frame_index = frame->first;
+ std::vector<SamplePoint> sample_points = frame->second;
+
+ bc_update_scene(mContext, scene, frame_index);
+
+ for (int spi = 0; spi < sample_points.size(); spi++) {
+ SamplePoint &point = sample_points[spi];
+ Object *ob = point.get_object();
+ float mat[4][4];
+
+ if (ob->type == OB_ARMATURE) {
+ /* For Armatures we need to check if this maybe is a pose sample point*/
+ Bone *bone = point.get_bone();
+ if (bone) {
+ if (bone_matrix_local_get(ob, bone, mat, for_opensim)) {
+ point.set_matrix(mat);
+ }
+ continue;
+ }
+ }
+
+ /* When this SamplePoint is not for a Bone,
+ * then we just store the Object local matrix here
+ */
+
+ BKE_object_matrix_local_get(ob, mat);
+ point.set_matrix(mat);
+
+ }
+ }
+}
+
+/*
+* enable fcurves driving a specific bone, disable all the rest
+* if bone_name = NULL enable all fcurves
+*/
+void AnimationCurveCache::enable_fcurves(bAction *act, char *bone_name)
+{
+ FCurve *fcu;
+ char prefix[200];
+
+ if (bone_name)
+ BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
+
+ for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
+ if (bone_name) {
+ if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
+ fcu->flag &= ~FCURVE_DISABLED;
+ else
+ fcu->flag |= FCURVE_DISABLED;
+ }
+ else {
+ fcu->flag &= ~FCURVE_DISABLED;
+ }
+ }
+}
+/*
+* Sample the scene at frames where object fcurves
+* have defined keys.
+*/
+void AnimationCurveCache::sampleScene(Scene *scene, BC_export_transformation_type atm_type, bool for_opensim, bool keyframe_at_end)
+{
+ create_sample_frames_from_keyframes();
+ sampleMain(scene, atm_type, for_opensim);
+}
+
+void AnimationCurveCache::sampleScene(Scene *scene, BC_export_transformation_type atm_type, int sampling_rate, bool for_opensim, bool keyframe_at_end)
+{
+ create_sample_frames_generated(scene->r.sfra, scene->r.efra, sampling_rate, keyframe_at_end);
+ sampleMain(scene, atm_type, for_opensim);
+}
+
+std::vector<FCurve *> *AnimationCurveCache::getSampledCurves(Object *ob)
+{
+ std::map<Object *, std::vector<FCurve *>>::iterator fcurves;
+ fcurves = cached_curves.find(ob);
+ return (fcurves == cached_curves.end()) ? NULL : &fcurves->second;
+}
+
+std::vector<SamplePoint> &AnimationCurveCache::getFrameInfos(int frame_index)
+{
+ std::map<int, std::vector<SamplePoint>>::iterator frames = sample_frames.find(frame_index);
+ if (frames == sample_frames.end()) {
+ std::vector<SamplePoint> sample_points;
+ sample_frames[frame_index] = sample_points;
+ }
+ return sample_frames[frame_index];
+}
+
+
+void AnimationCurveCache::add_sample_point(SamplePoint &point)
+{
+ int frame_index = point.get_frame();
+ std::vector<SamplePoint> &frame_infos = getFrameInfos(frame_index);
+ frame_infos.push_back(point);
+}
+
+/*
+* loop over all cached objects
+* loop over all fcurves
+* record all keyframes
+*
+* The vector sample_frames finally contains a list of vectors
+* where each vector contains a list of SamplePoints which
+* need to be processed when evaluating the animation.
+*/
+void AnimationCurveCache::create_sample_frames_from_keyframes()
+{
+ sample_frames.clear();
+ for (int i = 0; i < cached_objects.size(); i++) {
+ Object *ob = cached_objects[i];
+ bAction *action = bc_getSceneObjectAction(ob);
+ FCurve *fcu = (FCurve *)action->curves.first;
+
+ for (; fcu; fcu = fcu->next) {
+ for (unsigned int i = 0; i < fcu->totvert; i++) {
+ float f = fcu->bezt[i].vec[1][0];
+ int frame_index = int(f);
+ SamplePoint sample_point(frame_index, ob, fcu, i);
+ add_sample_point(sample_point);
+ }
+ }
+ }
+}
+
+/*
+* loop over all cached objects
+* loop over active action using a stesize of sampling_rate
+* record all frames
+*
+* The vector sample_frames finally contains a list of vectors
+* where each vector contains a list of SamplePoints which
+* need to be processed when evaluating the animation.
+* Note: The FCurves of the objects will not be used here.
+*/
+void AnimationCurveCache::create_sample_frames_generated(float sfra, float efra, int sampling_rate, int keyframe_at_end)
+{
+ sample_frames.clear();
+
+ for (int i = 0; i < cached_objects.size(); i++) {
+
+ Object *ob = cached_objects[i];
+ float f = sfra;
+
+ do {
+ int frame_index = int(f);
+ SamplePoint sample_point(frame_index, ob);
+ add_sample_point(sample_point);
+
+ /* Depending on the Object type add more sample points here
+ */
+
+ if (ob && ob->type == OB_ARMATURE) {
+ LISTBASE_FOREACH(bPoseChannel *, pchan, &ob->pose->chanbase) {
+ SamplePoint point(frame_index, ob, pchan->bone);
+ add_sample_point(sample_point);
+ }
+ }
+
+ if (f == efra)
+ break;
+ f += sampling_rate;
+ if (f > efra)
+ if (keyframe_at_end)
+ f = efra; // make sure the last frame is always exported
+ else
+ break;
+ } while (true);
+ }
+}
+
+Matrix::Matrix()
+{
+ unit_m4(matrix);
+}
+
+Matrix::Matrix(float (&mat)[4][4])
+{
+ set_matrix(mat);
+}
+
+void Matrix::set_matrix(float(&mat)[4][4])
+{
+ copy_m4_m4(matrix, mat);
+}
+
+void Matrix::set_matrix(Matrix &mat)
+{
+ copy_m4_m4(matrix, mat.matrix);
+}
+
+void Matrix::get_matrix(float(&mat)[4][4])
+{
+ copy_m4_m4(mat, matrix);
+}
+
+SamplePoint::SamplePoint(int frame, Object *ob)
+{
+ this->frame = frame;
+ this->fcu = NULL;
+ this->ob = ob;
+ this->pose_bone = NULL;
+ this->index = -1;
+}
+
+SamplePoint::SamplePoint(int frame, Object *ob, FCurve *fcu, int index)
+{
+ this->frame = frame;
+ this->fcu = fcu;
+ this->ob = ob;
+ this->pose_bone = NULL;
+ this->index = index;
+ this->path = std::string(fcu->rna_path);
+
+ /* Further elaborate on what this Fcurve is doing by checking
+ * its rna_path
+ */
+
+ if (ob && ob->type == OB_ARMATURE) {
+ char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones[");
+ bPose *pose = ob->pose;
+ if (boneName) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
+ this->pose_bone = pchan->bone;
+ }
+ }
+}
+
+
+SamplePoint::SamplePoint(int frame, Object *ob, Bone *bone)
+{
+ this->frame = frame;
+ this->fcu = NULL;
+ this->ob = ob;
+ this->pose_bone = bone;
+ this->index = -1;
+ this->path = "pose.bones[\"" + id_name(bone) + "\"].matrix";
+}
+
+Matrix &SamplePoint::get_matrix()
+{
+ return matrix;
+}
+
+void SamplePoint::set_matrix(Matrix &mat)
+{
+ this->matrix.set_matrix(mat);
+}
+
+void SamplePoint::set_matrix(float(&mat)[4][4])
+{
+
+}
+
+Object *SamplePoint::get_object()
+{
+ return this->ob;
+}
+
+Bone *SamplePoint::get_bone()
+{
+ return this->pose_bone;
+}
+
+FCurve *SamplePoint::get_fcurve()
+{
+ return this->fcu;
+}
+
+int SamplePoint::get_frame()
+{
+ return this->frame;
+}
+
+int SamplePoint::get_fcurve_index()
+{
+ return this->index;
+}
+
+std::string &SamplePoint::get_path()
+{
+ return path;
+} \ No newline at end of file