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(EvaluationContext *eval_ctx, Scene *sce)
39 bool has_animations = hasAnimations(sce);
41 this->eval_ctx = eval_ctx;
46 forEachObjectInExportSet(sce, *this, this->export_settings->export_set);
50 return has_animations;
53 bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
55 for (int i = 0; i < values.size(); i += channel_count) {
56 for (int j = 0; j < channel_count; j++) {
57 if (!bc_in_range(values[j], values[i+j], 0.000001))
64 * This function creates a complete LINEAR Collada <Animation> Entry with all needed
65 * <source>, <sampler>, and <channel> entries.
66 * This is is used for creating sampled Transformation Animations for either:
69 * times contains the time points in seconds from within the timeline
70 * values contains the data (list of single floats)
72 * axis_name = ['X' | 'Y' | 'Z']
73 * is_rot indicates if the animation is a rotation
76 * times contains the time points in seconds from within the timeline
77 * values contains the data (list of floats where each 3 entries are one vector)
79 * axis_name = "" (actually not used)
80 * is_rot = false (see xxx below)
82 * xxx: I tried to create a 3 axis rotation animation
83 * like for translation or scale. But i could not
84 * figure out how to setup the channel for this case.
85 * So for now rotations are exported as 3 separate 1-axis collada animations
86 * See export_sampled_animation() further down.
88 void AnimationExporter::create_sampled_animation(int channel_count,
89 std::vector<float> ×,
90 std::vector<float> &values,
93 std::string axis_name,
98 if (is_flat_line(values, channel_count))
101 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
103 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
105 /* create input source */
106 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
108 /* create output source */
109 std::string output_id;
110 if (channel_count == 1)
111 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
112 else if (channel_count == 3)
113 output_id = create_xyz_source(&values[0], times.size(), anim_id);
114 else if (channel_count == 16)
115 output_id = create_4x4_source(times, values, anim_id);
117 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
118 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
120 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
121 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
123 /* TODO create in/out tangents source (LINEAR) */
124 std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
127 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
131 std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
132 addChannel(COLLADABU::URI(empty, sampler_id), target);
139 * Export all animation FCurves of an Object.
141 * Note: This uses the keyframes as sample points,
142 * and exports "baked keyframes" while keeping the tangent infromation
143 * of the FCurves intact. This works for simple cases, but breaks
144 * especially when negative scales are involved in the animation.
146 * If it is necessary to conserve the Animation precisely then
147 * use export_sampled_animation_set() instead.
149 void AnimationExporter::export_keyframed_animation_set(Object *ob)
151 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
153 return; /* object has no animation */
156 if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
158 std::vector<float> ctimes;
159 std::vector<float[4][4]> values;
160 find_keyframes(ob, ctimes);
161 if (ctimes.size() > 0)
162 export_sampled_matrix_animation(ob, ctimes);
167 //for armature animations as objects
168 if (ob->type == OB_ARMATURE)
169 transformName = fcu->rna_path;
171 transformName = extract_transform_name(fcu->rna_path);
174 STREQ(transformName, "location") ||
175 STREQ(transformName, "scale") ||
176 (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
177 STREQ(transformName, "rotation_quaternion"))
179 create_keyframed_animation(ob, fcu, transformName, false);
187 * Export the sampled animation of an Object.
189 * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
190 * and then evaluates the transformation,
191 * and exports "baked samples" This works always, however currently the interpolation type is set
192 * to LINEAR for now. (maybe later this can be changed to BEZIER)
194 * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
195 * However be aware that exporting keyframed animation may modify the animation slightly.
196 * Also keyframed animation exports tend to break when negative scales are involved.
198 void AnimationExporter::export_sampled_animation_set(Object *ob)
200 std::vector<float>ctimes;
201 find_sampleframes(ob, ctimes);
202 if (ctimes.size() > 0) {
203 if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
204 export_sampled_matrix_animation(ob, ctimes);
206 export_sampled_transrotloc_animation(ob, ctimes);
210 void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
212 UnitConverter converter;
214 std::vector<float> values;
216 for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
220 bc_update_scene(eval_ctx, scene, *ctime);
221 BKE_object_matrix_local_get(ob, fmat);
223 converter.mat4_to_dae(outmat, fmat);
225 if (this->export_settings->limit_precision)
226 bc_sanitize_mat(outmat, 6);
228 for (int i = 0; i < 4; i++)
229 for (int j = 0; j < 4; j++)
230 values.push_back(outmat[j][i]);
233 std::string ob_name = id_name(ob);
235 create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
238 void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
244 static int SCALE = 4;
246 std::vector<float> baked_curves[5];
248 for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
255 bc_update_scene(eval_ctx, scene, *ctime);
257 BKE_object_matrix_local_get(ob, fmat);
258 mat4_decompose(floc, fquat, fsize, fmat);
259 quat_to_eul(feul, fquat);
261 baked_curves[LOC].push_back(floc[0]);
262 baked_curves[LOC].push_back(floc[1]);
263 baked_curves[LOC].push_back(floc[2]);
265 baked_curves[EULX].push_back(feul[0]);
266 baked_curves[EULY].push_back(feul[1]);
267 baked_curves[EULZ].push_back(feul[2]);
269 baked_curves[SCALE].push_back(fsize[0]);
270 baked_curves[SCALE].push_back(fsize[1]);
271 baked_curves[SCALE].push_back(fsize[2]);
275 std::string ob_name = id_name(ob);
277 create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false);
278 create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false);
280 /* Not sure how to export rotation as a 3channel animation,
281 * so separate into 3 single animations for now:
284 create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
285 create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
286 create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
288 fprintf(stdout, "Animation Export: Baked %d frames for %s (sampling rate: %d)\n",
289 (int)baked_curves[0].size(),
291 this->export_settings->sampling_rate);
294 /* called for each exported object */
295 void AnimationExporter::operator()(Object *ob)
299 /* bool isMatAnim = false; */ /* UNUSED */
301 //Export transform animations
302 if (ob->adt && ob->adt->action) {
304 if (ob->type == OB_ARMATURE) {
305 /* Export skeletal animation (if any)*/
306 bArmature *arm = (bArmature *)ob->data;
307 for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
308 write_bone_animation_matrix(ob, bone);
311 /* Armatures can have object animation and skeletal animation*/
312 if (this->export_settings->sampling_rate < 1) {
313 export_keyframed_animation_set(ob);
316 export_sampled_animation_set(ob);
320 export_object_constraint_animation(ob);
322 //This needs to be handled by extra profiles, so postponed for now
323 //export_morph_animation(ob);
325 //Export Lamp parameter animations
326 if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
327 FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
329 transformName = extract_transform_name(fcu->rna_path);
331 if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
332 (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
334 create_keyframed_animation(ob, fcu, transformName, true);
340 //Export Camera parameter animations
341 if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
342 FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
344 transformName = extract_transform_name(fcu->rna_path);
346 if ((STREQ(transformName, "lens")) ||
347 (STREQ(transformName, "ortho_scale")) ||
348 (STREQ(transformName, "clip_end")) ||
349 (STREQ(transformName, "clip_start")))
351 create_keyframed_animation(ob, fcu, transformName, true);
357 //Export Material parameter animations.
358 for (int a = 0; a < ob->totcol; a++) {
359 Material *ma = give_current_material(ob, a + 1);
361 if (ma->adt && ma->adt->action) {
362 /* isMatAnim = true; */
363 FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
365 transformName = extract_transform_name(fcu->rna_path);
367 if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
368 (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
369 (STREQ(transformName, "ior")))
371 create_keyframed_animation(ob, fcu, transformName, true, ma);
379 void AnimationExporter::export_object_constraint_animation(Object *ob)
381 std::vector<float> fra;
382 //Takes frames of target animations
383 make_anim_frames_from_targets(ob, fra);
386 dae_baked_object_animation(fra, ob);
389 void AnimationExporter::export_morph_animation(Object *ob)
393 Key *key = BKE_key_from_object(ob);
396 if (key->adt && key->adt->action) {
397 fcu = (FCurve *)key->adt->action->curves.first;
400 transformName = extract_transform_name(fcu->rna_path);
402 create_keyframed_animation(ob, fcu, transformName, true);
410 void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
412 ListBase *conlist = get_active_constraints(this->eval_ctx, ob);
413 if (conlist == NULL) return;
415 for (con = (bConstraint *)conlist->first; con; con = con->next) {
416 ListBase targets = {NULL, NULL};
418 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
420 if (!validateConstraints(con)) continue;
422 if (cti && cti->get_constraint_targets) {
423 bConstraintTarget *ct;
426 * - constraints should use ct->matrix, not directly accessing values
427 * - ct->matrix members have not yet been calculated here!
429 cti->get_constraint_targets(con, &targets);
431 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
435 find_keyframes(obtar, frames);
438 if (cti->flush_constraint_targets)
439 cti->flush_constraint_targets(con, &targets, 1);
444 //euler sources from quternion sources
445 float *AnimationExporter::get_eul_source_for_quat(Object *ob)
447 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
448 const int keys = fcu->totvert;
449 float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
450 float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
454 char *transformName = extract_transform_name(fcu->rna_path);
456 if (STREQ(transformName, "rotation_quaternion") ) {
457 for (int i = 0; i < fcu->totvert; i++) {
458 *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
464 for (int i = 0; i < keys; i++) {
465 for (int j = 0; j < 4; j++)
466 temp_quat[j] = quat[(i * 4) + j];
468 quat_to_eul(temp_eul, temp_quat);
470 for (int k = 0; k < 3; k++)
471 eul[i * 3 + k] = temp_eul[k];
479 //Get proper name for bones
480 std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
482 //hard-way to derive the bone name from rna_path. Must find more compact method
483 std::string rna_path = std::string(fcu->rna_path);
485 char *boneName = strtok((char *)rna_path.c_str(), "\"");
486 boneName = strtok(NULL, "\"");
488 if (boneName != NULL)
489 return /*id_name(ob) + "_" +*/ std::string(boneName);
494 std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
496 std::string rna_path = std::string(fcu->rna_path);
497 return translate_id(rna_path);
500 /* convert f-curves to animation curves and write */
501 void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
503 const char *axis_name = NULL;
506 bool has_tangents = false;
507 bool quatRotation = false;
511 if (STREQ(transformName, "rotation_quaternion") ) {
512 fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
517 //axis names for colors
518 else if (STREQ(transformName, "color") ||
519 STREQ(transformName, "specular_color") ||
520 STREQ(transformName, "diffuse_color") ||
521 STREQ(transformName, "alpha"))
523 const char *axis_names[] = {"R", "G", "B"};
524 if (fcu->array_index < 3)
525 axis_name = axis_names[fcu->array_index];
529 * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
530 * We will use the object to evaluate the animation on all keyframes and calculate the
531 * resulting object matrix. We need this to incorporate the
532 * effects of the parent inverse matrix (when it contains a rotation component)
534 * TODO: try to combine exported fcurves into 3 channel animations like done
535 * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
539 STREQ(transformName, "scale") ||
540 STREQ(transformName, "location") ||
541 STREQ(transformName, "rotation_euler"))
543 const char *axis_names[] = {"X", "Y", "Z"};
544 if (fcu->array_index < 3) {
545 axis_name = axis_names[fcu->array_index];
550 /* no axis name. single parameter */
554 std::string ob_name = std::string("null");
557 if (ob->type == OB_ARMATURE) {
558 ob_name = getObjectBoneName(ob, fcu);
563 (char *)translate_id(ob_name).c_str(),
564 (char *)translate_id(transformName).c_str(),
569 ob_name = id_name(ob) + "_material";
571 ob_name = id_name(ob);
577 (char *)translate_id(ob_name).c_str(),
578 (char *)getAnimationPathId(fcu).c_str(),
582 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
584 // create input source
585 std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
587 // create output source
588 std::string output_id;
590 //quat rotations are skipped for now, because of complications with determining axis.
592 float *eul = get_eul_source_for_quat(ob);
593 float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
594 for (int i = 0; i < fcu->totvert; i++) {
595 eul_axis[i] = eul[i * 3 + fcu->array_index];
597 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
601 else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
602 output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
605 output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
608 // create interpolations source
609 std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
611 // handle tangents (if required)
612 std::string intangent_id;
613 std::string outtangent_id;
616 // create in_tangent source
617 intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
619 // create out_tangent source
620 outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
623 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
624 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
626 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
627 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
629 // this input is required
630 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
633 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
634 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
642 target = translate_id(ob_name) +
643 "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
645 if (ob->type == OB_LAMP)
646 target = get_light_id(ob) +
647 "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
649 if (ob->type == OB_CAMERA)
650 target = get_camera_id(ob) +
651 "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
654 target = translate_id(id_name(ma)) + "-effect" +
655 "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
656 //if shape key animation, this is the main problem, how to define the channel targets.
657 /*target = get_morph_id(ob) +
660 addChannel(COLLADABU::URI(empty, sampler_id), target);
667 //write bone animations in transform matrix sources
668 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
673 //This will only export animations of bones in deform group.
674 /* if (!is_bone_deform_group(bone)) return; */
676 sample_and_write_bone_animation_matrix(ob_arm, bone);
678 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
679 write_bone_animation_matrix(ob_arm, child);
682 bool AnimationExporter::is_bone_deform_group(Bone *bone)
685 //Check if current bone is deform
686 if ((bone->flag & BONE_NO_DEFORM) == 0) return true;
689 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
690 //loop through all the children until deform bone is found, and then return
691 is_def = is_bone_deform_group(child);
692 if (is_def) return true;
695 //no deform bone found in children also
699 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
701 bArmature *arm = (bArmature *)ob_arm->data;
702 int flag = arm->flag;
703 std::vector<float> fra;
706 //Check if there is a fcurve in the armature for the bone in param
707 //when baking this check is not needed, solve every bone for every frame.
708 /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
711 std::string bone_name = getObjectBoneName(ob_arm, fcu);
712 int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
717 if (!(fcu)) return;*/
719 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
724 if (this->export_settings->sampling_rate < 1)
725 find_keyframes(ob_arm, fra);
727 find_sampleframes(ob_arm, fra);
729 if (flag & ARM_RESTPOS) {
730 arm->flag &= ~ARM_RESTPOS;
731 BKE_pose_where_is(eval_ctx, scene, ob_arm);
735 dae_baked_animation(fra, ob_arm, bone);
738 if (flag & ARM_RESTPOS)
740 BKE_pose_where_is(eval_ctx, scene, ob_arm);
743 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
745 std::string ob_name = id_name(ob_arm);
746 std::string bone_name = bone->name;
752 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
753 (char *)translate_id(bone_name).c_str(), "pose_matrix");
755 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
757 // create input source
758 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
760 // create output source
761 std::string output_id;
763 output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
765 // create interpolations source
766 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
768 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
769 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
771 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
772 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
774 // TODO create in/out tangents source
776 // this input is required
777 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
781 std::string target = get_joint_id(bone, ob_arm) + "/transform";
782 addChannel(COLLADABU::URI(empty, sampler_id), target);
787 void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
789 std::string ob_name = id_name(ob);
795 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
798 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
800 // create input source
801 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
803 // create output source
804 std::string output_id;
805 output_id = create_4x4_source( fra, ob, NULL, anim_id);
807 // create interpolations source
808 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
810 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
811 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
813 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
814 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
816 // TODO create in/out tangents source
818 // this input is required
819 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
823 std::string target = translate_id(ob_name) + "/transform";
824 addChannel(COLLADABU::URI(empty, sampler_id), target);
829 // dae_bone_animation -> add_bone_animation
830 // (blend this into dae_bone_animation)
831 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
833 const char *axis_names[] = {"X", "Y", "Z"};
834 const char *axis_name = NULL;
836 bool is_rot = tm_type == 0;
842 BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
843 tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
846 axis_name = axis_names[axis];
848 std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
850 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
851 (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
853 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
855 // create input source
856 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
858 // create output source
859 std::string output_id;
861 output_id = create_xyz_source(values, fra.size(), anim_id);
863 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
865 // create interpolations source
866 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
868 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
869 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
871 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
872 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
874 // TODO create in/out tangents source
876 // this input is required
877 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
881 std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
882 addChannel(COLLADABU::URI(empty, sampler_id), target);
887 float AnimationExporter::convert_time(float frame)
889 return FRA2TIME(frame);
892 float AnimationExporter::convert_angle(float angle)
894 return COLLADABU::Math::Utils::radToDegF(angle);
897 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
900 case COLLADASW::InputSemantic::INPUT:
901 return INPUT_SOURCE_ID_SUFFIX;
902 case COLLADASW::InputSemantic::OUTPUT:
903 return OUTPUT_SOURCE_ID_SUFFIX;
904 case COLLADASW::InputSemantic::INTERPOLATION:
905 return INTERPOLATION_SOURCE_ID_SUFFIX;
906 case COLLADASW::InputSemantic::IN_TANGENT:
907 return INTANGENT_SOURCE_ID_SUFFIX;
908 case COLLADASW::InputSemantic::OUT_TANGENT:
909 return OUTTANGENT_SOURCE_ID_SUFFIX;
916 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
917 COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
920 case COLLADASW::InputSemantic::INPUT:
921 param.push_back("TIME");
923 case COLLADASW::InputSemantic::OUTPUT:
925 param.push_back("ANGLE");
929 param.push_back(axis);
933 param.push_back("TRANSFORM");
935 else { //assumes if axis isn't specified all axises are added
936 param.push_back("X");
937 param.push_back("Y");
938 param.push_back("Z");
942 case COLLADASW::InputSemantic::IN_TANGENT:
943 case COLLADASW::InputSemantic::OUT_TANGENT:
944 param.push_back("X");
945 param.push_back("Y");
952 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length)
955 case COLLADASW::InputSemantic::INPUT:
957 values[0] = convert_time(bezt->vec[1][0]);
959 case COLLADASW::InputSemantic::OUTPUT:
962 values[0] = RAD2DEGF(bezt->vec[1][1]);
965 values[0] = bezt->vec[1][1];
969 case COLLADASW::InputSemantic::IN_TANGENT:
971 values[0] = convert_time(bezt->vec[0][0]);
972 if (bezt->ipo != BEZT_IPO_BEZ) {
973 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
978 values[1] = RAD2DEGF(bezt->vec[0][1]);
981 values[1] = bezt->vec[0][1];
985 case COLLADASW::InputSemantic::OUT_TANGENT:
987 values[0] = convert_time(bezt->vec[2][0]);
988 if (bezt->ipo != BEZT_IPO_BEZ) {
989 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
994 values[1] = RAD2DEGF(bezt->vec[2][1]);
997 values[1] = bezt->vec[2][1];
1006 // old function to keep compatibility for calls where offset and object are not needed
1007 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
1009 return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
1012 void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
1014 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1015 ListBase *conlist = get_active_constraints(this->eval_ctx, ob);
1017 for (con = (bConstraint *)conlist->first; con; con = con->next) {
1018 ListBase targets = { NULL, NULL };
1020 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1022 if (cti && cti->get_constraint_targets) {
1023 bConstraintTarget *ct;
1025 cti->get_constraint_targets(con, &targets);
1026 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1030 BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1031 BKE_object_where_is_calc_time(this->eval_ctx, scene, obtar, ctime);
1035 if (cti->flush_constraint_targets)
1036 cti->flush_constraint_targets(con, &targets, 1);
1039 BKE_object_where_is_calc_time(this->eval_ctx, scene, ob, ctime);
1043 * ob is needed to aply parent inverse information to fcurve.
1044 * TODO: Here we have to step over all keyframes for each object and for each fcurve.
1045 * Instead of processing each fcurve one by one,
1046 * step over the animation from keyframe to keyframe,
1047 * then create adjusted fcurves (and entries) for all affected objects.
1048 * Then we would need to step through the scene only once.
1050 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
1052 std::string source_id = anim_id + get_semantic_suffix(semantic);
1054 bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
1055 bool is_euler = strstr(fcu->rna_path, "rotation_euler");
1056 bool is_translation = strstr(fcu->rna_path, "location");
1057 bool is_scale = strstr(fcu->rna_path, "scale");
1058 bool is_tangent = false;
1059 int offset_index = 0;
1061 COLLADASW::FloatSourceF source(mSW);
1062 source.setId(source_id);
1063 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1064 source.setAccessorCount(fcu->totvert);
1067 case COLLADASW::InputSemantic::INPUT:
1068 case COLLADASW::InputSemantic::OUTPUT:
1069 source.setAccessorStride(1);
1072 case COLLADASW::InputSemantic::IN_TANGENT:
1073 case COLLADASW::InputSemantic::OUT_TANGENT:
1074 source.setAccessorStride(2);
1082 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1083 add_source_parameters(param, semantic, is_angle, axis_name, false);
1085 source.prepareToAppendValues();
1087 for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
1088 float fixed_val = 0;
1091 float frame = fcu->bezt[frame_index].vec[1][0];
1092 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1094 evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
1096 BKE_object_matrix_local_get(ob, fmat);
1100 mat4_decompose(floc, fquat, fsize, fmat);
1104 quat_to_eul(eul, fquat);
1105 fixed_val = RAD2DEGF(eul[fcu->array_index]);
1107 else if (is_translation) {
1108 fixed_val = floc[fcu->array_index];
1110 else if (is_scale) {
1111 fixed_val = fsize[fcu->array_index];
1115 float values[3]; // be careful!
1118 get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
1122 get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
1123 offset = values[offset_index] - bases[0];
1126 for (int j = 0; j < length; j++) {
1128 if (j == offset_index) {
1130 val = fixed_val + offset;
1133 val = values[j] + offset;
1138 source.appendValues(val);
1148 * Similar to create_source_from_fcurve, but adds conversion of lens
1149 * animation data from focal length to FOV.
1151 std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id)
1153 std::string source_id = anim_id + get_semantic_suffix(semantic);
1155 COLLADASW::FloatSourceF source(mSW);
1156 source.setId(source_id);
1157 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1158 source.setAccessorCount(fcu->totvert);
1160 source.setAccessorStride(1);
1162 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1163 add_source_parameters(param, semantic, false, "", false);
1165 source.prepareToAppendValues();
1167 for (unsigned int i = 0; i < fcu->totvert; i++) {
1168 float values[3]; // be careful!
1170 get_source_values(&fcu->bezt[i], semantic, false, values, &length);
1171 for (int j = 0; j < length; j++)
1173 float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x));
1174 source.appendValues(val);
1184 * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
1186 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)
1188 std::string source_id = anim_id + get_semantic_suffix(semantic);
1190 COLLADASW::FloatSourceF source(mSW);
1191 source.setId(source_id);
1192 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1193 source.setAccessorCount(tot);
1194 source.setAccessorStride(1);
1196 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1197 add_source_parameters(param, semantic, is_rot, axis_name, false);
1199 source.prepareToAppendValues();
1201 for (int i = 0; i < tot; i++) {
1203 ////if (semantic == COLLADASW::InputSemantic::INPUT)
1204 // val = convert_time(val);
1207 val = RAD2DEGF(val);
1208 source.appendValues(val);
1217 * only used for sources with INPUT semantic
1219 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)
1221 std::string source_id = anim_id + get_semantic_suffix(semantic);
1223 COLLADASW::FloatSourceF source(mSW);
1224 source.setId(source_id);
1225 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1226 source.setAccessorCount(fra.size());
1227 source.setAccessorStride(1);
1229 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1230 add_source_parameters(param, semantic, is_rot, axis_name, false);
1232 source.prepareToAppendValues();
1234 std::vector<float>::iterator it;
1235 for (it = fra.begin(); it != fra.end(); it++) {
1237 //if (semantic == COLLADASW::InputSemantic::INPUT)
1238 val = convert_time(val);
1240 val = convert_angle(val);*/
1241 source.appendValues(val);
1249 std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
1251 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1252 std::string source_id = anim_id + get_semantic_suffix(semantic);
1254 COLLADASW::Float4x4Source source(mSW);
1255 source.setId(source_id);
1256 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1257 source.setAccessorCount(ctimes.size());
1258 source.setAccessorStride(16);
1260 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1261 add_source_parameters(param, semantic, false, NULL, true);
1263 source.prepareToAppendValues();
1265 std::vector<float>::iterator it;
1267 for (it = values.begin(); it != values.end(); it+=16) {
1270 bc_copy_m4_farray(mat, &*it);
1272 UnitConverter converter;
1273 double outmat[4][4];
1274 converter.mat4_to_dae_double(outmat, mat);
1276 if (this->export_settings->limit_precision)
1277 bc_sanitize_mat(outmat, 6);
1279 source.appendValues(outmat);
1286 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
1288 bool is_bone_animation = ob->type == OB_ARMATURE && bone;
1290 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1291 std::string source_id = anim_id + get_semantic_suffix(semantic);
1293 COLLADASW::Float4x4Source source(mSW);
1294 source.setId(source_id);
1295 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1296 source.setAccessorCount(frames.size());
1297 source.setAccessorStride(16);
1299 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1300 add_source_parameters(param, semantic, false, NULL, true);
1302 source.prepareToAppendValues();
1304 bPoseChannel *parchan = NULL;
1305 bPoseChannel *pchan = NULL;
1307 if (is_bone_animation) {
1308 bPose *pose = ob->pose;
1309 pchan = BKE_pose_channel_find_name(pose, bone->name);
1313 parchan = pchan->parent;
1315 enable_fcurves(ob->adt->action, bone->name);
1318 std::vector<float>::iterator it;
1320 for (it = frames.begin(); it != frames.end(); it++) {
1321 float mat[4][4], ipar[4][4];
1324 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1325 bc_update_scene(eval_ctx, scene, ctime);
1326 if (is_bone_animation) {
1328 if (pchan->flag & POSE_CHAIN) {
1329 enable_fcurves(ob->adt->action, NULL);
1330 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1331 BKE_pose_where_is(eval_ctx, scene, ob);
1334 BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
1337 // compute bone local mat
1339 invert_m4_m4(ipar, parchan->pose_mat);
1340 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1343 copy_m4_m4(mat, pchan->pose_mat);
1345 /* OPEN_SIM_COMPATIBILITY
1346 * AFAIK animation to second life is via BVH, but no
1347 * reason to not have the collada-animation be correct
1349 if (export_settings->open_sim) {
1351 copy_m4_m4(temp, bone->arm_mat);
1352 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1355 mul_m4_m4m4(mat, mat, temp);
1358 copy_m4_m4(temp, bone->parent->arm_mat);
1359 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1361 mul_m4_m4m4(mat, temp, mat);
1367 copy_m4_m4(mat, ob->obmat);
1370 UnitConverter converter;
1372 double outmat[4][4];
1373 converter.mat4_to_dae_double(outmat, mat);
1375 if (this->export_settings->limit_precision)
1376 bc_sanitize_mat(outmat, 6);
1378 source.appendValues(outmat);
1382 BIK_release_tree(scene, ob, ctime);
1386 enable_fcurves(ob->adt->action, NULL);
1396 * only used for sources with OUTPUT semantic ( locations and scale)
1398 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
1400 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1401 std::string source_id = anim_id + get_semantic_suffix(semantic);
1403 COLLADASW::FloatSourceF source(mSW);
1404 source.setId(source_id);
1405 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1406 source.setAccessorCount(tot);
1407 source.setAccessorStride(3);
1409 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1410 add_source_parameters(param, semantic, false, NULL, false);
1412 source.prepareToAppendValues();
1414 for (int i = 0; i < tot; i++) {
1415 source.appendValues(*v, *(v + 1), *(v + 2));
1424 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
1426 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1428 COLLADASW::NameSource source(mSW);
1429 source.setId(source_id);
1430 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1431 source.setAccessorCount(fcu->totvert);
1432 source.setAccessorStride(1);
1434 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1435 param.push_back("INTERPOLATION");
1437 source.prepareToAppendValues();
1439 *has_tangents = false;
1441 for (unsigned int i = 0; i < fcu->totvert; i++) {
1442 if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
1443 source.appendValues(BEZIER_NAME);
1444 *has_tangents = true;
1446 else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
1447 source.appendValues(STEP_NAME);
1449 else { // BEZT_IPO_LIN
1450 source.appendValues(LINEAR_NAME);
1453 // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
1460 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
1462 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1464 COLLADASW::NameSource source(mSW);
1465 source.setId(source_id);
1466 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1467 source.setAccessorCount(tot);
1468 source.setAccessorStride(1);
1470 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1471 param.push_back("INTERPOLATION");
1473 source.prepareToAppendValues();
1475 for (int i = 0; i < tot; i++) {
1476 source.appendValues(LINEAR_NAME);
1484 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1486 std::string tm_name;
1487 // when given rna_path, determine tm_type from it
1489 char *name = extract_transform_name(rna_path);
1491 if (STREQ(name, "color"))
1493 else if (STREQ(name, "spot_size"))
1495 else if (STREQ(name, "spot_blend"))
1497 else if (STREQ(name, "distance"))
1508 tm_name = "fall_off_angle";
1511 tm_name = "fall_off_exponent";
1514 tm_name = "blender/blender_dist";
1522 if (tm_name.size()) {
1524 return tm_name + "." + std::string(axis_name);
1529 return std::string("");
1532 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1534 std::string tm_name;
1535 // when given rna_path, determine tm_type from it
1537 char *name = extract_transform_name(rna_path);
1539 if (STREQ(name, "lens"))
1541 else if (STREQ(name, "ortho_scale"))
1543 else if (STREQ(name, "clip_end"))
1545 else if (STREQ(name, "clip_start"))
1571 if (tm_name.size()) {
1573 return tm_name + "." + std::string(axis_name);
1578 return std::string("");
1582 * Assign sid of the animated parameter or transform for rotation,
1583 * axis name is always appended and the value of append_axis is ignored
1585 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1587 std::string tm_name;
1588 bool is_angle = false;
1589 // when given rna_path, determine tm_type from it
1591 char *name = extract_transform_name(rna_path);
1593 if (STREQ(name, "rotation_euler"))
1595 else if (STREQ(name, "rotation_quaternion"))
1597 else if (STREQ(name, "scale"))
1599 else if (STREQ(name, "location"))
1601 else if (STREQ(name, "specular_hardness"))
1603 else if (STREQ(name, "specular_color"))
1605 else if (STREQ(name, "diffuse_color"))
1607 else if (STREQ(name, "alpha"))
1609 else if (STREQ(name, "ior"))
1619 tm_name = "rotation";
1626 tm_name = "location";
1629 tm_name = "shininess";
1632 tm_name = "specular";
1635 tm_name = "diffuse";
1638 tm_name = "transparency";
1641 tm_name = "index_of_refraction";
1649 if (tm_name.size()) {
1651 return tm_name + std::string(axis_name) + ".ANGLE";
1654 return tm_name + "." + std::string(axis_name);
1659 return std::string("");
1662 char *AnimationExporter::extract_transform_name(char *rna_path)
1664 char *dot = strrchr(rna_path, '.');
1665 return dot ? (dot + 1) : rna_path;
1669 * enable fcurves driving a specific bone, disable all the rest
1670 * if bone_name = NULL enable all fcurves
1672 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1678 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1680 for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
1682 if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
1683 fcu->flag &= ~FCURVE_DISABLED;
1685 fcu->flag |= FCURVE_DISABLED;
1688 fcu->flag &= ~FCURVE_DISABLED;
1693 bool AnimationExporter::hasAnimations(Scene *sce)
1697 for (node=this->export_settings->export_set; node; node=node->next) {
1698 Object *ob = (Object *)node->link;
1701 //Check for object transform animations
1702 if (ob->adt && ob->adt->action)
1703 fcu = (FCurve *)ob->adt->action->curves.first;
1704 //Check for Lamp parameter animations
1705 else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
1706 fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
1707 //Check for Camera parameter animations
1708 else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
1709 fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
1711 //Check Material Effect parameter animations.
1712 for (int a = 0; a < ob->totcol; a++) {
1713 Material *ma = give_current_material(ob, a + 1);
1715 if (ma->adt && ma->adt->action) {
1716 fcu = (FCurve *)ma->adt->action->curves.first;
1720 //check shape key animation
1722 Key *key = BKE_key_from_object(ob);
1723 if (key && key->adt && key->adt->action)
1724 fcu = (FCurve *)key->adt->action->curves.first;
1732 //------------------------------- Not used in the new system.--------------------------------------------------------
1733 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1736 find_keyframes(ob, fra, prefix, "rotation_euler");
1737 else if (rotmode == ROT_MODE_QUAT)
1738 find_keyframes(ob, fra, prefix, "rotation_quaternion");
1739 /*else if (rotmode == ROT_MODE_AXISANGLE)
1743 /* Take care to always have the first frame and the last frame in the animation
1744 * regardless of the sampling_rate setting
1746 void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
1748 int frame = scene->r.sfra;
1750 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1751 fra.push_back(ctime);
1752 if (frame == scene->r.efra)
1754 frame += this->export_settings->sampling_rate;
1755 if (frame > scene->r.efra)
1756 frame = scene->r.efra; // make sure the last frame is always exported
1762 * find keyframes of all the objects animations
1764 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
1766 if (ob->adt && ob->adt->action) {
1767 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1769 for (; fcu; fcu = fcu->next) {
1770 for (unsigned int i = 0; i < fcu->totvert; i++) {
1771 float f = fcu->bezt[i].vec[1][0];
1772 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1777 // keep the keys in ascending order
1778 std::sort(fra.begin(), fra.end());
1782 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1784 if (ob->adt && ob->adt->action) {
1785 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1787 for (; fcu; fcu = fcu->next) {
1788 if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
1791 char *name = extract_transform_name(fcu->rna_path);
1792 if (STREQ(name, tm_name)) {
1793 for (unsigned int i = 0; i < fcu->totvert; i++) {
1794 float f = fcu->bezt[i].vec[1][0];
1795 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1801 // keep the keys in ascending order
1802 std::sort(fra.begin(), fra.end());
1806 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1811 //write bone animations for 3 transform types
1815 for (int i = 0; i < 3; i++)
1816 sample_and_write_bone_animation(ob_arm, bone, i);
1818 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
1819 write_bone_animation(ob_arm, child);
1822 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1824 bArmature *arm = (bArmature *)ob_arm->data;
1825 int flag = arm->flag;
1826 std::vector<float> fra;
1829 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1831 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
1834 //Fill frame array with key frame values framed at \param:transform_type
1835 switch (transform_type) {
1837 find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1840 find_keyframes(ob_arm, fra, prefix, "scale");
1843 find_keyframes(ob_arm, fra, prefix, "location");
1849 // exit rest position
1850 if (flag & ARM_RESTPOS) {
1851 arm->flag &= ~ARM_RESTPOS;
1852 BKE_pose_where_is(eval_ctx, scene, ob_arm);
1854 //v array will hold all values which will be exported.
1856 float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1857 sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1859 if (transform_type == 0) {
1860 // write x, y, z curves separately if it is rotation
1861 float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
1863 for (int i = 0; i < 3; i++) {
1864 for (unsigned int j = 0; j < fra.size(); j++)
1865 axisValues[j] = values[j * 3 + i];
1867 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1869 MEM_freeN(axisValues);
1872 // write xyz at once if it is location or scale
1873 dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1880 if (flag & ARM_RESTPOS)
1882 BKE_pose_where_is(eval_ctx, scene, ob_arm);
1885 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1887 bPoseChannel *parchan = NULL;
1888 bPose *pose = ob_arm->pose;
1890 pchan = BKE_pose_channel_find_name(pose, bone->name);
1895 parchan = pchan->parent;
1897 enable_fcurves(ob_arm->adt->action, bone->name);
1899 std::vector<float>::iterator it;
1900 for (it = frames.begin(); it != frames.end(); it++) {
1901 float mat[4][4], ipar[4][4];
1903 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
1906 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1907 BKE_pose_where_is_bone(eval_ctx, scene, ob_arm, pchan, ctime, 1);
1909 // compute bone local mat
1911 invert_m4_m4(ipar, parchan->pose_mat);
1912 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1915 copy_m4_m4(mat, pchan->pose_mat);
1919 mat4_to_eul(v, mat);
1922 mat4_to_size(v, mat);
1925 copy_v3_v3(v, mat[3]);
1932 enable_fcurves(ob_arm->adt->action, NULL);
1935 bool AnimationExporter::validateConstraints(bConstraint *con)
1938 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1939 /* these we can skip completely (invalid constraints...) */
1940 if (cti == NULL) valid = false;
1941 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
1942 /* these constraints can't be evaluated anyway */
1943 if (cti->evaluate_constraint == NULL) valid = false;
1944 /* influence == 0 should be ignored */
1945 if (con->enforce == 0.0f) valid = false;
1952 * Needed for sampled animations.
1953 * This function calculates the object matrix at a given time,
1954 * also taking constraints into account.
1956 * XXX: Why looking at the constraints here is necessary?
1957 * Maybe this can be done better?
1959 void AnimationExporter::calc_obmat_at_time(Object *ob, float ctime )
1962 ListBase *conlist = get_active_constraints(this->eval_ctx, ob);
1964 BKE_scene_frame_set(scene, ctime);
1966 Main *bmain = bc_get_main();
1967 EvaluationContext *ev_context = bc_get_evaluation_context();
1968 BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
1970 ListBase *conlist = get_active_constraints(ob);
1973 for (con = (bConstraint *)conlist->first; con; con = con->next) {
1974 ListBase targets = {NULL, NULL};
1976 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1978 if (cti && cti->get_constraint_targets) {
1979 bConstraintTarget *ct;
1981 cti->get_constraint_targets(con, &targets);
1982 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1986 BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1987 BKE_object_where_is_calc_time(eval_ctx, scene, obtar, ctime);
1991 if (cti->flush_constraint_targets)
1992 cti->flush_constraint_targets(con, &targets, 1);
1996 BKE_object_where_is_calc_time(eval_ctx, scene, ob, ctime);
1997 copy_m4_m4(mat, ob->obmat);
1999 BKE_object_where_is_calc_time(scene, ob, ctime);