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