21 static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = {
22 {
"color", {
"R",
"G",
"B"}},
23 {
"specular_color", {
"R",
"G",
"B"}},
24 {
"diffuse_color", {
"R",
"G",
"B"}},
25 {
"alpha", {
"R",
"G",
"B"}},
26 {
"scale", {
"X",
"Y",
"Z"}},
27 {
"location", {
"X",
"Y",
"Z"}},
28 {
"rotation_euler", {
"X",
"Y",
"Z"}}};
30 std::map<std::string, std::vector<std::string>>::const_iterator it;
32 it = BC_COLLADA_AXIS_FROM_TYPE.find(channel_type);
33 if (it == BC_COLLADA_AXIS_FROM_TYPE.end()) {
37 const std::vector<std::string> &subchannel = it->second;
38 if (
id >= subchannel.size()) {
41 return subchannel[id];
56 std::vector<std::string> anim_meta_entry;
58 anim_meta_entry.push_back(action_name);
73 Scene *sce = export_settings.get_scene();
75 LinkNode *export_set = this->export_settings.get_export_set();
77 int animation_count = 0;
82 animation_count = animated_subset.size();
90 BCObjectSet::iterator it;
91 for (it = animated_subset.begin(); it != animated_subset.end(); ++it) {
96 catch (std::invalid_argument &iae) {
97 fprintf(stderr,
"Animation export interrupted");
98 fprintf(stderr,
"Exception was: %s", iae.what());
108 if (this->export_settings->include_all_actions) {
114 return animation_count;
119 bool container_is_open =
false;
128 bool export_as_matrix = this->export_settings.get_animation_transformation_type() ==
131 if (export_as_matrix) {
140#ifdef WITH_MORPH_ANIMATION
157 bool export_as_matrix)
160 bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
162 BCAnimationCurveMap::iterator it;
163 for (it = curves->begin(); it != curves->end(); ++it) {
166 if (channel_type ==
"rotation_quaternion") {
173 if (export_as_matrix && curve.is_transform_curve()) {
181 if (!keep_flat_curves && !curve.is_animated()) {
198 bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
200 std::vector<float> frames;
201 sampler.get_object_frames(frames, ob);
202 if (!frames.empty()) {
204 bool is_animated =
sampler.get_object_samples(samples, ob);
205 if (keep_flat_curves || is_animated) {
208 std::string action_name = (action ==
nullptr) ? name +
"-action" :
id_name(action);
209 std::string channel_type =
"transform";
213 std::string target =
translate_id(name) +
'/' + channel_type;
217 id, name, target, frames, samples, global_rotation_type, ob->
parentinv);
224 bool is_export_root = this->export_settings.is_export_root(ob);
225 if (!is_export_root) {
229 bool apply_global_rotation = this->export_settings.get_apply_global_orientation();
238 bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
240 std::vector<float> frames;
241 sampler.get_bone_frames(frames, ob, bone);
243 if (!frames.empty()) {
245 bool is_animated =
sampler.get_bone_samples(samples, ob, bone);
246 if (keep_flat_curves || is_animated) {
262 if (channel_type ==
"lens") {
271 curve.get_value_map(lens_values);
275 BCAnimationCurveMap::iterator cit = curves.find(sensor_key);
276 if (cit != curves.end()) {
277 sensor_curve = cit->second;
280 BCValueMap::const_iterator vit;
281 for (vit = lens_values.begin(); vit != lens_values.end(); ++vit) {
282 int frame = vit->first;
283 float lens_value = vit->second;
287 sensor_value = sensor_curve->
get_value(frame);
290 sensor_value = ((
Camera *)ob->
data)->sensor_x;
311 int channel_index = curve.get_channel_index();
313 std::string channel_type = curve.get_channel_type();
314 std::string axis =
get_axis_name(channel_type, channel_index);
316 std::string action_name;
318 action_name = (action) ?
id_name(action) :
"constraint_anim";
320 const std::string curve_name =
encode_xml(curve.get_animation_name(ob));
321 std::string
id =
bc_get_action_id(action_name, curve_name, channel_target, axis,
".");
326 int material_index = curve.get_subindex();
339 id, curve_name, collada_target, axis, curve, global_rotation_type);
348 std::string bone_name(bone->
name);
355 id, name, target, frames, samples, global_rotation_type, ob->
parentinv);
382 std::string collada_target,
389 curve.get_frames(frames);
390 curve.get_values(values);
391 std::string channel_target = curve.get_channel_target();
394 stdout,
"Export animation curve %s (%d control points)\n",
id.c_str(),
int(frames.size()));
395 openAnimation(
id, name);
402 source_type, COLLADASW::InputSemantic::OUTPUT, values,
id, axis);
404 bool has_tangents =
false;
405 std::string interpolation_id;
406 if (this->export_settings.get_keep_smooth_curves()) {
413 std::string intangent_id;
414 std::string outtangent_id;
417 COLLADASW::InputSemantic::IN_TANGENT, curve,
id, axis);
419 COLLADASW::InputSemantic::OUT_TANGENT, curve,
id, axis);
422 std::string sampler_id = std::string(
id) + SAMPLER_ID_SUFFIX;
424 COLLADASW::LibraryAnimations::Sampler
sampler(sw, sampler_id);
427 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(
EMPTY_STRING, output_id));
428 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION,
432 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT,
434 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT,
439 addChannel(COLLADABU::URI(
EMPTY_STRING, sampler_id), collada_target);
454 stdout,
"Export animation matrix %s (%d control points)\n",
id.c_str(),
int(frames.size()));
463 std::string sampler_id = std::string(
id) + SAMPLER_ID_SUFFIX;
464 COLLADASW::LibraryAnimations::Sampler
sampler(sw, sampler_id);
467 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(
EMPTY_STRING, output_id));
468 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION,
474 addChannel(COLLADABU::URI(
EMPTY_STRING, sampler_id), target);
482 case COLLADASW::InputSemantic::INPUT:
483 return INPUT_SOURCE_ID_SUFFIX;
484 case COLLADASW::InputSemantic::OUTPUT:
485 return OUTPUT_SOURCE_ID_SUFFIX;
486 case COLLADASW::InputSemantic::INTERPOLATION:
487 return INTERPOLATION_SOURCE_ID_SUFFIX;
488 case COLLADASW::InputSemantic::IN_TANGENT:
489 return INTANGENT_SOURCE_ID_SUFFIX;
490 case COLLADASW::InputSemantic::OUT_TANGENT:
491 return OUTTANGENT_SOURCE_ID_SUFFIX;
499 COLLADASW::InputSemantic::Semantics semantic,
501 const std::string axis,
505 case COLLADASW::InputSemantic::INPUT:
506 param.push_back(
"TIME");
508 case COLLADASW::InputSemantic::OUTPUT:
510 param.push_back(
"ANGLE");
514 param.push_back(axis);
516 else if (transform) {
517 param.push_back(
"TRANSFORM");
521 param.push_back(
"X");
522 param.push_back(
"Y");
523 param.push_back(
"Z");
527 case COLLADASW::InputSemantic::IN_TANGENT:
528 case COLLADASW::InputSemantic::OUT_TANGENT:
529 param.push_back(
"X");
530 param.push_back(
"Y");
538 COLLADASW::InputSemantic::Semantics semantic,
540 const std::string &anim_id,
541 std::string axis_name)
543 Scene *scene = this->export_settings.get_scene();
545 std::string channel = curve.get_channel_target();
549 bool is_angle = (
bc_startswith(channel,
"rotation") || channel ==
"spot_size");
551 COLLADASW::FloatSourceF source(mSW);
552 source.setId(source_id);
553 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
554 source.setAccessorCount(curve.sample_count());
555 source.setAccessorStride(2);
557 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
560 source.prepareToAppendValues();
562 const FCurve *fcu = curve.get_fcurve();
563 int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2;
565 for (
int i = 0; i < fcu->
totvert; i++) {
568 float sampled_time = bezt.
vec[tangent][0];
569 float sampled_val = bezt.
vec[tangent][1];
572 sampled_val =
RAD2DEGF(sampled_val);
575 source.appendValues(
FRA2TIME(sampled_time));
576 source.appendValues(sampled_val);
584 COLLADASW::InputSemantic::Semantics semantic,
585 std::vector<float> &values,
586 const std::string &anim_id,
587 const std::string axis_name)
589 BlenderContext &blender_context = this->export_settings.get_blender_context();
590 Scene *scene = blender_context.get_scene();
594 int entry_count = values.size() / stride;
597 COLLADASW::FloatSourceF source(mSW);
598 source.setId(source_id);
599 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
600 source.setAccessorCount(entry_count);
601 source.setAccessorStride(stride);
603 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
606 source.prepareToAppendValues();
608 for (
int i = 0; i < entry_count; i++) {
609 float val = values[i];
610 switch (source_type) {
620 source.appendValues(val);
630 const std::string &anim_id,
634 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
637 COLLADASW::Float4x4Source source(mSW);
638 source.setId(source_id);
639 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
640 source.setAccessorCount(samples.size());
641 source.setAccessorStride(16);
643 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
646 source.prepareToAppendValues();
648 BCMatrixSampleMap::iterator it;
650 int precision = this->export_settings.get_limit_precision() ? 6 : -1;
651 for (it = samples.begin(); it != samples.end(); it++) {
653 BCMatrix global_transform = this->export_settings.get_global_transform();
655 if (this->export_settings.get_apply_global_orientation()) {
656 sample.apply_transform(global_transform);
659 sample.add_transform(global_transform);
661 sample.get_matrix(daemat,
true, precision);
662 source.appendValues(daemat);
670 const std::string &anim_id,
671 const std::string axis,
674 std::string source_id = anim_id +
get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
676 COLLADASW::NameSource source(mSW);
677 source.setId(source_id);
678 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
679 source.setAccessorCount(curve.sample_count());
680 source.setAccessorStride(1);
682 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
683 param.push_back(
"INTERPOLATION");
685 source.prepareToAppendValues();
687 *has_tangents =
false;
689 std::vector<float> frames;
690 curve.get_frames(frames);
692 for (
uint i = 0; i < curve.sample_count(); i++) {
693 float frame = frames[i];
694 int ipo = curve.get_interpolation_type(frame);
696 source.appendValues(BEZIER_NAME);
697 *has_tangents =
true;
700 source.appendValues(STEP_NAME);
704 source.appendValues(LINEAR_NAME);
715 const std::string &anim_id)
717 std::string source_id = anim_id +
get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
719 COLLADASW::NameSource source(mSW);
720 source.setId(source_id);
721 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
722 source.setAccessorCount(tot);
723 source.setAccessorStride(1);
725 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
726 param.push_back(
"INTERPOLATION");
728 source.prepareToAppendValues();
730 for (
int i = 0; i < tot; i++) {
731 source.appendValues(LINEAR_NAME);
747 static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = {
748 {
"rotation",
"rotation"},
749 {
"rotation_euler",
"rotation"},
750 {
"rotation_quaternion",
"rotation"},
752 {
"location",
"location"},
755 {
"specular_color",
"specular"},
756 {
"diffuse_color",
"diffuse"},
757 {
"ior",
"index_of_refraction"},
758 {
"specular_hardness",
"specular_hardness"},
763 {
"fall_off_angle",
"falloff_angle"},
764 {
"spot_size",
"falloff_angle"},
765 {
"fall_off_exponent",
"falloff_exponent"},
766 {
"spot_blend",
"falloff_exponent"},
768 {
"blender/blender_dist",
"blender/blender_dist"},
770 {
"distance",
"blender/blender_dist"},
778 {
"ortho_scale",
"xmag"},
779 {
"clip_end",
"zfar"},
780 {
"clip_start",
"znear"}};
782 std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(
784 if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end()) {
787 std::string tm_name = name_it->second;
792 const std::string axis_name)
794 std::string channel_target = curve.get_channel_target();
795 std::string channel_type = curve.get_channel_type();
798 bool is_angle = curve.is_rotation_curve();
800 if (!tm_name.empty()) {
802 return tm_name + std::string(axis_name) +
".ANGLE";
804 if (!axis_name.empty()) {
805 return tm_name +
"." + std::string(axis_name);
814#ifdef WITH_MORPH_ANIMATION
825 BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path);
827 create_keyframed_animation(ob, fcu, tm_type,
true,
sampler);
@ BC_SOURCE_TYPE_TIMEFRAME
std::vector< float > BCValues
std::map< int, float > BCValueMap
@ BC_ANIMATION_TYPE_MATERIAL
@ BC_ANIMATION_TYPE_CAMERA
std::map< BCCurveKey, BCAnimationCurve * > BCAnimationCurveMap
std::vector< float > BCFrames
std::map< int, const BCMatrix * > BCMatrixSampleMap
Key * BKE_key_from_object(Object *ob)
struct Material * BKE_object_material_get(struct Object *ob, short act)
#define LISTBASE_FOREACH(type, var, list)
float focallength_to_fov(float focal_length, float sensor)
#define SNPRINTF(dst, format,...)
@ BC_TRANSFORMATION_TYPE_MATRIX
void exportAnimationClips(Scene *sce)
void export_collada_matrix_animation(std::string id, std::string name, std::string target, BCFrames &frames, BCMatrixSampleMap &samples, BC_global_rotation_type global_rotation_type, Matrix &parentinv)
std::string get_axis_name(std::string channel, int id)
std::string collada_interpolation_source(const BCAnimationCurve &curve, const std::string &anim_id, std::string axis_name, bool *has_tangents)
void add_source_parameters(COLLADASW::SourceBase::ParameterNameList ¶m, COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const std::string axis, bool transform)
void close_animation_container(bool has_container)
void openAnimationWithClip(std::string id, std::string name)
bool open_animation_container(bool has_container, Object *ob)
void export_collada_curve_animation(std::string id, std::string name, std::string target, std::string axis, BCAnimationCurve &curve, BC_global_rotation_type global_rotation_type)
void exportAnimation(Object *ob, BCAnimationSampler &sampler)
void export_matrix_animation(Object *ob, BCAnimationSampler &sampler)
void export_curve_animation_set(Object *ob, BCAnimationSampler &sampler, bool export_as_matrix)
bool is_bone_deform_group(Bone *bone)
void export_bone_animations_recursive(Object *ob_arm, Bone *bone, BCAnimationSampler &sampler)
void export_bone_animation(Object *ob, Bone *bone, BCFrames &frames, BCMatrixSampleMap &samples)
BCAnimationCurve * get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves)
void export_curve_animation(Object *ob, BCAnimationCurve &curve)
void export_morph_animation(Object *ob)
std::string get_collada_name(std::string channel_type) const
std::string collada_linear_interpolation_source(int tot, const std::string &anim_id)
std::string get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name)
std::vector< std::vector< std::string > > anim_meta
std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
std::string collada_tangent_from_curve(COLLADASW::InputSemantic::Semantics semantic, BCAnimationCurve &curve, const std::string &anim_id, const std::string axis_name)
std::string collada_source_from_values(BC_animation_source_type source_type, COLLADASW::InputSemantic::Semantics semantic, std::vector< float > &values, const std::string &anim_id, const std::string axis_name)
float get_value(float frame)
void add_value(float val, int frame)
std::string get_channel_type() const
std::string get_channel_target() const
static void get_animated_from_export_set(std::set< Object * > &animated_objects, LinkNode &export_set)
void sample_scene(BCExportSettings &export_settings, bool keyframe_at_end)
std::string encode_xml(const std::string &xml)
std::string translate_id(const char *idString)
std::string id_name(void *id)
bool bc_has_animations(Object *ob)
std::string bc_get_action_id(std::string action_name, std::string ob_name, std::string channel_type, std::string axis_name, std::string axis_separator)
std::set< Object * > BCObjectSet
bAction * bc_getSceneObjectAction(Object *ob)
bool bc_startswith(std::string const &value, std::string const &starting)
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx sampler(1, ImageType::FLOAT_2D, "matte_tx") .image(0
Vector< FCurve * > fcurves_for_assigned_action(AnimData *adt)