Blender V4.3
AnimationExporter.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "AnimationExporter.h"
11#include "BCAnimationSampler.h"
12#include "GeometryExporter.h"
13#include "MaterialExporter.h"
14#include "collada_utils.h"
15
16std::string EMPTY_STRING;
17
18std::string AnimationExporter::get_axis_name(std::string channel_type, int id)
19{
20
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"}}};
29
30 std::map<std::string, std::vector<std::string>>::const_iterator it;
31
32 it = BC_COLLADA_AXIS_FROM_TYPE.find(channel_type);
33 if (it == BC_COLLADA_AXIS_FROM_TYPE.end()) {
34 return "";
35 }
36
37 const std::vector<std::string> &subchannel = it->second;
38 if (id >= subchannel.size()) {
39 return "";
40 }
41 return subchannel[id];
42}
43
45{
46 if (!has_container) {
47 char anim_id[200];
48 SNPRINTF(anim_id, "action_container-%s", translate_id(id_name(ob)).c_str());
49 openAnimation(anim_id, encode_xml(id_name(ob)));
50 }
51 return true;
52}
53
54void AnimationExporter::openAnimationWithClip(std::string action_id, std::string action_name)
55{
56 std::vector<std::string> anim_meta_entry;
57 anim_meta_entry.push_back(translate_id(action_id));
58 anim_meta_entry.push_back(action_name);
59 anim_meta.push_back(anim_meta_entry);
60
61 openAnimation(translate_id(action_id), action_name);
62}
63
65{
66 if (has_container) {
67 closeAnimation();
68 }
69}
70
72{
73 Scene *sce = export_settings.get_scene();
74
75 LinkNode *export_set = this->export_settings.get_export_set();
76 bool has_anim_data = bc_has_animations(sce, export_set);
77 int animation_count = 0;
78 if (has_anim_data) {
79
80 BCObjectSet animated_subset;
81 BCAnimationSampler::get_animated_from_export_set(animated_subset, *export_set);
82 animation_count = animated_subset.size();
83 BCAnimationSampler animation_sampler(export_settings, animated_subset);
84
85 try {
86 animation_sampler.sample_scene(export_settings, /*keyframe_at_end = */ true);
87
88 openLibrary();
89
90 BCObjectSet::iterator it;
91 for (it = animated_subset.begin(); it != animated_subset.end(); ++it) {
92 Object *ob = *it;
93 exportAnimation(ob, animation_sampler);
94 }
95 }
96 catch (std::invalid_argument &iae) {
97 fprintf(stderr, "Animation export interrupted");
98 fprintf(stderr, "Exception was: %s", iae.what());
99 }
100
101 closeLibrary();
102
103#if 0
104 /* TODO: If all actions shall be exported, we need to call the
105 * AnimationClipExporter which will figure out which actions
106 * need to be exported for which objects
107 */
108 if (this->export_settings->include_all_actions) {
109 AnimationClipExporter ace(eval_ctx, sw, export_settings, anim_meta);
110 ace.exportAnimationClips(sce);
111 }
112#endif
113 }
114 return animation_count;
115}
116
118{
119 bool container_is_open = false;
120
121 /* Transform animations (trans, rot, scale). */
122 container_is_open = open_animation_container(container_is_open, ob);
123
124 /* Now take care of the Object Animations
125 * NOTE: For Armatures the skeletal animation has already been exported (see above)
126 * However Armatures also can have Object animation.
127 */
128 bool export_as_matrix = this->export_settings.get_animation_transformation_type() ==
130
131 if (export_as_matrix) {
132 /* export all transform_curves as one single matrix animation */
134 }
135
136 export_curve_animation_set(ob, sampler, export_as_matrix);
137
138 if (ob->type == OB_ARMATURE && export_as_matrix) {
139
140#ifdef WITH_MORPH_ANIMATION
141 /* TODO: This needs to be handled by extra profiles, postponed for now */
143#endif
144
145 /* Export skeletal animation (if any) */
146 bArmature *arm = (bArmature *)ob->data;
147 LISTBASE_FOREACH (Bone *, root_bone, &arm->bonebase) {
149 }
150 }
151
152 close_animation_container(container_is_open);
153}
154
157 bool export_as_matrix)
158{
159 BCAnimationCurveMap *curves = sampler.get_curves(ob);
160 bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
161
162 BCAnimationCurveMap::iterator it;
163 for (it = curves->begin(); it != curves->end(); ++it) {
164 BCAnimationCurve &curve = *it->second;
165 std::string channel_type = curve.get_channel_type();
166 if (channel_type == "rotation_quaternion") {
167 /* Can not export Quaternion animation in Collada as far as i know)
168 * Maybe automatically convert to euler rotation?
169 * Discard for now. */
170 continue;
171 }
172
173 if (export_as_matrix && curve.is_transform_curve()) {
174 /* All Transform curves will be exported within a single matrix animation,
175 * see export_matrix_animation()
176 * No need to export the curves here again.
177 */
178 continue;
179 }
180
181 if (!keep_flat_curves && !curve.is_animated()) {
182 continue;
183 }
184
185 BCAnimationCurve *mcurve = get_modified_export_curve(ob, curve, *curves);
186 if (mcurve) {
187 export_curve_animation(ob, *mcurve);
188 delete mcurve;
189 }
190 else {
191 export_curve_animation(ob, curve);
192 }
193 }
194}
195
197{
198 bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
199
200 std::vector<float> frames;
201 sampler.get_object_frames(frames, ob);
202 if (!frames.empty()) {
203 BCMatrixSampleMap samples;
204 bool is_animated = sampler.get_object_samples(samples, ob);
205 if (keep_flat_curves || is_animated) {
206 bAction *action = bc_getSceneObjectAction(ob);
207 std::string name = encode_xml(id_name(ob));
208 std::string action_name = (action == nullptr) ? name + "-action" : id_name(action);
209 std::string channel_type = "transform";
210 std::string axis;
211 std::string id = bc_get_action_id(action_name, name, channel_type, axis);
212
213 std::string target = translate_id(name) + '/' + channel_type;
214
215 BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
217 id, name, target, frames, samples, global_rotation_type, ob->parentinv);
218 }
219 }
220}
221
222BC_global_rotation_type AnimationExporter::get_global_rotation_type(Object *ob)
223{
224 bool is_export_root = this->export_settings.is_export_root(ob);
225 if (!is_export_root) {
226 return BC_NO_ROTATION;
227 }
228
229 bool apply_global_rotation = this->export_settings.get_apply_global_orientation();
230
231 return (apply_global_rotation) ? BC_DATA_ROTATION : BC_OBJECT_ROTATION;
232}
233
235 Bone *bone,
237{
238 bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
239
240 std::vector<float> frames;
241 sampler.get_bone_frames(frames, ob, bone);
242
243 if (!frames.empty()) {
244 BCMatrixSampleMap samples;
245 bool is_animated = sampler.get_bone_samples(samples, ob, bone);
246 if (keep_flat_curves || is_animated) {
247 export_bone_animation(ob, bone, frames, samples);
248 }
249 }
250
251 LISTBASE_FOREACH (Bone *, child, &bone->childbase) {
253 }
254}
255
257 BCAnimationCurve &curve,
258 BCAnimationCurveMap &curves)
259{
260 std::string channel_type = curve.get_channel_type();
261 BCAnimationCurve *mcurve = nullptr;
262 if (channel_type == "lens") {
263
264 /* Create an xfov curve */
265
266 BCCurveKey key(BC_ANIMATION_TYPE_CAMERA, "xfov", 0);
267 mcurve = new BCAnimationCurve(key, ob);
268
269 /* now tricky part: transform the fcurve */
270 BCValueMap lens_values;
271 curve.get_value_map(lens_values);
272
273 BCAnimationCurve *sensor_curve = nullptr;
274 BCCurveKey sensor_key(BC_ANIMATION_TYPE_CAMERA, "sensor_width", 0);
275 BCAnimationCurveMap::iterator cit = curves.find(sensor_key);
276 if (cit != curves.end()) {
277 sensor_curve = cit->second;
278 }
279
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;
284
285 float sensor_value;
286 if (sensor_curve) {
287 sensor_value = sensor_curve->get_value(frame);
288 }
289 else {
290 sensor_value = ((Camera *)ob->data)->sensor_x;
291 }
292 float value = RAD2DEGF(focallength_to_fov(lens_value, sensor_value));
293 mcurve->add_value(value, frame);
294 }
295 /* to reset the handles */
296 mcurve->clean_handles();
297 }
298 return mcurve;
299}
300
302{
303 std::string channel_target = curve.get_channel_target();
304
305 /*
306 * Some curves can not be exported as is and need some conversion
307 * For more information see implementation of get_modified_export_curve()
308 * NOTE: if mcurve is not null then it must be deleted at end of this method;
309 */
310
311 int channel_index = curve.get_channel_index();
312 /* RGB or XYZ or "" */
313 std::string channel_type = curve.get_channel_type();
314 std::string axis = get_axis_name(channel_type, channel_index);
315
316 std::string action_name;
317 bAction *action = bc_getSceneObjectAction(ob);
318 action_name = (action) ? id_name(action) : "constraint_anim";
319
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, ".");
322
323 std::string collada_target = translate_id(curve_name);
324
325 if (curve.is_of_animation_type(BC_ANIMATION_TYPE_MATERIAL)) {
326 int material_index = curve.get_subindex();
327 Material *ma = BKE_object_material_get(ob, material_index + 1);
328 if (ma) {
329 collada_target = translate_id(id_name(ma)) + "-effect/common/" +
330 get_collada_sid(curve, axis);
331 }
332 }
333 else {
334 collada_target += "/" + get_collada_sid(curve, axis);
335 }
336
337 BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
339 id, curve_name, collada_target, axis, curve, global_rotation_type);
340}
341
343 Bone *bone,
344 BCFrames &frames,
345 BCMatrixSampleMap &samples)
346{
347 bAction *action = bc_getSceneObjectAction(ob);
348 std::string bone_name(bone->name);
349 std::string name = encode_xml(id_name(ob));
350 std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix");
351 std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform";
352
353 BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
355 id, name, target, frames, samples, global_rotation_type, ob->parentinv);
356}
357
359{
360 bool is_def;
361 /* Check if current bone is deform */
362 if ((bone->flag & BONE_NO_DEFORM) == 0) {
363 return true;
364 }
365 /* Check child bones */
366
367 LISTBASE_FOREACH (Bone *, child, &bone->childbase) {
368 /* loop through all the children until deform bone is found, and then return */
369 is_def = is_bone_deform_group(child);
370 if (is_def) {
371 return true;
372 }
373 }
374
375 /* no deform bone found in children also */
376 return false;
377}
378
380 std::string id,
381 std::string name,
382 std::string collada_target,
383 std::string axis,
384 BCAnimationCurve &curve,
385 BC_global_rotation_type global_rotation_type)
386{
387 BCFrames frames;
388 BCValues values;
389 curve.get_frames(frames);
390 curve.get_values(values);
391 std::string channel_target = curve.get_channel_target();
392
393 fprintf(
394 stdout, "Export animation curve %s (%d control points)\n", id.c_str(), int(frames.size()));
395 openAnimation(id, name);
396 BC_animation_source_type source_type = curve.is_rotation_curve() ? BC_SOURCE_TYPE_ANGLE :
398
399 std::string input_id = collada_source_from_values(
400 BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, axis);
401 std::string output_id = collada_source_from_values(
402 source_type, COLLADASW::InputSemantic::OUTPUT, values, id, axis);
403
404 bool has_tangents = false;
405 std::string interpolation_id;
406 if (this->export_settings.get_keep_smooth_curves()) {
407 interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents);
408 }
409 else {
410 interpolation_id = collada_linear_interpolation_source(frames.size(), id);
411 }
412
413 std::string intangent_id;
414 std::string outtangent_id;
415 if (has_tangents) {
416 intangent_id = collada_tangent_from_curve(
417 COLLADASW::InputSemantic::IN_TANGENT, curve, id, axis);
418 outtangent_id = collada_tangent_from_curve(
419 COLLADASW::InputSemantic::OUT_TANGENT, curve, id, axis);
420 }
421
422 std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
423
424 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
425
426 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
427 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
428 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION,
429 COLLADABU::URI(EMPTY_STRING, interpolation_id));
430
431 if (has_tangents) {
432 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT,
433 COLLADABU::URI(EMPTY_STRING, intangent_id));
434 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT,
435 COLLADABU::URI(EMPTY_STRING, outtangent_id));
436 }
437
438 addSampler(sampler);
439 addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), collada_target);
440
441 closeAnimation();
442}
443
445 std::string id,
446 std::string name,
447 std::string target,
448 BCFrames &frames,
449 BCMatrixSampleMap &samples,
450 BC_global_rotation_type global_rotation_type,
451 Matrix &parentinv)
452{
453 fprintf(
454 stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size()));
455
456 openAnimationWithClip(id, name);
457
458 std::string input_id = collada_source_from_values(
459 BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, "");
460 std::string output_id = collada_source_from_values(samples, id, global_rotation_type, parentinv);
461 std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id);
462
463 std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
464 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
465
466 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
467 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
468 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION,
469 COLLADABU::URI(EMPTY_STRING, interpolation_id));
470
471 /* Matrix animation has no tangents */
472
473 addSampler(sampler);
474 addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), target);
475
476 closeAnimation();
477}
478
479std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
480{
481 switch (semantic) {
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;
492 default:
493 break;
494 }
495 return "";
496}
497
498void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList &param,
499 COLLADASW::InputSemantic::Semantics semantic,
500 bool is_rot,
501 const std::string axis,
502 bool transform)
503{
504 switch (semantic) {
505 case COLLADASW::InputSemantic::INPUT:
506 param.push_back("TIME");
507 break;
508 case COLLADASW::InputSemantic::OUTPUT:
509 if (is_rot) {
510 param.push_back("ANGLE");
511 }
512 else {
513 if (!axis.empty()) {
514 param.push_back(axis);
515 }
516 else if (transform) {
517 param.push_back("TRANSFORM");
518 }
519 else {
520 /* assumes if axis isn't specified all axes are added */
521 param.push_back("X");
522 param.push_back("Y");
523 param.push_back("Z");
524 }
525 }
526 break;
527 case COLLADASW::InputSemantic::IN_TANGENT:
528 case COLLADASW::InputSemantic::OUT_TANGENT:
529 param.push_back("X");
530 param.push_back("Y");
531 break;
532 default:
533 break;
534 }
535}
536
538 COLLADASW::InputSemantic::Semantics semantic,
539 BCAnimationCurve &curve,
540 const std::string &anim_id,
541 std::string axis_name)
542{
543 Scene *scene = this->export_settings.get_scene();
544
545 std::string channel = curve.get_channel_target();
546
547 const std::string source_id = anim_id + get_semantic_suffix(semantic);
548
549 bool is_angle = (bc_startswith(channel, "rotation") || channel == "spot_size");
550
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);
556
557 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
558 add_source_parameters(param, semantic, is_angle, axis_name, false);
559
560 source.prepareToAppendValues();
561
562 const FCurve *fcu = curve.get_fcurve();
563 int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2;
564
565 for (int i = 0; i < fcu->totvert; i++) {
566 BezTriple &bezt = fcu->bezt[i];
567
568 float sampled_time = bezt.vec[tangent][0];
569 float sampled_val = bezt.vec[tangent][1];
570
571 if (is_angle) {
572 sampled_val = RAD2DEGF(sampled_val);
573 }
574
575 source.appendValues(FRA2TIME(sampled_time));
576 source.appendValues(sampled_val);
577 }
578 source.finish();
579 return source_id;
580}
581
583 BC_animation_source_type source_type,
584 COLLADASW::InputSemantic::Semantics semantic,
585 std::vector<float> &values,
586 const std::string &anim_id,
587 const std::string axis_name)
588{
589 BlenderContext &blender_context = this->export_settings.get_blender_context();
590 Scene *scene = blender_context.get_scene();
591 /* T can be float, int or double */
592
593 int stride = 1;
594 int entry_count = values.size() / stride;
595 std::string source_id = anim_id + get_semantic_suffix(semantic);
596
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);
602
603 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
604 add_source_parameters(param, semantic, source_type == BC_SOURCE_TYPE_ANGLE, axis_name, false);
605
606 source.prepareToAppendValues();
607
608 for (int i = 0; i < entry_count; i++) {
609 float val = values[i];
610 switch (source_type) {
612 val = FRA2TIME(val);
613 break;
615 val = RAD2DEGF(val);
616 break;
617 default:
618 break;
619 }
620 source.appendValues(val);
621 }
622
623 source.finish();
624
625 return source_id;
626}
627
629 BCMatrixSampleMap &samples,
630 const std::string &anim_id,
631 BC_global_rotation_type global_rotation_type,
632 Matrix &parentinv)
633{
634 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
635 std::string source_id = anim_id + get_semantic_suffix(semantic);
636
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);
642
643 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
644 add_source_parameters(param, semantic, false, "", true);
645
646 source.prepareToAppendValues();
647
648 BCMatrixSampleMap::iterator it;
649 /* could be made configurable */
650 int precision = this->export_settings.get_limit_precision() ? 6 : -1;
651 for (it = samples.begin(); it != samples.end(); it++) {
652 BCMatrix sample = BCMatrix(*it->second);
653 BCMatrix global_transform = this->export_settings.get_global_transform();
654 DMatrix daemat;
655 if (this->export_settings.get_apply_global_orientation()) {
656 sample.apply_transform(global_transform);
657 }
658 else {
659 sample.add_transform(global_transform);
660 }
661 sample.get_matrix(daemat, true, precision);
662 source.appendValues(daemat);
663 }
664
665 source.finish();
666 return source_id;
667}
668
670 const std::string &anim_id,
671 const std::string axis,
672 bool *has_tangents)
673{
674 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
675
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);
681
682 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
683 param.push_back("INTERPOLATION");
684
685 source.prepareToAppendValues();
686
687 *has_tangents = false;
688
689 std::vector<float> frames;
690 curve.get_frames(frames);
691
692 for (uint i = 0; i < curve.sample_count(); i++) {
693 float frame = frames[i];
694 int ipo = curve.get_interpolation_type(frame);
695 if (ipo == BEZT_IPO_BEZ) {
696 source.appendValues(BEZIER_NAME);
697 *has_tangents = true;
698 }
699 else if (ipo == BEZT_IPO_CONST) {
700 source.appendValues(STEP_NAME);
701 }
702 else {
703 /* BEZT_IPO_LIN */
704 source.appendValues(LINEAR_NAME);
705 }
706 }
707 /* unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS */
708
709 source.finish();
710
711 return source_id;
712}
713
715 const std::string &anim_id)
716{
717 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
718
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);
724
725 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
726 param.push_back("INTERPOLATION");
727
728 source.prepareToAppendValues();
729
730 for (int i = 0; i < tot; i++) {
731 source.appendValues(LINEAR_NAME);
732 }
733
734 source.finish();
735
736 return source_id;
737}
738
739std::string AnimationExporter::get_collada_name(std::string channel_type) const
740{
741 /*
742 * Translation table to map FCurve animation types to Collada animation.
743 * TODO: Maybe we can keep the names from the fcurves here instead of
744 * mapping. However this is what i found in the old code. So keep
745 * this map for now.
746 */
747 static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = {
748 {"rotation", "rotation"},
749 {"rotation_euler", "rotation"},
750 {"rotation_quaternion", "rotation"},
751 {"scale", "scale"},
752 {"location", "location"},
753
754 /* Materials */
755 {"specular_color", "specular"},
756 {"diffuse_color", "diffuse"},
757 {"ior", "index_of_refraction"},
758 {"specular_hardness", "specular_hardness"},
759 {"alpha", "alpha"},
760
761 /* Lights */
762 {"color", "color"},
763 {"fall_off_angle", "falloff_angle"},
764 {"spot_size", "falloff_angle"},
765 {"fall_off_exponent", "falloff_exponent"},
766 {"spot_blend", "falloff_exponent"},
767 /* Special blender profile (TODO: make this more elegant). */
768 {"blender/blender_dist", "blender/blender_dist"},
769 /* Special blender profile (TODO: make this more elegant). */
770 {"distance", "blender/blender_dist"},
771
772 /* Cameras */
773 {"lens", "xfov"},
774 {"xfov", "xfov"},
775 {"xmag", "xmag"},
776 {"zfar", "zfar"},
777 {"znear", "znear"},
778 {"ortho_scale", "xmag"},
779 {"clip_end", "zfar"},
780 {"clip_start", "znear"}};
781
782 std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(
783 channel_type);
784 if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end()) {
785 return "";
786 }
787 std::string tm_name = name_it->second;
788 return tm_name;
789}
790
792 const std::string axis_name)
793{
794 std::string channel_target = curve.get_channel_target();
795 std::string channel_type = curve.get_channel_type();
796 std::string tm_name = get_collada_name(channel_type);
797
798 bool is_angle = curve.is_rotation_curve();
799
800 if (!tm_name.empty()) {
801 if (is_angle) {
802 return tm_name + std::string(axis_name) + ".ANGLE";
803 }
804 if (!axis_name.empty()) {
805 return tm_name + "." + std::string(axis_name);
806 }
807
808 return tm_name;
809 }
810
811 return tm_name;
812}
813
814#ifdef WITH_MORPH_ANIMATION
815/* TODO: This function needs to be implemented similar to the material animation export
816 * So we have to update BCSample for this to work. */
818{
819 Key *key = BKE_key_from_object(ob);
820 if (!key) {
821 return;
822 }
823
824 for (FCurve *fcu : blender::animrig::legacy::fcurves_for_assigned_action(key->adt)) {
825 BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path);
826
827 create_keyframed_animation(ob, fcu, tm_type, true, sampler);
828 }
829}
830#endif
std::string EMPTY_STRING
BC_animation_source_type
@ BC_SOURCE_TYPE_TIMEFRAME
@ BC_SOURCE_TYPE_VALUE
@ BC_SOURCE_TYPE_ANGLE
BC_global_rotation_type
@ BC_DATA_ROTATION
@ BC_OBJECT_ROTATION
@ BC_NO_ROTATION
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)
Definition key.cc:1820
struct Material * BKE_object_material_get(struct Object *ob, short act)
#define LISTBASE_FOREACH(type, var, list)
#define RAD2DEGF(_rad)
float focallength_to_fov(float focal_length, float sensor)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
unsigned int uint
@ BONE_NO_DEFORM
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ OB_ARMATURE
#define FRA2TIME(a)
@ 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 &param, 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)
float vec[3][3]
char name[64]
ListBase childbase
BezTriple * bezt
unsigned int totvert
float parentinv[4][4]