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