2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
20 * ***** END GPL LICENSE BLOCK *****
23 #include "GeometryExporter.h"
24 #include "AnimationExporter.h"
25 #include "MaterialExporter.h"
27 template<class Functor>
28 void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
31 for (node = export_set; node; node = node->next) {
32 Object *ob = (Object *)node->link;
37 bool AnimationExporter::exportAnimations(Scene *sce)
39 bool has_animations = hasAnimations(sce);
45 forEachObjectInExportSet(sce, *this, this->export_settings->export_set);
49 return has_animations;
52 bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
54 for (int i = 0; i < values.size(); i += channel_count) {
55 for (int j = 0; j < channel_count; j++) {
56 if (!bc_in_range(values[j], values[i+j], 0.000001))
63 * This function creates a complete LINEAR Collada <Animation> Entry with all needed
64 * <source>, <sampler>, and <channel> entries.
65 * This is is used for creating sampled Transformation Animations for either:
68 * times contains the time points in seconds from within the timeline
69 * values contains the data (list of single floats)
71 * axis_name = ['X' | 'Y' | 'Z']
72 * is_rot indicates if the animation is a rotation
75 * times contains the time points in seconds from within the timeline
76 * values contains the data (list of floats where each 3 entries are one vector)
78 * axis_name = "" (actually not used)
79 * is_rot = false (see xxx below)
81 * xxx: I tried to create a 3 axis rotation animation
82 * like for translation or scale. But i could not
83 * figure out how to setup the channel for this case.
84 * So for now rotations are exported as 3 separate 1-axis collada animations
85 * See export_sampled_animation() further down.
87 void AnimationExporter::create_sampled_animation(int channel_count,
88 std::vector<float> ×,
89 std::vector<float> &values,
92 std::string axis_name,
97 if (is_flat_line(values, channel_count))
100 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
102 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
104 /* create input source */
105 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
107 /* create output source */
108 std::string output_id;
109 if (channel_count == 1)
110 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
111 else if (channel_count == 3)
112 output_id = create_xyz_source(&values[0], times.size(), anim_id);
113 else if (channel_count == 16)
114 output_id = create_4x4_source(times, values, anim_id);
116 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
117 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
119 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
120 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
122 /* TODO create in/out tangents source (LINEAR) */
123 std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
126 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
130 std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
131 addChannel(COLLADABU::URI(empty, sampler_id), target);
138 * Export all animation FCurves of an Object.
140 * Note: This uses the keyframes as sample points,
141 * and exports "baked keyframes" while keeping the tangent infromation
142 * of the FCurves intact. This works for simple cases, but breaks
143 * especially when negative scales are involved in the animation.
145 * If it is necessary to conserve the Animation precisely then
146 * use export_sampled_animation_set() instead.
148 void AnimationExporter::export_keyframed_animation_set(Object *ob)
150 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
152 return; /* object has no animation */
155 if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
157 std::vector<float> ctimes;
158 std::vector<float[4][4]> values;
159 find_keyframes(ob, ctimes);
160 if (ctimes.size() > 0)
161 export_sampled_matrix_animation(ob, ctimes);
166 //for armature animations as objects
167 if (ob->type == OB_ARMATURE)
168 transformName = fcu->rna_path;
170 transformName = extract_transform_name(fcu->rna_path);
173 STREQ(transformName, "location") ||
174 STREQ(transformName, "scale") ||
175 (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
176 STREQ(transformName, "rotation_quaternion"))
178 create_keyframed_animation(ob, fcu, transformName, false);
186 * Export the sampled animation of an Object.
188 * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
189 * and then evaluates the transformation,
190 * and exports "baked samples" This works always, however currently the interpolation type is set
191 * to LINEAR for now. (maybe later this can be changed to BEZIER)
193 * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
194 * However be aware that exporting keyframed animation may modify the animation slightly.
195 * Also keyframed animation exports tend to break when negative scales are involved.
197 void AnimationExporter::export_sampled_animation_set(Object *ob)
199 std::vector<float>ctimes;
200 find_sampleframes(ob, ctimes);
201 if (ctimes.size() > 0) {
202 if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
203 export_sampled_matrix_animation(ob, ctimes);
205 export_sampled_transrotloc_animation(ob, ctimes);
209 void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
211 UnitConverter converter;
213 std::vector<float> values;
215 for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
219 bc_update_scene(scene, *ctime);
220 BKE_object_matrix_local_get(ob, fmat);
221 converter.mat4_to_dae(outmat, fmat);
223 if (this->export_settings->limit_precision)
224 bc_sanitize_mat(outmat, 6);
226 for (int i = 0; i < 4; i++)
227 for (int j = 0; j < 4; j++)
228 values.push_back(outmat[j][i]);
231 std::string ob_name = id_name(ob);
233 create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
236 void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
242 static int SCALE = 4;
244 std::vector<float> baked_curves[5];
246 for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
253 bc_update_scene(scene, *ctime);
255 BKE_object_matrix_local_get(ob, fmat);
256 mat4_decompose(floc, fquat, fsize, fmat);
257 quat_to_eul(feul, fquat);
259 baked_curves[LOC].push_back(floc[0]);
260 baked_curves[LOC].push_back(floc[1]);
261 baked_curves[LOC].push_back(floc[2]);
263 baked_curves[EULX].push_back(feul[0]);
264 baked_curves[EULY].push_back(feul[1]);
265 baked_curves[EULZ].push_back(feul[2]);
267 baked_curves[SCALE].push_back(fsize[0]);
268 baked_curves[SCALE].push_back(fsize[1]);
269 baked_curves[SCALE].push_back(fsize[2]);
273 std::string ob_name = id_name(ob);
275 create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false);
276 create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false);
278 /* Not sure how to export rotation as a 3channel animation,
279 * so separate into 3 single animations for now:
282 create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
283 create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
284 create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
286 fprintf(stdout, "Animation Export: Baked %zd frames for %s (sampling rate: %d)\n",
287 baked_curves[0].size(),
289 this->export_settings->sampling_rate);
292 /* called for each exported object */
293 void AnimationExporter::operator()(Object *ob)
297 /* bool isMatAnim = false; */ /* UNUSED */
299 //Export transform animations
300 if (ob->adt && ob->adt->action) {
302 if (ob->type == OB_ARMATURE) {
303 /* Export skeletal animation (if any)*/
304 bArmature *arm = (bArmature *)ob->data;
305 for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
306 write_bone_animation_matrix(ob, bone);
309 /* Armatures can have object animation and skeletal animation*/
310 if (this->export_settings->sampling_rate < 1) {
311 export_keyframed_animation_set(ob);
314 export_sampled_animation_set(ob);
318 export_object_constraint_animation(ob);
320 //This needs to be handled by extra profiles, so postponed for now
321 //export_morph_animation(ob);
323 //Export Lamp parameter animations
324 if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
325 FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
327 transformName = extract_transform_name(fcu->rna_path);
329 if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
330 (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
332 create_keyframed_animation(ob, fcu, transformName, true);
338 //Export Camera parameter animations
339 if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
340 FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
342 transformName = extract_transform_name(fcu->rna_path);
344 if ((STREQ(transformName, "lens")) ||
345 (STREQ(transformName, "ortho_scale")) ||
346 (STREQ(transformName, "clip_end")) ||
347 (STREQ(transformName, "clip_start")))
349 create_keyframed_animation(ob, fcu, transformName, true);
355 //Export Material parameter animations.
356 for (int a = 0; a < ob->totcol; a++) {
357 Material *ma = give_current_material(ob, a + 1);
359 if (ma->adt && ma->adt->action) {
360 /* isMatAnim = true; */
361 FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
363 transformName = extract_transform_name(fcu->rna_path);
365 if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
366 (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
367 (STREQ(transformName, "ior")))
369 create_keyframed_animation(ob, fcu, transformName, true, ma);
377 void AnimationExporter::export_object_constraint_animation(Object *ob)
379 std::vector<float> fra;
380 //Takes frames of target animations
381 make_anim_frames_from_targets(ob, fra);
384 dae_baked_object_animation(fra, ob);
387 void AnimationExporter::export_morph_animation(Object *ob)
391 Key *key = BKE_key_from_object(ob);
394 if (key->adt && key->adt->action) {
395 fcu = (FCurve *)key->adt->action->curves.first;
398 transformName = extract_transform_name(fcu->rna_path);
400 create_keyframed_animation(ob, fcu, transformName, true);
408 void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
410 ListBase *conlist = get_active_constraints(ob);
411 if (conlist == NULL) return;
413 for (con = (bConstraint *)conlist->first; con; con = con->next) {
414 ListBase targets = {NULL, NULL};
416 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
418 if (!validateConstraints(con)) continue;
420 if (cti && cti->get_constraint_targets) {
421 bConstraintTarget *ct;
424 * - constraints should use ct->matrix, not directly accessing values
425 * - ct->matrix members have not yet been calculated here!
427 cti->get_constraint_targets(con, &targets);
429 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
433 find_keyframes(obtar, frames);
436 if (cti->flush_constraint_targets)
437 cti->flush_constraint_targets(con, &targets, 1);
442 //euler sources from quternion sources
443 float *AnimationExporter::get_eul_source_for_quat(Object *ob)
445 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
446 const int keys = fcu->totvert;
447 float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
448 float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
452 char *transformName = extract_transform_name(fcu->rna_path);
454 if (STREQ(transformName, "rotation_quaternion") ) {
455 for (int i = 0; i < fcu->totvert; i++) {
456 *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
462 for (int i = 0; i < keys; i++) {
463 for (int j = 0; j < 4; j++)
464 temp_quat[j] = quat[(i * 4) + j];
466 quat_to_eul(temp_eul, temp_quat);
468 for (int k = 0; k < 3; k++)
469 eul[i * 3 + k] = temp_eul[k];
477 //Get proper name for bones
478 std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
480 //hard-way to derive the bone name from rna_path. Must find more compact method
481 std::string rna_path = std::string(fcu->rna_path);
483 char *boneName = strtok((char *)rna_path.c_str(), "\"");
484 boneName = strtok(NULL, "\"");
486 if (boneName != NULL)
487 return /*id_name(ob) + "_" +*/ std::string(boneName);
492 std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
494 std::string rna_path = std::string(fcu->rna_path);
495 return translate_id(rna_path);
498 /* convert f-curves to animation curves and write */
499 void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
501 const char *axis_name = NULL;
504 bool has_tangents = false;
505 bool quatRotation = false;
509 if (STREQ(transformName, "rotation_quaternion") ) {
510 fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
515 //axis names for colors
516 else if (STREQ(transformName, "color") ||
517 STREQ(transformName, "specular_color") ||
518 STREQ(transformName, "diffuse_color") ||
519 STREQ(transformName, "alpha"))
521 const char *axis_names[] = {"R", "G", "B"};
522 if (fcu->array_index < 3)
523 axis_name = axis_names[fcu->array_index];
527 * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
528 * We will use the object to evaluate the animation on all keyframes and calculate the
529 * resulting object matrix. We need this to incorporate the
530 * effects of the parent inverse matrix (when it contains a rotation component)
532 * TODO: try to combine exported fcurves into 3 channel animations like done
533 * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
537 STREQ(transformName, "scale") ||
538 STREQ(transformName, "location") ||
539 STREQ(transformName, "rotation_euler"))
541 const char *axis_names[] = {"X", "Y", "Z"};
542 if (fcu->array_index < 3) {
543 axis_name = axis_names[fcu->array_index];
548 /* no axis name. single parameter */
552 std::string ob_name = std::string("null");
555 if (ob->type == OB_ARMATURE) {
556 ob_name = getObjectBoneName(ob, fcu);
561 (char *)translate_id(ob_name).c_str(),
562 (char *)translate_id(transformName).c_str(),
567 ob_name = id_name(ob) + "_material";
569 ob_name = id_name(ob);
575 (char *)translate_id(ob_name).c_str(),
576 (char *)getAnimationPathId(fcu).c_str(),
580 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
582 // create input source
583 std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
585 // create output source
586 std::string output_id;
588 //quat rotations are skipped for now, because of complications with determining axis.
590 float *eul = get_eul_source_for_quat(ob);
591 float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
592 for (int i = 0; i < fcu->totvert; i++) {
593 eul_axis[i] = eul[i * 3 + fcu->array_index];
595 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
599 else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
600 output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
603 output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
606 // create interpolations source
607 std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
609 // handle tangents (if required)
610 std::string intangent_id;
611 std::string outtangent_id;
614 // create in_tangent source
615 intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
617 // create out_tangent source
618 outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
621 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
622 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
624 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
625 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
627 // this input is required
628 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
631 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
632 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
640 target = translate_id(ob_name) +
641 "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
643 if (ob->type == OB_LAMP)
644 target = get_light_id(ob) +
645 "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
647 if (ob->type == OB_CAMERA)
648 target = get_camera_id(ob) +
649 "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
652 target = translate_id(id_name(ma)) + "-effect" +
653 "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
654 //if shape key animation, this is the main problem, how to define the channel targets.
655 /*target = get_morph_id(ob) +
658 addChannel(COLLADABU::URI(empty, sampler_id), target);
665 //write bone animations in transform matrix sources
666 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
671 //This will only export animations of bones in deform group.
672 /* if (!is_bone_deform_group(bone)) return; */
674 sample_and_write_bone_animation_matrix(ob_arm, bone);
676 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
677 write_bone_animation_matrix(ob_arm, child);
680 bool AnimationExporter::is_bone_deform_group(Bone *bone)
683 //Check if current bone is deform
684 if ((bone->flag & BONE_NO_DEFORM) == 0) return true;
687 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
688 //loop through all the children until deform bone is found, and then return
689 is_def = is_bone_deform_group(child);
690 if (is_def) return true;
693 //no deform bone found in children also
697 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
699 bArmature *arm = (bArmature *)ob_arm->data;
700 int flag = arm->flag;
701 std::vector<float> fra;
704 //Check if there is a fcurve in the armature for the bone in param
705 //when baking this check is not needed, solve every bone for every frame.
706 /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
709 std::string bone_name = getObjectBoneName(ob_arm, fcu);
710 int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
715 if (!(fcu)) return;*/
717 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
722 if (this->export_settings->sampling_rate < 1)
723 find_keyframes(ob_arm, fra);
725 find_sampleframes(ob_arm, fra);
727 if (flag & ARM_RESTPOS) {
728 arm->flag &= ~ARM_RESTPOS;
729 BKE_pose_where_is(scene, ob_arm);
733 dae_baked_animation(fra, ob_arm, bone);
736 if (flag & ARM_RESTPOS)
738 BKE_pose_where_is(scene, ob_arm);
741 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
743 std::string ob_name = id_name(ob_arm);
744 std::string bone_name = bone->name;
750 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
751 (char *)translate_id(bone_name).c_str(), "pose_matrix");
753 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
755 // create input source
756 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
758 // create output source
759 std::string output_id;
761 output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
763 // create interpolations source
764 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
766 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
767 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
769 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
770 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
772 // TODO create in/out tangents source
774 // this input is required
775 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
779 std::string target = get_joint_id(bone, ob_arm) + "/transform";
780 addChannel(COLLADABU::URI(empty, sampler_id), target);
785 void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
787 std::string ob_name = id_name(ob);
793 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
796 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
798 // create input source
799 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
801 // create output source
802 std::string output_id;
803 output_id = create_4x4_source( fra, ob, NULL, anim_id);
805 // create interpolations source
806 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
808 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
809 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
811 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
812 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
814 // TODO create in/out tangents source
816 // this input is required
817 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
821 std::string target = translate_id(ob_name) + "/transform";
822 addChannel(COLLADABU::URI(empty, sampler_id), target);
827 // dae_bone_animation -> add_bone_animation
828 // (blend this into dae_bone_animation)
829 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
831 const char *axis_names[] = {"X", "Y", "Z"};
832 const char *axis_name = NULL;
834 bool is_rot = tm_type == 0;
840 BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
841 tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
844 axis_name = axis_names[axis];
846 std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
848 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
849 (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
851 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
853 // create input source
854 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
856 // create output source
857 std::string output_id;
859 output_id = create_xyz_source(values, fra.size(), anim_id);
861 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
863 // create interpolations source
864 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
866 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
867 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
869 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
870 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
872 // TODO create in/out tangents source
874 // this input is required
875 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
879 std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
880 addChannel(COLLADABU::URI(empty, sampler_id), target);
885 float AnimationExporter::convert_time(float frame)
887 return FRA2TIME(frame);
890 float AnimationExporter::convert_angle(float angle)
892 return COLLADABU::Math::Utils::radToDegF(angle);
895 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
898 case COLLADASW::InputSemantic::INPUT:
899 return INPUT_SOURCE_ID_SUFFIX;
900 case COLLADASW::InputSemantic::OUTPUT:
901 return OUTPUT_SOURCE_ID_SUFFIX;
902 case COLLADASW::InputSemantic::INTERPOLATION:
903 return INTERPOLATION_SOURCE_ID_SUFFIX;
904 case COLLADASW::InputSemantic::IN_TANGENT:
905 return INTANGENT_SOURCE_ID_SUFFIX;
906 case COLLADASW::InputSemantic::OUT_TANGENT:
907 return OUTTANGENT_SOURCE_ID_SUFFIX;
914 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
915 COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
918 case COLLADASW::InputSemantic::INPUT:
919 param.push_back("TIME");
921 case COLLADASW::InputSemantic::OUTPUT:
923 param.push_back("ANGLE");
927 param.push_back(axis);
931 param.push_back("TRANSFORM");
933 else { //assumes if axis isn't specified all axises are added
934 param.push_back("X");
935 param.push_back("Y");
936 param.push_back("Z");
940 case COLLADASW::InputSemantic::IN_TANGENT:
941 case COLLADASW::InputSemantic::OUT_TANGENT:
942 param.push_back("X");
943 param.push_back("Y");
950 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length)
953 case COLLADASW::InputSemantic::INPUT:
955 values[0] = convert_time(bezt->vec[1][0]);
957 case COLLADASW::InputSemantic::OUTPUT:
960 values[0] = RAD2DEGF(bezt->vec[1][1]);
963 values[0] = bezt->vec[1][1];
967 case COLLADASW::InputSemantic::IN_TANGENT:
969 values[0] = convert_time(bezt->vec[0][0]);
970 if (bezt->ipo != BEZT_IPO_BEZ) {
971 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
976 values[1] = RAD2DEGF(bezt->vec[0][1]);
979 values[1] = bezt->vec[0][1];
983 case COLLADASW::InputSemantic::OUT_TANGENT:
985 values[0] = convert_time(bezt->vec[2][0]);
986 if (bezt->ipo != BEZT_IPO_BEZ) {
987 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
992 values[1] = RAD2DEGF(bezt->vec[2][1]);
995 values[1] = bezt->vec[2][1];
1004 // old function to keep compatibility for calls where offset and object are not needed
1005 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
1007 return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
1010 void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
1012 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1013 ListBase *conlist = get_active_constraints(ob);
1015 for (con = (bConstraint *)conlist->first; con; con = con->next) {
1016 ListBase targets = { NULL, NULL };
1018 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1020 if (cti && cti->get_constraint_targets) {
1021 bConstraintTarget *ct;
1023 cti->get_constraint_targets(con, &targets);
1024 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1028 BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1029 BKE_object_where_is_calc_time(scene, obtar, ctime);
1033 if (cti->flush_constraint_targets)
1034 cti->flush_constraint_targets(con, &targets, 1);
1037 BKE_object_where_is_calc_time(scene, ob, ctime);
1041 * ob is needed to aply parent inverse information to fcurve.
1042 * TODO: Here we have to step over all keyframes for each object and for each fcurve.
1043 * Instead of processing each fcurve one by one,
1044 * step over the animation from keyframe to keyframe,
1045 * then create adjusted fcurves (and entries) for all affected objects.
1046 * Then we would need to step through the scene only once.
1048 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
1050 std::string source_id = anim_id + get_semantic_suffix(semantic);
1052 bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
1053 bool is_euler = strstr(fcu->rna_path, "rotation_euler");
1054 bool is_translation = strstr(fcu->rna_path, "location");
1055 bool is_scale = strstr(fcu->rna_path, "scale");
1056 bool is_tangent = false;
1057 int offset_index = 0;
1059 COLLADASW::FloatSourceF source(mSW);
1060 source.setId(source_id);
1061 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1062 source.setAccessorCount(fcu->totvert);
1065 case COLLADASW::InputSemantic::INPUT:
1066 case COLLADASW::InputSemantic::OUTPUT:
1067 source.setAccessorStride(1);
1070 case COLLADASW::InputSemantic::IN_TANGENT:
1071 case COLLADASW::InputSemantic::OUT_TANGENT:
1072 source.setAccessorStride(2);
1080 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1081 add_source_parameters(param, semantic, is_angle, axis_name, false);
1083 source.prepareToAppendValues();
1085 for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
1086 float fixed_val = 0;
1089 float frame = fcu->bezt[frame_index].vec[1][0];
1090 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1092 evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
1094 BKE_object_matrix_local_get(ob, fmat);
1098 mat4_decompose(floc, fquat, fsize, fmat);
1102 quat_to_eul(eul, fquat);
1103 fixed_val = RAD2DEGF(eul[fcu->array_index]);
1105 else if (is_translation) {
1106 fixed_val = floc[fcu->array_index];
1108 else if (is_scale) {
1109 fixed_val = fsize[fcu->array_index];
1113 float values[3]; // be careful!
1116 get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
1120 get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
1121 offset = values[offset_index] - bases[0];
1124 for (int j = 0; j < length; j++) {
1126 if (j == offset_index) {
1128 val = fixed_val + offset;
1131 val = values[j] + offset;
1136 source.appendValues(val);
1146 * Similar to create_source_from_fcurve, but adds conversion of lens
1147 * animation data from focal length to FOV.
1149 std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id)
1151 std::string source_id = anim_id + get_semantic_suffix(semantic);
1153 COLLADASW::FloatSourceF source(mSW);
1154 source.setId(source_id);
1155 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1156 source.setAccessorCount(fcu->totvert);
1158 source.setAccessorStride(1);
1160 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1161 add_source_parameters(param, semantic, false, "", false);
1163 source.prepareToAppendValues();
1165 for (unsigned int i = 0; i < fcu->totvert; i++) {
1166 float values[3]; // be careful!
1168 get_source_values(&fcu->bezt[i], semantic, false, values, &length);
1169 for (int j = 0; j < length; j++)
1171 float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x));
1172 source.appendValues(val);
1182 * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
1184 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)
1186 std::string source_id = anim_id + get_semantic_suffix(semantic);
1188 COLLADASW::FloatSourceF source(mSW);
1189 source.setId(source_id);
1190 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1191 source.setAccessorCount(tot);
1192 source.setAccessorStride(1);
1194 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1195 add_source_parameters(param, semantic, is_rot, axis_name, false);
1197 source.prepareToAppendValues();
1199 for (int i = 0; i < tot; i++) {
1201 ////if (semantic == COLLADASW::InputSemantic::INPUT)
1202 // val = convert_time(val);
1205 val = RAD2DEGF(val);
1206 source.appendValues(val);
1215 * only used for sources with INPUT semantic
1217 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)
1219 std::string source_id = anim_id + get_semantic_suffix(semantic);
1221 COLLADASW::FloatSourceF source(mSW);
1222 source.setId(source_id);
1223 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1224 source.setAccessorCount(fra.size());
1225 source.setAccessorStride(1);
1227 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1228 add_source_parameters(param, semantic, is_rot, axis_name, false);
1230 source.prepareToAppendValues();
1232 std::vector<float>::iterator it;
1233 for (it = fra.begin(); it != fra.end(); it++) {
1235 //if (semantic == COLLADASW::InputSemantic::INPUT)
1236 val = convert_time(val);
1238 val = convert_angle(val);*/
1239 source.appendValues(val);
1247 std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
1249 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1250 std::string source_id = anim_id + get_semantic_suffix(semantic);
1252 COLLADASW::Float4x4Source source(mSW);
1253 source.setId(source_id);
1254 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1255 source.setAccessorCount(ctimes.size());
1256 source.setAccessorStride(16);
1258 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1259 add_source_parameters(param, semantic, false, NULL, true);
1261 source.prepareToAppendValues();
1263 bPoseChannel *parchan = NULL;
1264 bPoseChannel *pchan = NULL;
1267 std::vector<float>::iterator it;
1269 for (it = values.begin(); it != values.end(); it+=16) {
1272 bc_copy_m4_farray(mat, &*it);
1274 UnitConverter converter;
1275 double outmat[4][4];
1276 converter.mat4_to_dae_double(outmat, mat);
1278 if (this->export_settings->limit_precision)
1279 bc_sanitize_mat(outmat, 6);
1281 source.appendValues(outmat);
1288 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
1290 bool is_bone_animation = ob->type == OB_ARMATURE && bone;
1292 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1293 std::string source_id = anim_id + get_semantic_suffix(semantic);
1295 COLLADASW::Float4x4Source source(mSW);
1296 source.setId(source_id);
1297 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1298 source.setAccessorCount(frames.size());
1299 source.setAccessorStride(16);
1301 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1302 add_source_parameters(param, semantic, false, NULL, true);
1304 source.prepareToAppendValues();
1306 bPoseChannel *parchan = NULL;
1307 bPoseChannel *pchan = NULL;
1309 if (is_bone_animation) {
1310 bPose *pose = ob->pose;
1311 pchan = BKE_pose_channel_find_name(pose, bone->name);
1315 parchan = pchan->parent;
1317 enable_fcurves(ob->adt->action, bone->name);
1320 std::vector<float>::iterator it;
1322 for (it = frames.begin(); it != frames.end(); it++) {
1323 float mat[4][4], ipar[4][4];
1326 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1327 bc_update_scene(scene, ctime);
1328 if (is_bone_animation) {
1329 if (pchan->flag & POSE_CHAIN) {
1330 enable_fcurves(ob->adt->action, NULL);
1331 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1332 BKE_pose_where_is(scene, ob);
1335 BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
1338 // compute bone local mat
1340 invert_m4_m4(ipar, parchan->pose_mat);
1341 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1344 copy_m4_m4(mat, pchan->pose_mat);
1346 /* OPEN_SIM_COMPATIBILITY
1347 * AFAIK animation to second life is via BVH, but no
1348 * reason to not have the collada-animation be correct
1350 if (export_settings->open_sim) {
1352 copy_m4_m4(temp, bone->arm_mat);
1353 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1356 mul_m4_m4m4(mat, mat, temp);
1359 copy_m4_m4(temp, bone->parent->arm_mat);
1360 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1362 mul_m4_m4m4(mat, temp, mat);
1368 copy_m4_m4(mat, ob->obmat);
1371 UnitConverter converter;
1373 double outmat[4][4];
1374 converter.mat4_to_dae_double(outmat, mat);
1376 if (this->export_settings->limit_precision)
1377 bc_sanitize_mat(outmat, 6);
1379 source.appendValues(outmat);
1383 BIK_release_tree(scene, ob, ctime);
1387 enable_fcurves(ob->adt->action, NULL);
1397 * only used for sources with OUTPUT semantic ( locations and scale)
1399 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
1401 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1402 std::string source_id = anim_id + get_semantic_suffix(semantic);
1404 COLLADASW::FloatSourceF source(mSW);
1405 source.setId(source_id);
1406 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1407 source.setAccessorCount(tot);
1408 source.setAccessorStride(3);
1410 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1411 add_source_parameters(param, semantic, false, NULL, false);
1413 source.prepareToAppendValues();
1415 for (int i = 0; i < tot; i++) {
1416 source.appendValues(*v, *(v + 1), *(v + 2));
1425 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
1427 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1429 COLLADASW::NameSource source(mSW);
1430 source.setId(source_id);
1431 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1432 source.setAccessorCount(fcu->totvert);
1433 source.setAccessorStride(1);
1435 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1436 param.push_back("INTERPOLATION");
1438 source.prepareToAppendValues();
1440 *has_tangents = false;
1442 for (unsigned int i = 0; i < fcu->totvert; i++) {
1443 if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
1444 source.appendValues(BEZIER_NAME);
1445 *has_tangents = true;
1447 else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
1448 source.appendValues(STEP_NAME);
1450 else { // BEZT_IPO_LIN
1451 source.appendValues(LINEAR_NAME);
1454 // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
1461 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
1463 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1465 COLLADASW::NameSource source(mSW);
1466 source.setId(source_id);
1467 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1468 source.setAccessorCount(tot);
1469 source.setAccessorStride(1);
1471 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1472 param.push_back("INTERPOLATION");
1474 source.prepareToAppendValues();
1476 for (int i = 0; i < tot; i++) {
1477 source.appendValues(LINEAR_NAME);
1485 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1487 std::string tm_name;
1488 // when given rna_path, determine tm_type from it
1490 char *name = extract_transform_name(rna_path);
1492 if (STREQ(name, "color"))
1494 else if (STREQ(name, "spot_size"))
1496 else if (STREQ(name, "spot_blend"))
1498 else if (STREQ(name, "distance"))
1509 tm_name = "fall_off_angle";
1512 tm_name = "fall_off_exponent";
1515 tm_name = "blender/blender_dist";
1523 if (tm_name.size()) {
1525 return tm_name + "." + std::string(axis_name);
1530 return std::string("");
1533 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1535 std::string tm_name;
1536 // when given rna_path, determine tm_type from it
1538 char *name = extract_transform_name(rna_path);
1540 if (STREQ(name, "lens"))
1542 else if (STREQ(name, "ortho_scale"))
1544 else if (STREQ(name, "clip_end"))
1546 else if (STREQ(name, "clip_start"))
1572 if (tm_name.size()) {
1574 return tm_name + "." + std::string(axis_name);
1579 return std::string("");
1583 * Assign sid of the animated parameter or transform for rotation,
1584 * axis name is always appended and the value of append_axis is ignored
1586 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1588 std::string tm_name;
1589 bool is_angle = false;
1590 // when given rna_path, determine tm_type from it
1592 char *name = extract_transform_name(rna_path);
1594 if (STREQ(name, "rotation_euler"))
1596 else if (STREQ(name, "rotation_quaternion"))
1598 else if (STREQ(name, "scale"))
1600 else if (STREQ(name, "location"))
1602 else if (STREQ(name, "specular_hardness"))
1604 else if (STREQ(name, "specular_color"))
1606 else if (STREQ(name, "diffuse_color"))
1608 else if (STREQ(name, "alpha"))
1610 else if (STREQ(name, "ior"))
1620 tm_name = "rotation";
1627 tm_name = "location";
1630 tm_name = "shininess";
1633 tm_name = "specular";
1636 tm_name = "diffuse";
1639 tm_name = "transparency";
1642 tm_name = "index_of_refraction";
1650 if (tm_name.size()) {
1652 return tm_name + std::string(axis_name) + ".ANGLE";
1655 return tm_name + "." + std::string(axis_name);
1660 return std::string("");
1663 char *AnimationExporter::extract_transform_name(char *rna_path)
1665 char *dot = strrchr(rna_path, '.');
1666 return dot ? (dot + 1) : rna_path;
1670 * enable fcurves driving a specific bone, disable all the rest
1671 * if bone_name = NULL enable all fcurves
1673 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1679 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1681 for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
1683 if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
1684 fcu->flag &= ~FCURVE_DISABLED;
1686 fcu->flag |= FCURVE_DISABLED;
1689 fcu->flag &= ~FCURVE_DISABLED;
1694 bool AnimationExporter::hasAnimations(Scene *sce)
1698 for (node=this->export_settings->export_set; node; node=node->next) {
1699 Object *ob = (Object *)node->link;
1702 //Check for object transform animations
1703 if (ob->adt && ob->adt->action)
1704 fcu = (FCurve *)ob->adt->action->curves.first;
1705 //Check for Lamp parameter animations
1706 else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
1707 fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
1708 //Check for Camera parameter animations
1709 else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
1710 fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
1712 //Check Material Effect parameter animations.
1713 for (int a = 0; a < ob->totcol; a++) {
1714 Material *ma = give_current_material(ob, a + 1);
1716 if (ma->adt && ma->adt->action) {
1717 fcu = (FCurve *)ma->adt->action->curves.first;
1721 //check shape key animation
1723 Key *key = BKE_key_from_object(ob);
1724 if (key && key->adt && key->adt->action)
1725 fcu = (FCurve *)key->adt->action->curves.first;
1733 //------------------------------- Not used in the new system.--------------------------------------------------------
1734 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1737 find_keyframes(ob, fra, prefix, "rotation_euler");
1738 else if (rotmode == ROT_MODE_QUAT)
1739 find_keyframes(ob, fra, prefix, "rotation_quaternion");
1740 /*else if (rotmode == ROT_MODE_AXISANGLE)
1744 /* Take care to always have the first frame and the last frame in the animation
1745 * regardless of the sampling_rate setting
1747 void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
1749 int frame = scene->r.sfra;
1751 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1752 fra.push_back(ctime);
1753 if (frame == scene->r.efra)
1755 frame += this->export_settings->sampling_rate;
1756 if (frame > scene->r.efra)
1757 frame = scene->r.efra; // make sure the last frame is always exported
1763 * find keyframes of all the objects animations
1765 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
1767 if (ob->adt && ob->adt->action) {
1768 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1770 for (; fcu; fcu = fcu->next) {
1771 for (unsigned int i = 0; i < fcu->totvert; i++) {
1772 float f = fcu->bezt[i].vec[1][0];
1773 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1778 // keep the keys in ascending order
1779 std::sort(fra.begin(), fra.end());
1783 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1785 if (ob->adt && ob->adt->action) {
1786 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1788 for (; fcu; fcu = fcu->next) {
1789 if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
1792 char *name = extract_transform_name(fcu->rna_path);
1793 if (STREQ(name, tm_name)) {
1794 for (unsigned int i = 0; i < fcu->totvert; i++) {
1795 float f = fcu->bezt[i].vec[1][0];
1796 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1802 // keep the keys in ascending order
1803 std::sort(fra.begin(), fra.end());
1807 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1812 //write bone animations for 3 transform types
1816 for (int i = 0; i < 3; i++)
1817 sample_and_write_bone_animation(ob_arm, bone, i);
1819 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
1820 write_bone_animation(ob_arm, child);
1823 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1825 bArmature *arm = (bArmature *)ob_arm->data;
1826 int flag = arm->flag;
1827 std::vector<float> fra;
1830 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1832 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
1835 //Fill frame array with key frame values framed at \param:transform_type
1836 switch (transform_type) {
1838 find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1841 find_keyframes(ob_arm, fra, prefix, "scale");
1844 find_keyframes(ob_arm, fra, prefix, "location");
1850 // exit rest position
1851 if (flag & ARM_RESTPOS) {
1852 arm->flag &= ~ARM_RESTPOS;
1853 BKE_pose_where_is(scene, ob_arm);
1855 //v array will hold all values which will be exported.
1857 float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1858 sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1860 if (transform_type == 0) {
1861 // write x, y, z curves separately if it is rotation
1862 float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
1864 for (int i = 0; i < 3; i++) {
1865 for (unsigned int j = 0; j < fra.size(); j++)
1866 axisValues[j] = values[j * 3 + i];
1868 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1870 MEM_freeN(axisValues);
1873 // write xyz at once if it is location or scale
1874 dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1881 if (flag & ARM_RESTPOS)
1883 BKE_pose_where_is(scene, ob_arm);
1886 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1888 bPoseChannel *parchan = NULL;
1889 bPose *pose = ob_arm->pose;
1891 pchan = BKE_pose_channel_find_name(pose, bone->name);
1896 parchan = pchan->parent;
1898 enable_fcurves(ob_arm->adt->action, bone->name);
1900 std::vector<float>::iterator it;
1901 for (it = frames.begin(); it != frames.end(); it++) {
1902 float mat[4][4], ipar[4][4];
1904 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
1907 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1908 BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
1910 // compute bone local mat
1912 invert_m4_m4(ipar, parchan->pose_mat);
1913 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1916 copy_m4_m4(mat, pchan->pose_mat);
1920 mat4_to_eul(v, mat);
1923 mat4_to_size(v, mat);
1926 copy_v3_v3(v, mat[3]);
1933 enable_fcurves(ob_arm->adt->action, NULL);
1936 bool AnimationExporter::validateConstraints(bConstraint *con)
1939 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1940 /* these we can skip completely (invalid constraints...) */
1941 if (cti == NULL) valid = false;
1942 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
1943 /* these constraints can't be evaluated anyway */
1944 if (cti->evaluate_constraint == NULL) valid = false;
1945 /* influence == 0 should be ignored */
1946 if (con->enforce == 0.0f) valid = false;
1953 * Needed for sampled animations.
1954 * This function calculates the object matrix at a given time,
1955 * also taking constraints into account.
1957 * XXX: Why looking at the constraints here is necessary?
1958 * Maybe this can be done better?
1960 void AnimationExporter::calc_obmat_at_time(Object *ob, float ctime )
1962 BKE_scene_frame_set(scene, ctime);
1964 Main *bmain = bc_get_main();
1965 EvaluationContext *ev_context = bc_get_evaluation_context();
1966 BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
1968 ListBase *conlist = get_active_constraints(ob);
1970 for (con = (bConstraint *)conlist->first; con; con = con->next) {
1971 ListBase targets = {NULL, NULL};
1973 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1975 if (cti && cti->get_constraint_targets) {
1976 bConstraintTarget *ct;
1978 cti->get_constraint_targets(con, &targets);
1979 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1983 BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1984 BKE_object_where_is_calc_time(scene, obtar, ctime);
1988 if (cti->flush_constraint_targets)
1989 cti->flush_constraint_targets(con, &targets, 1);
1992 BKE_object_where_is_calc_time(scene, ob, ctime);