Blender V4.5
AnimationImporter.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2010-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstddef>
10
11#include "COLLADAFWAnimation.h"
12#include "COLLADAFWAnimationCurve.h"
13#include "COLLADAFWAnimationList.h"
14#include "COLLADAFWCamera.h"
15#include "COLLADAFWEffect.h"
16#include "COLLADAFWLight.h"
17#include "COLLADAFWNode.h"
18#include "COLLADAFWRotate.h"
19#include "COLLADAFWUniqueId.h"
20
21#include "DNA_armature_types.h"
22
23#include "ED_keyframing.hh"
24
25#include "ANIM_action.hh"
26#include "ANIM_action_legacy.hh"
27#include "ANIM_animdata.hh"
28#include "ANIM_fcurve.hh"
29
30#include "BLI_math_matrix.h"
31#include "BLI_string.h"
32
33#include "BKE_action.hh"
34#include "BKE_armature.hh"
35#include "BKE_fcurve.hh"
36#include "BKE_object.hh"
37
38#include "AnimationImporter.h"
39#include "ArmatureImporter.h"
40#include "collada_utils.h"
41
42#include <algorithm>
43
44/* first try node name, if not available (since is optional), fall back to original id */
45template<class T> static const char *bc_get_joint_name(T *node)
46{
47 const std::string &id = node->getName();
48 return id.empty() ? node->getOriginalId().c_str() : id.c_str();
49}
50
55static void ensure_action_and_slot_for_id(Main *bmain, ID &id)
56{
57 bAction *dna_action = blender::animrig::id_action_ensure(bmain, &id);
58 BLI_assert(dna_action != nullptr);
59
61 /* We don't ensure a slot for legacy actions, since they don't have slots. */
62 return;
63 }
64
65 blender::animrig::Action &action = dna_action->wrap();
67 id);
68 BLI_assert(slot != nullptr);
70}
71
72FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
73{
76 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
77 fcu->array_index = array_index;
78 return fcu;
79}
80
81void AnimationImporter::add_bezt(FCurve *fcu,
82 float frame,
83 float value,
85{
86 // float fps = float(FPS);
87 BezTriple bez;
88 memset(&bez, 0, sizeof(BezTriple));
89 bez.vec[1][0] = frame;
90 bez.vec[1][1] = value;
91 bez.ipo = ipo; /* use default interpolation mode here... */
92 bez.f1 = bez.f2 = bez.f3 = SELECT;
93 bez.h1 = bez.h2 = HD_AUTO;
96}
97
98void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
99{
100 COLLADAFW::FloatOrDoubleArray &input = curve->getInputValues();
101 COLLADAFW::FloatOrDoubleArray &output = curve->getOutputValues();
102
103 float fps = float(FPS);
104 size_t dim = curve->getOutDimension();
105 uint i;
106
107 std::vector<FCurve *> &fcurves = curve_map[curve->getUniqueId()];
108
109 switch (dim) {
110 case 1: /* X, Y, Z or angle */
111 case 3: /* XYZ */
112 case 4:
113 case 16: /* matrix */
114 {
115 for (i = 0; i < dim; i++) {
116 FCurve *fcu = BKE_fcurve_create();
117
119 fcu->array_index = 0;
120 fcu->auto_smoothing = U.auto_smoothing_new;
121
122 for (uint j = 0; j < curve->getKeyCount(); j++) {
123 BezTriple bez;
124 memset(&bez, 0, sizeof(BezTriple));
125
126 /* input, output */
127 bez.vec[1][0] = bc_get_float_value(input, j) * fps;
128 bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
129 bez.h1 = bez.h2 = HD_AUTO;
130
131 if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ||
132 curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_STEP)
133 {
134 COLLADAFW::FloatOrDoubleArray &intan = curve->getInTangentValues();
135 COLLADAFW::FloatOrDoubleArray &outtan = curve->getOutTangentValues();
136
137 /* In-tangent. */
138 uint index = 2 * (j * dim + i);
139 bez.vec[0][0] = bc_get_float_value(intan, index) * fps;
140 bez.vec[0][1] = bc_get_float_value(intan, index + 1);
141
142 /* Out-tangent. */
143 bez.vec[2][0] = bc_get_float_value(outtan, index) * fps;
144 bez.vec[2][1] = bc_get_float_value(outtan, index + 1);
145 if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) {
146 bez.ipo = BEZT_IPO_BEZ;
147 bez.h1 = bez.h2 = HD_AUTO_ANIM;
148 }
149 else {
150 bez.ipo = BEZT_IPO_CONST;
151 }
152 }
153 else {
154 bez.ipo = BEZT_IPO_LIN;
155 }
156#if 0
157 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
158#endif
159 bez.f1 = bez.f2 = bez.f3 = SELECT;
160
162 }
163
165
166 fcurves.push_back(fcu);
167 unused_curves.push_back(fcu);
168 }
169 break;
170 }
171 default:
172 fprintf(stderr,
173 "Output dimension of %d is not yet supported (animation id = %s)\n",
174 int(dim),
175 curve->getOriginalId().c_str());
176 }
177}
178
179void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
180{
181 for (uint i = 0; i < cu->totvert; i++) {
182 /* TODO: convert handles too. */
183 cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f);
184 cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f);
185 cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f);
186 }
187}
188
189void AnimationImporter::fcurve_scale(FCurve *cu, int scale)
190{
191 for (uint i = 0; i < cu->totvert; i++) {
192 /* TODO: convert handles too. */
193 cu->bezt[i].vec[1][1] *= scale;
194 cu->bezt[i].vec[0][1] *= scale;
195 cu->bezt[i].vec[2][1] *= scale;
196 }
197}
198
199void AnimationImporter::fcurve_is_used(FCurve *fcu)
200{
201 unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu),
202 unused_curves.end());
203}
204
206{
207 /* free unused FCurves */
208 for (FCurve *unused_curve : unused_curves) {
209 BKE_fcurve_free(unused_curve);
210 }
211
212 if (!unused_curves.empty()) {
213 fprintf(stderr, "removed %d unused curves\n", int(unused_curves.size()));
214 }
215}
216
217bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim)
218{
219 if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
220 COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve *)anim;
221
222 /* XXX Don't know if it's necessary
223 * Should we check outPhysicalDimension? */
224 if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) {
225 fprintf(stderr, "Inputs physical dimension is not time.\n");
226 return true;
227 }
228
229 /* a curve can have mixed interpolation type,
230 * in this case curve->getInterpolationTypes returns a list of interpolation types per key */
231 COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
232
233 if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
234 switch (interp) {
235 case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
236 case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
237 case COLLADAFW::AnimationCurve::INTERPOLATION_STEP:
238 animation_to_fcurves(curve);
239 break;
240 default:
241 /* TODO: there are also CARDINAL, HERMITE, BSPLINE and STEP types. */
242 fprintf(stderr,
243 "CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n");
244 break;
245 }
246 }
247 else {
248 /* not supported yet */
249 fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n");
250 }
251 }
252 else {
253 fprintf(stderr, "FORMULA animation type is not supported yet.\n");
254 }
255
256 return true;
257}
258
259bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *animlist)
260{
261 const COLLADAFW::UniqueId &animlist_id = animlist->getUniqueId();
262 animlist_map[animlist_id] = animlist;
263
264#if 0
265
266 /* should not happen */
267 if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
268 return true;
269 }
270
271 /* for bones rna_path is like: pose.bones["bone-name"].rotation */
272
273#endif
274
275 return true;
276}
277
278void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob)
279{
280 float mat[4][4];
281 TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
282 if (ob) {
283 copy_m4_m4(ob->runtime->object_to_world.ptr(), mat);
284 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), false, false);
285 }
286}
287
288void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves,
289 const char *rna_path,
290 int array_index,
291 int scale)
292{
293 std::vector<FCurve *>::iterator it;
294 int i;
295 for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) {
296 FCurve *fcu = *it;
297 fcu->rna_path = BLI_strdup(rna_path);
298
299 if (array_index == -1) {
300 fcu->array_index = i;
301 }
302 else {
303 fcu->array_index = array_index;
304 }
305
306 if (scale != 1) {
307 fcurve_scale(fcu, scale);
308 }
309
310 fcurve_is_used(fcu);
311 }
312}
313
314void AnimationImporter::unused_fcurve(std::vector<FCurve *> *curves)
315{
316 /* when an error happens and we can't actually use curve remove it from unused_curves */
317 std::vector<FCurve *>::iterator it;
318 for (it = curves->begin(); it != curves->end(); it++) {
319 FCurve *fcu = *it;
320 fcurve_is_used(fcu);
321 }
322}
323
324void AnimationImporter::find_frames(std::vector<float> *frames, std::vector<FCurve *> *curves)
325{
326 std::vector<FCurve *>::iterator iter;
327 for (iter = curves->begin(); iter != curves->end(); iter++) {
328 FCurve *fcu = *iter;
329
330 for (uint k = 0; k < fcu->totvert; k++) {
331 /* get frame value from bezTriple */
332 float fra = fcu->bezt[k].vec[1][0];
333 /* if frame already not added add frame to frames */
334 if (std::find(frames->begin(), frames->end(), fra) == frames->end()) {
335 frames->push_back(fra);
336 }
337 }
338 }
339}
340
341static int get_animation_axis_index(const COLLADABU::Math::Vector3 &axis)
342{
343 int index;
344 if (COLLADABU::Math::Vector3::UNIT_X == axis) {
345 index = 0;
346 }
347 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
348 index = 1;
349 }
350 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
351 index = 2;
352 }
353 else {
354 index = -1;
355 }
356 return index;
357}
358
360 COLLADAFW::Transformation *transform,
361 const COLLADAFW::AnimationList::AnimationBinding *binding,
362 std::vector<FCurve *> *curves,
363 bool is_joint,
364 char *joint_path)
365{
366 COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
367 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
368 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
369
370 /* to check if the no of curves are valid */
371 bool xyz =
372 (ELEM(tm_type, COLLADAFW::Transformation::TRANSLATE, COLLADAFW::Transformation::SCALE) &&
373 binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
374
375 if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) {
376 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, int(curves->size()));
377 return;
378 }
379
380 char rna_path[100];
381
382 switch (tm_type) {
383 case COLLADAFW::Transformation::TRANSLATE:
384 case COLLADAFW::Transformation::SCALE: {
385 bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE;
386 if (is_joint) {
387 SNPRINTF(rna_path, "%s.%s", joint_path, loc ? "location" : "scale");
388 }
389 else {
390 STRNCPY(rna_path, loc ? "location" : "scale");
391 }
392
393 switch (binding->animationClass) {
394 case COLLADAFW::AnimationList::POSITION_X:
395 modify_fcurve(curves, rna_path, 0);
396 break;
397 case COLLADAFW::AnimationList::POSITION_Y:
398 modify_fcurve(curves, rna_path, 1);
399 break;
400 case COLLADAFW::AnimationList::POSITION_Z:
401 modify_fcurve(curves, rna_path, 2);
402 break;
403 case COLLADAFW::AnimationList::POSITION_XYZ:
404 modify_fcurve(curves, rna_path, -1);
405 break;
406 default:
407 unused_fcurve(curves);
408 fprintf(stderr,
409 "AnimationClass %d is not supported for %s.\n",
410 binding->animationClass,
411 loc ? "TRANSLATE" : "SCALE");
412 }
413 break;
414 }
415
416 case COLLADAFW::Transformation::ROTATE: {
417 if (is_joint) {
418 SNPRINTF(rna_path, "%s.rotation_euler", joint_path);
419 }
420 else {
421 STRNCPY(rna_path, "rotation_euler");
422 }
423 std::vector<FCurve *>::iterator iter;
424 for (iter = curves->begin(); iter != curves->end(); iter++) {
425 FCurve *fcu = *iter;
426
427 /* if transform is rotation the fcurves values must be turned in to radian. */
428 if (is_rotation) {
429 fcurve_deg_to_rad(fcu);
430 }
431 }
432 const COLLADAFW::Rotate *rot = (COLLADAFW::Rotate *)transform;
433 const COLLADABU::Math::Vector3 &axis = rot->getRotationAxis();
434
435 switch (binding->animationClass) {
436 case COLLADAFW::AnimationList::ANGLE: {
437 int axis_index = get_animation_axis_index(axis);
438 if (axis_index >= 0) {
439 modify_fcurve(curves, rna_path, axis_index);
440 }
441 else {
442 unused_fcurve(curves);
443 }
444 break;
445 }
446 case COLLADAFW::AnimationList::AXISANGLE:
447 /* TODO: convert axis-angle to quaternion? or XYZ? */
448 default:
449 unused_fcurve(curves);
450 fprintf(stderr,
451 "AnimationClass %d is not supported for ROTATE transformation.\n",
452 binding->animationClass);
453 }
454 break;
455 }
456
457 case COLLADAFW::Transformation::MATRIX:
458#if 0
459 {
460 COLLADAFW::Matrix *mat = (COLLADAFW::Matrix *)transform;
461 COLLADABU::Math::Matrix4 mat4 = mat->getMatrix();
462 switch (binding->animationClass) {
463 case COLLADAFW::AnimationList::TRANSFORM:
464 }
465 }
466#endif
467 unused_fcurve(curves);
468 break;
469 case COLLADAFW::Transformation::SKEW:
470 case COLLADAFW::Transformation::LOOKAT:
471 unused_fcurve(curves);
472 fprintf(stderr, "Animation of SKEW and LOOKAT transformations is not supported yet.\n");
473 break;
474 }
475}
476
477void AnimationImporter::Assign_color_animations(const COLLADAFW::UniqueId &listid,
478 AnimData &adt,
479 const char *anim_type)
480{
481 BLI_assert(adt.action != nullptr);
482
483 char rna_path[100];
484 STRNCPY(rna_path, anim_type);
485
486 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
487 if (animlist == nullptr) {
488 fprintf(stderr,
489 "Collada: No animlist found for ID: %s of type %s\n",
490 listid.toAscii().c_str(),
491 anim_type);
492 return;
493 }
494
495 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
496 /* all the curves belonging to the current binding */
497 std::vector<FCurve *> animcurves;
498 for (uint j = 0; j < bindings.getCount(); j++) {
499 animcurves = curve_map[bindings[j].animation];
500
501 switch (bindings[j].animationClass) {
502 case COLLADAFW::AnimationList::COLOR_R:
503 modify_fcurve(&animcurves, rna_path, 0);
504 break;
505 case COLLADAFW::AnimationList::COLOR_G:
506 modify_fcurve(&animcurves, rna_path, 1);
507 break;
508 case COLLADAFW::AnimationList::COLOR_B:
509 modify_fcurve(&animcurves, rna_path, 2);
510 break;
511 case COLLADAFW::AnimationList::COLOR_RGB:
512 case COLLADAFW::AnimationList::COLOR_RGBA: /* to do-> set intensity */
513 modify_fcurve(&animcurves, rna_path, -1);
514 break;
515
516 default:
517 unused_fcurve(&animcurves);
518 fprintf(stderr,
519 "AnimationClass %d is not supported for %s.\n",
520 bindings[j].animationClass,
521 "COLOR");
522 }
523
524 std::vector<FCurve *>::iterator iter;
525 /* Add the curves of the current animation to the object */
526 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
527 FCurve *fcu = *iter;
529 adt.action->wrap(), adt.slot_handle, *fcu, std::nullopt);
530 fcurve_is_used(fcu);
531 }
532 }
533}
534
535void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listid,
536 AnimData &adt,
537 const char *anim_type)
538{
539 BLI_assert(adt.action != nullptr);
540
541 char rna_path[100];
542 if (animlist_map.find(listid) == animlist_map.end()) {
543 return;
544 }
545
546 /* anim_type has animations */
547 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
548 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
549 /* all the curves belonging to the current binding */
550 std::vector<FCurve *> animcurves;
551 for (uint j = 0; j < bindings.getCount(); j++) {
552 animcurves = curve_map[bindings[j].animation];
553
554 STRNCPY(rna_path, anim_type);
555 modify_fcurve(&animcurves, rna_path, 0);
556 std::vector<FCurve *>::iterator iter;
557 /* Add the curves of the current animation to the object */
558 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
559 FCurve *fcu = *iter;
560 /* All anim_types whose values are to be converted from Degree to Radians can be ORed here
561 */
562 if (STREQ("spot_size", anim_type)) {
563 /* NOTE: Do NOT convert if imported file was made by blender <= 2.69.10
564 * Reason: old blender versions stored spot_size in radians (was a bug)
565 */
566 if (this->import_from_version.empty() ||
567 BLI_strcasecmp_natural(this->import_from_version.c_str(), "2.69.10") != -1)
568 {
569 fcurve_deg_to_rad(fcu);
570 }
571 }
573
575 adt.action->wrap(), adt.slot_handle, *fcu, std::nullopt);
576 fcurve_is_used(fcu);
577 }
578 }
579}
580
582 int fov_type,
583 float aspect,
584 float sensorx)
585{
586 /* NOTE: Needs more testing (As we currently have no official test data for this) */
587 float xfov = (fov_type == CAMERA_YFOV) ?
588 (2.0f * atanf(aspect * tanf(DEG2RADF(in_xfov) * 0.5f))) :
589 DEG2RADF(in_xfov);
590 return fov_to_focallength(xfov, sensorx);
591}
592
593void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId &listid,
594 AnimData &adt,
595 const double aspect,
596 const Camera *cam,
597 const char *anim_type,
598 int fov_type)
599{
600 BLI_assert(adt.action != nullptr);
601
602 char rna_path[100];
603 if (animlist_map.find(listid) == animlist_map.end()) {
604 return;
605 }
606
607 /* anim_type has animations */
608 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
609 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
610 /* all the curves belonging to the current binding */
611 std::vector<FCurve *> animcurves;
612 for (uint j = 0; j < bindings.getCount(); j++) {
613 animcurves = curve_map[bindings[j].animation];
614
615 STRNCPY(rna_path, anim_type);
616
617 modify_fcurve(&animcurves, rna_path, 0);
618 std::vector<FCurve *>::iterator iter;
619 /* Add the curves of the current animation to the object */
620 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
621 FCurve *fcu = *iter;
622
623 for (uint i = 0; i < fcu->totvert; i++) {
624 fcu->bezt[i].vec[0][1] = convert_to_focal_length(
625 fcu->bezt[i].vec[0][1], fov_type, aspect, cam->sensor_x);
626 fcu->bezt[i].vec[1][1] = convert_to_focal_length(
627 fcu->bezt[i].vec[1][1], fov_type, aspect, cam->sensor_x);
628 fcu->bezt[i].vec[2][1] = convert_to_focal_length(
629 fcu->bezt[i].vec[2][1], fov_type, aspect, cam->sensor_x);
630 }
631
633 adt.action->wrap(), adt.slot_handle, *fcu, std::nullopt);
634 fcurve_is_used(fcu);
635 }
636 }
637}
638
640 std::vector<FCurve *> &animcurves,
641 COLLADAFW::Node *root,
642 COLLADAFW::Node *node,
643 COLLADAFW::Transformation *tm)
644{
645 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
646 const char *bone_name = is_joint ? bc_get_joint_name(node) : nullptr;
647 char joint_path[200];
648 if (is_joint) {
649 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
650 }
651
652 std::vector<float> frames;
653 find_frames(&frames, &animcurves);
654
655 float irest_dae[4][4];
656 float rest[4][4], irest[4][4];
657
658 if (is_joint) {
659 get_joint_rest_mat(irest_dae, root, node);
660 invert_m4(irest_dae);
661
662 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
663 if (!bone) {
664 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
665 return;
666 }
667
668 unit_m4(rest);
669 copy_m4_m4(rest, bone->arm_mat);
670 invert_m4_m4(irest, rest);
671 }
672 /* new curves to assign matrix transform animation */
673 FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale */
674 uint totcu = 10;
675 const char *tm_str = nullptr;
676 char rna_path[200];
677 for (int i = 0; i < totcu; i++) {
678
679 int axis = i;
680
681 if (i < 4) {
682 tm_str = "rotation_quaternion";
683 axis = i;
684 }
685 else if (i < 7) {
686 tm_str = "location";
687 axis = i - 4;
688 }
689 else {
690 tm_str = "scale";
691 axis = i - 7;
692 }
693
694 if (is_joint) {
695 SNPRINTF(rna_path, "%s.%s", joint_path, tm_str);
696 }
697 else {
698 STRNCPY(rna_path, tm_str);
699 }
700 newcu[i] = create_fcurve(axis, rna_path);
701 newcu[i]->totvert = frames.size();
702 }
703
704 if (frames.empty()) {
705 return;
706 }
707
708 std::sort(frames.begin(), frames.end());
709
710 std::vector<float>::iterator it;
711
712 /* sample values at each frame */
713 for (it = frames.begin(); it != frames.end(); it++) {
714 float fra = *it;
715
716 float mat[4][4];
717 float matfra[4][4];
718
719 unit_m4(matfra);
720
721 /* calc object-space mat */
722 evaluate_transform_at_frame(matfra, node, fra);
723
724 /* for joints, we need a special matrix */
725 if (is_joint) {
726 /* special matrix: iR * M * iR_dae * R
727 * where R, iR are bone rest and inverse rest mats in world space (Blender bones),
728 * iR_dae is joint inverse rest matrix (DAE)
729 * and M is an evaluated joint world-space matrix (DAE) */
730 float temp[4][4], par[4][4];
731
732 /* calc M */
733 calc_joint_parent_mat_rest(par, nullptr, root, node);
734 mul_m4_m4m4(temp, par, matfra);
735
736 /* calc special matrix */
737 mul_m4_series(mat, irest, temp, irest_dae, rest);
738 }
739 else {
740 copy_m4_m4(mat, matfra);
741 }
742
743 float rot[4], loc[3], scale[3];
744 mat4_decompose(loc, rot, scale, mat);
745
746 /* add keys */
747 for (int i = 0; i < totcu; i++) {
748 if (i < 4) {
749 add_bezt(newcu[i], fra, rot[i]);
750 }
751 else if (i < 7) {
752 add_bezt(newcu[i], fra, loc[i - 4]);
753 }
754 else {
755 add_bezt(newcu[i], fra, scale[i - 7]);
756 }
757 }
758 }
759 Main *bmain = CTX_data_main(mContext);
760
762
763 /* add curves */
764 for (int i = 0; i < totcu; i++) {
765 if (is_joint) {
766 add_bone_fcurve(ob, node, newcu[i]);
767 }
768 else {
770 ob->adt->action->wrap(), ob->adt->slot_handle, *newcu[i], std::nullopt);
771 }
772#if 0
773 fcurve_is_used(newcu[i]); /* never added to unused */
774#endif
775 }
776
777 if (is_joint) {
778 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
779 chan->rotmode = ROT_MODE_QUAT;
780 }
781 else {
783 }
784}
785
786/*
787 * This function returns the aspect ration from the Collada camera.
788 *
789 * NOTE:COLLADA allows to specify either XFov, or YFov alone.
790 * In that case the aspect ratio can be determined from
791 * the viewport aspect ratio (which is 1:1 ?)
792 * XXX: check this: its probably wrong!
793 * If both values are specified, then the aspect ration is simply xfov/yfov
794 * and if aspect ratio is defined, then .. well then its that one.
795 */
796static double get_aspect_ratio(const COLLADAFW::Camera *camera)
797{
798 double aspect = camera->getAspectRatio().getValue();
799
800 if (aspect == 0) {
801 const double yfov = camera->getYFov().getValue();
802
803 if (yfov == 0) {
804 aspect = 1; /* assume yfov and xfov are equal */
805 }
806 else {
807 const double xfov = camera->getXFov().getValue();
808 if (xfov == 0) {
809 aspect = 1;
810 }
811 else {
812 aspect = xfov / yfov;
813 }
814 }
815 }
816 return aspect;
817}
818
820 COLLADAFW::Node *node,
821 std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map,
822 std::multimap<COLLADAFW::UniqueId, Object *> &object_map,
823 std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map,
824 std::map<COLLADAFW::UniqueId, Material *> uid_material_map)
825{
826 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
827 COLLADAFW::UniqueId uid = node->getUniqueId();
828 COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid];
829
830 Object *ob;
831 if (is_joint) {
832 ob = armature_importer->get_armature_for_joint(root);
833 }
834 else {
835 ob = object_map.find(uid) == object_map.end() ? nullptr : object_map.find(uid)->second;
836 }
837
838 if (!ob) {
839 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
840 return;
841 }
842
843 AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
844 Main *bmain = CTX_data_main(mContext);
845
846 if ((animType->transform) != 0) {
847 // const char *bone_name = is_joint ? bc_get_joint_name(node) : nullptr; /* UNUSED */
848 char joint_path[200];
849
850 if (is_joint) {
851 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
852 }
853
855
856 const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations();
857
858 /* for each transformation in node */
859 for (uint i = 0; i < nodeTransforms.getCount(); i++) {
860 COLLADAFW::Transformation *transform = nodeTransforms[i];
861 COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
862
863 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
864 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
865
866 const COLLADAFW::UniqueId &listid = transform->getAnimationList();
867
868 /* check if transformation has animations */
869 if (animlist_map.find(listid) == animlist_map.end()) {
870 continue;
871 }
872
873 /* transformation has animations */
874 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
875 const COLLADAFW::AnimationList::AnimationBindings &bindings =
876 animlist->getAnimationBindings();
877 /* all the curves belonging to the current binding */
878 std::vector<FCurve *> animcurves;
879 for (uint j = 0; j < bindings.getCount(); j++) {
880 animcurves = curve_map[bindings[j].animation];
881 if (is_matrix) {
882 apply_matrix_curves(ob, animcurves, root, node, transform);
883 }
884 else {
885 /* Calculate RNA-paths and array index of F-Curves according to transformation and
886 * animation class */
887 Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path);
888
889 std::vector<FCurve *>::iterator iter;
890 /* Add the curves of the current animation to the object */
891 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
892 FCurve *fcu = *iter;
894 ob->adt->action->wrap(), ob->adt->slot_handle, *fcu, std::nullopt);
895 fcurve_is_used(fcu);
896 }
897 }
898 }
899
900 if (is_rotation && !(is_joint || is_matrix)) {
901 ob->rotmode = ROT_MODE_EUL;
902 }
903 }
904 }
905
906 if ((animType->light) != 0) {
907 Light *lamp = (Light *)ob->data;
908 ensure_action_and_slot_for_id(bmain, lamp->id);
909
910 const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights();
911
912 for (uint i = 0; i < nodeLights.getCount(); i++) {
913 const COLLADAFW::Light *light = (COLLADAFW::Light *)
914 FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
915
916 if ((animType->light & LIGHT_COLOR) != 0) {
917 const COLLADAFW::Color *col = &light->getColor();
918 const COLLADAFW::UniqueId &listid = col->getAnimationList();
919
920 Assign_color_animations(listid, *lamp->adt, "color");
921 }
922 if ((animType->light & LIGHT_FOA) != 0) {
923 const COLLADAFW::AnimatableFloat *foa = &light->getFallOffAngle();
924 const COLLADAFW::UniqueId &listid = foa->getAnimationList();
925
926 Assign_float_animations(listid, *lamp->adt, "spot_size");
927 }
928 if ((animType->light & LIGHT_FOE) != 0) {
929 const COLLADAFW::AnimatableFloat *foe = &light->getFallOffExponent();
930 const COLLADAFW::UniqueId &listid = foe->getAnimationList();
931
932 Assign_float_animations(listid, *lamp->adt, "spot_blend");
933 }
934 }
935 }
936
937 if (animType->camera != 0) {
938
939 Camera *cam = (Camera *)ob->data;
941
942 const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras();
943
944 for (uint i = 0; i < nodeCameras.getCount(); i++) {
945 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *)
946 FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
947
948 if ((animType->camera & CAMERA_XFOV) != 0) {
949 const COLLADAFW::AnimatableFloat *xfov = &camera->getXFov();
950 const COLLADAFW::UniqueId &listid = xfov->getAnimationList();
951 double aspect = get_aspect_ratio(camera);
952 Assign_lens_animations(listid, *cam->adt, aspect, cam, "lens", CAMERA_XFOV);
953 }
954
955 else if ((animType->camera & CAMERA_YFOV) != 0) {
956 const COLLADAFW::AnimatableFloat *yfov = &camera->getYFov();
957 const COLLADAFW::UniqueId &listid = yfov->getAnimationList();
958 double aspect = get_aspect_ratio(camera);
959 Assign_lens_animations(listid, *cam->adt, aspect, cam, "lens", CAMERA_YFOV);
960 }
961
962 else if ((animType->camera & CAMERA_XMAG) != 0) {
963 const COLLADAFW::AnimatableFloat *xmag = &camera->getXMag();
964 const COLLADAFW::UniqueId &listid = xmag->getAnimationList();
965 Assign_float_animations(listid, *cam->adt, "ortho_scale");
966 }
967
968 else if ((animType->camera & CAMERA_YMAG) != 0) {
969 const COLLADAFW::AnimatableFloat *ymag = &camera->getYMag();
970 const COLLADAFW::UniqueId &listid = ymag->getAnimationList();
971 Assign_float_animations(listid, *cam->adt, "ortho_scale");
972 }
973
974 if ((animType->camera & CAMERA_ZFAR) != 0) {
975 const COLLADAFW::AnimatableFloat *zfar = &camera->getFarClippingPlane();
976 const COLLADAFW::UniqueId &listid = zfar->getAnimationList();
977 Assign_float_animations(listid, *cam->adt, "clip_end");
978 }
979
980 if ((animType->camera & CAMERA_ZNEAR) != 0) {
981 const COLLADAFW::AnimatableFloat *znear = &camera->getNearClippingPlane();
982 const COLLADAFW::UniqueId &listid = znear->getAnimationList();
983 Assign_float_animations(listid, *cam->adt, "clip_start");
984 }
985 }
986 }
987 if (animType->material != 0) {
988 const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries();
989 for (uint i = 0; i < nodeGeoms.getCount(); i++) {
990 const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings();
991 for (uint j = 0; j < matBinds.getCount(); j++) {
992 const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial();
993 const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]);
994 if (ef != nullptr) { /* can be nullptr #28909. */
995 Material *ma = uid_material_map[matuid];
996 if (!ma) {
997 fprintf(stderr,
998 "Collada: Node %s refers to undefined material\n",
999 node->getName().c_str());
1000 continue;
1001 }
1003
1004 const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects();
1005 COLLADAFW::EffectCommon *efc = commonEffects[0];
1006 if ((animType->material & MATERIAL_SHININESS) != 0) {
1007 const COLLADAFW::FloatOrParam *shin = &efc->getShininess();
1008 const COLLADAFW::UniqueId &listid = shin->getAnimationList();
1009 Assign_float_animations(listid, *ma->adt, "specular_hardness");
1010 }
1011
1012 if ((animType->material & MATERIAL_IOR) != 0) {
1013 const COLLADAFW::FloatOrParam *ior = &efc->getIndexOfRefraction();
1014 const COLLADAFW::UniqueId &listid = ior->getAnimationList();
1015 Assign_float_animations(listid, *ma->adt, "raytrace_transparency.ior");
1016 }
1017
1018 if ((animType->material & MATERIAL_SPEC_COLOR) != 0) {
1019 const COLLADAFW::ColorOrTexture *cot = &efc->getSpecular();
1020 const COLLADAFW::UniqueId &listid = cot->getColor().getAnimationList();
1021 Assign_color_animations(listid, *ma->adt, "specular_color");
1022 }
1023
1024 if ((animType->material & MATERIAL_DIFF_COLOR) != 0) {
1025 const COLLADAFW::ColorOrTexture *cot = &efc->getDiffuse();
1026 const COLLADAFW::UniqueId &listid = cot->getColor().getAnimationList();
1027 Assign_color_animations(listid, *ma->adt, "diffuse_color");
1028 }
1029 }
1030 }
1031 }
1032 }
1033
1034 delete animType;
1035}
1036
1037AnimationImporter::AnimMix *AnimationImporter::get_animation_type(
1038 const COLLADAFW::Node *node,
1039 std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
1040{
1041 AnimMix *types = new AnimMix();
1042
1043 const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations();
1044
1045 /* for each transformation in node */
1046 for (uint i = 0; i < nodeTransforms.getCount(); i++) {
1047 COLLADAFW::Transformation *transform = nodeTransforms[i];
1048 const COLLADAFW::UniqueId &listid = transform->getAnimationList();
1049
1050 /* check if transformation has animations */
1051 if (animlist_map.find(listid) == animlist_map.end()) {
1052 continue;
1053 }
1054
1055 types->transform = types->transform | BC_NODE_TRANSFORM;
1056 break;
1057 }
1058 const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights();
1059
1060 for (uint i = 0; i < nodeLights.getCount(); i++) {
1061 const COLLADAFW::Light *light = (COLLADAFW::Light *)
1062 FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
1063 types->light = setAnimType(&light->getColor(), (types->light), LIGHT_COLOR);
1064 types->light = setAnimType(&light->getFallOffAngle(), (types->light), LIGHT_FOA);
1065 types->light = setAnimType(&light->getFallOffExponent(), (types->light), LIGHT_FOE);
1066
1067 if (types->light != 0) {
1068 break;
1069 }
1070 }
1071
1072 const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras();
1073 for (uint i = 0; i < nodeCameras.getCount(); i++) {
1074 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *)
1075 FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
1076 if (camera == nullptr) {
1077 /* Can happen if the node refers to an unknown camera. */
1078 continue;
1079 }
1080
1081 const bool is_perspective_type = camera->getCameraType() == COLLADAFW::Camera::PERSPECTIVE;
1082
1083 int addition;
1084 const COLLADAFW::Animatable *mag;
1085 const COLLADAFW::UniqueId listid = camera->getYMag().getAnimationList();
1086 if (animlist_map.find(listid) != animlist_map.end()) {
1087 mag = &camera->getYMag();
1088 addition = (is_perspective_type) ? CAMERA_YFOV : CAMERA_YMAG;
1089 }
1090 else {
1091 mag = &camera->getXMag();
1092 addition = (is_perspective_type) ? CAMERA_XFOV : CAMERA_XMAG;
1093 }
1094 types->camera = setAnimType(mag, (types->camera), addition);
1095
1096 types->camera = setAnimType(&camera->getFarClippingPlane(), (types->camera), CAMERA_ZFAR);
1097 types->camera = setAnimType(&camera->getNearClippingPlane(), (types->camera), CAMERA_ZNEAR);
1098
1099 if (types->camera != 0) {
1100 break;
1101 }
1102 }
1103
1104 const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries();
1105 for (uint i = 0; i < nodeGeoms.getCount(); i++) {
1106 const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings();
1107 for (uint j = 0; j < matBinds.getCount(); j++) {
1108 const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial();
1109 const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]);
1110 if (ef != nullptr) { /* can be nullptr #28909. */
1111 const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects();
1112 if (!commonEffects.empty()) {
1113 COLLADAFW::EffectCommon *efc = commonEffects[0];
1114 types->material = setAnimType(
1115 &efc->getShininess(), (types->material), MATERIAL_SHININESS);
1116 types->material = setAnimType(
1117 &efc->getSpecular().getColor(), (types->material), MATERIAL_SPEC_COLOR);
1118 types->material = setAnimType(
1119 &efc->getDiffuse().getColor(), (types->material), MATERIAL_DIFF_COLOR);
1120#if 0
1121 types->material = setAnimType(&(efc->get()), (types->material), MATERIAL_TRANSPARENCY);
1122#endif
1123 types->material = setAnimType(
1124 &efc->getIndexOfRefraction(), (types->material), MATERIAL_IOR);
1125 }
1126 }
1127 }
1128 }
1129 return types;
1130}
1131
1132int AnimationImporter::setAnimType(const COLLADAFW::Animatable *prop, int types, int addition)
1133{
1134 int anim_type;
1135 const COLLADAFW::UniqueId &listid = prop->getAnimationList();
1136 if (animlist_map.find(listid) != animlist_map.end()) {
1137 anim_type = types | addition;
1138 }
1139 else {
1140 anim_type = types;
1141 }
1142
1143 return anim_type;
1144}
1145
1147 COLLADAFW::Node *node,
1148 float fra)
1149{
1150 const COLLADAFW::TransformationPointerArray &tms = node->getTransformations();
1151
1152 unit_m4(mat);
1153
1154 for (uint i = 0; i < tms.getCount(); i++) {
1155 COLLADAFW::Transformation *tm = tms[i];
1156 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1157 float m[4][4];
1158
1159 unit_m4(m);
1160
1161 std::string nodename = node->getName().empty() ? node->getOriginalId() : node->getName();
1162 if (!evaluate_animation(tm, m, fra, nodename.c_str())) {
1163 switch (type) {
1164 case COLLADAFW::Transformation::ROTATE:
1165 dae_rotate_to_mat4(tm, m);
1166 break;
1167 case COLLADAFW::Transformation::TRANSLATE:
1168 dae_translate_to_mat4(tm, m);
1169 break;
1170 case COLLADAFW::Transformation::SCALE:
1171 dae_scale_to_mat4(tm, m);
1172 break;
1173 case COLLADAFW::Transformation::MATRIX:
1174 dae_matrix_to_mat4(tm, m);
1175 break;
1176 default:
1177 fprintf(stderr, "unsupported transformation type %d\n", type);
1178 }
1179 }
1180
1181 float temp[4][4];
1182 copy_m4_m4(temp, mat);
1183
1184 mul_m4_m4m4(mat, temp, m);
1185 }
1186}
1187
1188static void report_class_type_unsupported(const char *path,
1189 const COLLADAFW::AnimationList::AnimationClass animclass,
1190 const COLLADAFW::Transformation::TransformationType type)
1191{
1192 if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) {
1193 fprintf(stderr, "%s: UNKNOWN animation class\n", path);
1194 }
1195 else {
1196 fprintf(stderr,
1197 "%s: animation class %d is not supported yet for transformation type %d\n",
1198 path,
1199 animclass,
1200 type);
1201 }
1202}
1203
1204bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm,
1205 float mat[4][4],
1206 float fra,
1207 const char *node_id)
1208{
1209 const COLLADAFW::UniqueId &listid = tm->getAnimationList();
1210 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1211
1212 if (!ELEM(type,
1213 COLLADAFW::Transformation::ROTATE,
1214 COLLADAFW::Transformation::SCALE,
1215 COLLADAFW::Transformation::TRANSLATE,
1216 COLLADAFW::Transformation::MATRIX))
1217 {
1218 fprintf(stderr, "animation of transformation %d is not supported yet\n", type);
1219 return false;
1220 }
1221
1222 if (animlist_map.find(listid) == animlist_map.end()) {
1223 return false;
1224 }
1225
1226 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1227 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
1228
1229 if (bindings.getCount()) {
1230 float vec[3];
1231
1232 bool is_scale = (type == COLLADAFW::Transformation::SCALE);
1233 bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE);
1234
1235 if (is_scale) {
1236 dae_scale_to_v3(tm, vec);
1237 }
1238 else if (is_translate) {
1239 dae_translate_to_v3(tm, vec);
1240 }
1241
1242 for (uint index = 0; index < bindings.getCount(); index++) {
1243 const COLLADAFW::AnimationList::AnimationBinding &binding = bindings[index];
1244 std::vector<FCurve *> &curves = curve_map[binding.animation];
1245 COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass;
1246 char path[100];
1247
1248 switch (type) {
1249 case COLLADAFW::Transformation::ROTATE:
1250 SNPRINTF(path, "%s.rotate (binding %u)", node_id, index);
1251 break;
1252 case COLLADAFW::Transformation::SCALE:
1253 SNPRINTF(path, "%s.scale (binding %u)", node_id, index);
1254 break;
1255 case COLLADAFW::Transformation::TRANSLATE:
1256 SNPRINTF(path, "%s.translate (binding %u)", node_id, index);
1257 break;
1258 case COLLADAFW::Transformation::MATRIX:
1259 SNPRINTF(path, "%s.matrix (binding %u)", node_id, index);
1260 break;
1261 default:
1262 break;
1263 }
1264
1265 if (type == COLLADAFW::Transformation::ROTATE) {
1266 if (curves.size() != 1) {
1267 fprintf(stderr, "expected 1 curve, got %d\n", int(curves.size()));
1268 return false;
1269 }
1270
1271 /* TODO: support other animation-classes. */
1272 if (animclass != COLLADAFW::AnimationList::ANGLE) {
1273 report_class_type_unsupported(path, animclass, type);
1274 return false;
1275 }
1276
1277 COLLADABU::Math::Vector3 &axis = ((COLLADAFW::Rotate *)tm)->getRotationAxis();
1278
1279 float ax[3] = {float(axis[0]), float(axis[1]), float(axis[2])};
1280 float angle = evaluate_fcurve(curves[0], fra);
1281 axis_angle_to_mat4(mat, ax, angle);
1282
1283 return true;
1284 }
1285 if (is_scale || is_translate) {
1286 bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ;
1287
1288 if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) {
1289 if (is_xyz) {
1290 fprintf(stderr, "%s: expected 3 curves, got %d\n", path, int(curves.size()));
1291 }
1292 else {
1293 fprintf(stderr, "%s: expected 1 curve, got %d\n", path, int(curves.size()));
1294 }
1295 return false;
1296 }
1297
1298 switch (animclass) {
1299 case COLLADAFW::AnimationList::POSITION_X:
1300 vec[0] = evaluate_fcurve(curves[0], fra);
1301 break;
1302 case COLLADAFW::AnimationList::POSITION_Y:
1303 vec[1] = evaluate_fcurve(curves[0], fra);
1304 break;
1305 case COLLADAFW::AnimationList::POSITION_Z:
1306 vec[2] = evaluate_fcurve(curves[0], fra);
1307 break;
1308 case COLLADAFW::AnimationList::POSITION_XYZ:
1309 vec[0] = evaluate_fcurve(curves[0], fra);
1310 vec[1] = evaluate_fcurve(curves[1], fra);
1311 vec[2] = evaluate_fcurve(curves[2], fra);
1312 break;
1313 default:
1314 report_class_type_unsupported(path, animclass, type);
1315 break;
1316 }
1317 }
1318 else if (type == COLLADAFW::Transformation::MATRIX) {
1319 /* for now, of matrix animation,
1320 * support only the case when all values are packed into one animation */
1321 if (curves.size() != 16) {
1322 fprintf(stderr, "%s: expected 16 curves, got %d\n", path, int(curves.size()));
1323 return false;
1324 }
1325
1326 COLLADABU::Math::Matrix4 matrix;
1327 int mi = 0, mj = 0;
1328
1329 for (const FCurve *curve : curves) {
1330 matrix.setElement(mi, mj, evaluate_fcurve(curve, fra));
1331 mj++;
1332 if (mj == 4) {
1333 mi++;
1334 mj = 0;
1335 }
1336 }
1338 return true;
1339 }
1340 }
1341
1342 if (is_scale) {
1343 size_to_mat4(mat, vec);
1344 }
1345 else {
1346 copy_v3_v3(mat[3], vec);
1347 }
1348
1349 return is_scale || is_translate;
1350 }
1351
1352 return false;
1353}
1354
1356 COLLADAFW::Node *root,
1357 COLLADAFW::Node *node)
1358{
1359 /* if bind mat is not available,
1360 * use "current" node transform, i.e. all those tms listed inside <node> */
1361 if (!armature_importer->get_joint_bind_mat(mat, node)) {
1362 float par[4][4], m[4][4];
1363
1364 calc_joint_parent_mat_rest(par, nullptr, root, node);
1365 get_node_mat(m, node, nullptr, nullptr);
1366 mul_m4_m4m4(mat, par, m);
1367 }
1368}
1369
1371 float par[4][4],
1372 COLLADAFW::Node *node,
1373 COLLADAFW::Node *end)
1374{
1375 float m[4][4];
1376
1377 if (node == end) {
1378 par ? copy_m4_m4(mat, par) : unit_m4(mat);
1379 return true;
1380 }
1381
1382 /* use bind matrix if available or calc "current" world mat */
1383 if (!armature_importer->get_joint_bind_mat(m, node)) {
1384 if (par) {
1385 float temp[4][4];
1386 get_node_mat(temp, node, nullptr, nullptr);
1387 mul_m4_m4m4(m, par, temp);
1388 }
1389 else {
1390 get_node_mat(m, node, nullptr, nullptr);
1391 }
1392 }
1393
1394 COLLADAFW::NodePointerArray &children = node->getChildNodes();
1395 for (uint i = 0; i < children.getCount(); i++) {
1396 if (calc_joint_parent_mat_rest(mat, m, children[i], end)) {
1397 return true;
1398 }
1399 }
1400
1401 return false;
1402}
1403
1404void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu)
1405{
1406 BLI_assert(ob->adt != nullptr && ob->adt->action != nullptr);
1407
1408 const char *bone_name = bc_get_joint_name(node);
1409
1411 ob->adt->action->wrap(), ob->adt->slot_handle, *fcu, bone_name);
1412}
1413
1414void AnimationImporter::set_import_from_version(std::string import_from_version)
1415{
1416 this->import_from_version = import_from_version;
1417}
Functions and classes to work with Actions.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
Functions to modify FCurves.
static const char * bc_get_joint_name(T *node)
static void report_class_type_unsupported(const char *path, const COLLADAFW::AnimationList::AnimationClass animclass, const COLLADAFW::Transformation::TransformationType type)
static double get_aspect_ratio(const COLLADAFW::Camera *camera)
static void ensure_action_and_slot_for_id(Main *bmain, ID &id)
static int get_animation_axis_index(const COLLADABU::Math::Vector3 &axis)
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
Bone * BKE_armature_find_bone_name(bArmature *arm, const char *name)
Definition armature.cc:812
Main * CTX_data_main(const bContext *C)
FCurve * BKE_fcurve_create()
void BKE_fcurve_handles_recalc(FCurve *fcu)
float evaluate_fcurve(const FCurve *fcu, float evaltime)
void BKE_fcurve_free(FCurve *fcu)
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define DEG2RADF(_deg)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4])
void size_to_mat4(float R[4][4], const float size[3])
#define mul_m4_series(...)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
bool invert_m4(float mat[4][4])
void unit_m4(float m[4][4])
void axis_angle_to_mat4(float R[4][4], const float axis[3], float angle)
float fov_to_focallength(float hfov, float sensor)
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.cc:30
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
int char char int int int BLI_strcasecmp_natural(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define STREQ(a, b)
@ ROT_MODE_QUAT
@ ROT_MODE_EUL
@ INSERTKEY_NOFLAGS
@ FCURVE_SELECTED
@ FCURVE_VISIBLE
struct FCurve FCurve
@ HD_AUTO_ANIM
@ HD_AUTO
eBezTriple_Interpolation
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ BEZT_IPO_LIN
struct BezTriple BezTriple
#define FPS
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
#define U
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node)
float convert_to_focal_length(float in_xfov, int fov_type, float aspect, float sensorx)
void find_frames(std::vector< float > *frames, std::vector< FCurve * > *curves)
bool evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id)
void read_node_transform(COLLADAFW::Node *node, Object *ob)
void Assign_transform_animations(COLLADAFW::Transformation *transform, const COLLADAFW::AnimationList::AnimationBinding *binding, std::vector< FCurve * > *curves, bool is_joint, char *joint_path)
int setAnimType(const COLLADAFW::Animatable *prop, int type, int addition)
void Assign_float_animations(const COLLADAFW::UniqueId &listid, AnimData &adt, const char *anim_type)
bool write_animation_list(const COLLADAFW::AnimationList *animlist)
AnimMix * get_animation_type(const COLLADAFW::Node *node, std::map< COLLADAFW::UniqueId, const COLLADAFW::Object * > FW_object_map)
void unused_fcurve(std::vector< FCurve * > *curves)
void Assign_color_animations(const COLLADAFW::UniqueId &listid, AnimData &adt, const char *anim_type)
void add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu)
void modify_fcurve(std::vector< FCurve * > *curves, const char *rna_path, int array_index, int scale=1)
bool calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end)
void evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra)
void apply_matrix_curves(Object *ob, std::vector< FCurve * > &animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm)
void Assign_lens_animations(const COLLADAFW::UniqueId &listid, AnimData &adt, double aspect, const Camera *cam, const char *anim_type, int fov_type)
void translate_Animations(COLLADAFW::Node *Node, std::map< COLLADAFW::UniqueId, COLLADAFW::Node * > &root_map, std::multimap< COLLADAFW::UniqueId, Object * > &object_map, std::map< COLLADAFW::UniqueId, const COLLADAFW::Object * > FW_object_map, std::map< COLLADAFW::UniqueId, Material * > uid_material_map)
bool write_animation(const COLLADAFW::Animation *anim)
void set_import_from_version(std::string import_from_version)
void dae_matrix_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
void dae_translate_to_v3(COLLADAFW::Transformation *tm, float v[3])
void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map< COLLADAFW::UniqueId, Animation > *animation_map, Object *ob)
void dae_scale_to_v3(COLLADAFW::Transformation *tm, float v[3])
void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in)
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, uint index)
#define SELECT
#define tanf(x)
#define atanf(x)
#define rot(x, k)
uint col
#define input
#define output
static char ** types
Definition makesdna.cc:71
ccl_device_inline float interp(const float a, const float b, const float t)
Definition math_base.h:502
#define T
bool action_treat_as_legacy(const bAction &action)
void action_fcurve_attach(Action &action, slot_handle_t action_slot, FCurve &fcurve_to_attach, std::optional< StringRefNull > group_name)
Slot * assign_action_ensure_slot_for_keying(Action &action, ID &animated_id)
bAction * id_action_ensure(Main *bmain, ID *id)
Definition animdata.cc:195
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
Lesser Key-framing API call.
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
bAction * action
int32_t slot_handle
float vec[3][3]
float arm_mat[4][4]
struct AnimData * adt
float sensor_x
char * rna_path
BezTriple * bezt
int array_index
unsigned int totvert
char auto_smoothing
Definition DNA_ID.h:404
struct AnimData * adt
struct AnimData * adt
struct bPose * pose
ObjectRuntimeHandle * runtime
struct AnimData * adt
i
Definition text_draw.cc:230