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 // called for each exported object
53 void AnimationExporter::operator()(Object *ob)
57 /* bool isMatAnim = false; */ /* UNUSED */
59 //Export transform animations
60 if (ob->adt && ob->adt->action) {
61 fcu = (FCurve *)ob->adt->action->curves.first;
63 //transform matrix export for bones are temporarily disabled here.
64 if (ob->type == OB_ARMATURE) {
65 bArmature *arm = (bArmature *)ob->data;
66 for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
67 write_bone_animation_matrix(ob, bone);
71 //for armature animations as objects
72 if (ob->type == OB_ARMATURE)
73 transformName = fcu->rna_path;
75 transformName = extract_transform_name(fcu->rna_path);
77 if ((STREQ(transformName, "location") || STREQ(transformName, "scale")) ||
78 (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
79 (STREQ(transformName, "rotation_quaternion")))
81 dae_animation(ob, fcu, transformName, false);
88 export_object_constraint_animation(ob);
90 //This needs to be handled by extra profiles, so postponed for now
91 //export_morph_animation(ob);
93 //Export Lamp parameter animations
94 if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
95 fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
97 transformName = extract_transform_name(fcu->rna_path);
99 if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
100 (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
102 dae_animation(ob, fcu, transformName, true);
108 //Export Camera parameter animations
109 if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
110 fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
112 transformName = extract_transform_name(fcu->rna_path);
114 if ((STREQ(transformName, "lens")) ||
115 (STREQ(transformName, "ortho_scale")) ||
116 (STREQ(transformName, "clip_end")) ||
117 (STREQ(transformName, "clip_start")))
119 dae_animation(ob, fcu, transformName, true);
125 //Export Material parameter animations.
126 for (int a = 0; a < ob->totcol; a++) {
127 Material *ma = give_current_material(ob, a + 1);
129 if (ma->adt && ma->adt->action) {
130 /* isMatAnim = true; */
131 fcu = (FCurve *)ma->adt->action->curves.first;
133 transformName = extract_transform_name(fcu->rna_path);
135 if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
136 (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
137 (STREQ(transformName, "ior")))
139 dae_animation(ob, fcu, transformName, true, ma);
147 void AnimationExporter::export_object_constraint_animation(Object *ob)
149 std::vector<float> fra;
150 //Takes frames of target animations
151 make_anim_frames_from_targets(ob, fra);
154 dae_baked_object_animation(fra, ob);
157 void AnimationExporter::export_morph_animation(Object *ob)
161 Key *key = BKE_key_from_object(ob);
164 if (key->adt && key->adt->action) {
165 fcu = (FCurve *)key->adt->action->curves.first;
168 transformName = extract_transform_name(fcu->rna_path);
170 dae_animation(ob, fcu, transformName, true);
178 void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
180 ListBase *conlist = get_active_constraints(ob);
181 if (conlist == NULL) return;
183 for (con = (bConstraint *)conlist->first; con; con = con->next) {
184 ListBase targets = {NULL, NULL};
186 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
188 if (!validateConstraints(con)) continue;
190 if (cti && cti->get_constraint_targets) {
191 bConstraintTarget *ct;
194 * - constraints should use ct->matrix, not directly accessing values
195 * - ct->matrix members have not yet been calculated here!
197 cti->get_constraint_targets(con, &targets);
199 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
203 find_frames(obtar, frames);
206 if (cti->flush_constraint_targets)
207 cti->flush_constraint_targets(con, &targets, 1);
212 //euler sources from quternion sources
213 float *AnimationExporter::get_eul_source_for_quat(Object *ob)
215 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
216 const int keys = fcu->totvert;
217 float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
218 float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
222 char *transformName = extract_transform_name(fcu->rna_path);
224 if (STREQ(transformName, "rotation_quaternion") ) {
225 for (int i = 0; i < fcu->totvert; i++) {
226 *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
232 for (int i = 0; i < keys; i++) {
233 for (int j = 0; j < 4; j++)
234 temp_quat[j] = quat[(i * 4) + j];
236 quat_to_eul(temp_eul, temp_quat);
238 for (int k = 0; k < 3; k++)
239 eul[i * 3 + k] = temp_eul[k];
247 //Get proper name for bones
248 std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
250 //hard-way to derive the bone name from rna_path. Must find more compact method
251 std::string rna_path = std::string(fcu->rna_path);
253 char *boneName = strtok((char *)rna_path.c_str(), "\"");
254 boneName = strtok(NULL, "\"");
256 if (boneName != NULL)
257 return /*id_name(ob) + "_" +*/ std::string(boneName);
262 std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
264 std::string rna_path = std::string(fcu->rna_path);
265 return translate_id(rna_path);
268 //convert f-curves to animation curves and write
269 void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
271 const char *axis_name = NULL;
274 bool has_tangents = false;
275 bool quatRotation = false;
277 if (STREQ(transformName, "rotation_quaternion") ) {
278 fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
283 //axis names for colors
284 else if (STREQ(transformName, "color") ||
285 STREQ(transformName, "specular_color") ||
286 STREQ(transformName, "diffuse_color") ||
287 STREQ(transformName, "alpha"))
289 const char *axis_names[] = {"R", "G", "B"};
290 if (fcu->array_index < 3)
291 axis_name = axis_names[fcu->array_index];
294 //axis names for transforms
295 else if (STREQ(transformName, "location") ||
296 STREQ(transformName, "scale") ||
297 STREQ(transformName, "rotation_euler") ||
298 STREQ(transformName, "rotation_quaternion"))
300 const char *axis_names[] = {"X", "Y", "Z"};
301 if (fcu->array_index < 3)
302 axis_name = axis_names[fcu->array_index];
305 /* no axis name. single parameter */
309 std::string ob_name = std::string("null");
312 if (ob->type == OB_ARMATURE) {
313 ob_name = getObjectBoneName(ob, fcu);
318 (char *)translate_id(ob_name).c_str(),
319 (char *)translate_id(transformName).c_str(),
324 ob_name = id_name(ob) + "_material";
326 ob_name = id_name(ob);
332 (char *)translate_id(ob_name).c_str(),
333 (char *)getAnimationPathId(fcu).c_str(),
337 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
339 // create input source
340 std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
342 // create output source
343 std::string output_id;
345 //quat rotations are skipped for now, because of complications with determining axis.
347 float *eul = get_eul_source_for_quat(ob);
348 float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
349 for (int i = 0; i < fcu->totvert; i++) {
350 eul_axis[i] = eul[i * 3 + fcu->array_index];
352 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
356 else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
357 output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
360 output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
363 // create interpolations source
364 std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
366 // handle tangents (if required)
367 std::string intangent_id;
368 std::string outtangent_id;
371 // create in_tangent source
372 intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
374 // create out_tangent source
375 outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
378 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
379 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
381 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
382 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
384 // this input is required
385 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
388 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
389 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
397 target = translate_id(ob_name) +
398 "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
400 if (ob->type == OB_LAMP)
401 target = get_light_id(ob) +
402 "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
404 if (ob->type == OB_CAMERA)
405 target = get_camera_id(ob) +
406 "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
409 target = translate_id(id_name(ma)) + "-effect" +
410 "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
411 //if shape key animation, this is the main problem, how to define the channel targets.
412 /*target = get_morph_id(ob) +
415 addChannel(COLLADABU::URI(empty, sampler_id), target);
422 //write bone animations in transform matrix sources
423 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
428 //This will only export animations of bones in deform group.
429 /* if (!is_bone_deform_group(bone)) return; */
431 sample_and_write_bone_animation_matrix(ob_arm, bone);
433 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
434 write_bone_animation_matrix(ob_arm, child);
437 bool AnimationExporter::is_bone_deform_group(Bone *bone)
440 //Check if current bone is deform
441 if ((bone->flag & BONE_NO_DEFORM) == 0) return true;
444 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
445 //loop through all the children until deform bone is found, and then return
446 is_def = is_bone_deform_group(child);
447 if (is_def) return true;
450 //no deform bone found in children also
454 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
456 bArmature *arm = (bArmature *)ob_arm->data;
457 int flag = arm->flag;
458 std::vector<float> fra;
461 //Check if there is a fcurve in the armature for the bone in param
462 //when baking this check is not needed, solve every bone for every frame.
463 /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
466 std::string bone_name = getObjectBoneName(ob_arm, fcu);
467 int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
472 if (!(fcu)) return;*/
474 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
478 //every inserted keyframe of bones.
479 find_frames(ob_arm, fra);
481 if (flag & ARM_RESTPOS) {
482 arm->flag &= ~ARM_RESTPOS;
483 BKE_pose_where_is(scene, ob_arm);
487 dae_baked_animation(fra, ob_arm, bone);
490 if (flag & ARM_RESTPOS)
492 BKE_pose_where_is(scene, ob_arm);
495 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
497 std::string ob_name = id_name(ob_arm);
498 std::string bone_name = bone->name;
504 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
505 (char *)translate_id(bone_name).c_str(), "pose_matrix");
507 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
509 // create input source
510 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
512 // create output source
513 std::string output_id;
515 output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
517 // create interpolations source
518 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
520 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
521 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
523 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
524 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
526 // TODO create in/out tangents source
528 // this input is required
529 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
533 std::string target = translate_id(bone_name) + "/transform";
534 addChannel(COLLADABU::URI(empty, sampler_id), target);
539 void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
541 std::string ob_name = id_name(ob);
547 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
550 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
552 // create input source
553 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
555 // create output source
556 std::string output_id;
557 output_id = create_4x4_source( fra, ob, NULL, anim_id);
559 // create interpolations source
560 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
562 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
563 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
565 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
566 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
568 // TODO create in/out tangents source
570 // this input is required
571 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
575 std::string target = translate_id(ob_name) + "/transform";
576 addChannel(COLLADABU::URI(empty, sampler_id), target);
581 // dae_bone_animation -> add_bone_animation
582 // (blend this into dae_bone_animation)
583 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
585 const char *axis_names[] = {"X", "Y", "Z"};
586 const char *axis_name = NULL;
588 bool is_rot = tm_type == 0;
594 BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
595 tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
598 axis_name = axis_names[axis];
600 std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
602 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
603 (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
605 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
607 // create input source
608 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
610 // create output source
611 std::string output_id;
613 output_id = create_xyz_source(values, fra.size(), anim_id);
615 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
617 // create interpolations source
618 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
620 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
621 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
623 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
624 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
626 // TODO create in/out tangents source
628 // this input is required
629 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
633 std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
634 addChannel(COLLADABU::URI(empty, sampler_id), target);
639 float AnimationExporter::convert_time(float frame)
641 return FRA2TIME(frame);
644 float AnimationExporter::convert_angle(float angle)
646 return COLLADABU::Math::Utils::radToDegF(angle);
649 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
652 case COLLADASW::InputSemantic::INPUT:
653 return INPUT_SOURCE_ID_SUFFIX;
654 case COLLADASW::InputSemantic::OUTPUT:
655 return OUTPUT_SOURCE_ID_SUFFIX;
656 case COLLADASW::InputSemantic::INTERPOLATION:
657 return INTERPOLATION_SOURCE_ID_SUFFIX;
658 case COLLADASW::InputSemantic::IN_TANGENT:
659 return INTANGENT_SOURCE_ID_SUFFIX;
660 case COLLADASW::InputSemantic::OUT_TANGENT:
661 return OUTTANGENT_SOURCE_ID_SUFFIX;
668 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
669 COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
672 case COLLADASW::InputSemantic::INPUT:
673 param.push_back("TIME");
675 case COLLADASW::InputSemantic::OUTPUT:
677 param.push_back("ANGLE");
681 param.push_back(axis);
685 param.push_back("TRANSFORM");
687 else { //assumes if axis isn't specified all axises are added
688 param.push_back("X");
689 param.push_back("Y");
690 param.push_back("Z");
694 case COLLADASW::InputSemantic::IN_TANGENT:
695 case COLLADASW::InputSemantic::OUT_TANGENT:
696 param.push_back("X");
697 param.push_back("Y");
704 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length)
707 case COLLADASW::InputSemantic::INPUT:
709 values[0] = convert_time(bezt->vec[1][0]);
711 case COLLADASW::InputSemantic::OUTPUT:
714 values[0] = RAD2DEGF(bezt->vec[1][1]);
717 values[0] = bezt->vec[1][1];
721 case COLLADASW::InputSemantic::IN_TANGENT:
723 values[0] = convert_time(bezt->vec[0][0]);
724 if (bezt->ipo != BEZT_IPO_BEZ) {
725 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
730 values[1] = RAD2DEGF(bezt->vec[0][1]);
733 values[1] = bezt->vec[0][1];
737 case COLLADASW::InputSemantic::OUT_TANGENT:
739 values[0] = convert_time(bezt->vec[2][0]);
740 if (bezt->ipo != BEZT_IPO_BEZ) {
741 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
746 values[1] = RAD2DEGF(bezt->vec[2][1]);
749 values[1] = bezt->vec[2][1];
758 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
760 std::string source_id = anim_id + get_semantic_suffix(semantic);
762 //bool is_angle = STREQ(fcu->rna_path, "rotation");
763 bool is_angle = false;
765 if (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path,"spot_size")) is_angle = true;
767 COLLADASW::FloatSourceF source(mSW);
768 source.setId(source_id);
769 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
770 source.setAccessorCount(fcu->totvert);
773 case COLLADASW::InputSemantic::INPUT:
774 case COLLADASW::InputSemantic::OUTPUT:
775 source.setAccessorStride(1);
777 case COLLADASW::InputSemantic::IN_TANGENT:
778 case COLLADASW::InputSemantic::OUT_TANGENT:
779 source.setAccessorStride(2);
786 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
787 add_source_parameters(param, semantic, is_angle, axis_name, false);
789 source.prepareToAppendValues();
791 for (unsigned int i = 0; i < fcu->totvert; i++) {
792 float values[3]; // be careful!
794 get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length);
795 for (int j = 0; j < length; j++)
796 source.appendValues(values[j]);
805 * Similar to create_source_from_fcurve, but adds conversion of lens
806 * animation data from focal length to FOV.
808 std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id)
810 std::string source_id = anim_id + get_semantic_suffix(semantic);
812 COLLADASW::FloatSourceF source(mSW);
813 source.setId(source_id);
814 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
815 source.setAccessorCount(fcu->totvert);
817 source.setAccessorStride(1);
819 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
820 add_source_parameters(param, semantic, false, "", false);
822 source.prepareToAppendValues();
824 for (unsigned int i = 0; i < fcu->totvert; i++) {
825 float values[3]; // be careful!
827 get_source_values(&fcu->bezt[i], semantic, false, values, &length);
828 for (int j = 0; j < length; j++)
830 float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x));
831 source.appendValues(val);
842 //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified )
843 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)
845 std::string source_id = anim_id + get_semantic_suffix(semantic);
847 COLLADASW::FloatSourceF source(mSW);
848 source.setId(source_id);
849 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
850 source.setAccessorCount(tot);
851 source.setAccessorStride(1);
853 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
854 add_source_parameters(param, semantic, is_rot, axis_name, false);
856 source.prepareToAppendValues();
858 for (int i = 0; i < tot; i++) {
860 ////if (semantic == COLLADASW::InputSemantic::INPUT)
861 // val = convert_time(val);
865 source.appendValues(val);
872 // only used for sources with INPUT semantic
873 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)
875 std::string source_id = anim_id + get_semantic_suffix(semantic);
877 COLLADASW::FloatSourceF source(mSW);
878 source.setId(source_id);
879 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
880 source.setAccessorCount(fra.size());
881 source.setAccessorStride(1);
883 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
884 add_source_parameters(param, semantic, is_rot, axis_name, false);
886 source.prepareToAppendValues();
888 std::vector<float>::iterator it;
889 for (it = fra.begin(); it != fra.end(); it++) {
891 //if (semantic == COLLADASW::InputSemantic::INPUT)
892 val = convert_time(val);
894 val = convert_angle(val);*/
895 source.appendValues(val);
904 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
906 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
907 std::string source_id = anim_id + get_semantic_suffix(semantic);
909 COLLADASW::Float4x4Source source(mSW);
910 source.setId(source_id);
911 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
912 source.setAccessorCount(frames.size());
913 source.setAccessorStride(16);
915 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
916 add_source_parameters(param, semantic, false, NULL, true);
918 source.prepareToAppendValues();
920 bPoseChannel *parchan = NULL;
921 bPoseChannel *pchan = NULL;
923 if (ob->type == OB_ARMATURE && bone) {
924 bPose *pose = ob->pose;
925 pchan = BKE_pose_channel_find_name(pose, bone->name);
929 parchan = pchan->parent;
931 enable_fcurves(ob->adt->action, bone->name);
934 std::vector<float>::iterator it;
936 for (it = frames.begin(); it != frames.end(); it++) {
937 float mat[4][4], ipar[4][4];
939 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
940 CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
941 //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene);
942 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
945 if (pchan->flag & POSE_CHAIN) {
946 enable_fcurves(ob->adt->action, NULL);
947 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
948 BKE_pose_where_is(scene, ob);
951 BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
954 // compute bone local mat
956 invert_m4_m4(ipar, parchan->pose_mat);
957 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
960 copy_m4_m4(mat, pchan->pose_mat);
962 // OPEN_SIM_COMPATIBILITY
963 // AFAIK animation to second life is via BVH, but no
964 // reason to not have the collada-animation be correct
965 if (export_settings->open_sim) {
967 copy_m4_m4(temp, bone->arm_mat);
968 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
971 mul_m4_m4m4(mat, mat, temp);
974 copy_m4_m4(temp, bone->parent->arm_mat);
975 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
977 mul_m4_m4m4(mat, temp, mat);
983 calc_ob_mat_at_time(ob, ctime, mat);
986 UnitConverter converter;
989 converter.mat4_to_dae_double(outmat, mat);
991 source.appendValues(outmat);
995 BIK_release_tree(scene, ob, ctime);
999 enable_fcurves(ob->adt->action, NULL);
1008 // only used for sources with OUTPUT semantic ( locations and scale)
1009 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
1011 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1012 std::string source_id = anim_id + get_semantic_suffix(semantic);
1014 COLLADASW::FloatSourceF source(mSW);
1015 source.setId(source_id);
1016 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1017 source.setAccessorCount(tot);
1018 source.setAccessorStride(3);
1020 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1021 add_source_parameters(param, semantic, false, NULL, false);
1023 source.prepareToAppendValues();
1025 for (int i = 0; i < tot; i++) {
1026 source.appendValues(*v, *(v + 1), *(v + 2));
1035 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
1037 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1039 COLLADASW::NameSource source(mSW);
1040 source.setId(source_id);
1041 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1042 source.setAccessorCount(fcu->totvert);
1043 source.setAccessorStride(1);
1045 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1046 param.push_back("INTERPOLATION");
1048 source.prepareToAppendValues();
1050 *has_tangents = false;
1052 for (unsigned int i = 0; i < fcu->totvert; i++) {
1053 if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
1054 source.appendValues(BEZIER_NAME);
1055 *has_tangents = true;
1057 else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
1058 source.appendValues(STEP_NAME);
1060 else { // BEZT_IPO_LIN
1061 source.appendValues(LINEAR_NAME);
1064 // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
1071 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
1073 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1075 COLLADASW::NameSource source(mSW);
1076 source.setId(source_id);
1077 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1078 source.setAccessorCount(tot);
1079 source.setAccessorStride(1);
1081 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
1082 param.push_back("INTERPOLATION");
1084 source.prepareToAppendValues();
1086 for (int i = 0; i < tot; i++) {
1087 source.appendValues(LINEAR_NAME);
1095 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1097 std::string tm_name;
1098 // when given rna_path, determine tm_type from it
1100 char *name = extract_transform_name(rna_path);
1102 if (STREQ(name, "color"))
1104 else if (STREQ(name, "spot_size"))
1106 else if (STREQ(name, "spot_blend"))
1108 else if (STREQ(name, "distance"))
1119 tm_name = "fall_off_angle";
1122 tm_name = "fall_off_exponent";
1125 tm_name = "blender/blender_dist";
1133 if (tm_name.size()) {
1135 return tm_name + "." + std::string(axis_name);
1140 return std::string("");
1143 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1145 std::string tm_name;
1146 // when given rna_path, determine tm_type from it
1148 char *name = extract_transform_name(rna_path);
1150 if (STREQ(name, "lens"))
1152 else if (STREQ(name, "ortho_scale"))
1154 else if (STREQ(name, "clip_end"))
1156 else if (STREQ(name, "clip_start"))
1182 if (tm_name.size()) {
1184 return tm_name + "." + std::string(axis_name);
1189 return std::string("");
1192 // Assign sid of the animated parameter or transform
1193 // for rotation, axis name is always appended and the value of append_axis is ignored
1194 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1196 std::string tm_name;
1197 bool is_angle = false;
1198 // when given rna_path, determine tm_type from it
1200 char *name = extract_transform_name(rna_path);
1202 if (STREQ(name, "rotation_euler"))
1204 else if (STREQ(name, "rotation_quaternion"))
1206 else if (STREQ(name, "scale"))
1208 else if (STREQ(name, "location"))
1210 else if (STREQ(name, "specular_hardness"))
1212 else if (STREQ(name, "specular_color"))
1214 else if (STREQ(name, "diffuse_color"))
1216 else if (STREQ(name, "alpha"))
1218 else if (STREQ(name, "ior"))
1228 tm_name = "rotation";
1235 tm_name = "location";
1238 tm_name = "shininess";
1241 tm_name = "specular";
1244 tm_name = "diffuse";
1247 tm_name = "transparency";
1250 tm_name = "index_of_refraction";
1258 if (tm_name.size()) {
1260 return tm_name + std::string(axis_name) + ".ANGLE";
1263 return tm_name + "." + std::string(axis_name);
1268 return std::string("");
1271 char *AnimationExporter::extract_transform_name(char *rna_path)
1273 char *dot = strrchr(rna_path, '.');
1274 return dot ? (dot + 1) : rna_path;
1277 //find keyframes of all the objects animations
1278 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra)
1280 if (ob->adt && ob->adt->action) {
1281 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1283 for (; fcu; fcu = fcu->next) {
1284 for (unsigned int i = 0; i < fcu->totvert; i++) {
1285 float f = fcu->bezt[i].vec[1][0];
1286 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1291 // keep the keys in ascending order
1292 std::sort(fra.begin(), fra.end());
1298 // enable fcurves driving a specific bone, disable all the rest
1299 // if bone_name = NULL enable all fcurves
1300 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1306 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1308 for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
1310 if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
1311 fcu->flag &= ~FCURVE_DISABLED;
1313 fcu->flag |= FCURVE_DISABLED;
1316 fcu->flag &= ~FCURVE_DISABLED;
1321 bool AnimationExporter::hasAnimations(Scene *sce)
1325 for (node=this->export_settings->export_set; node; node=node->next) {
1326 Object *ob = (Object *)node->link;
1329 //Check for object transform animations
1330 if (ob->adt && ob->adt->action)
1331 fcu = (FCurve *)ob->adt->action->curves.first;
1332 //Check for Lamp parameter animations
1333 else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
1334 fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
1335 //Check for Camera parameter animations
1336 else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
1337 fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
1339 //Check Material Effect parameter animations.
1340 for (int a = 0; a < ob->totcol; a++) {
1341 Material *ma = give_current_material(ob, a + 1);
1343 if (ma->adt && ma->adt->action) {
1344 fcu = (FCurve *)ma->adt->action->curves.first;
1348 //check shape key animation
1350 Key *key = BKE_key_from_object(ob);
1351 if (key && key->adt && key->adt->action)
1352 fcu = (FCurve *)key->adt->action->curves.first;
1360 //------------------------------- Not used in the new system.--------------------------------------------------------
1361 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1364 find_frames(ob, fra, prefix, "rotation_euler");
1365 else if (rotmode == ROT_MODE_QUAT)
1366 find_frames(ob, fra, prefix, "rotation_quaternion");
1367 /*else if (rotmode == ROT_MODE_AXISANGLE)
1371 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1373 if (ob->adt && ob->adt->action) {
1374 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1376 for (; fcu; fcu = fcu->next) {
1377 if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
1380 char *name = extract_transform_name(fcu->rna_path);
1381 if (STREQ(name, tm_name)) {
1382 for (unsigned int i = 0; i < fcu->totvert; i++) {
1383 float f = fcu->bezt[i].vec[1][0];
1384 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1390 // keep the keys in ascending order
1391 std::sort(fra.begin(), fra.end());
1395 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1400 //write bone animations for 3 transform types
1404 for (int i = 0; i < 3; i++)
1405 sample_and_write_bone_animation(ob_arm, bone, i);
1407 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
1408 write_bone_animation(ob_arm, child);
1411 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1413 bArmature *arm = (bArmature *)ob_arm->data;
1414 int flag = arm->flag;
1415 std::vector<float> fra;
1418 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1420 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
1423 //Fill frame array with key frame values framed at \param:transform_type
1424 switch (transform_type) {
1426 find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1429 find_frames(ob_arm, fra, prefix, "scale");
1432 find_frames(ob_arm, fra, prefix, "location");
1438 // exit rest position
1439 if (flag & ARM_RESTPOS) {
1440 arm->flag &= ~ARM_RESTPOS;
1441 BKE_pose_where_is(scene, ob_arm);
1443 //v array will hold all values which will be exported.
1445 float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1446 sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1448 if (transform_type == 0) {
1449 // write x, y, z curves separately if it is rotation
1450 float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
1452 for (int i = 0; i < 3; i++) {
1453 for (unsigned int j = 0; j < fra.size(); j++)
1454 axisValues[j] = values[j * 3 + i];
1456 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1458 MEM_freeN(axisValues);
1461 // write xyz at once if it is location or scale
1462 dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1469 if (flag & ARM_RESTPOS)
1471 BKE_pose_where_is(scene, ob_arm);
1474 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1476 bPoseChannel *parchan = NULL;
1477 bPose *pose = ob_arm->pose;
1479 pchan = BKE_pose_channel_find_name(pose, bone->name);
1484 parchan = pchan->parent;
1486 enable_fcurves(ob_arm->adt->action, bone->name);
1488 std::vector<float>::iterator it;
1489 for (it = frames.begin(); it != frames.end(); it++) {
1490 float mat[4][4], ipar[4][4];
1492 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
1495 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1496 BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
1498 // compute bone local mat
1500 invert_m4_m4(ipar, parchan->pose_mat);
1501 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1504 copy_m4_m4(mat, pchan->pose_mat);
1508 mat4_to_eul(v, mat);
1511 mat4_to_size(v, mat);
1514 copy_v3_v3(v, mat[3]);
1521 enable_fcurves(ob_arm->adt->action, NULL);
1524 bool AnimationExporter::validateConstraints(bConstraint *con)
1527 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1528 /* these we can skip completely (invalid constraints...) */
1529 if (cti == NULL) valid = false;
1530 if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
1531 /* these constraints can't be evaluated anyway */
1532 if (cti->evaluate_constraint == NULL) valid = false;
1533 /* influence == 0 should be ignored */
1534 if (con->enforce == 0.0f) valid = false;
1539 void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4])
1541 ListBase *conlist = get_active_constraints(ob);
1543 for (con = (bConstraint *)conlist->first; con; con = con->next) {
1544 ListBase targets = {NULL, NULL};
1546 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1548 if (cti && cti->get_constraint_targets) {
1549 bConstraintTarget *ct;
1551 cti->get_constraint_targets(con, &targets);
1552 for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1556 BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1557 BKE_object_where_is_calc_time(scene, obtar, ctime);
1561 if (cti->flush_constraint_targets)
1562 cti->flush_constraint_targets(con, &targets, 1);
1565 BKE_object_where_is_calc_time(scene, ob, ctime);
1566 copy_m4_m4(mat, ob->obmat);