1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup collada
19 */
20
21 #include <stddef.h>
22
23 /* COLLADABU_ASSERT, may be able to remove later */
24 #include "COLLADABUPlatform.h"
25
26 #include "DNA_armature_types.h"
27
28 #include "ED_keyframing.h"
29
30 #include "BLI_listbase.h"
31 #include "BLI_math.h"
32 #include "BLI_string.h"
33 #include "BLI_string_utils.h"
34
35 #include "BLT_translation.h"
36
37 #include "BKE_action.h"
38 #include "BKE_armature.h"
39 #include "BKE_fcurve.h"
40 #include "BKE_object.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "AnimationImporter.h"
45 #include "ArmatureImporter.h"
46 #include "MaterialExporter.h"
47 #include "collada_utils.h"
48
49 #include <algorithm>
50
51 /* first try node name, if not available (since is optional), fall back to original id */
bc_get_joint_name(T * node)52 template<class T> static const char *bc_get_joint_name(T *node)
53 {
54 const std::string &id = node->getName();
55 return id.empty() ? node->getOriginalId().c_str() : id.c_str();
56 }
57
create_fcurve(int array_index,const char * rna_path)58 FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
59 {
60 FCurve *fcu = BKE_fcurve_create();
61 fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
62 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
63 fcu->array_index = array_index;
64 return fcu;
65 }
66
add_bezt(FCurve * fcu,float frame,float value,eBezTriple_Interpolation ipo)67 void AnimationImporter::add_bezt(FCurve *fcu,
68 float frame,
69 float value,
70 eBezTriple_Interpolation ipo)
71 {
72 // float fps = (float)FPS;
73 BezTriple bez;
74 memset(&bez, 0, sizeof(BezTriple));
75 bez.vec[1][0] = frame;
76 bez.vec[1][1] = value;
77 bez.ipo = ipo; /* use default interpolation mode here... */
78 bez.f1 = bez.f2 = bez.f3 = SELECT;
79 bez.h1 = bez.h2 = HD_AUTO;
80 insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
81 calchandles_fcurve(fcu);
82 }
83
84 /* create one or several fcurves depending on the number of parameters being animated */
animation_to_fcurves(COLLADAFW::AnimationCurve * curve)85 void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
86 {
87 COLLADAFW::FloatOrDoubleArray &input = curve->getInputValues();
88 COLLADAFW::FloatOrDoubleArray &output = curve->getOutputValues();
89
90 float fps = (float)FPS;
91 size_t dim = curve->getOutDimension();
92 unsigned int i;
93
94 std::vector<FCurve *> &fcurves = curve_map[curve->getUniqueId()];
95
96 switch (dim) {
97 case 1: /* X, Y, Z or angle */
98 case 3: /* XYZ */
99 case 4:
100 case 16: /* matrix */
101 {
102 for (i = 0; i < dim; i++) {
103 FCurve *fcu = BKE_fcurve_create();
104
105 fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
106 fcu->array_index = 0;
107 fcu->auto_smoothing = U.auto_smoothing_new;
108
109 for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
110 BezTriple bez;
111 memset(&bez, 0, sizeof(BezTriple));
112
113 /* input, output */
114 bez.vec[1][0] = bc_get_float_value(input, j) * fps;
115 bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
116 bez.h1 = bez.h2 = HD_AUTO;
117
118 if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ||
119 curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_STEP) {
120 COLLADAFW::FloatOrDoubleArray &intan = curve->getInTangentValues();
121 COLLADAFW::FloatOrDoubleArray &outtan = curve->getOutTangentValues();
122
123 /* intangent */
124 unsigned int index = 2 * (j * dim + i);
125 bez.vec[0][0] = bc_get_float_value(intan, index) * fps;
126 bez.vec[0][1] = bc_get_float_value(intan, index + 1);
127
128 /* outtangent */
129 bez.vec[2][0] = bc_get_float_value(outtan, index) * fps;
130 bez.vec[2][1] = bc_get_float_value(outtan, index + 1);
131 if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) {
132 bez.ipo = BEZT_IPO_BEZ;
133 bez.h1 = bez.h2 = HD_AUTO_ANIM;
134 }
135 else {
136 bez.ipo = BEZT_IPO_CONST;
137 }
138 }
139 else {
140 bez.ipo = BEZT_IPO_LIN;
141 }
142 #if 0
143 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
144 #endif
145 bez.f1 = bez.f2 = bez.f3 = SELECT;
146
147 insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
148 }
149
150 calchandles_fcurve(fcu);
151
152 fcurves.push_back(fcu);
153 unused_curves.push_back(fcu);
154 }
155 } break;
156 default:
157 fprintf(stderr,
158 "Output dimension of %d is not yet supported (animation id = %s)\n",
159 (int)dim,
160 curve->getOriginalId().c_str());
161 }
162 }
163
fcurve_deg_to_rad(FCurve * cu)164 void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
165 {
166 for (unsigned int i = 0; i < cu->totvert; i++) {
167 /* TODO convert handles too */
168 cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f);
169 cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f);
170 cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f);
171 }
172 }
173
fcurve_scale(FCurve * cu,int scale)174 void AnimationImporter::fcurve_scale(FCurve *cu, int scale)
175 {
176 for (unsigned int i = 0; i < cu->totvert; i++) {
177 /* TODO convert handles too */
178 cu->bezt[i].vec[1][1] *= scale;
179 cu->bezt[i].vec[0][1] *= scale;
180 cu->bezt[i].vec[2][1] *= scale;
181 }
182 }
183
fcurve_is_used(FCurve * fcu)184 void AnimationImporter::fcurve_is_used(FCurve *fcu)
185 {
186 unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu),
187 unused_curves.end());
188 }
189
add_fcurves_to_object(Main * bmain,Object * ob,std::vector<FCurve * > & curves,char * rna_path,int array_index,Animation * animated)190 void AnimationImporter::add_fcurves_to_object(Main *bmain,
191 Object *ob,
192 std::vector<FCurve *> &curves,
193 char *rna_path,
194 int array_index,
195 Animation *animated)
196 {
197 bAction *act;
198
199 if (!ob->adt || !ob->adt->action) {
200 act = ED_id_action_ensure(bmain, (ID *)&ob->id);
201 }
202 else {
203 act = ob->adt->action;
204 }
205
206 std::vector<FCurve *>::iterator it;
207 int i;
208
209 #if 0
210 char *p = strstr(rna_path, "rotation_euler");
211 bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0';
212
213 /* convert degrees to radians for rotation */
214 if (is_rotation) {
215 fcurve_deg_to_rad(fcu);
216 }
217 #endif
218
219 for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) {
220 FCurve *fcu = *it;
221 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
222
223 if (array_index == -1) {
224 fcu->array_index = i;
225 }
226 else {
227 fcu->array_index = array_index;
228 }
229
230 if (ob->type == OB_ARMATURE) {
231 bActionGroup *grp = NULL;
232 const char *bone_name = bc_get_joint_name(animated->node);
233
234 if (bone_name) {
235 /* try to find group */
236 grp = BKE_action_group_find_name(act, bone_name);
237
238 /* no matching groups, so add one */
239 if (grp == NULL) {
240 /* Add a new group, and make it active */
241 grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
242
243 grp->flag = AGRP_SELECTED;
244 BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
245
246 BLI_addtail(&act->groups, grp);
247 BLI_uniquename(&act->groups,
248 grp,
249 CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"),
250 '.',
251 offsetof(bActionGroup, name),
252 64);
253 }
254
255 /* add F-Curve to group */
256 action_groups_add_channel(act, grp, fcu);
257 fcurve_is_used(fcu);
258 }
259 #if 0
260 if (is_rotation) {
261 fcurves_actionGroup_map[grp].push_back(fcu);
262 }
263 #endif
264 }
265 else {
266 BLI_addtail(&act->curves, fcu);
267 fcurve_is_used(fcu);
268 }
269 }
270 }
271
~AnimationImporter()272 AnimationImporter::~AnimationImporter()
273 {
274 /* free unused FCurves */
275 for (std::vector<FCurve *>::iterator it = unused_curves.begin(); it != unused_curves.end();
276 it++) {
277 BKE_fcurve_free(*it);
278 }
279
280 if (!unused_curves.empty()) {
281 fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size());
282 }
283 }
284
write_animation(const COLLADAFW::Animation * anim)285 bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim)
286 {
287 if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
288 COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve *)anim;
289
290 /* XXX Don't know if it's necessary
291 * Should we check outPhysicalDimension? */
292 if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) {
293 fprintf(stderr, "Inputs physical dimension is not time.\n");
294 return true;
295 }
296
297 /* a curve can have mixed interpolation type,
298 * in this case curve->getInterpolationTypes returns a list of interpolation types per key */
299 COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
300
301 if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
302 switch (interp) {
303 case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
304 case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
305 case COLLADAFW::AnimationCurve::INTERPOLATION_STEP:
306 animation_to_fcurves(curve);
307 break;
308 default:
309 /* TODO there are also CARDINAL, HERMITE, BSPLINE and STEP types. */
310 fprintf(stderr,
311 "CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n");
312 break;
313 }
314 }
315 else {
316 /* not supported yet */
317 fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n");
318 }
319 }
320 else {
321 fprintf(stderr, "FORMULA animation type is not supported yet.\n");
322 }
323
324 return true;
325 }
326
327 /* called on post-process stage after writeVisualScenes */
write_animation_list(const COLLADAFW::AnimationList * animlist)328 bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *animlist)
329 {
330 const COLLADAFW::UniqueId &animlist_id = animlist->getUniqueId();
331 animlist_map[animlist_id] = animlist;
332
333 #if 0
334
335 /* should not happen */
336 if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
337 return true;
338 }
339
340 /* for bones rna_path is like: pose.bones["bone-name"].rotation */
341
342 #endif
343
344 return true;
345 }
346
347 /**
348 * \todo refactor read_node_transform to not automatically apply anything,
349 * but rather return the transform matrix, so caller can do with it what is
350 * necessary. Same for \ref get_node_mat
351 */
read_node_transform(COLLADAFW::Node * node,Object * ob)352 void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob)
353 {
354 float mat[4][4];
355 TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
356 if (ob) {
357 copy_m4_m4(ob->obmat, mat);
358 BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
359 }
360 }
361
362 #if 0
363 virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
364 {
365 bActionGroup *grp;
366 int i;
367
368 for (grp = (bActionGroup *)act->groups.first; grp; grp = grp->next) {
369
370 FCurve *eulcu[3] = {NULL, NULL, NULL};
371
372 if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) {
373 continue;
374 }
375
376 std::vector<FCurve *> &rot_fcurves = fcurves_actionGroup_map[grp];
377
378 if (rot_fcurves.size() > 3) {
379 continue;
380 }
381
382 for (i = 0; i < rot_fcurves.size(); i++) {
383 eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i];
384 }
385
386 char joint_path[100];
387 char rna_path[100];
388
389 BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name);
390 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path);
391
392 FCurve *quatcu[4] = {
393 create_fcurve(0, rna_path),
394 create_fcurve(1, rna_path),
395 create_fcurve(2, rna_path),
396 create_fcurve(3, rna_path),
397 };
398
399 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, grp->name);
400
401 float m4[4][4], irest[3][3];
402 invert_m4_m4(m4, chan->bone->arm_mat);
403 copy_m3_m4(irest, m4);
404
405 for (i = 0; i < 3; i++) {
406
407 FCurve *cu = eulcu[i];
408
409 if (!cu) {
410 continue;
411 }
412
413 for (int j = 0; j < cu->totvert; j++) {
414 float frame = cu->bezt[j].vec[1][0];
415
416 float eul[3] = {
417 eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f,
418 eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f,
419 eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f,
420 };
421
422 /* make eul relative to bone rest pose */
423 float rot[3][3], rel[3][3], quat[4];
424
425 # if 0
426 eul_to_mat3(rot, eul);
427 mul_m3_m3m3(rel, irest, rot);
428 mat3_to_quat(quat, rel);
429 # endif
430
431 eul_to_quat(quat, eul);
432
433 for (int k = 0; k < 4; k++) {
434 create_bezt(quatcu[k], frame, quat[k], U.ipo_new);
435 }
436 }
437 }
438
439 /* now replace old Euler curves */
440
441 for (i = 0; i < 3; i++) {
442 if (!eulcu[i]) {
443 continue;
444 }
445
446 action_groups_remove_channel(act, eulcu[i]);
447 BKE_fcurve_free(eulcu[i]);
448 }
449
450 chan->rotmode = ROT_MODE_QUAT;
451
452 for (i = 0; i < 4; i++) {
453 action_groups_add_channel(act, grp, quatcu[i]);
454 }
455 }
456
457 bPoseChannel *pchan;
458 for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
459 pchan->rotmode = ROT_MODE_QUAT;
460 }
461 }
462 #endif
463
464 /* sets the rna_path and array index to curve */
modify_fcurve(std::vector<FCurve * > * curves,const char * rna_path,int array_index,int scale)465 void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves,
466 const char *rna_path,
467 int array_index,
468 int scale)
469 {
470 std::vector<FCurve *>::iterator it;
471 int i;
472 for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) {
473 FCurve *fcu = *it;
474 fcu->rna_path = BLI_strdup(rna_path);
475
476 if (array_index == -1) {
477 fcu->array_index = i;
478 }
479 else {
480 fcu->array_index = array_index;
481 }
482
483 if (scale != 1) {
484 fcurve_scale(fcu, scale);
485 }
486
487 fcurve_is_used(fcu);
488 }
489 }
490
unused_fcurve(std::vector<FCurve * > * curves)491 void AnimationImporter::unused_fcurve(std::vector<FCurve *> *curves)
492 {
493 /* when an error happens and we can't actually use curve remove it from unused_curves */
494 std::vector<FCurve *>::iterator it;
495 for (it = curves->begin(); it != curves->end(); it++) {
496 FCurve *fcu = *it;
497 fcurve_is_used(fcu);
498 }
499 }
500
find_frames(std::vector<float> * frames,std::vector<FCurve * > * curves)501 void AnimationImporter::find_frames(std::vector<float> *frames, std::vector<FCurve *> *curves)
502 {
503 std::vector<FCurve *>::iterator iter;
504 for (iter = curves->begin(); iter != curves->end(); iter++) {
505 FCurve *fcu = *iter;
506
507 for (unsigned int k = 0; k < fcu->totvert; k++) {
508 /* get frame value from bezTriple */
509 float fra = fcu->bezt[k].vec[1][0];
510 /* if frame already not added add frame to frames */
511 if (std::find(frames->begin(), frames->end(), fra) == frames->end()) {
512 frames->push_back(fra);
513 }
514 }
515 }
516 }
517
get_animation_axis_index(const COLLADABU::Math::Vector3 & axis)518 static int get_animation_axis_index(const COLLADABU::Math::Vector3 &axis)
519 {
520 int index;
521 if (COLLADABU::Math::Vector3::UNIT_X == axis) {
522 index = 0;
523 }
524 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
525 index = 1;
526 }
527 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
528 index = 2;
529 }
530 else {
531 index = -1;
532 }
533 return index;
534 }
535
536 /* creates the rna_paths and array indices of fcurves from animations using transformation and
537 * bound animation class of each animation. */
Assign_transform_animations(COLLADAFW::Transformation * transform,const COLLADAFW::AnimationList::AnimationBinding * binding,std::vector<FCurve * > * curves,bool is_joint,char * joint_path)538 void AnimationImporter::Assign_transform_animations(
539 COLLADAFW::Transformation *transform,
540 const COLLADAFW::AnimationList::AnimationBinding *binding,
541 std::vector<FCurve *> *curves,
542 bool is_joint,
543 char *joint_path)
544 {
545 COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
546 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
547 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
548
549 /* to check if the no of curves are valid */
550 bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE ||
551 tm_type == COLLADAFW::Transformation::SCALE) &&
552 binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
553
554 if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) {
555 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size());
556 return;
557 }
558
559 char rna_path[100];
560
561 switch (tm_type) {
562 case COLLADAFW::Transformation::TRANSLATE:
563 case COLLADAFW::Transformation::SCALE: {
564 bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE;
565 if (is_joint) {
566 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
567 }
568 else {
569 BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
570 }
571
572 switch (binding->animationClass) {
573 case COLLADAFW::AnimationList::POSITION_X:
574 modify_fcurve(curves, rna_path, 0);
575 break;
576 case COLLADAFW::AnimationList::POSITION_Y:
577 modify_fcurve(curves, rna_path, 1);
578 break;
579 case COLLADAFW::AnimationList::POSITION_Z:
580 modify_fcurve(curves, rna_path, 2);
581 break;
582 case COLLADAFW::AnimationList::POSITION_XYZ:
583 modify_fcurve(curves, rna_path, -1);
584 break;
585 default:
586 unused_fcurve(curves);
587 fprintf(stderr,
588 "AnimationClass %d is not supported for %s.\n",
589 binding->animationClass,
590 loc ? "TRANSLATE" : "SCALE");
591 }
592 break;
593 }
594
595 case COLLADAFW::Transformation::ROTATE: {
596 if (is_joint) {
597 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
598 }
599 else {
600 BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
601 }
602 std::vector<FCurve *>::iterator iter;
603 for (iter = curves->begin(); iter != curves->end(); iter++) {
604 FCurve *fcu = *iter;
605
606 /* if transform is rotation the fcurves values must be turned in to radian. */
607 if (is_rotation) {
608 fcurve_deg_to_rad(fcu);
609 }
610 }
611 COLLADAFW::Rotate *rot = (COLLADAFW::Rotate *)transform;
612 COLLADABU::Math::Vector3 &axis = rot->getRotationAxis();
613
614 switch (binding->animationClass) {
615 case COLLADAFW::AnimationList::ANGLE: {
616 int axis_index = get_animation_axis_index(axis);
617 if (axis_index >= 0) {
618 modify_fcurve(curves, rna_path, axis_index);
619 }
620 else {
621 unused_fcurve(curves);
622 }
623 } break;
624 case COLLADAFW::AnimationList::AXISANGLE:
625 /* TODO convert axis-angle to quat? or XYZ? */
626 default:
627 unused_fcurve(curves);
628 fprintf(stderr,
629 "AnimationClass %d is not supported for ROTATE transformation.\n",
630 binding->animationClass);
631 }
632 break;
633 }
634
635 case COLLADAFW::Transformation::MATRIX:
636 #if 0
637 {
638 COLLADAFW::Matrix *mat = (COLLADAFW::Matrix *)transform;
639 COLLADABU::Math::Matrix4 mat4 = mat->getMatrix();
640 switch (binding->animationClass) {
641 case COLLADAFW::AnimationList::TRANSFORM:
642 }
643 }
644 #endif
645 unused_fcurve(curves);
646 break;
647 case COLLADAFW::Transformation::SKEW:
648 case COLLADAFW::Transformation::LOOKAT:
649 unused_fcurve(curves);
650 fprintf(stderr, "Animation of SKEW and LOOKAT transformations is not supported yet.\n");
651 break;
652 }
653 }
654
655 /* creates the rna_paths and array indices of fcurves from animations using color and bound
656 * animation class of each animation. */
Assign_color_animations(const COLLADAFW::UniqueId & listid,ListBase * AnimCurves,const char * anim_type)657 void AnimationImporter::Assign_color_animations(const COLLADAFW::UniqueId &listid,
658 ListBase *AnimCurves,
659 const char *anim_type)
660 {
661 char rna_path[100];
662 BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
663
664 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
665 if (animlist == NULL) {
666 fprintf(stderr,
667 "Collada: No animlist found for ID: %s of type %s\n",
668 listid.toAscii().c_str(),
669 anim_type);
670 return;
671 }
672
673 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
674 /* all the curves belonging to the current binding */
675 std::vector<FCurve *> animcurves;
676 for (unsigned int j = 0; j < bindings.getCount(); j++) {
677 animcurves = curve_map[bindings[j].animation];
678
679 switch (bindings[j].animationClass) {
680 case COLLADAFW::AnimationList::COLOR_R:
681 modify_fcurve(&animcurves, rna_path, 0);
682 break;
683 case COLLADAFW::AnimationList::COLOR_G:
684 modify_fcurve(&animcurves, rna_path, 1);
685 break;
686 case COLLADAFW::AnimationList::COLOR_B:
687 modify_fcurve(&animcurves, rna_path, 2);
688 break;
689 case COLLADAFW::AnimationList::COLOR_RGB:
690 case COLLADAFW::AnimationList::COLOR_RGBA: /* to do-> set intensity */
691 modify_fcurve(&animcurves, rna_path, -1);
692 break;
693
694 default:
695 unused_fcurve(&animcurves);
696 fprintf(stderr,
697 "AnimationClass %d is not supported for %s.\n",
698 bindings[j].animationClass,
699 "COLOR");
700 }
701
702 std::vector<FCurve *>::iterator iter;
703 /* Add the curves of the current animation to the object */
704 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
705 FCurve *fcu = *iter;
706 BLI_addtail(AnimCurves, fcu);
707 fcurve_is_used(fcu);
708 }
709 }
710 }
711
Assign_float_animations(const COLLADAFW::UniqueId & listid,ListBase * AnimCurves,const char * anim_type)712 void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listid,
713 ListBase *AnimCurves,
714 const char *anim_type)
715 {
716 char rna_path[100];
717 if (animlist_map.find(listid) == animlist_map.end()) {
718 return;
719 }
720
721 /* anim_type has animations */
722 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
723 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
724 /* all the curves belonging to the current binding */
725 std::vector<FCurve *> animcurves;
726 for (unsigned int j = 0; j < bindings.getCount(); j++) {
727 animcurves = curve_map[bindings[j].animation];
728
729 BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
730 modify_fcurve(&animcurves, rna_path, 0);
731 std::vector<FCurve *>::iterator iter;
732 /* Add the curves of the current animation to the object */
733 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
734 FCurve *fcu = *iter;
735 /* All anim_types whose values are to be converted from Degree to Radians can be ORed here
736 */
737 if (STREQ("spot_size", anim_type)) {
738 /* NOTE: Do NOT convert if imported file was made by blender <= 2.69.10
739 * Reason: old blender versions stored spot_size in radians (was a bug)
740 */
741 if (this->import_from_version.empty() ||
742 BLI_strcasecmp_natural(this->import_from_version.c_str(), "2.69.10") != -1) {
743 fcurve_deg_to_rad(fcu);
744 }
745 }
746 /** XXX What About animtype "rotation" ? */
747
748 BLI_addtail(AnimCurves, fcu);
749 fcurve_is_used(fcu);
750 }
751 }
752 }
753
convert_to_focal_length(float in_xfov,int fov_type,float aspect,float sensorx)754 float AnimationImporter::convert_to_focal_length(float in_xfov,
755 int fov_type,
756 float aspect,
757 float sensorx)
758 {
759 /* NOTE: Needs more testing (As we currently have no official test data for this) */
760 float xfov = (fov_type == CAMERA_YFOV) ?
761 (2.0f * atanf(aspect * tanf(DEG2RADF(in_xfov) * 0.5f))) :
762 DEG2RADF(in_xfov);
763 return fov_to_focallength(xfov, sensorx);
764 }
765
766 /*
767 * Lens animations must be stored in COLLADA by using FOV,
768 * while blender internally uses focal length.
769 * The imported animation curves must be converted appropriately.
770 */
Assign_lens_animations(const COLLADAFW::UniqueId & listid,ListBase * AnimCurves,const double aspect,Camera * cam,const char * anim_type,int fov_type)771 void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId &listid,
772 ListBase *AnimCurves,
773 const double aspect,
774 Camera *cam,
775 const char *anim_type,
776 int fov_type)
777 {
778 char rna_path[100];
779 if (animlist_map.find(listid) == animlist_map.end()) {
780 return;
781 }
782
783 /* anim_type has animations */
784 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
785 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
786 /* all the curves belonging to the current binding */
787 std::vector<FCurve *> animcurves;
788 for (unsigned int j = 0; j < bindings.getCount(); j++) {
789 animcurves = curve_map[bindings[j].animation];
790
791 BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
792
793 modify_fcurve(&animcurves, rna_path, 0);
794 std::vector<FCurve *>::iterator iter;
795 /* Add the curves of the current animation to the object */
796 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
797 FCurve *fcu = *iter;
798
799 for (unsigned int i = 0; i < fcu->totvert; i++) {
800 fcu->bezt[i].vec[0][1] = convert_to_focal_length(
801 fcu->bezt[i].vec[0][1], fov_type, aspect, cam->sensor_x);
802 fcu->bezt[i].vec[1][1] = convert_to_focal_length(
803 fcu->bezt[i].vec[1][1], fov_type, aspect, cam->sensor_x);
804 fcu->bezt[i].vec[2][1] = convert_to_focal_length(
805 fcu->bezt[i].vec[2][1], fov_type, aspect, cam->sensor_x);
806 }
807
808 BLI_addtail(AnimCurves, fcu);
809 fcurve_is_used(fcu);
810 }
811 }
812 }
813
apply_matrix_curves(Object * ob,std::vector<FCurve * > & animcurves,COLLADAFW::Node * root,COLLADAFW::Node * node,COLLADAFW::Transformation * tm)814 void AnimationImporter::apply_matrix_curves(Object *ob,
815 std::vector<FCurve *> &animcurves,
816 COLLADAFW::Node *root,
817 COLLADAFW::Node *node,
818 COLLADAFW::Transformation *tm)
819 {
820 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
821 const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
822 char joint_path[200];
823 if (is_joint) {
824 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
825 }
826
827 std::vector<float> frames;
828 find_frames(&frames, &animcurves);
829
830 float irest_dae[4][4];
831 float rest[4][4], irest[4][4];
832
833 if (is_joint) {
834 get_joint_rest_mat(irest_dae, root, node);
835 invert_m4(irest_dae);
836
837 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
838 if (!bone) {
839 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
840 return;
841 }
842
843 unit_m4(rest);
844 copy_m4_m4(rest, bone->arm_mat);
845 invert_m4_m4(irest, rest);
846 }
847 /* new curves to assign matrix transform animation */
848 FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale */
849 unsigned int totcu = 10;
850 const char *tm_str = NULL;
851 char rna_path[200];
852 for (int i = 0; i < totcu; i++) {
853
854 int axis = i;
855
856 if (i < 4) {
857 tm_str = "rotation_quaternion";
858 axis = i;
859 }
860 else if (i < 7) {
861 tm_str = "location";
862 axis = i - 4;
863 }
864 else {
865 tm_str = "scale";
866 axis = i - 7;
867 }
868
869 if (is_joint) {
870 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
871 }
872 else {
873 BLI_strncpy(rna_path, tm_str, sizeof(rna_path));
874 }
875 newcu[i] = create_fcurve(axis, rna_path);
876 newcu[i]->totvert = frames.size();
877 }
878
879 if (frames.empty()) {
880 return;
881 }
882
883 std::sort(frames.begin(), frames.end());
884
885 std::vector<float>::iterator it;
886
887 #if 0
888 float qref[4];
889 unit_qt(qref);
890 #endif
891
892 /* sample values at each frame */
893 for (it = frames.begin(); it != frames.end(); it++) {
894 float fra = *it;
895
896 float mat[4][4];
897 float matfra[4][4];
898
899 unit_m4(matfra);
900
901 /* calc object-space mat */
902 evaluate_transform_at_frame(matfra, node, fra);
903
904 /* for joints, we need a special matrix */
905 if (is_joint) {
906 /* special matrix: iR * M * iR_dae * R
907 * where R, iR are bone rest and inverse rest mats in world space (Blender bones),
908 * iR_dae is joint inverse rest matrix (DAE)
909 * and M is an evaluated joint world-space matrix (DAE) */
910 float temp[4][4], par[4][4];
911
912 /* calc M */
913 calc_joint_parent_mat_rest(par, NULL, root, node);
914 mul_m4_m4m4(temp, par, matfra);
915
916 #if 0
917 evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
918 #endif
919
920 /* calc special matrix */
921 mul_m4_series(mat, irest, temp, irest_dae, rest);
922 }
923 else {
924 copy_m4_m4(mat, matfra);
925 }
926
927 float rot[4], loc[3], scale[3];
928 mat4_decompose(loc, rot, scale, mat);
929
930 /* add keys */
931 for (int i = 0; i < totcu; i++) {
932 if (i < 4) {
933 add_bezt(newcu[i], fra, rot[i]);
934 }
935 else if (i < 7) {
936 add_bezt(newcu[i], fra, loc[i - 4]);
937 }
938 else {
939 add_bezt(newcu[i], fra, scale[i - 7]);
940 }
941 }
942 }
943 Main *bmain = CTX_data_main(mContext);
944 ED_id_action_ensure(bmain, (ID *)&ob->id);
945
946 ListBase *curves = &ob->adt->action->curves;
947
948 /* add curves */
949 for (int i = 0; i < totcu; i++) {
950 if (is_joint) {
951 add_bone_fcurve(ob, node, newcu[i]);
952 }
953 else {
954 BLI_addtail(curves, newcu[i]);
955 }
956 #if 0
957 fcurve_is_used(newcu[i]); /* never added to unused */
958 #endif
959 }
960
961 if (is_joint) {
962 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
963 chan->rotmode = ROT_MODE_QUAT;
964 }
965 else {
966 ob->rotmode = ROT_MODE_QUAT;
967 }
968 }
969
970 /*
971 * This function returns the aspect ration from the Collada camera.
972 *
973 * Note:COLLADA allows to specify either XFov, or YFov alone.
974 * In that case the aspect ratio can be determined from
975 * the viewport aspect ratio (which is 1:1 ?)
976 * XXX: check this: its probably wrong!
977 * If both values are specified, then the aspect ration is simply xfov/yfov
978 * and if aspect ratio is defined, then .. well then its that one.
979 */
get_aspect_ratio(const COLLADAFW::Camera * camera)980 static double get_aspect_ratio(const COLLADAFW::Camera *camera)
981 {
982 double aspect = camera->getAspectRatio().getValue();
983
984 if (aspect == 0) {
985 const double yfov = camera->getYFov().getValue();
986
987 if (yfov == 0) {
988 aspect = 1; /* assume yfov and xfov are equal */
989 }
990 else {
991 const double xfov = camera->getXFov().getValue();
992 if (xfov == 0) {
993 aspect = 1;
994 }
995 else {
996 aspect = xfov / yfov;
997 }
998 }
999 }
1000 return aspect;
1001 }
1002
get_animation_curves(Main * bmain,Material * ma)1003 static ListBase &get_animation_curves(Main *bmain, Material *ma)
1004 {
1005 bAction *act;
1006 if (!ma->adt || !ma->adt->action) {
1007 act = ED_id_action_ensure(bmain, (ID *)&ma->id);
1008 }
1009 else {
1010 act = ma->adt->action;
1011 }
1012
1013 return act->curves;
1014 }
1015
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)1016 void AnimationImporter::translate_Animations(
1017 COLLADAFW::Node *node,
1018 std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map,
1019 std::multimap<COLLADAFW::UniqueId, Object *> &object_map,
1020 std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map,
1021 std::map<COLLADAFW::UniqueId, Material *> uid_material_map)
1022 {
1023 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
1024 COLLADAFW::UniqueId uid = node->getUniqueId();
1025 COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid];
1026
1027 Object *ob;
1028 if (is_joint) {
1029 ob = armature_importer->get_armature_for_joint(root);
1030 }
1031 else {
1032 ob = object_map.find(uid) == object_map.end() ? NULL : object_map.find(uid)->second;
1033 }
1034
1035 if (!ob) {
1036 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
1037 return;
1038 }
1039
1040 AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
1041 bAction *act;
1042 Main *bmain = CTX_data_main(mContext);
1043
1044 if ((animType->transform) != 0) {
1045 /* const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; */ /* UNUSED */
1046 char joint_path[200];
1047
1048 if (is_joint) {
1049 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
1050 }
1051
1052 if (!ob->adt || !ob->adt->action) {
1053 act = ED_id_action_ensure(bmain, (ID *)&ob->id);
1054 }
1055 else {
1056 act = ob->adt->action;
1057 }
1058
1059 /* Get the list of animation curves of the object */
1060 ListBase *AnimCurves = &(act->curves);
1061
1062 const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations();
1063
1064 /* for each transformation in node */
1065 for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
1066 COLLADAFW::Transformation *transform = nodeTransforms[i];
1067 COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
1068
1069 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
1070 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
1071
1072 const COLLADAFW::UniqueId &listid = transform->getAnimationList();
1073
1074 /* check if transformation has animations */
1075 if (animlist_map.find(listid) == animlist_map.end()) {
1076 continue;
1077 }
1078
1079 /* transformation has animations */
1080 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1081 const COLLADAFW::AnimationList::AnimationBindings &bindings =
1082 animlist->getAnimationBindings();
1083 /* all the curves belonging to the current binding */
1084 std::vector<FCurve *> animcurves;
1085 for (unsigned int j = 0; j < bindings.getCount(); j++) {
1086 animcurves = curve_map[bindings[j].animation];
1087 if (is_matrix) {
1088 apply_matrix_curves(ob, animcurves, root, node, transform);
1089 }
1090 else {
1091 /* calculate rnapaths and array index of fcurves according to transformation and
1092 * animation class */
1093 Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path);
1094
1095 std::vector<FCurve *>::iterator iter;
1096 /* Add the curves of the current animation to the object */
1097 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
1098 FCurve *fcu = *iter;
1099
1100 BLI_addtail(AnimCurves, fcu);
1101 fcurve_is_used(fcu);
1102 }
1103 }
1104 }
1105
1106 if (is_rotation && !(is_joint || is_matrix)) {
1107 ob->rotmode = ROT_MODE_EUL;
1108 }
1109 }
1110 }
1111
1112 if ((animType->light) != 0) {
1113 Light *lamp = (Light *)ob->data;
1114 if (!lamp->adt || !lamp->adt->action) {
1115 act = ED_id_action_ensure(bmain, (ID *)&lamp->id);
1116 }
1117 else {
1118 act = lamp->adt->action;
1119 }
1120
1121 ListBase *AnimCurves = &(act->curves);
1122 const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights();
1123
1124 for (unsigned int i = 0; i < nodeLights.getCount(); i++) {
1125 const COLLADAFW::Light *light = (COLLADAFW::Light *)
1126 FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
1127
1128 if ((animType->light & LIGHT_COLOR) != 0) {
1129 const COLLADAFW::Color *col = &(light->getColor());
1130 const COLLADAFW::UniqueId &listid = col->getAnimationList();
1131
1132 Assign_color_animations(listid, AnimCurves, "color");
1133 }
1134 if ((animType->light & LIGHT_FOA) != 0) {
1135 const COLLADAFW::AnimatableFloat *foa = &(light->getFallOffAngle());
1136 const COLLADAFW::UniqueId &listid = foa->getAnimationList();
1137
1138 Assign_float_animations(listid, AnimCurves, "spot_size");
1139 }
1140 if ((animType->light & LIGHT_FOE) != 0) {
1141 const COLLADAFW::AnimatableFloat *foe = &(light->getFallOffExponent());
1142 const COLLADAFW::UniqueId &listid = foe->getAnimationList();
1143
1144 Assign_float_animations(listid, AnimCurves, "spot_blend");
1145 }
1146 }
1147 }
1148
1149 if (animType->camera != 0) {
1150
1151 Camera *cam = (Camera *)ob->data;
1152 if (!cam->adt || !cam->adt->action) {
1153 act = ED_id_action_ensure(bmain, (ID *)&cam->id);
1154 }
1155 else {
1156 act = cam->adt->action;
1157 }
1158
1159 ListBase *AnimCurves = &(act->curves);
1160 const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras();
1161
1162 for (unsigned int i = 0; i < nodeCameras.getCount(); i++) {
1163 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *)
1164 FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
1165
1166 if ((animType->camera & CAMERA_XFOV) != 0) {
1167 const COLLADAFW::AnimatableFloat *xfov = &(camera->getXFov());
1168 const COLLADAFW::UniqueId &listid = xfov->getAnimationList();
1169 double aspect = get_aspect_ratio(camera);
1170 Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_XFOV);
1171 }
1172
1173 else if ((animType->camera & CAMERA_YFOV) != 0) {
1174 const COLLADAFW::AnimatableFloat *yfov = &(camera->getYFov());
1175 const COLLADAFW::UniqueId &listid = yfov->getAnimationList();
1176 double aspect = get_aspect_ratio(camera);
1177 Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_YFOV);
1178 }
1179
1180 else if ((animType->camera & CAMERA_XMAG) != 0) {
1181 const COLLADAFW::AnimatableFloat *xmag = &(camera->getXMag());
1182 const COLLADAFW::UniqueId &listid = xmag->getAnimationList();
1183 Assign_float_animations(listid, AnimCurves, "ortho_scale");
1184 }
1185
1186 else if ((animType->camera & CAMERA_YMAG) != 0) {
1187 const COLLADAFW::AnimatableFloat *ymag = &(camera->getYMag());
1188 const COLLADAFW::UniqueId &listid = ymag->getAnimationList();
1189 Assign_float_animations(listid, AnimCurves, "ortho_scale");
1190 }
1191
1192 if ((animType->camera & CAMERA_ZFAR) != 0) {
1193 const COLLADAFW::AnimatableFloat *zfar = &(camera->getFarClippingPlane());
1194 const COLLADAFW::UniqueId &listid = zfar->getAnimationList();
1195 Assign_float_animations(listid, AnimCurves, "clip_end");
1196 }
1197
1198 if ((animType->camera & CAMERA_ZNEAR) != 0) {
1199 const COLLADAFW::AnimatableFloat *znear = &(camera->getNearClippingPlane());
1200 const COLLADAFW::UniqueId &listid = znear->getAnimationList();
1201 Assign_float_animations(listid, AnimCurves, "clip_start");
1202 }
1203 }
1204 }
1205 if (animType->material != 0) {
1206
1207 Material *ma = BKE_object_material_get(ob, 1);
1208 if (!ma->adt || !ma->adt->action) {
1209 act = ED_id_action_ensure(bmain, (ID *)&ma->id);
1210 }
1211 else {
1212 act = ma->adt->action;
1213 }
1214
1215 const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries();
1216 for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) {
1217 const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings();
1218 for (unsigned int j = 0; j < matBinds.getCount(); j++) {
1219 const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial();
1220 const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]);
1221 if (ef != NULL) { /* can be NULL T28909. */
1222 Material *ma = uid_material_map[matuid];
1223 if (!ma) {
1224 fprintf(stderr,
1225 "Collada: Node %s refers to undefined material\n",
1226 node->getName().c_str());
1227 continue;
1228 }
1229 ListBase &AnimCurves = get_animation_curves(bmain, ma);
1230 const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects();
1231 COLLADAFW::EffectCommon *efc = commonEffects[0];
1232 if ((animType->material & MATERIAL_SHININESS) != 0) {
1233 const COLLADAFW::FloatOrParam *shin = &(efc->getShininess());
1234 const COLLADAFW::UniqueId &listid = shin->getAnimationList();
1235 Assign_float_animations(listid, &AnimCurves, "specular_hardness");
1236 }
1237
1238 if ((animType->material & MATERIAL_IOR) != 0) {
1239 const COLLADAFW::FloatOrParam *ior = &(efc->getIndexOfRefraction());
1240 const COLLADAFW::UniqueId &listid = ior->getAnimationList();
1241 Assign_float_animations(listid, &AnimCurves, "raytrace_transparency.ior");
1242 }
1243
1244 if ((animType->material & MATERIAL_SPEC_COLOR) != 0) {
1245 const COLLADAFW::ColorOrTexture *cot = &(efc->getSpecular());
1246 const COLLADAFW::UniqueId &listid = cot->getColor().getAnimationList();
1247 Assign_color_animations(listid, &AnimCurves, "specular_color");
1248 }
1249
1250 if ((animType->material & MATERIAL_DIFF_COLOR) != 0) {
1251 const COLLADAFW::ColorOrTexture *cot = &(efc->getDiffuse());
1252 const COLLADAFW::UniqueId &listid = cot->getColor().getAnimationList();
1253 Assign_color_animations(listid, &AnimCurves, "diffuse_color");
1254 }
1255 }
1256 }
1257 }
1258 }
1259
1260 delete animType;
1261 }
1262
add_bone_animation_sampled(Object * ob,std::vector<FCurve * > & animcurves,COLLADAFW::Node * root,COLLADAFW::Node * node,COLLADAFW::Transformation * tm)1263 void AnimationImporter::add_bone_animation_sampled(Object *ob,
1264 std::vector<FCurve *> &animcurves,
1265 COLLADAFW::Node *root,
1266 COLLADAFW::Node *node,
1267 COLLADAFW::Transformation *tm)
1268 {
1269 const char *bone_name = bc_get_joint_name(node);
1270 char joint_path[200];
1271 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
1272
1273 std::vector<float> frames;
1274 find_frames(&frames, &animcurves);
1275
1276 /* convert degrees to radians */
1277 if (tm->getTransformationType() == COLLADAFW::Transformation::ROTATE) {
1278
1279 std::vector<FCurve *>::iterator iter;
1280 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
1281 FCurve *fcu = *iter;
1282
1283 fcurve_deg_to_rad(fcu);
1284 }
1285 }
1286
1287 float irest_dae[4][4];
1288 float rest[4][4], irest[4][4];
1289
1290 get_joint_rest_mat(irest_dae, root, node);
1291 invert_m4(irest_dae);
1292
1293 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
1294 if (!bone) {
1295 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
1296 return;
1297 }
1298
1299 unit_m4(rest);
1300 copy_m4_m4(rest, bone->arm_mat);
1301 invert_m4_m4(irest, rest);
1302
1303 /* new curves to assign matrix transform animation */
1304 FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale. */
1305 unsigned int totcu = 10;
1306 const char *tm_str = NULL;
1307 char rna_path[200];
1308 for (int i = 0; i < totcu; i++) {
1309
1310 int axis = i;
1311
1312 if (i < 4) {
1313 tm_str = "rotation_quaternion";
1314 axis = i;
1315 }
1316 else if (i < 7) {
1317 tm_str = "location";
1318 axis = i - 4;
1319 }
1320 else {
1321 tm_str = "scale";
1322 axis = i - 7;
1323 }
1324
1325 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
1326
1327 newcu[i] = create_fcurve(axis, rna_path);
1328 newcu[i]->totvert = frames.size();
1329 }
1330
1331 if (frames.empty()) {
1332 return;
1333 }
1334
1335 std::sort(frames.begin(), frames.end());
1336
1337 BCQuat qref;
1338
1339 std::vector<float>::iterator it;
1340
1341 /* sample values at each frame */
1342 for (it = frames.begin(); it != frames.end(); it++) {
1343 float fra = *it;
1344
1345 Matrix mat;
1346 Matrix matfra;
1347
1348 unit_m4(matfra);
1349
1350 /* calc object-space mat */
1351 evaluate_transform_at_frame(matfra, node, fra);
1352
1353 /* for joints, we need a special matrix
1354 * special matrix: iR * M * iR_dae * R
1355 * where R, iR are bone rest and inverse rest mats in world space (Blender bones),
1356 * iR_dae is joint inverse rest matrix (DAE)
1357 * and M is an evaluated joint world-space matrix (DAE). */
1358 Matrix temp, par;
1359
1360 /* calc M */
1361 calc_joint_parent_mat_rest(par, NULL, root, node);
1362 mul_m4_m4m4(temp, par, matfra);
1363
1364 /* evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); */
1365
1366 /* calc special matrix */
1367 mul_m4_series(mat, irest, temp, irest_dae, rest);
1368
1369 Vector loc, scale;
1370
1371 qref.rotate_to(mat);
1372
1373 copy_v3_v3(loc, mat[3]);
1374 mat4_to_size(scale, mat);
1375
1376 /* add keys */
1377 for (int i = 0; i < totcu; i++) {
1378 if (i < 4) {
1379 add_bezt(newcu[i], fra, qref.quat()[i]);
1380 }
1381 else if (i < 7) {
1382 add_bezt(newcu[i], fra, loc[i - 4]);
1383 }
1384 else {
1385 add_bezt(newcu[i], fra, scale[i - 7]);
1386 }
1387 }
1388 }
1389 Main *bmain = CTX_data_main(mContext);
1390 ED_id_action_ensure(bmain, (ID *)&ob->id);
1391
1392 /* add curves */
1393 for (int i = 0; i < totcu; i++) {
1394 add_bone_fcurve(ob, node, newcu[i]);
1395 #if 0
1396 fcurve_is_used(newcu[i]); /* never added to unused */
1397 #endif
1398 }
1399
1400 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
1401 chan->rotmode = ROT_MODE_QUAT;
1402 }
1403
1404 /* Check if object is animated by checking if animlist_map
1405 * holds the animlist_id of node transforms */
get_animation_type(const COLLADAFW::Node * node,std::map<COLLADAFW::UniqueId,const COLLADAFW::Object * > FW_object_map)1406 AnimationImporter::AnimMix *AnimationImporter::get_animation_type(
1407 const COLLADAFW::Node *node,
1408 std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
1409 {
1410 AnimMix *types = new AnimMix();
1411
1412 const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations();
1413
1414 /* for each transformation in node */
1415 for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
1416 COLLADAFW::Transformation *transform = nodeTransforms[i];
1417 const COLLADAFW::UniqueId &listid = transform->getAnimationList();
1418
1419 /* check if transformation has animations */
1420 if (animlist_map.find(listid) == animlist_map.end()) {
1421 continue;
1422 }
1423
1424 types->transform = types->transform | BC_NODE_TRANSFORM;
1425 break;
1426 }
1427 const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights();
1428
1429 for (unsigned int i = 0; i < nodeLights.getCount(); i++) {
1430 const COLLADAFW::Light *light = (COLLADAFW::Light *)
1431 FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
1432 types->light = setAnimType(&(light->getColor()), (types->light), LIGHT_COLOR);
1433 types->light = setAnimType(&(light->getFallOffAngle()), (types->light), LIGHT_FOA);
1434 types->light = setAnimType(&(light->getFallOffExponent()), (types->light), LIGHT_FOE);
1435
1436 if (types->light != 0) {
1437 break;
1438 }
1439 }
1440
1441 const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras();
1442 for (unsigned int i = 0; i < nodeCameras.getCount(); i++) {
1443 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *)
1444 FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
1445 if (camera == NULL) {
1446 /* Can happen if the node refers to an unknown camera. */
1447 continue;
1448 }
1449
1450 const bool is_perspective_type = camera->getCameraType() == COLLADAFW::Camera::PERSPECTIVE;
1451
1452 int addition;
1453 const COLLADAFW::Animatable *mag;
1454 const COLLADAFW::UniqueId listid = camera->getYMag().getAnimationList();
1455 if (animlist_map.find(listid) != animlist_map.end()) {
1456 mag = &(camera->getYMag());
1457 addition = (is_perspective_type) ? CAMERA_YFOV : CAMERA_YMAG;
1458 }
1459 else {
1460 mag = &(camera->getXMag());
1461 addition = (is_perspective_type) ? CAMERA_XFOV : CAMERA_XMAG;
1462 }
1463 types->camera = setAnimType(mag, (types->camera), addition);
1464
1465 types->camera = setAnimType(&(camera->getFarClippingPlane()), (types->camera), CAMERA_ZFAR);
1466 types->camera = setAnimType(&(camera->getNearClippingPlane()), (types->camera), CAMERA_ZNEAR);
1467
1468 if (types->camera != 0) {
1469 break;
1470 }
1471 }
1472
1473 const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries();
1474 for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) {
1475 const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings();
1476 for (unsigned int j = 0; j < matBinds.getCount(); j++) {
1477 const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial();
1478 const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]);
1479 if (ef != NULL) { /* can be NULL T28909. */
1480 const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects();
1481 if (!commonEffects.empty()) {
1482 COLLADAFW::EffectCommon *efc = commonEffects[0];
1483 types->material = setAnimType(
1484 &(efc->getShininess()), (types->material), MATERIAL_SHININESS);
1485 types->material = setAnimType(
1486 &(efc->getSpecular().getColor()), (types->material), MATERIAL_SPEC_COLOR);
1487 types->material = setAnimType(
1488 &(efc->getDiffuse().getColor()), (types->material), MATERIAL_DIFF_COLOR);
1489 #if 0
1490 types->material = setAnimType(&(efc->get()), (types->material), MATERIAL_TRANSPARENCY);
1491 #endif
1492 types->material = setAnimType(
1493 &(efc->getIndexOfRefraction()), (types->material), MATERIAL_IOR);
1494 }
1495 }
1496 }
1497 }
1498 return types;
1499 }
1500
setAnimType(const COLLADAFW::Animatable * prop,int types,int addition)1501 int AnimationImporter::setAnimType(const COLLADAFW::Animatable *prop, int types, int addition)
1502 {
1503 int anim_type;
1504 const COLLADAFW::UniqueId &listid = prop->getAnimationList();
1505 if (animlist_map.find(listid) != animlist_map.end()) {
1506 anim_type = types | addition;
1507 }
1508 else {
1509 anim_type = types;
1510 }
1511
1512 return anim_type;
1513 }
1514
1515 /* Is not used anymore. */
find_frames_old(std::vector<float> * frames,COLLADAFW::Node * node,COLLADAFW::Transformation::TransformationType tm_type)1516 void AnimationImporter::find_frames_old(std::vector<float> *frames,
1517 COLLADAFW::Node *node,
1518 COLLADAFW::Transformation::TransformationType tm_type)
1519 {
1520 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
1521 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
1522 /* for each <rotate>, <translate>, etc. there is a separate Transformation */
1523 const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations();
1524
1525 unsigned int i;
1526 /* find frames at which to sample plus convert all rotation keys to radians */
1527 for (i = 0; i < nodeTransforms.getCount(); i++) {
1528 COLLADAFW::Transformation *transform = nodeTransforms[i];
1529 COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType();
1530
1531 if (nodeTmType == tm_type) {
1532 /* get animation bindings for the current transformation */
1533 const COLLADAFW::UniqueId &listid = transform->getAnimationList();
1534 /* if transform is animated its animlist must exist. */
1535 if (animlist_map.find(listid) != animlist_map.end()) {
1536
1537 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1538 const COLLADAFW::AnimationList::AnimationBindings &bindings =
1539 animlist->getAnimationBindings();
1540
1541 if (bindings.getCount()) {
1542 /* for each AnimationBinding get the fcurves which animate the transform */
1543 for (unsigned int j = 0; j < bindings.getCount(); j++) {
1544 std::vector<FCurve *> &curves = curve_map[bindings[j].animation];
1545 bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE ||
1546 nodeTmType == COLLADAFW::Transformation::SCALE) &&
1547 bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
1548
1549 if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) {
1550 std::vector<FCurve *>::iterator iter;
1551
1552 for (iter = curves.begin(); iter != curves.end(); iter++) {
1553 FCurve *fcu = *iter;
1554
1555 /* if transform is rotation the fcurves values must be turned in to radian. */
1556 if (is_rotation) {
1557 fcurve_deg_to_rad(fcu);
1558 }
1559
1560 for (unsigned int k = 0; k < fcu->totvert; k++) {
1561 /* get frame value from bezTriple */
1562 float fra = fcu->bezt[k].vec[1][0];
1563 /* if frame already not added add frame to frames */
1564 if (std::find(frames->begin(), frames->end(), fra) == frames->end()) {
1565 frames->push_back(fra);
1566 }
1567 }
1568 }
1569 }
1570 else {
1571 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size());
1572 }
1573 }
1574 }
1575 }
1576 }
1577 }
1578 }
1579
1580 /* prerequisites:
1581 * animlist_map - map animlist id -> animlist
1582 * curve_map - map anim id -> curve(s) */
translate_animation_OLD(COLLADAFW::Node * node,std::map<COLLADAFW::UniqueId,Object * > & object_map,std::map<COLLADAFW::UniqueId,COLLADAFW::Node * > & root_map,COLLADAFW::Transformation::TransformationType tm_type,Object * par_job)1583 Object *AnimationImporter::translate_animation_OLD(
1584 COLLADAFW::Node *node,
1585 std::map<COLLADAFW::UniqueId, Object *> &object_map,
1586 std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &root_map,
1587 COLLADAFW::Transformation::TransformationType tm_type,
1588 Object *par_job)
1589 {
1590
1591 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
1592 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
1593 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
1594
1595 COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ?
1596 node :
1597 root_map[node->getUniqueId()];
1598 Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) :
1599 object_map[node->getUniqueId()];
1600 const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
1601 if (!ob) {
1602 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
1603 return NULL;
1604 }
1605
1606 /* frames at which to sample */
1607 std::vector<float> frames;
1608
1609 find_frames_old(&frames, node, tm_type);
1610
1611 unsigned int i;
1612
1613 float irest_dae[4][4];
1614 float rest[4][4], irest[4][4];
1615
1616 if (is_joint) {
1617 get_joint_rest_mat(irest_dae, root, node);
1618 invert_m4(irest_dae);
1619
1620 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
1621 if (!bone) {
1622 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
1623 return NULL;
1624 }
1625
1626 unit_m4(rest);
1627 copy_m4_m4(rest, bone->arm_mat);
1628 invert_m4_m4(irest, rest);
1629 }
1630
1631 Object *job = NULL;
1632
1633 #ifdef ARMATURE_TEST
1634 FCurve *job_curves[10];
1635 job = get_joint_object(root, node, par_job);
1636 #endif
1637
1638 if (frames.empty()) {
1639 return job;
1640 }
1641
1642 std::sort(frames.begin(), frames.end());
1643
1644 const char *tm_str = NULL;
1645 switch (tm_type) {
1646 case COLLADAFW::Transformation::ROTATE:
1647 tm_str = "rotation_quaternion";
1648 break;
1649 case COLLADAFW::Transformation::SCALE:
1650 tm_str = "scale";
1651 break;
1652 case COLLADAFW::Transformation::TRANSLATE:
1653 tm_str = "location";
1654 break;
1655 case COLLADAFW::Transformation::MATRIX:
1656 break;
1657 default:
1658 return job;
1659 }
1660
1661 char rna_path[200];
1662 char joint_path[200];
1663
1664 if (is_joint) {
1665 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
1666 }
1667
1668 /* new curves */
1669 FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale */
1670 unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3);
1671
1672 for (i = 0; i < totcu; i++) {
1673
1674 int axis = i;
1675
1676 if (is_matrix) {
1677 if (i < 4) {
1678 tm_str = "rotation_quaternion";
1679 axis = i;
1680 }
1681 else if (i < 7) {
1682 tm_str = "location";
1683 axis = i - 4;
1684 }
1685 else {
1686 tm_str = "scale";
1687 axis = i - 7;
1688 }
1689 }
1690
1691 if (is_joint) {
1692 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
1693 }
1694 else {
1695 BLI_strncpy(rna_path, tm_str, sizeof(rna_path));
1696 }
1697 newcu[i] = create_fcurve(axis, rna_path);
1698
1699 #ifdef ARMATURE_TEST
1700 if (is_joint) {
1701 job_curves[i] = create_fcurve(axis, tm_str);
1702 }
1703 #endif
1704 }
1705
1706 std::vector<float>::iterator it;
1707
1708 /* sample values at each frame */
1709 for (it = frames.begin(); it != frames.end(); it++) {
1710 float fra = *it;
1711
1712 float mat[4][4];
1713 float matfra[4][4];
1714
1715 unit_m4(matfra);
1716
1717 /* calc object-space mat */
1718 evaluate_transform_at_frame(matfra, node, fra);
1719
1720 /* for joints, we need a special matrix */
1721 if (is_joint) {
1722 /* special matrix: iR * M * iR_dae * R
1723 * where R, iR are bone rest and inverse rest mats in world space (Blender bones),
1724 * iR_dae is joint inverse rest matrix (DAE)
1725 * and M is an evaluated joint world-space matrix (DAE). */
1726 float temp[4][4], par[4][4];
1727
1728 /* calc M */
1729 calc_joint_parent_mat_rest(par, NULL, root, node);
1730 mul_m4_m4m4(temp, par, matfra);
1731
1732 /* evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); */
1733
1734 /* calc special matrix */
1735 mul_m4_series(mat, irest, temp, irest_dae, rest);
1736 }
1737 else {
1738 copy_m4_m4(mat, matfra);
1739 }
1740
1741 float val[4] = {};
1742 float rot[4], loc[3], scale[3];
1743
1744 switch (tm_type) {
1745 case COLLADAFW::Transformation::ROTATE:
1746 mat4_to_quat(val, mat);
1747 break;
1748 case COLLADAFW::Transformation::SCALE:
1749 mat4_to_size(val, mat);
1750 break;
1751 case COLLADAFW::Transformation::TRANSLATE:
1752 copy_v3_v3(val, mat[3]);
1753 break;
1754 case COLLADAFW::Transformation::MATRIX:
1755 mat4_to_quat(rot, mat);
1756 copy_v3_v3(loc, mat[3]);
1757 mat4_to_size(scale, mat);
1758 break;
1759 default:
1760 break;
1761 }
1762
1763 /* add keys */
1764 for (i = 0; i < totcu; i++) {
1765 if (is_matrix) {
1766 if (i < 4) {
1767 add_bezt(newcu[i], fra, rot[i]);
1768 }
1769 else if (i < 7) {
1770 add_bezt(newcu[i], fra, loc[i - 4]);
1771 }
1772 else {
1773 add_bezt(newcu[i], fra, scale[i - 7]);
1774 }
1775 }
1776 else {
1777 add_bezt(newcu[i], fra, val[i]);
1778 }
1779 }
1780
1781 #ifdef ARMATURE_TEST
1782 if (is_joint) {
1783 switch (tm_type) {
1784 case COLLADAFW::Transformation::ROTATE:
1785 mat4_to_quat(val, matfra);
1786 break;
1787 case COLLADAFW::Transformation::SCALE:
1788 mat4_to_size(val, matfra);
1789 break;
1790 case COLLADAFW::Transformation::TRANSLATE:
1791 copy_v3_v3(val, matfra[3]);
1792 break;
1793 case MATRIX:
1794 mat4_to_quat(rot, matfra);
1795 copy_v3_v3(loc, matfra[3]);
1796 mat4_to_size(scale, matfra);
1797 break;
1798 default:
1799 break;
1800 }
1801
1802 for (i = 0; i < totcu; i++) {
1803 if (is_matrix) {
1804 if (i < 4) {
1805 add_bezt(job_curves[i], fra, rot[i]);
1806 }
1807 else if (i < 7) {
1808 add_bezt(job_curves[i], fra, loc[i - 4]);
1809 }
1810 else {
1811 add_bezt(job_curves[i], fra, scale[i - 7]);
1812 }
1813 }
1814 else {
1815 add_bezt(job_curves[i], fra, val[i]);
1816 }
1817 }
1818 }
1819 #endif
1820 }
1821 Main *bmain = CTX_data_main(mContext);
1822 ED_id_action_ensure(bmain, (ID *)&ob->id);
1823
1824 ListBase *curves = &ob->adt->action->curves;
1825
1826 /* add curves */
1827 for (i = 0; i < totcu; i++) {
1828 if (is_joint) {
1829 add_bone_fcurve(ob, node, newcu[i]);
1830 }
1831 else {
1832 BLI_addtail(curves, newcu[i]);
1833 }
1834
1835 #ifdef ARMATURE_TEST
1836 if (is_joint) {
1837 BLI_addtail(&job->adt->action->curves, job_curves[i]);
1838 }
1839 #endif
1840 }
1841
1842 if (is_rotation || is_matrix) {
1843 if (is_joint) {
1844 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
1845 chan->rotmode = (is_matrix) ? ROT_MODE_QUAT : ROT_MODE_EUL;
1846 }
1847 else {
1848 ob->rotmode = (is_matrix) ? ROT_MODE_QUAT : ROT_MODE_EUL;
1849 }
1850 }
1851
1852 return job;
1853 }
1854
1855 /* internal, better make it private
1856 * warning: evaluates only rotation and only assigns matrix transforms now
1857 * prerequisites: animlist_map, curve_map */
evaluate_transform_at_frame(float mat[4][4],COLLADAFW::Node * node,float fra)1858 void AnimationImporter::evaluate_transform_at_frame(float mat[4][4],
1859 COLLADAFW::Node *node,
1860 float fra)
1861 {
1862 const COLLADAFW::TransformationPointerArray &tms = node->getTransformations();
1863
1864 unit_m4(mat);
1865
1866 for (unsigned int i = 0; i < tms.getCount(); i++) {
1867 COLLADAFW::Transformation *tm = tms[i];
1868 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1869 float m[4][4];
1870
1871 unit_m4(m);
1872
1873 std::string nodename = node->getName().empty() ? node->getOriginalId() : node->getName();
1874 if (!evaluate_animation(tm, m, fra, nodename.c_str())) {
1875 switch (type) {
1876 case COLLADAFW::Transformation::ROTATE:
1877 dae_rotate_to_mat4(tm, m);
1878 break;
1879 case COLLADAFW::Transformation::TRANSLATE:
1880 dae_translate_to_mat4(tm, m);
1881 break;
1882 case COLLADAFW::Transformation::SCALE:
1883 dae_scale_to_mat4(tm, m);
1884 break;
1885 case COLLADAFW::Transformation::MATRIX:
1886 dae_matrix_to_mat4(tm, m);
1887 break;
1888 default:
1889 fprintf(stderr, "unsupported transformation type %d\n", type);
1890 }
1891 }
1892
1893 float temp[4][4];
1894 copy_m4_m4(temp, mat);
1895
1896 mul_m4_m4m4(mat, temp, m);
1897 }
1898 }
1899
report_class_type_unsupported(const char * path,const COLLADAFW::AnimationList::AnimationClass animclass,const COLLADAFW::Transformation::TransformationType type)1900 static void report_class_type_unsupported(const char *path,
1901 const COLLADAFW::AnimationList::AnimationClass animclass,
1902 const COLLADAFW::Transformation::TransformationType type)
1903 {
1904 if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) {
1905 fprintf(stderr, "%s: UNKNOWN animation class\n", path);
1906 }
1907 else {
1908 fprintf(stderr,
1909 "%s: animation class %d is not supported yet for transformation type %d\n",
1910 path,
1911 animclass,
1912 type);
1913 }
1914 }
1915
1916 /* return true to indicate that mat contains a sane value */
evaluate_animation(COLLADAFW::Transformation * tm,float mat[4][4],float fra,const char * node_id)1917 bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm,
1918 float mat[4][4],
1919 float fra,
1920 const char *node_id)
1921 {
1922 const COLLADAFW::UniqueId &listid = tm->getAnimationList();
1923 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1924
1925 if (type != COLLADAFW::Transformation::ROTATE && type != COLLADAFW::Transformation::SCALE &&
1926 type != COLLADAFW::Transformation::TRANSLATE && type != COLLADAFW::Transformation::MATRIX) {
1927 fprintf(stderr, "animation of transformation %d is not supported yet\n", type);
1928 return false;
1929 }
1930
1931 if (animlist_map.find(listid) == animlist_map.end()) {
1932 return false;
1933 }
1934
1935 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1936 const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings();
1937
1938 if (bindings.getCount()) {
1939 float vec[3];
1940
1941 bool is_scale = (type == COLLADAFW::Transformation::SCALE);
1942 bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE);
1943
1944 if (is_scale) {
1945 dae_scale_to_v3(tm, vec);
1946 }
1947 else if (is_translate) {
1948 dae_translate_to_v3(tm, vec);
1949 }
1950
1951 for (unsigned int index = 0; index < bindings.getCount(); index++) {
1952 const COLLADAFW::AnimationList::AnimationBinding &binding = bindings[index];
1953 std::vector<FCurve *> &curves = curve_map[binding.animation];
1954 COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass;
1955 char path[100];
1956
1957 switch (type) {
1958 case COLLADAFW::Transformation::ROTATE:
1959 BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, index);
1960 break;
1961 case COLLADAFW::Transformation::SCALE:
1962 BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, index);
1963 break;
1964 case COLLADAFW::Transformation::TRANSLATE:
1965 BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, index);
1966 break;
1967 case COLLADAFW::Transformation::MATRIX:
1968 BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, index);
1969 break;
1970 default:
1971 break;
1972 }
1973
1974 if (type == COLLADAFW::Transformation::ROTATE) {
1975 if (curves.size() != 1) {
1976 fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size());
1977 return false;
1978 }
1979
1980 /* TODO support other animclasses */
1981 if (animclass != COLLADAFW::AnimationList::ANGLE) {
1982 report_class_type_unsupported(path, animclass, type);
1983 return false;
1984 }
1985
1986 COLLADABU::Math::Vector3 &axis = ((COLLADAFW::Rotate *)tm)->getRotationAxis();
1987
1988 float ax[3] = {(float)axis[0], (float)axis[1], (float)axis[2]};
1989 float angle = evaluate_fcurve(curves[0], fra);
1990 axis_angle_to_mat4(mat, ax, angle);
1991
1992 return true;
1993 }
1994 if (is_scale || is_translate) {
1995 bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ;
1996
1997 if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) {
1998 if (is_xyz) {
1999 fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size());
2000 }
2001 else {
2002 fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size());
2003 }
2004 return false;
2005 }
2006
2007 switch (animclass) {
2008 case COLLADAFW::AnimationList::POSITION_X:
2009 vec[0] = evaluate_fcurve(curves[0], fra);
2010 break;
2011 case COLLADAFW::AnimationList::POSITION_Y:
2012 vec[1] = evaluate_fcurve(curves[0], fra);
2013 break;
2014 case COLLADAFW::AnimationList::POSITION_Z:
2015 vec[2] = evaluate_fcurve(curves[0], fra);
2016 break;
2017 case COLLADAFW::AnimationList::POSITION_XYZ:
2018 vec[0] = evaluate_fcurve(curves[0], fra);
2019 vec[1] = evaluate_fcurve(curves[1], fra);
2020 vec[2] = evaluate_fcurve(curves[2], fra);
2021 break;
2022 default:
2023 report_class_type_unsupported(path, animclass, type);
2024 break;
2025 }
2026 }
2027 else if (type == COLLADAFW::Transformation::MATRIX) {
2028 /* for now, of matrix animation,
2029 * support only the case when all values are packed into one animation */
2030 if (curves.size() != 16) {
2031 fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size());
2032 return false;
2033 }
2034
2035 COLLADABU::Math::Matrix4 matrix;
2036 int mi = 0, mj = 0;
2037
2038 for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) {
2039 matrix.setElement(mi, mj, evaluate_fcurve(*it, fra));
2040 mj++;
2041 if (mj == 4) {
2042 mi++;
2043 mj = 0;
2044 }
2045 }
2046 UnitConverter::dae_matrix_to_mat4_(mat, matrix);
2047 return true;
2048 }
2049 }
2050
2051 if (is_scale) {
2052 size_to_mat4(mat, vec);
2053 }
2054 else {
2055 copy_v3_v3(mat[3], vec);
2056 }
2057
2058 return is_scale || is_translate;
2059 }
2060
2061 return false;
2062 }
2063
2064 /* gives a world-space mat of joint at rest position */
get_joint_rest_mat(float mat[4][4],COLLADAFW::Node * root,COLLADAFW::Node * node)2065 void AnimationImporter::get_joint_rest_mat(float mat[4][4],
2066 COLLADAFW::Node *root,
2067 COLLADAFW::Node *node)
2068 {
2069 /* if bind mat is not available,
2070 * use "current" node transform, i.e. all those tms listed inside <node> */
2071 if (!armature_importer->get_joint_bind_mat(mat, node)) {
2072 float par[4][4], m[4][4];
2073
2074 calc_joint_parent_mat_rest(par, NULL, root, node);
2075 get_node_mat(m, node, NULL, NULL);
2076 mul_m4_m4m4(mat, par, m);
2077 }
2078 }
2079
2080 /* gives a world-space mat, end's mat not included */
calc_joint_parent_mat_rest(float mat[4][4],float par[4][4],COLLADAFW::Node * node,COLLADAFW::Node * end)2081 bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4],
2082 float par[4][4],
2083 COLLADAFW::Node *node,
2084 COLLADAFW::Node *end)
2085 {
2086 float m[4][4];
2087
2088 if (node == end) {
2089 par ? copy_m4_m4(mat, par) : unit_m4(mat);
2090 return true;
2091 }
2092
2093 /* use bind matrix if available or calc "current" world mat */
2094 if (!armature_importer->get_joint_bind_mat(m, node)) {
2095 if (par) {
2096 float temp[4][4];
2097 get_node_mat(temp, node, NULL, NULL);
2098 mul_m4_m4m4(m, par, temp);
2099 }
2100 else {
2101 get_node_mat(m, node, NULL, NULL);
2102 }
2103 }
2104
2105 COLLADAFW::NodePointerArray &children = node->getChildNodes();
2106 for (unsigned int i = 0; i < children.getCount(); i++) {
2107 if (calc_joint_parent_mat_rest(mat, m, children[i], end)) {
2108 return true;
2109 }
2110 }
2111
2112 return false;
2113 }
2114
2115 #ifdef ARMATURE_TEST
get_joint_object(COLLADAFW::Node * root,COLLADAFW::Node * node,Object * par_job)2116 Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root,
2117 COLLADAFW::Node *node,
2118 Object *par_job)
2119 {
2120 if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) {
2121 Object *job = bc_add_object(scene, OB_EMPTY, (char *)get_joint_name(node));
2122
2123 job->lay = BKE_scene_base_find(scene, job)->lay = 2;
2124
2125 mul_v3_fl(job->scale, 0.5f);
2126 DEG_id_tag_update(&job->id, ID_RECALC_TRANSFORM);
2127
2128 ED_id_action_ensure((ID *)&job->id);
2129
2130 job->rotmode = ROT_MODE_QUAT;
2131
2132 float mat[4][4];
2133 get_joint_rest_mat(mat, root, node);
2134
2135 if (par_job) {
2136 float temp[4][4], ipar[4][4];
2137 invert_m4_m4(ipar, par_job->obmat);
2138 copy_m4_m4(temp, mat);
2139 mul_m4_m4m4(mat, ipar, temp);
2140 }
2141
2142 bc_decompose(mat, job->loc, NULL, job->quat, job->scale);
2143
2144 if (par_job) {
2145 job->parent = par_job;
2146
2147 DEG_id_tag_update(&par_job->id, ID_RECALC_TRANSFORM);
2148 job->parsubstr[0] = 0;
2149 }
2150
2151 BKE_object_where_is_calc(scene, job);
2152
2153 /* after parenting and layer change */
2154 DEG_relations_tag_update(CTX_data_main(C));
2155
2156 joint_objects[node->getUniqueId()] = job;
2157 }
2158
2159 return joint_objects[node->getUniqueId()];
2160 }
2161 #endif
2162
2163 #if 0
2164 /* recursively evaluates joint tree until end is found,
2165 * mat then is world-space matrix of end mat must be identity on enter, node must be root. */
2166 bool AnimationImporter::evaluate_joint_world_transform_at_frame(
2167 float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra)
2168 {
2169 float m[4][4];
2170 if (par) {
2171 float temp[4][4];
2172 evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f);
2173 mul_m4_m4m4(m, par, temp);
2174 }
2175 else {
2176 evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f);
2177 }
2178
2179 if (node == end) {
2180 copy_m4_m4(mat, m);
2181 return true;
2182 }
2183 else {
2184 COLLADAFW::NodePointerArray &children = node->getChildNodes();
2185 for (int i = 0; i < children.getCount(); i++) {
2186 if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra)) {
2187 return true;
2188 }
2189 }
2190 }
2191
2192 return false;
2193 }
2194 #endif
2195
add_bone_fcurve(Object * ob,COLLADAFW::Node * node,FCurve * fcu)2196 void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu)
2197 {
2198 const char *bone_name = bc_get_joint_name(node);
2199 bAction *act = ob->adt->action;
2200
2201 /* try to find group */
2202 bActionGroup *grp = BKE_action_group_find_name(act, bone_name);
2203
2204 /* no matching groups, so add one */
2205 if (grp == NULL) {
2206 /* Add a new group, and make it active */
2207 grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
2208
2209 grp->flag = AGRP_SELECTED;
2210 BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
2211
2212 BLI_addtail(&act->groups, grp);
2213 BLI_uniquename(&act->groups,
2214 grp,
2215 CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"),
2216 '.',
2217 offsetof(bActionGroup, name),
2218 64);
2219 }
2220
2221 /* add F-Curve to group */
2222 action_groups_add_channel(act, grp, fcu);
2223 }
2224
set_import_from_version(std::string import_from_version)2225 void AnimationImporter::set_import_from_version(std::string import_from_version)
2226 {
2227 this->import_from_version = import_from_version;
2228 }
2229