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