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
8
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 }
545
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
struct FCurve FCurve
@ INSERTKEY_NOFLAGS
@ FCURVE_SELECTED
@ FCURVE_VISIBLE
@ HD_AUTO_ANIM
@ HD_AUTO
struct BezTriple BezTriple
eBezTriple_Interpolation
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ BEZT_IPO_LIN
#define FPS
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
#define U
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
#define output
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 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 offsetof(t, d)
draw_view in_light_buf[] float
#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)
#define 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.
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
void index(const bNode &, void *r_value)
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