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/AnimationExporter.cpp')
-rw-r--r--source/blender/collada/AnimationExporter.cpp2028
1 files changed, 438 insertions, 1590 deletions
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index 4113e871e74..4491b7412a6 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -26,656 +26,338 @@
#include "GeometryExporter.h"
#include "AnimationExporter.h"
+#include "AnimationClipExporter.h"
+#include "BCAnimationSampler.h"
#include "MaterialExporter.h"
+#include "collada_utils.h"
-template<class Functor>
-void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
-{
- LinkNode *node;
- for (node = export_set; node; node = node->next) {
- Object *ob = (Object *)node->link;
- f(ob);
- }
-}
+std::string EMPTY_STRING;
-bool AnimationExporter::exportAnimations(Main *bmain, Scene *sce)
+std::string AnimationExporter::get_axis_name(std::string channel, int id)
{
- bool has_animations = hasAnimations(sce);
- m_bmain = bmain;
- if (has_animations) {
- this->scene = sce;
+ static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = {
+ { "color" ,{ "R", "G", "B" } },
+ { "specular_color",{ "R", "G", "B" } },
+ { "diffuse_color",{ "R", "G", "B" } },
+ { "alpha",{ "R", "G", "B" } },
+ { "scale",{ "X", "Y", "Z" } },
+ { "location",{ "X", "Y", "Z" } },
+ { "rotation_euler",{ "X", "Y", "Z" } }
+ };
- openLibrary();
+ std::map<std::string, std::vector<std::string>>::const_iterator it;
+ it = BC_COLLADA_AXIS_FROM_TYPE.find(channel);
+ if (it == BC_COLLADA_AXIS_FROM_TYPE.end())
+ return "";
- forEachObjectInExportSet(sce, *this, this->export_settings->export_set);
-
- closeLibrary();
- }
- return has_animations;
+ const std::vector<std::string> &subchannel = it->second;
+ if (id >= subchannel.size())
+ return "";
+ return subchannel[id];
}
-bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
+bool AnimationExporter::open_animation_container(bool has_container, Object *ob)
{
- 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;
- }
+ if (!has_container) {
+ char anim_id[200];
+ sprintf(anim_id, "action_container-%s", translate_id(id_name(ob)).c_str());
+ openAnimation(anim_id, encode_xml(id_name(ob)));
}
return true;
}
-/*
- * This function creates a complete LINEAR Collada <Animation> Entry with all needed
- * <source>, <sampler>, and <channel> entries.
- * This is is used for creating sampled Transformation Animations for either:
- *
- * 1-axis animation:
- * times contains the time points in seconds from within the timeline
- * values contains the data (list of single floats)
- * channel_count = 1
- * axis_name = ['X' | 'Y' | 'Z']
- * is_rot indicates if the animation is a rotation
- *
- * 3-axis animation:
- * times contains the time points in seconds from within the timeline
- * values contains the data (list of floats where each 3 entries are one vector)
- * channel_count = 3
- * axis_name = "" (actually not used)
- * is_rot = false (see xxx below)
- *
- * xxx:
- * I tried to create a 3 axis rotation animation
- * like for translation or scale. But i could not
- * figure out how to setup the channel for this case.
- * So for now rotations are exported as 3 separate 1-axis collada animations
- * See export_sampled_animation() further down.
- */
-void AnimationExporter::create_sampled_animation(int channel_count,
- std::vector<float> &times,
- std::vector<float> &values,
- std::string ob_name,
- std::string label,
- 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);
-
- /* create input source */
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
-
- /* create output source */
- 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)
- 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);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- /* TODO create in/out tangents source (LINEAR) */
- std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
-
- /* Create Sampler */
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
- addSampler(sampler);
-
- /* Create channel */
- std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
-
-}
-
-/*
- * Export all animation FCurves of an Object.
- *
- * Note: This uses the keyframes as sample points,
- * and exports "baked keyframes" while keeping the tangent information
- * of the FCurves intact. This works for simple cases, but breaks
- * especially when negative scales are involved in the animation.
- *
- * If it is necessary to conserve the Animation precisely then
- * use export_sampled_animation_set() instead.
- */
-void AnimationExporter::export_keyframed_animation_set(Object *ob)
+void AnimationExporter::openAnimationWithClip(std::string action_id, std::string action_name)
{
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
- if (!fcu) {
- return; /* object has no animation */
- }
-
- if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
+ std::vector<std::string> anim_meta_entry;
+ anim_meta_entry.push_back(translate_id(action_id));
+ anim_meta_entry.push_back(action_name);
+ anim_meta.push_back(anim_meta_entry);
- std::vector<float> ctimes;
- 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;
- }
- }
+ openAnimation(translate_id(action_id), action_name);
}
-/*
- * Export the sampled animation of an Object.
- *
- * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
- * and then evaluates the transformation,
- * and exports "baked samples" This works always, however currently the interpolation type is set
- * to LINEAR for now. (maybe later this can be changed to BEZIER)
- *
- * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
- * However be aware that exporting keyframed animation may modify the animation slightly.
- * Also keyframed animation exports tend to break when negative scales are involved.
- */
-void AnimationExporter::export_sampled_animation_set(Object *ob)
+void AnimationExporter::close_animation_container(bool has_container)
{
- 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);
- }
+ if (has_container)
+ closeAnimation();
}
-void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
+bool AnimationExporter::exportAnimations()
{
- UnitConverter converter;
+ Scene *sce = blender_context.get_scene();
- std::vector<float> values;
+ LinkNode &export_set = *this->export_settings->export_set;
+ bool has_anim_data = bc_has_animations(sce, export_set);
+ int animation_count = 0;
+ if (has_anim_data) {
- for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
- float fmat[4][4];
+ BCObjectSet animated_subset;
+ BCAnimationSampler::get_animated_from_export_set(animated_subset, export_set);
+ animation_count = animated_subset.size();
+ BCAnimationSampler animation_sampler(blender_context, animated_subset);
- bc_update_scene(m_bmain, depsgraph, scene, *ctime);
- BKE_object_matrix_local_get(ob, fmat);
- if (this->export_settings->limit_precision)
- bc_sanitize_mat(fmat, 6);
-
- for (int i = 0; i < 4; i++)
- for (int j = 0; j < 4; j++)
- values.push_back(fmat[i][j]);
- }
+ try {
+ animation_sampler.sample_scene(
+ export_settings->sampling_rate,
+ /*keyframe_at_end = */ true,
+ export_settings->open_sim,
+ export_settings->keep_keyframes,
+ export_settings->export_animation_type
+ );
- std::string ob_name = id_name(ob);
+ openLibrary();
- create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
-}
+ BCObjectSet::iterator it;
+ for (it = animated_subset.begin(); it != animated_subset.end(); ++it) {
+ Object *ob = *it;
+ exportAnimation(ob, animation_sampler);
+ }
+ }
+ catch (std::invalid_argument &iae)
+ {
+ fprintf(stderr, "Animation export interrupted");
+ fprintf(stderr, "Exception was: %s", iae.what());
+ }
-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;
-
- std::vector<float> baked_curves[5];
-
- for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
- float fmat[4][4];
- float floc[3];
- float fquat[4];
- float fsize[3];
- float feul[3];
-
- bc_update_scene(m_bmain, depsgraph, scene, *ctime);
- BKE_object_matrix_local_get(ob, fmat);
- mat4_decompose(floc, fquat, fsize, fmat);
- quat_to_eul(feul, fquat);
-
- baked_curves[LOC].push_back(floc[0]);
- baked_curves[LOC].push_back(floc[1]);
- baked_curves[LOC].push_back(floc[2]);
-
- baked_curves[EULX].push_back(feul[0]);
- baked_curves[EULY].push_back(feul[1]);
- baked_curves[EULZ].push_back(feul[2]);
-
- baked_curves[SCALE].push_back(fsize[0]);
- baked_curves[SCALE].push_back(fsize[1]);
- baked_curves[SCALE].push_back(fsize[2]);
+ closeLibrary();
+#if 0
+ /* TODO: If all actions shall be exported, we need to call the
+ * AnimationClipExporter which will figure out which actions
+ * need to be exported for which objects
+ */
+ if (this->export_settings->include_all_actions) {
+ AnimationClipExporter ace(eval_ctx, sw, export_settings, anim_meta);
+ ace.exportAnimationClips(sce);
+ }
+#endif
}
-
- std::string ob_name = id_name(ob);
-
- 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, 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 %d frames for %s (sampling rate: %d)\n",
- (int)baked_curves[0].size(),
- ob->id.name,
- this->export_settings->sampling_rate);
+ return animation_count;
}
/* called for each exported object */
-void AnimationExporter::operator()(Object *ob)
+void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler)
{
- char *transformName;
+ bool container_is_open = false;
- /* bool isMatAnim = false; */ /* UNUSED */
+ //Transform animations (trans, rot, scale)
+ container_is_open = open_animation_container(container_is_open, ob);
- //Export transform animations
- if (ob->adt && ob->adt->action) {
+ /* Now take care of the Object Animations
+ * Note: For Armatures the skeletal animation has already been exported (see above)
+ * However Armatures also can have Object animation.
+ */
+ bool export_as_matrix = this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX;
+ if (export_as_matrix) {
+ export_matrix_animation(ob, sampler); // export all transform_curves as one single matrix animation
+ }
- 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);
- }
+ export_curve_animation_set(ob, sampler, export_as_matrix);
- /* Armatures can have object animation and skeletal animation*/
- if (this->export_settings->sampling_rate < 1) {
- export_keyframed_animation_set(ob);
- }
- else {
- export_sampled_animation_set(ob);
- }
- }
+ if (ob->type == OB_ARMATURE) {
- export_object_constraint_animation(ob);
+#ifdef WITH_MORPH_ANIMATION
+ /* TODO: This needs to be handled by extra profiles, postponed for now */
+ export_morph_animation(ob);
+#endif
- //This needs to be handled by extra profiles, so postponed for now
- //export_morph_animation(ob);
+ /* Export skeletal animation (if any) */
+ bArmature *arm = (bArmature *)ob->data;
+ for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next)
+ export_bone_animations_recursive(ob, root_bone, sampler);
+ }
- //Export Lamp parameter animations
- if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
- FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
+ close_animation_container(container_is_open);
+}
- if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
- (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
- {
- create_keyframed_animation(ob, fcu, transformName, true);
- }
- fcu = fcu->next;
+/*
+ * Export all animation FCurves of an Object.
+ *
+ * Note: This uses the keyframes as sample points,
+ * and exports "baked keyframes" while keeping the tangent information
+ * of the FCurves intact. This works for simple cases, but breaks
+ * especially when negative scales are involved in the animation.
+ * And when parent inverse matrices are involved (when exporting
+ * object hierarchies)
+ *
+ */
+void AnimationExporter::export_curve_animation_set(Object *ob, BCAnimationSampler &sampler, bool export_as_matrix)
+{
+ BCAnimationCurveMap *curves = sampler.get_curves(ob);
+
+ BCAnimationCurveMap::iterator it;
+ for (it = curves->begin(); it != curves->end(); ++it) {
+ BCAnimationCurve &curve = *it->second;
+ if (curve.get_channel_target() == "rotation_quaternion") {
+ /*
+ Can not export Quaternion animation in Collada as far as i know)
+ Maybe automatically convert to euler rotation?
+ Discard for now.
+ */
+ continue;
+ }
+
+ if (export_as_matrix && curve.is_transform_curve()) {
+ /* All Transform curves will be exported within a single matrix animation,
+ * see export_matrix_animation()
+ * No need to export the curves here again.
+ */
+ continue;
}
- }
- //Export Camera parameter animations
- if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
- FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
-
- if ((STREQ(transformName, "lens")) ||
- (STREQ(transformName, "ortho_scale")) ||
- (STREQ(transformName, "clip_end")) ||
- (STREQ(transformName, "clip_start")))
- {
- create_keyframed_animation(ob, fcu, transformName, true);
- }
- fcu = fcu->next;
+ if (!curve.is_animated()) {
+ continue;
}
- }
- //Export Material parameter animations.
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
- if (!ma) continue;
- if (ma->adt && ma->adt->action) {
- /* isMatAnim = true; */
- FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
-
- if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
- (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
- (STREQ(transformName, "ior")))
- {
- create_keyframed_animation(ob, fcu, transformName, true, ma);
- }
- fcu = fcu->next;
- }
+ BCAnimationCurve *mcurve = get_modified_export_curve(ob, curve, *curves);
+ if (mcurve) {
+ export_curve_animation(ob, *mcurve);
+ delete mcurve;
+ }
+ else {
+ export_curve_animation(ob, curve);
}
}
}
-void AnimationExporter::export_object_constraint_animation(Object *ob)
+void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler &sampler)
{
- std::vector<float> fra;
- //Takes frames of target animations
- make_anim_frames_from_targets(ob, fra);
-
- if (fra.size())
- dae_baked_object_animation(fra, ob);
-}
-
-void AnimationExporter::export_morph_animation(Object *ob)
-{
- FCurve *fcu;
- char *transformName;
- Key *key = BKE_key_from_object(ob);
- if (!key) return;
-
- if (key->adt && key->adt->action) {
- fcu = (FCurve *)key->adt->action->curves.first;
-
- while (fcu) {
- transformName = extract_transform_name(fcu->rna_path);
+ std::vector<float> frames;
+ sampler.get_object_frames(frames, ob);
+ if (frames.size() > 0) {
+ BCMatrixSampleMap samples;
+ bool is_animated = sampler.get_object_samples(samples, ob);
+ if (is_animated) {
+ bAction *action = bc_getSceneObjectAction(ob);
+ std::string name = encode_xml(id_name(ob));
+ std::string action_name = (action == NULL) ? name + "-action" : id_name(action);
+ std::string channel_type = "transform";
+ std::string axis = "";
+ std::string id = bc_get_action_id(action_name, name, channel_type, axis);
- create_keyframed_animation(ob, fcu, transformName, true);
+ std::string target = translate_id(name) + '/' + channel_type;
- fcu = fcu->next;
+ export_collada_matrix_animation(id, name, target, frames, samples);
}
}
-
}
-void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
+//write bone animations in transform matrix sources
+void AnimationExporter::export_bone_animations_recursive(Object *ob, Bone *bone, BCAnimationSampler &sampler)
{
- ListBase *conlist = get_active_constraints(ob);
- if (conlist == NULL) return;
- bConstraint *con;
- for (con = (bConstraint *)conlist->first; con; con = con->next) {
- ListBase targets = {NULL, NULL};
-
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
- if (!validateConstraints(con)) continue;
-
- if (cti && cti->get_constraint_targets) {
- bConstraintTarget *ct;
- Object *obtar;
- /* get targets
- * - constraints should use ct->matrix, not directly accessing values
- * - ct->matrix members have not yet been calculated here!
- */
- cti->get_constraint_targets(con, &targets);
-
- for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
- obtar = ct->tar;
-
- if (obtar)
- find_keyframes(obtar, frames);
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
+ std::vector<float> frames;
+ sampler.get_bone_frames(frames, ob, bone);
+
+ if (frames.size()) {
+ BCMatrixSampleMap samples;
+ bool is_animated = sampler.get_bone_samples(samples, ob, bone);
+ if (is_animated) {
+ export_bone_animation(ob, bone, frames, samples);
}
}
+
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
+ export_bone_animations_recursive(ob, child, sampler);
}
-//euler sources from quternion sources
-float *AnimationExporter::get_eul_source_for_quat(Object *ob)
-{
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
- const int keys = fcu->totvert;
- float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
- float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
- float temp_quat[4];
- float temp_eul[3];
- while (fcu) {
- char *transformName = extract_transform_name(fcu->rna_path);
-
- if (STREQ(transformName, "rotation_quaternion") ) {
- for (int i = 0; i < fcu->totvert; i++) {
- *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
+/*
+* In some special cases the exported Curve needs to be replaced
+* by a modified curve (for collada purposes)
+* This method checks if a conversion is necessary and if applicable
+* returns a pointer to the modified BCAnimationCurve.
+* IMPORTANT: the modified curve must be deleted by the caller when no longer needed
+* if no conversion is needed this method returns a NULL;
+*/
+BCAnimationCurve *AnimationExporter::get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves)
+{
+ std::string channel_target = curve.get_channel_target();
+ BCAnimationCurve *mcurve = NULL;
+ if (channel_target == "lens") {
+
+ /* Create an xfov curve */
+
+ BCCurveKey key(BC_ANIMATION_TYPE_CAMERA, "xfov", 0);
+ mcurve = new BCAnimationCurve(key, ob);
+
+ // now tricky part: transform the fcurve
+ BCValueMap lens_values;
+ curve.get_value_map(lens_values);
+
+ BCAnimationCurve *sensor_curve = NULL;
+ BCCurveKey sensor_key(BC_ANIMATION_TYPE_CAMERA, "sensor_width", 0);
+ BCAnimationCurveMap::iterator cit = curves.find(sensor_key);
+ if (cit != curves.end()) {
+ sensor_curve = cit->second;
+ }
+
+ BCValueMap::const_iterator vit;
+ for (vit = lens_values.begin(); vit != lens_values.end(); ++vit) {
+ int frame = vit->first;
+ float lens_value = vit->second;
+
+ float sensor_value;
+ if (sensor_curve) {
+ sensor_value = sensor_curve->get_value(frame);
}
+ else {
+ sensor_value = ((Camera *)ob->data)->sensor_x;
+ }
+ float value = RAD2DEGF(focallength_to_fov(lens_value, sensor_value));
+ mcurve->add_value(value, frame);
}
- fcu = fcu->next;
+ mcurve->clean_handles(); // to reset the handles
}
-
- for (int i = 0; i < keys; i++) {
- for (int j = 0; j < 4; j++)
- temp_quat[j] = quat[(i * 4) + j];
-
- quat_to_eul(temp_eul, temp_quat);
-
- for (int k = 0; k < 3; k++)
- eul[i * 3 + k] = temp_eul[k];
-
- }
- MEM_freeN(quat);
- return eul;
-
-}
-
-//Get proper name for bones
-std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
-{
- //hard-way to derive the bone name from rna_path. Must find more compact method
- std::string rna_path = std::string(fcu->rna_path);
-
- char *boneName = strtok((char *)rna_path.c_str(), "\"");
- boneName = strtok(NULL, "\"");
-
- if (boneName != NULL)
- return /*id_name(ob) + "_" +*/ std::string(boneName);
- else
- return id_name(ob);
+ return mcurve;
}
-std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
+void AnimationExporter::export_curve_animation(
+ Object *ob,
+ BCAnimationCurve &curve)
{
- std::string rna_path = std::string(fcu->rna_path);
- return translate_id(rna_path);
-}
-
-/* convert f-curves to animation curves and write */
-void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
-{
- const char *axis_name = NULL;
- char anim_id[200];
-
- bool has_tangents = false;
- bool quatRotation = false;
-
- Object *obj = NULL;
-
- if (STREQ(transformName, "rotation_quaternion") ) {
- fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
- quatRotation = true;
- return;
- }
-
- //axis names for colors
- else if (STREQ(transformName, "color") ||
- STREQ(transformName, "specular_color") ||
- STREQ(transformName, "diffuse_color") ||
- STREQ(transformName, "alpha"))
- {
- const char *axis_names[] = {"R", "G", "B"};
- if (fcu->array_index < 3)
- axis_name = axis_names[fcu->array_index];
- }
+ std::string channel_target = curve.get_channel_target();
/*
- * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
- * We will use the object to evaluate the animation on all keyframes and calculate the
- * resulting object matrix. We need this to incorporate the
- * effects of the parent inverse matrix (when it contains a rotation component)
- *
- * TODO: try to combine exported fcurves into 3 channel animations like done
- * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
+ * Some curves can not be exported as is and need some conversion
+ * For more information see implementation oif get_modified_export_curve()
+ * note: if mcurve is not NULL then it must be deleted at end of this method;
*/
- else if (
- STREQ(transformName, "scale") ||
- STREQ(transformName, "location") ||
- STREQ(transformName, "rotation_euler"))
- {
- const char *axis_names[] = {"X", "Y", "Z"};
- if (fcu->array_index < 3) {
- axis_name = axis_names[fcu->array_index];
- obj = ob;
- }
- }
- else {
- /* no axis name. single parameter */
- axis_name = "";
- }
+ int channel_index = curve.get_channel_index();
+ std::string axis = get_axis_name(channel_target, channel_index); // RGB or XYZ or ""
- std::string ob_name = std::string("null");
+ std::string action_name;
+ bAction *action = bc_getSceneObjectAction(ob);
+ action_name = (action) ? id_name(action) : "constraint_anim";
- /* Create anim Id */
- if (ob->type == OB_ARMATURE) {
- ob_name = getObjectBoneName(ob, fcu);
- BLI_snprintf(
- anim_id,
- sizeof(anim_id),
- "%s_%s.%s",
- (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(transformName).c_str(),
- axis_name);
- }
- else {
- if (ma)
- ob_name = id_name(ob) + "_material";
- else
- ob_name = id_name(ob);
-
- BLI_snprintf(
- anim_id,
- sizeof(anim_id),
- "%s_%s_%s",
- (char *)translate_id(ob_name).c_str(),
- (char *)getAnimationPathId(fcu).c_str(),
- axis_name);
- }
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
+ const std::string curve_name = encode_xml(curve.get_animation_name(ob));
+ std::string id = bc_get_action_id(action_name, curve_name, channel_target, axis, ".");
- // create output source
- std::string output_id;
+ std::string collada_target = translate_id(curve_name);
- //quat rotations are skipped for now, because of complications with determining axis.
- if (quatRotation) {
- float *eul = get_eul_source_for_quat(ob);
- float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
- for (int i = 0; i < fcu->totvert; i++) {
- eul_axis[i] = eul[i * 3 + fcu->array_index];
+ if (curve.is_of_animation_type(BC_ANIMATION_TYPE_MATERIAL)) {
+ int material_index = curve.get_subindex();
+ Material *ma = give_current_material(ob, material_index + 1);
+ if (ma) {
+ collada_target = translate_id(id_name(ma)) + "-effect/common/" + get_collada_sid(curve, axis);
}
- output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
- MEM_freeN(eul);
- MEM_freeN(eul_axis);
- }
- else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
- output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
}
else {
- output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
+ collada_target += "/" + get_collada_sid(curve, axis);
}
- // create interpolations source
- std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
-
- // handle tangents (if required)
- std::string intangent_id;
- std::string outtangent_id;
-
- if (has_tangents) {
- // create in_tangent source
- intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
+ export_collada_curve_animation(id, curve_name, collada_target, axis, curve);
- // create out_tangent source
- outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
- }
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
- COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
-
- if (has_tangents) {
- sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
- sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
- }
-
- addSampler(sampler);
-
- std::string target;
-
- if (!is_param)
- target = translate_id(ob_name) +
- "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
- else {
- if (ob->type == OB_LAMP)
- target = get_light_id(ob) +
- "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
-
- if (ob->type == OB_CAMERA)
- target = get_camera_id(ob) +
- "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
-
- if (ma)
- target = translate_id(id_name(ma)) + "-effect" +
- "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
- //if shape key animation, this is the main problem, how to define the channel targets.
- /*target = get_morph_id(ob) +
- "/value" +*/
- }
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
}
-
-
-//write bone animations in transform matrix sources
-void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
+void AnimationExporter::export_bone_animation(Object *ob, Bone *bone, BCFrames &frames, BCMatrixSampleMap &samples)
{
- if (!ob_arm->adt)
- return;
+ bAction* action = bc_getSceneObjectAction(ob);
+ std::string bone_name(bone->name);
+ std::string name = encode_xml(id_name(ob));
+ std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix");
+ std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform";
- //This will only export animations of bones in deform group.
- /* if (!is_bone_deform_group(bone)) return; */
-
- sample_and_write_bone_animation_matrix(ob_arm, bone);
-
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
- write_bone_animation_matrix(ob_arm, child);
+ export_collada_matrix_animation(id, name, target, frames, samples);
}
bool AnimationExporter::is_bone_deform_group(Bone *bone)
@@ -695,204 +377,86 @@ bool AnimationExporter::is_bone_deform_group(Bone *bone)
return false;
}
-void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
-{
- bArmature *arm = (bArmature *)ob_arm->data;
- int flag = arm->flag;
- std::vector<float> fra;
- //char prefix[256];
-
- //Check if there is a fcurve in the armature for the bone in param
- //when baking this check is not needed, solve every bone for every frame.
- /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
-
- while (fcu) {
- std::string bone_name = getObjectBoneName(ob_arm, fcu);
- int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
- if (val == 0) break;
- fcu = fcu->next;
- }
- if (!(fcu)) return;*/
+void AnimationExporter::export_collada_curve_animation(
+ std::string id,
+ std::string name,
+ std::string collada_target,
+ std::string axis,
+ BCAnimationCurve &curve)
+{
+ BCFrames frames;
+ BCValues values;
+ curve.get_frames(frames);
+ curve.get_values(values);
+ std::string channel_target = curve.get_channel_target();
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
- if (!pchan)
- return;
+ fprintf(stdout, "Export animation curve %s (%d control points)\n", id.c_str(), int(frames.size()));
+ openAnimation(id, name);
+ BC_animation_source_type source_type = (curve.is_rotation_curve()) ? BC_SOURCE_TYPE_ANGLE : BC_SOURCE_TYPE_VALUE;
+ std::string input_id = collada_source_from_values(BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, axis);
+ std::string output_id = collada_source_from_values(source_type, COLLADASW::InputSemantic::OUTPUT, values, id, axis);
- if (this->export_settings->sampling_rate < 1)
- find_keyframes(ob_arm, fra);
+ bool has_tangents = false;
+ std::string interpolation_id;
+ if (this->export_settings->keep_smooth_curves)
+ interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents);
else
- find_sampleframes(ob_arm, fra);
+ interpolation_id = collada_linear_interpolation_source(frames.size(), id);
- if (flag & ARM_RESTPOS) {
- arm->flag &= ~ARM_RESTPOS;
- BKE_pose_where_is(depsgraph, scene, ob_arm);
- }
-
- if (fra.size()) {
- dae_baked_animation(fra, ob_arm, bone);
+ std::string intangent_id;
+ std::string outtangent_id;
+ if (has_tangents) {
+ intangent_id = collada_tangent_from_curve(COLLADASW::InputSemantic::IN_TANGENT, curve, id, axis);
+ outtangent_id = collada_tangent_from_curve(COLLADASW::InputSemantic::OUT_TANGENT, curve, id, axis);
}
- if (flag & ARM_RESTPOS)
- arm->flag = flag;
- BKE_pose_where_is(depsgraph, scene, ob_arm);
-}
-
-void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
-{
- std::string ob_name = id_name(ob_arm);
- std::string bone_name = bone->name;
- char anim_id[200];
-
- if (!fra.size())
- return;
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(bone_name).c_str(), "pose_matrix");
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
+ std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
- // create output source
- std::string output_id;
-
- output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
-
- // create interpolations source
- std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
- // TODO create in/out tangents source
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(EMPTY_STRING, interpolation_id));
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+ if (has_tangents) {
+ sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(EMPTY_STRING, intangent_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(EMPTY_STRING, outtangent_id));
+ }
addSampler(sampler);
-
- std::string target = get_joint_id(ob_arm, bone) + "/transform";
- addChannel(COLLADABU::URI(empty, sampler_id), target);
+ addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), collada_target);
closeAnimation();
}
-void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
+void AnimationExporter::export_collada_matrix_animation(std::string id, std::string name, std::string target, BCFrames &frames, BCMatrixSampleMap &samples)
{
- std::string ob_name = id_name(ob);
- char anim_id[200];
-
- if (!fra.size())
- return;
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
- "object_matrix");
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+ fprintf(stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size()));
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
+ openAnimationWithClip(id, name);
- // create output source
- std::string output_id;
- output_id = create_4x4_source( fra, ob, NULL, anim_id);
+ std::string input_id = collada_source_from_values(BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, "");
+ std::string output_id = collada_source_from_values(samples, id);
+ std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id);
- // create interpolations source
- std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
+ std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- // TODO create in/out tangents source
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
-
- addSampler(sampler);
- std::string target = translate_id(ob_name) + "/transform";
- addChannel(COLLADABU::URI(empty, sampler_id), target);
- closeAnimation();
-}
-
-// dae_bone_animation -> add_bone_animation
-// (blend this into dae_bone_animation)
-void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
-{
- const char *axis_names[] = {"X", "Y", "Z"};
- const char *axis_name = NULL;
- char anim_id[200];
- bool is_rot = tm_type == 0;
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(EMPTY_STRING, interpolation_id));
- if (!fra.size())
- return;
-
- char rna_path[200];
- BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
- tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
-
- if (axis > -1)
- axis_name = axis_names[axis];
-
- std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
-
- // create output source
- std::string output_id;
- if (axis == -1)
- output_id = create_xyz_source(values, fra.size(), anim_id);
- else
- output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
-
- // create interpolations source
- std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
-
- std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
- COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
- std::string empty;
- sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
- sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
-
- // TODO create in/out tangents source
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+ // Matrix animation has no tangents
addSampler(sampler);
-
- std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
- addChannel(COLLADABU::URI(empty, sampler_id), target);
+ addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), target);
closeAnimation();
}
-float AnimationExporter::convert_time(float frame)
-{
- return FRA2TIME(frame);
-}
-
-float AnimationExporter::convert_angle(float angle)
-{
- return COLLADABU::Math::Utils::radToDegF(angle);
-}
-
std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
{
switch (semantic) {
@@ -913,7 +477,10 @@ std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Sem
}
void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
- COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
+ COLLADASW::InputSemantic::Semantics semantic,
+ bool is_rot,
+ const std::string axis,
+ bool transform)
{
switch (semantic) {
case COLLADASW::InputSemantic::INPUT:
@@ -924,7 +491,7 @@ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNa
param.push_back("ANGLE");
}
else {
- if (axis) {
+ if (axis != "") {
param.push_back(axis);
}
else
@@ -948,262 +515,83 @@ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNa
}
}
-void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length)
+std::string AnimationExporter::collada_tangent_from_curve(COLLADASW::InputSemantic::Semantics semantic, BCAnimationCurve &curve, const std::string& anim_id, std::string axis_name)
{
- switch (semantic) {
- case COLLADASW::InputSemantic::INPUT:
- *length = 1;
- values[0] = convert_time(bezt->vec[1][0]);
- break;
- case COLLADASW::InputSemantic::OUTPUT:
- *length = 1;
- if (is_angle) {
- values[0] = RAD2DEGF(bezt->vec[1][1]);
- }
- else {
- values[0] = bezt->vec[1][1];
- }
- break;
+ Scene *scene = blender_context.get_scene();
+ std::string channel = curve.get_channel_target();
- case COLLADASW::InputSemantic::IN_TANGENT:
- *length = 2;
- values[0] = convert_time(bezt->vec[0][0]);
- if (bezt->ipo != BEZT_IPO_BEZ) {
- // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
- values[0] = 0;
- values[1] = 0;
- }
- else if (is_angle) {
- values[1] = RAD2DEGF(bezt->vec[0][1]);
- }
- else {
- values[1] = bezt->vec[0][1];
- }
- break;
+ const std::string source_id = anim_id + get_semantic_suffix(semantic);
- case COLLADASW::InputSemantic::OUT_TANGENT:
- *length = 2;
- values[0] = convert_time(bezt->vec[2][0]);
- if (bezt->ipo != BEZT_IPO_BEZ) {
- // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
- values[0] = 0;
- values[1] = 0;
- }
- else if (is_angle) {
- values[1] = RAD2DEGF(bezt->vec[2][1]);
- }
- else {
- values[1] = bezt->vec[2][1];
- }
- break;
- default:
- *length = 0;
- break;
- }
-}
-
-// old function to keep compatibility for calls where offset and object are not needed
-std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
-{
- return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
-}
-
-void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
-{
- BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
- ListBase *conlist = get_active_constraints(ob);
- bConstraint *con;
- for (con = (bConstraint *)conlist->first; con; con = con->next) {
- ListBase targets = { NULL, NULL };
-
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-
- if (cti && cti->get_constraint_targets) {
- bConstraintTarget *ct;
- Object *obtar;
- cti->get_constraint_targets(con, &targets);
- for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
- obtar = ct->tar;
-
- if (obtar) {
- BKE_animsys_evaluate_animdata(depsgraph, scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(this->depsgraph, scene, obtar, ctime);
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- BKE_object_where_is_calc_time(this->depsgraph, scene, ob, ctime);
-}
-
-/*
- * ob is needed to aply parent inverse information to fcurve.
- * TODO: Here we have to step over all keyframes for each object and for each fcurve.
- * Instead of processing each fcurve one by one,
- * step over the animation from keyframe to keyframe,
- * then create adjusted fcurves (and entries) for all affected objects.
- * Then we would need to step through the scene only once.
- */
-std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
-{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
- bool is_euler = strstr(fcu->rna_path, "rotation_euler");
- bool is_translation = strstr(fcu->rna_path, "location");
- bool is_scale = strstr(fcu->rna_path, "scale");
- bool is_tangent = false;
- int offset_index = 0;
+ bool is_angle = (bc_startswith(channel, "rotation") || channel == "spot_size");
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
-
- switch (semantic) {
- case COLLADASW::InputSemantic::INPUT:
- case COLLADASW::InputSemantic::OUTPUT:
- source.setAccessorStride(1);
- offset_index = 0;
- break;
- case COLLADASW::InputSemantic::IN_TANGENT:
- case COLLADASW::InputSemantic::OUT_TANGENT:
- source.setAccessorStride(2);
- offset_index = 1;
- is_tangent = true;
- break;
- default:
- break;
- }
+ source.setAccessorCount(curve.sample_count());
+ source.setAccessorStride(2);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
add_source_parameters(param, semantic, is_angle, axis_name, false);
source.prepareToAppendValues();
- for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
- float fixed_val = 0;
- if (ob) {
- float fmat[4][4];
- float frame = fcu->bezt[frame_index].vec[1][0];
- float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
-
- evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
-
- BKE_object_matrix_local_get(ob, fmat);
- float floc[3];
- float fquat[4];
- float fsize[3];
- mat4_decompose(floc, fquat, fsize, fmat);
-
- if (is_euler) {
- float eul[3];
- quat_to_eul(eul, fquat);
- fixed_val = RAD2DEGF(eul[fcu->array_index]);
- }
- else if (is_translation) {
- fixed_val = floc[fcu->array_index];
- }
- else if (is_scale) {
- fixed_val = fsize[fcu->array_index];
- }
- }
-
- float values[3]; // be careful!
- float offset = 0;
- int length = 0;
- get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
- if (is_tangent) {
- float bases[3];
- int len = 0;
- get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
- offset = values[offset_index] - bases[0];
- }
+ const FCurve *fcu = curve.get_fcurve();
+ int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2;
- for (int j = 0; j < length; j++) {
- float val;
- if (j == offset_index) {
- if (ob) {
- val = fixed_val + offset;
- }
- else {
- val = values[j] + offset;
- }
- } else {
- val = values[j];
- }
- source.appendValues(val);
- }
- }
+ for (int i = 0; i < fcu->totvert; ++i) {
+ BezTriple &bezt = fcu->bezt[i];
- source.finish();
-
- return source_id;
-}
-
-/*
- * Similar to create_source_from_fcurve, but adds conversion of lens
- * animation data from focal length to FOV.
- */
-std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id)
-{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
+ float sampled_time = bezt.vec[tangent][0];
+ float sampled_val = bezt.vec[tangent][1];
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
-
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, "", false);
+ if (is_angle) {
+ sampled_val = RAD2DEGF(sampled_val);
+ }
- source.prepareToAppendValues();
+ source.appendValues(FRA2TIME(sampled_time));
+ source.appendValues(sampled_val);
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float values[3]; // be careful!
- int length = 0;
- get_source_values(&fcu->bezt[i], semantic, false, values, &length);
- for (int j = 0; j < length; j++)
- {
- float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x));
- source.appendValues(val);
- }
}
-
source.finish();
-
return source_id;
}
-/*
- * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
- */
-std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
+std::string AnimationExporter::collada_source_from_values(
+ BC_animation_source_type source_type,
+ COLLADASW::InputSemantic::Semantics semantic,
+ std::vector<float> &values,
+ const std::string& anim_id,
+ const std::string axis_name)
{
+ Scene *scene = blender_context.get_scene();
+ /* T can be float, int or double */
+
+ int stride = 1;
+ int entry_count = values.size() / stride;
std::string source_id = anim_id + get_semantic_suffix(semantic);
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(1);
+ source.setAccessorCount(entry_count);
+ source.setAccessorStride(stride);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rot, axis_name, false);
+ add_source_parameters(param, semantic, source_type== BC_SOURCE_TYPE_ANGLE, axis_name, false);
source.prepareToAppendValues();
- for (int i = 0; i < tot; i++) {
- float val = v[i];
- ////if (semantic == COLLADASW::InputSemantic::INPUT)
- // val = convert_time(val);
- //else
- if (is_rot)
+ for (int i = 0; i < entry_count; i++) {
+ float val = values[i];
+ switch (source_type) {
+ case BC_SOURCE_TYPE_TIMEFRAME:
+ val = FRA2TIME(val);
+ break;
+ case BC_SOURCE_TYPE_ANGLE:
val = RAD2DEGF(val);
+ break;
+ default: break;
+ }
source.appendValues(val);
}
@@ -1213,39 +601,9 @@ std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic
}
/*
- * only used for sources with INPUT semantic
- */
-std::string AnimationExporter::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 source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fra.size());
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rot, axis_name, false);
-
- source.prepareToAppendValues();
-
- std::vector<float>::iterator it;
- for (it = fra.begin(); it != fra.end(); it++) {
- float val = *it;
- //if (semantic == COLLADASW::InputSemantic::INPUT)
- val = convert_time(val);
- /*else if (is_rot)
- val = convert_angle(val);*/
- source.appendValues(val);
- }
-
- source.finish();
-
- return source_id;
-}
-
-std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
+ * Create a collada matrix source for a set of samples
+*/
+std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &samples, const std::string &anim_id)
{
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -1253,181 +611,38 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std
COLLADASW::Float4x4Source source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(ctimes.size());
+ source.setAccessorCount(samples.size());
source.setAccessorStride(16);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, NULL, true);
+ add_source_parameters(param, semantic, false, "", true);
source.prepareToAppendValues();
- 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);
+ BCMatrixSampleMap::iterator it;
+ int precision = (this->export_settings->limit_precision) ? 6 : -1; // could be made configurable
+ for (it = samples.begin(); it != samples.end(); it++) {
+ const BCMatrix *sample = it->second;
+ double daemat[4][4];
+ sample->get_matrix(daemat, true, precision);
+ source.appendValues(daemat);
}
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);
-
- COLLADASW::Float4x4Source source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(frames.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;
-
- if (is_bone_animation) {
- bPose *pose = ob->pose;
- pchan = BKE_pose_channel_find_name(pose, bone->name);
- if (!pchan)
- return "";
-
- parchan = pchan->parent;
-
- enable_fcurves(ob->adt->action, bone->name);
- }
-
- std::vector<float>::iterator it;
- int j = 0;
- for (it = frames.begin(); it != frames.end(); it++) {
- float mat[4][4], ipar[4][4];
- float frame = *it;
-
- float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
- bc_update_scene(m_bmain, depsgraph, scene, ctime);
- if (is_bone_animation) {
-
- if (pchan->flag & POSE_CHAIN) {
- enable_fcurves(ob->adt->action, NULL);
- BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
- BKE_pose_where_is(depsgraph, scene, ob);
- }
- else {
- BKE_pose_where_is_bone(depsgraph, scene, ob, pchan, ctime, 1);
- }
-
- // compute bone local mat
- 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 (export_settings->open_sim) {
- 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);
- }
- }
-
- }
- else {
- copy_m4_m4(mat, ob->obmat);
- }
-
- 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);
-
- j++;
-
- BIK_release_tree(scene, ob, ctime);
- }
-
- if (ob->adt) {
- enable_fcurves(ob->adt->action, NULL);
- }
-
- source.finish();
-
- return source_id;
-}
-
-
-/*
- * only used for sources with OUTPUT semantic ( locations and scale)
- */
-std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
-{
- COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(3);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, NULL, false);
-
- source.prepareToAppendValues();
-
- for (int i = 0; i < tot; i++) {
- source.appendValues(*v, *(v + 1), *(v + 2));
- v += 3;
- }
-
- source.finish();
-
- return source_id;
-}
-
-std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
+std::string AnimationExporter::collada_interpolation_source(const BCAnimationCurve &curve,
+ const std::string& anim_id,
+ const std::string axis,
+ bool *has_tangents)
{
std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
COLLADASW::NameSource source(mSW);
source.setId(source_id);
source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
+ source.setAccessorCount(curve.sample_count());
source.setAccessorStride(1);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
@@ -1437,12 +652,17 @@ std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const st
*has_tangents = false;
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
+ std::vector<float>frames;
+ curve.get_frames(frames);
+
+ for (unsigned int i = 0; i < curve.sample_count(); i++) {
+ float frame = frames[i];
+ int ipo = curve.get_interpolation_type(frame);
+ if (ipo == BEZT_IPO_BEZ) {
source.appendValues(BEZIER_NAME);
*has_tangents = true;
}
- else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
+ else if (ipo == BEZT_IPO_CONST) {
source.appendValues(STEP_NAME);
}
else { // BEZT_IPO_LIN
@@ -1456,7 +676,7 @@ std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const st
return source_id;
}
-std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
+std::string AnimationExporter::collada_linear_interpolation_source(int tot, const std::string& anim_id)
{
std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
@@ -1480,474 +700,102 @@ std::string AnimationExporter::fake_interpolation_source(int tot, const std::str
return source_id;
}
-std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
-{
- std::string tm_name;
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (STREQ(name, "color"))
- tm_type = 1;
- else if (STREQ(name, "spot_size"))
- tm_type = 2;
- else if (STREQ(name, "spot_blend"))
- tm_type = 3;
- else if (STREQ(name, "distance"))
- tm_type = 4;
- else
- tm_type = -1;
- }
-
- switch (tm_type) {
- case 1:
- tm_name = "color";
- break;
- case 2:
- tm_name = "fall_off_angle";
- break;
- case 3:
- tm_name = "fall_off_exponent";
- break;
- case 4:
- tm_name = "blender/blender_dist";
- break;
-
- default:
- tm_name = "";
- break;
- }
-
- if (tm_name.size()) {
- if (axis_name[0])
- return tm_name + "." + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
-}
-
-std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
+const std::string AnimationExporter::get_collada_name(std::string channel_target) const
{
- std::string tm_name;
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (STREQ(name, "lens"))
- tm_type = 0;
- else if (STREQ(name, "ortho_scale"))
- tm_type = 1;
- else if (STREQ(name, "clip_end"))
- tm_type = 2;
- else if (STREQ(name, "clip_start"))
- tm_type = 3;
-
- else
- tm_type = -1;
- }
-
- switch (tm_type) {
- case 0:
- tm_name = "xfov";
- break;
- case 1:
- tm_name = "xmag";
- break;
- case 2:
- tm_name = "zfar";
- break;
- case 3:
- tm_name = "znear";
- break;
-
- default:
- tm_name = "";
- break;
- }
-
- if (tm_name.size()) {
- if (axis_name[0])
- return tm_name + "." + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
+ /*
+ * Translation table to map FCurve animation types to Collada animation.
+ * Todo: Maybe we can keep the names from the fcurves here instead of
+ * mapping. However this is what i found in the old code. So keep
+ * this map for now.
+ */
+ static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = {
+ { "rotation", "rotation" },
+ { "rotation_euler", "rotation" },
+ { "rotation_quaternion", "rotation" },
+ { "scale", "scale" },
+ { "location", "location" },
+
+ /* Materials */
+ { "specular_color", "specular" },
+ { "diffuse_color", "diffuse" },
+ { "ior", "index_of_refraction" },
+ { "specular_hardness", "specular_hardness" },
+ { "alpha", "alpha" },
+
+ /* Lamps */
+ { "color", "color" },
+ { "fall_off_angle", "falloff_angle" },
+ { "spot_size", "falloff_angle" },
+ { "fall_off_exponent", "falloff_exponent" },
+ { "spot_blend", "falloff_exponent" },
+ { "blender/blender_dist", "blender/blender_dist" }, // special blender profile (todo: make this more elegant)
+ { "distance", "blender/blender_dist" }, // special blender profile (todo: make this more elegant)
+
+ /* Cameras */
+ { "lens", "xfov" },
+ { "xfov", "xfov" },
+ { "xmag", "xmag" },
+ { "zfar", "zfar" },
+ { "znear", "znear" },
+ { "ortho_scale", "xmag" },
+ { "clip_end", "zfar" },
+ { "clip_start", "znear" }
+ };
+
+ std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(channel_target);
+ if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end())
+ return "";
+
+ std::string tm_name = name_it->second;
+ return tm_name;
}
/*
* Assign sid of the animated parameter or transform for rotation,
* axis name is always appended and the value of append_axis is ignored
*/
-std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
+std::string AnimationExporter::get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name)
{
- std::string tm_name;
- bool is_angle = false;
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (STREQ(name, "rotation_euler"))
- tm_type = 0;
- else if (STREQ(name, "rotation_quaternion"))
- tm_type = 1;
- else if (STREQ(name, "scale"))
- tm_type = 2;
- else if (STREQ(name, "location"))
- tm_type = 3;
- else if (STREQ(name, "specular_hardness"))
- tm_type = 4;
- else if (STREQ(name, "specular_color"))
- tm_type = 5;
- else if (STREQ(name, "diffuse_color"))
- tm_type = 6;
- else if (STREQ(name, "alpha"))
- tm_type = 7;
- else if (STREQ(name, "ior"))
- tm_type = 8;
+ std::string channel_target = curve.get_channel_target();
+ std::string tm_name = get_collada_name(channel_target);
- else
- tm_type = -1;
- }
+ bool is_angle = curve.is_rotation_curve();
- switch (tm_type) {
- case 0:
- case 1:
- tm_name = "rotation";
- is_angle = true;
- break;
- case 2:
- tm_name = "scale";
- break;
- case 3:
- tm_name = "location";
- break;
- case 4:
- tm_name = "shininess";
- break;
- case 5:
- tm_name = "specular";
- break;
- case 6:
- tm_name = "diffuse";
- break;
- case 7:
- tm_name = "transparency";
- break;
- case 8:
- tm_name = "index_of_refraction";
- break;
-
- default:
- tm_name = "";
- break;
- }
if (tm_name.size()) {
if (is_angle)
return tm_name + std::string(axis_name) + ".ANGLE";
else
- if (axis_name[0])
- return tm_name + "." + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
-}
-
-char *AnimationExporter::extract_transform_name(char *rna_path)
-{
- char *dot = strrchr(rna_path, '.');
- return dot ? (dot + 1) : rna_path;
-}
-
-/*
- * enable fcurves driving a specific bone, disable all the rest
- * if bone_name = NULL enable all fcurves
- */
-void AnimationExporter::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;
+ if (axis_name != "")
+ return tm_name + "." + std::string(axis_name);
else
- fcu->flag |= FCURVE_DISABLED;
- }
- else {
- fcu->flag &= ~FCURVE_DISABLED;
- }
+ return tm_name;
}
-}
-bool AnimationExporter::hasAnimations(Scene *sce)
-{
- LinkNode *node;
-
- for (node=this->export_settings->export_set; node; node=node->next) {
- Object *ob = (Object *)node->link;
-
- FCurve *fcu = 0;
- //Check for object transform animations
- if (ob->adt && ob->adt->action)
- fcu = (FCurve *)ob->adt->action->curves.first;
- //Check for Lamp parameter animations
- else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
- fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
- //Check for Camera parameter animations
- else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
- fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
-
- //Check Material Effect parameter animations.
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
- if (!ma) continue;
- if (ma->adt && ma->adt->action) {
- fcu = (FCurve *)ma->adt->action->curves.first;
- }
- }
-
- //check shape key animation
- if (!fcu) {
- Key *key = BKE_key_from_object(ob);
- if (key && key->adt && key->adt->action)
- fcu = (FCurve *)key->adt->action->curves.first;
- }
- if (fcu)
- return true;
- }
- return false;
-}
-
-//------------------------------- Not used in the new system.--------------------------------------------------------
-void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
-{
- if (rotmode > 0)
- find_keyframes(ob, fra, prefix, "rotation_euler");
- else if (rotmode == ROT_MODE_QUAT)
- find_keyframes(ob, fra, prefix, "rotation_quaternion");
- /*else if (rotmode == ROT_MODE_AXISANGLE)
- ;*/
+ return tm_name;
}
-/* Take care to always have the first frame and the last frame in the animation
- * regardless of the sampling_rate setting
- */
-void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
+#ifdef WITH_MORPH_ANIMATION
+/* TODO: This function needs to be implemented similar to the material animation export
+So we have to update BCSample for this to work.
+*/
+void AnimationExporter::export_morph_animation(Object *ob, BCAnimationSampler &sampler)
{
- int frame = scene->r.sfra;
- do {
- float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
- fra.push_back(ctime);
- if (frame == scene->r.efra)
- break;
- frame += this->export_settings->sampling_rate;
- if (frame > scene->r.efra)
- frame = scene->r.efra; // make sure the last frame is always exported
-
- } while (true);
-}
-
-/*
- * find keyframes of all the objects animations
- */
-void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
-{
- if (ob->adt && ob->adt->action) {
- FCurve *fcu = (FCurve *)ob->adt->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];
- if (std::find(fra.begin(), fra.end(), f) == fra.end())
- fra.push_back(f);
- }
- }
-
- // keep the keys in ascending order
- std::sort(fra.begin(), fra.end());
- }
-}
-
-void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
-{
- if (ob->adt && ob->adt->action) {
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
-
- for (; fcu; fcu = fcu->next) {
- if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
- continue;
-
- char *name = extract_transform_name(fcu->rna_path);
- if (STREQ(name, tm_name)) {
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float f = fcu->bezt[i].vec[1][0];
- if (std::find(fra.begin(), fra.end(), f) == fra.end())
- fra.push_back(f);
- }
- }
- }
-
- // keep the keys in ascending order
- std::sort(fra.begin(), fra.end());
- }
-}
-
-void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
-{
- if (!ob_arm->adt)
- return;
-
- //write bone animations for 3 transform types
- //i=0 --> rotations
- //i=1 --> scale
- //i=2 --> location
- for (int i = 0; i < 3; i++)
- sample_and_write_bone_animation(ob_arm, bone, i);
-
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
- write_bone_animation(ob_arm, child);
-}
-
-void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
-{
- bArmature *arm = (bArmature *)ob_arm->data;
- int flag = arm->flag;
- std::vector<float> fra;
- char prefix[256];
-
- BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
-
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
- if (!pchan)
- return;
- //Fill frame array with key frame values framed at \param:transform_type
- switch (transform_type) {
- case 0:
- find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
- break;
- case 1:
- find_keyframes(ob_arm, fra, prefix, "scale");
- break;
- case 2:
- find_keyframes(ob_arm, fra, prefix, "location");
- break;
- default:
- return;
- }
-
- // exit rest position
- if (flag & ARM_RESTPOS) {
- arm->flag &= ~ARM_RESTPOS;
- BKE_pose_where_is(depsgraph, scene, ob_arm);
- }
- //v array will hold all values which will be exported.
- if (fra.size()) {
- float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
- sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
-
- if (transform_type == 0) {
- // write x, y, z curves separately if it is rotation
- float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
-
- for (int i = 0; i < 3; i++) {
- for (unsigned int j = 0; j < fra.size(); j++)
- axisValues[j] = values[j * 3 + i];
-
- dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
- }
- MEM_freeN(axisValues);
- }
- else {
- // write xyz at once if it is location or scale
- dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
- }
-
- MEM_freeN(values);
- }
-
- // restore restpos
- if (flag & ARM_RESTPOS)
- arm->flag = flag;
- BKE_pose_where_is(depsgraph, scene, ob_arm);
-}
-
-void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
-{
- bPoseChannel *parchan = NULL;
- bPose *pose = ob_arm->pose;
-
- pchan = BKE_pose_channel_find_name(pose, bone->name);
-
- if (!pchan)
- return;
-
- parchan = pchan->parent;
-
- enable_fcurves(ob_arm->adt->action, bone->name);
-
- std::vector<float>::iterator it;
- for (it = frames.begin(); it != frames.end(); it++) {
- float mat[4][4], ipar[4][4];
+ FCurve *fcu;
+ Key *key = BKE_key_from_object(ob);
+ if (!key) return;
- float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
+ if (key->adt && key->adt->action) {
+ fcu = (FCurve *)key->adt->action->curves.first;
+ while (fcu) {
+ BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path);
- BKE_animsys_evaluate_animdata(depsgraph, scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
- BKE_pose_where_is_bone(depsgraph, scene, ob_arm, pchan, ctime, 1);
+ create_keyframed_animation(ob, fcu, tm_type, true, sampler);
- // compute bone local mat
- 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);
-
- switch (type) {
- case 0:
- mat4_to_eul(v, mat);
- break;
- case 1:
- mat4_to_size(v, mat);
- break;
- case 2:
- copy_v3_v3(v, mat[3]);
- break;
+ fcu = fcu->next;
}
-
- v += 3;
}
- enable_fcurves(ob_arm->adt->action, NULL);
-}
-
-bool AnimationExporter::validateConstraints(bConstraint *con)
-{
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- /* these we can skip completely (invalid constraints...) */
- if (cti == NULL)
- return false;
- if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
- return false;
-
- /* these constraints can't be evaluated anyway */
- if (cti->evaluate_constraint == NULL)
- return false;
-
- /* influence == 0 should be ignored */
- if (con->enforce == 0.0f)
- return false;
-
- /* validation passed */
- return true;
}
+#endif