Fixed Color animation import( support for Maya )
[blender.git] / source / blender / collada / AnimationImporter.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/collada/AnimationImporter.cpp
26  *  \ingroup collada
27  */
28
29 #include <stddef.h>
30
31 /* COLLADABU_ASSERT, may be able to remove later */
32 #include "COLLADABUPlatform.h"
33
34 #include "DNA_armature_types.h"
35
36 #include "ED_keyframing.h"
37
38 #include "BLI_listbase.h"
39 #include "BLI_math.h"
40 #include "BLI_path_util.h"
41 #include "BLI_string.h"
42
43 #include "BKE_action.h"
44 #include "BKE_armature.h"
45 #include "BKE_fcurve.h"
46 #include "BKE_object.h"
47
48 #include "MEM_guardedalloc.h"
49
50 #include "collada_utils.h"
51 #include "AnimationImporter.h"
52 #include "ArmatureImporter.h"
53
54 #include <algorithm>
55
56 // first try node name, if not available (since is optional), fall back to original id
57 template<class T>
58 static const char *bc_get_joint_name(T *node)
59 {
60         const std::string& id = node->getName();
61         return id.size() ? id.c_str() : node->getOriginalId().c_str();
62 }
63
64 FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
65 {
66         FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
67         
68         fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
69         fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
70         fcu->array_index = array_index;
71         return fcu;
72 }
73         
74 void AnimationImporter::create_bezt(FCurve *fcu, float frame, float output)
75 {
76         BezTriple bez;
77         memset(&bez, 0, sizeof(BezTriple));
78         bez.vec[1][0] = frame;
79         bez.vec[1][1] = output;
80         bez.ipo = U.ipo_new; /* use default interpolation mode here... */
81         bez.f1 = bez.f2 = bez.f3 = SELECT;
82         bez.h1 = bez.h2 = HD_AUTO;
83         insert_bezt_fcurve(fcu, &bez, 0);
84         calchandles_fcurve(fcu);
85 }
86
87 // create one or several fcurves depending on the number of parameters being animated
88 void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
89 {
90         COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
91         COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
92    
93         if( curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ) {
94         COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
95     COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
96         }
97         float fps = (float)FPS;
98         size_t dim = curve->getOutDimension();
99         unsigned int i;
100         
101         std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
102
103         switch (dim) {
104         case 1: // X, Y, Z or angle
105         case 3: // XYZ
106         case 4:
107         case 16: // matrix
108                 {
109                         for (i = 0; i < dim; i++ ) {
110                                 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
111                         
112                                 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
113                                 // fcu->rna_path = BLI_strdupn(path, strlen(path));
114                                 fcu->array_index = 0;
115                                 fcu->totvert = curve->getKeyCount();
116                         
117                                 // create beztriple for each key
118                                 for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
119                                         BezTriple bez;
120                                         memset(&bez, 0, sizeof(BezTriple));
121
122                                         
123                                         // input, output
124                                         bez.vec[1][0] = bc_get_float_value(input, j) * fps; 
125                                         bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
126
127
128                                         if( curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ) 
129                                         {
130                                                 COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
131                         COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
132
133                                                 // intangent
134                                                  bez.vec[0][0] = bc_get_float_value(intan, (j * 2 * dim ) + (2 * i)) * fps;
135                                                  bez.vec[0][1] = bc_get_float_value(intan, (j * 2 * dim )+ (2 * i) + 1);
136
137                                                  // outtangent
138                                                  bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim ) + (2 * i)) * fps;
139                                                  bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim )+ (2 * i) + 1);
140                                              bez.ipo = BEZT_IPO_BEZ;
141                                                  //bez.h1 = bez.h2 = HD_AUTO;   
142                                         }
143                                         else 
144                                         {
145                                                 bez.h1 = bez.h2 = HD_AUTO; 
146                                                 bez.ipo = BEZT_IPO_LIN;
147                                         }
148                                         // bez.ipo = U.ipo_new; /* use default interpolation mode here... */
149                                         bez.f1 = bez.f2 = bez.f3 = SELECT;
150                                         
151                                         insert_bezt_fcurve(fcu, &bez, 0);
152                                 }
153
154                                 calchandles_fcurve(fcu);
155
156                                 fcurves.push_back(fcu);
157                         }
158                 }
159                 break;
160         default:
161                 fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", (int)dim, curve->getOriginalId().c_str());
162         }
163
164         for (std::vector<FCurve*>::iterator it = fcurves.begin(); it != fcurves.end(); it++)
165                 unused_curves.push_back(*it);
166 }
167
168
169 void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
170 {
171         for (unsigned int i = 0; i < cu->totvert; i++) {
172                 // TODO convert handles too
173                 cu->bezt[i].vec[1][1] *= M_PI / 180.0f;
174                 cu->bezt[i].vec[0][1] *= M_PI / 180.0f;
175                 cu->bezt[i].vec[2][1] *= M_PI / 180.0f;
176                 cu->bezt[i].vec[1][0];
177         }
178 }
179
180 void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated)
181 {
182         bAction *act;
183         
184         if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1);
185         else act = ob->adt->action;
186         
187         std::vector<FCurve*>::iterator it;
188         int i;
189
190 #if 0
191         char *p = strstr(rna_path, "rotation_euler");
192         bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0';
193
194         // convert degrees to radians for rotation
195         if (is_rotation)
196                 fcurve_deg_to_rad(fcu);
197 #endif
198         
199         for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) {
200                 FCurve *fcu = *it;
201                 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
202                 
203                 if (array_index == -1) fcu->array_index = i;
204                 else fcu->array_index = array_index;
205         
206                 if (ob->type == OB_ARMATURE) {
207                         bActionGroup *grp = NULL;
208                         const char *bone_name = bc_get_joint_name(animated->node);
209                         
210                         if (bone_name) {
211                                 /* try to find group */
212                                 grp = action_groups_find_named(act, bone_name);
213                                 
214                                 /* no matching groups, so add one */
215                                 if (grp == NULL) {
216                                         /* Add a new group, and make it active */
217                                         grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
218                                         
219                                         grp->flag = AGRP_SELECTED;
220                                         BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
221                                         
222                                         BLI_addtail(&act->groups, grp);
223                                         BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
224                                 }
225                                 
226                                 /* add F-Curve to group */
227                                 action_groups_add_channel(act, grp, fcu);
228                                 
229                         }
230 #if 0
231                         if (is_rotation) {
232                                 fcurves_actionGroup_map[grp].push_back(fcu);
233                         }
234 #endif
235                 }
236                 else {
237                         BLI_addtail(&act->curves, fcu);
238                 }
239
240                 // curve is used, so remove it from unused_curves
241                 unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
242         }
243 }
244
245 AnimationImporter::AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
246                 TransformReader(conv), armature_importer(arm), scene(scene) { }
247
248 AnimationImporter::~AnimationImporter()
249 {
250         // free unused FCurves
251         for (std::vector<FCurve*>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++)
252                 free_fcurve(*it);
253
254         if (unused_curves.size())
255                 fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size());
256 }
257
258 bool AnimationImporter::write_animation(const COLLADAFW::Animation* anim) 
259 {
260         if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
261                 COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve*)anim;
262                 
263                 // XXX Don't know if it's necessary
264                 // Should we check outPhysicalDimension?
265                 if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) {
266                         fprintf(stderr, "Inputs physical dimension is not time. \n");
267                         return true;
268                 }
269
270                 // a curve can have mixed interpolation type,
271                 // in this case curve->getInterpolationTypes returns a list of interpolation types per key
272                 COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
273
274                 if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
275                         switch (interp) {
276                         case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
277                         case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
278                                 animation_to_fcurves(curve);
279                                 break;
280                         default:
281                                 // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types
282                                 fprintf(stderr, "CARDINAL, HERMITE, BSPLINE and STEP anim interpolation types not supported yet.\n");
283                                 break;
284                         }
285                 }
286                 else {
287                         // not supported yet
288                         fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n");
289                 }
290         }
291         else {
292                 fprintf(stderr, "FORMULA animation type is not supported yet.\n");
293         }
294         
295         return true;
296 }
297         
298 // called on post-process stage after writeVisualScenes
299 bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList* animlist) 
300 {
301         const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
302     
303         animlist_map[animlist_id] = animlist;
304     
305 #if 0
306
307         // should not happen
308         if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
309                 return true;
310         }
311
312         // for bones rna_path is like: pose.bones["bone-name"].rotation
313         
314         // what does this AnimationList animate?
315         Animation& animated = uid_animated_map[animlist_id];
316         Object *ob = animated.ob;
317     
318         char rna_path[100];
319         char joint_path[100];
320         bool is_joint = false;
321
322         // if ob is NULL, it should be a JOINT
323         if (!ob) {
324                 
325                 ob = armature_importer->get_armature_for_joint(animated.node);
326
327                 if (!ob) {
328 //                      fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node));
329                         return true;
330                 }
331
332                 armature_importer->get_rna_path_for_joint(animated.node, joint_path, sizeof(joint_path));
333
334                 is_joint = true;
335         }
336         printf("object for animlist: %s found\n", animlist->getUniqueId().toAscii().c_str());
337         const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
338
339         switch (animated.tm->getTransformationType()) {
340         case COLLADAFW::Transformation::TRANSLATE:
341         case COLLADAFW::Transformation::SCALE:
342                 {
343                         bool loc = animated.tm->getTransformationType() == COLLADAFW::Transformation::TRANSLATE;
344                         if (is_joint)
345                                 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
346                         else
347                                 BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
348
349                         for (int i = 0; i < bindings.getCount(); i++) {
350                                 const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
351                                 COLLADAFW::UniqueId anim_uid = binding.animation;
352
353                                 if (curve_map.find(anim_uid) == curve_map.end()) {
354                                         fprintf(stderr, "Cannot find FCurve by animation UID.\n");
355                                         continue;
356                                 }
357
358                                 std::vector<FCurve*>& fcurves = curve_map[anim_uid];
359                                 
360                                 switch (binding.animationClass) {
361                                 case COLLADAFW::AnimationList::POSITION_X:
362                                         add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated);
363                                         break;
364                                 case COLLADAFW::AnimationList::POSITION_Y:
365                                         add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated);
366                                         break;
367                                 case COLLADAFW::AnimationList::POSITION_Z:
368                                         add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated);
369                                         break;
370                                 case COLLADAFW::AnimationList::POSITION_XYZ:
371                                         add_fcurves_to_object(ob, fcurves, rna_path, -1, &animated);
372                                         break;
373                                 default:
374                                         fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
375                                                         binding.animationClass, loc ? "TRANSLATE" : "SCALE");
376                                 }
377                         }
378                 }
379                 break;
380         case COLLADAFW::Transformation::ROTATE:
381                 {
382                         if (is_joint)
383                                 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
384                         else
385                                 BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
386
387                         COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)animated.tm;
388                         COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
389                         
390                         for (int i = 0; i < bindings.getCount(); i++) {
391                                 const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
392                                 COLLADAFW::UniqueId anim_uid = binding.animation;
393
394                                 if (curve_map.find(anim_uid) == curve_map.end()) {
395                                         fprintf(stderr, "Cannot find FCurve by animation UID.\n");
396                                         continue;
397                                 }
398
399                                 std::vector<FCurve*>& fcurves = curve_map[anim_uid];
400
401                                 switch (binding.animationClass) {
402                                 case COLLADAFW::AnimationList::ANGLE:
403                                         if (COLLADABU::Math::Vector3::UNIT_X == axis) {
404                                                 add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated);
405                                         }
406                                         else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
407                                                 add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated);
408                                         }
409                                         else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
410                                                 add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated);
411                                         }
412                                         break;
413                                 case COLLADAFW::AnimationList::AXISANGLE:
414                                         // TODO convert axis-angle to quat? or XYZ?
415                                 default:
416                                         fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
417                                                         binding.animationClass);
418                                 }
419                         }
420                 }
421                 break;
422         case COLLADAFW::Transformation::MATRIX:
423         case COLLADAFW::Transformation::SKEW:
424         case COLLADAFW::Transformation::LOOKAT:
425                 fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
426                 break;
427         }
428 #endif
429         
430         return true;
431 }
432
433 // \todo refactor read_node_transform to not automatically apply anything,
434 // but rather return the transform matrix, so caller can do with it what is
435 // necessary. Same for \ref get_node_mat
436 void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob)
437 {
438         float mat[4][4];
439         TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
440         if (ob) {
441                 copy_m4_m4(ob->obmat, mat);
442                 object_apply_mat4(ob, ob->obmat, 0, 0);
443         }
444 }
445
446 #if 0
447 virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
448 {
449         bActionGroup *grp;
450         int i;
451         
452         for (grp = (bActionGroup*)act->groups.first; grp; grp = grp->next) {
453
454                 FCurve *eulcu[3] = {NULL, NULL, NULL};
455                 
456                 if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end())
457                         continue;
458
459                 std::vector<FCurve*> &rot_fcurves = fcurves_actionGroup_map[grp];
460                 
461                 if (rot_fcurves.size() > 3) continue;
462
463                 for (i = 0; i < rot_fcurves.size(); i++)
464                         eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i];
465
466                 char joint_path[100];
467                 char rna_path[100];
468
469                 BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name);
470                 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path);
471
472                 FCurve *quatcu[4] = {
473                         create_fcurve(0, rna_path),
474                         create_fcurve(1, rna_path),
475                         create_fcurve(2, rna_path),
476                         create_fcurve(3, rna_path)
477                 };
478
479                 bPoseChannel *chan = get_pose_channel(ob->pose, grp->name);
480
481                 float m4[4][4], irest[3][3];
482                 invert_m4_m4(m4, chan->bone->arm_mat);
483                 copy_m3_m4(irest, m4);
484
485                 for (i = 0; i < 3; i++) {
486
487                         FCurve *cu = eulcu[i];
488
489                         if (!cu) continue;
490
491                         for (int j = 0; j < cu->totvert; j++) {
492                                 float frame = cu->bezt[j].vec[1][0];
493
494                                 float eul[3] = {
495                                         eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f,
496                                         eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f,
497                                         eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f
498                                 };
499
500                                 // make eul relative to bone rest pose
501                                 float rot[3][3], rel[3][3], quat[4];
502
503                                 /*eul_to_mat3(rot, eul);
504
505                                 mul_m3_m3m3(rel, irest, rot);
506
507                                 mat3_to_quat(quat, rel);
508                                 */
509
510                                 eul_to_quat(quat, eul);
511
512                                 for (int k = 0; k < 4; k++)
513                                         create_bezt(quatcu[k], frame, quat[k]);
514                         }
515                 }
516
517                 // now replace old Euler curves
518
519                 for (i = 0; i < 3; i++) {
520                         if (!eulcu[i]) continue;
521
522                         action_groups_remove_channel(act, eulcu[i]);
523                         free_fcurve(eulcu[i]);
524                 }
525
526                 chan->rotmode = ROT_MODE_QUAT;
527
528                 for (i = 0; i < 4; i++)
529                         action_groups_add_channel(act, grp, quatcu[i]);
530         }
531
532         bPoseChannel *pchan;
533         for (pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
534                 pchan->rotmode = ROT_MODE_QUAT;
535         }
536 }
537 #endif
538
539
540 //sets the rna_path and array index to curve
541 void AnimationImporter::modify_fcurve(std::vector<FCurve*>* curves , char* rna_path , int array_index )
542 {   
543         std::vector<FCurve*>::iterator it;
544         int i;
545         for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) {
546                 FCurve *fcu = *it;
547                 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
548                 
549                 if (array_index == -1) fcu->array_index = i;
550                 else fcu->array_index = array_index;
551
552                 unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
553         }
554 }
555
556 void AnimationImporter::find_frames( std::vector<float>* frames , std::vector<FCurve*>* curves)
557 {
558         std::vector<FCurve*>::iterator iter;
559                 for (iter = curves->begin(); iter != curves->end(); iter++) {
560                         FCurve *fcu = *iter;
561         
562                 for (unsigned int k = 0; k < fcu->totvert; k++) {
563                         //get frame value from bezTriple
564                         float fra = fcu->bezt[k].vec[1][0];
565                         //if frame already not added add frame to frames
566                         if (std::find(frames->begin(), frames->end(), fra) == frames->end())
567                                 frames->push_back(fra);
568                                                         
569                 }
570                 }
571 }
572
573 //creates the rna_paths and array indices of fcurves from animations using transformation and bound animation class of each animation.
574 void AnimationImporter:: Assign_transform_animations(COLLADAFW::Transformation * transform , 
575                                                                                                          const COLLADAFW::AnimationList::AnimationBinding * binding,
576                                                                                                          std::vector<FCurve*>* curves, bool is_joint, char * joint_path)
577 {
578         COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
579         bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
580         bool is_rotation = tm_type  == COLLADAFW::Transformation::ROTATE;
581         
582         //to check if the no of curves are valid
583         bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE ||tm_type  == COLLADAFW::Transformation::SCALE) && binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
584                         
585         
586         if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) {
587                 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size());
588                 return;
589         }
590         
591         char rna_path[100];
592                                                         
593         switch (tm_type) {
594                 case COLLADAFW::Transformation::TRANSLATE:
595                 case COLLADAFW::Transformation::SCALE:
596                         {
597                                 bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE;
598                                 if (is_joint)
599                                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
600                                 else
601                                         BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
602
603                                 switch (binding->animationClass) {
604                                         case COLLADAFW::AnimationList::POSITION_X:
605                                                 modify_fcurve(curves, rna_path, 0 );
606                                                 break;
607                                         case COLLADAFW::AnimationList::POSITION_Y:
608                                                 modify_fcurve(curves, rna_path, 1 );
609                                                 break;
610                                         case COLLADAFW::AnimationList::POSITION_Z:
611                                                 modify_fcurve(curves, rna_path, 2 );
612                                                 break;
613                                         case COLLADAFW::AnimationList::POSITION_XYZ:
614                                                 modify_fcurve(curves, rna_path, -1 );
615                                                 break;
616                                         default:
617                                                 fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
618                                                                 binding->animationClass, loc ? "TRANSLATE" : "SCALE");
619                                         }
620                 break;
621                         }
622                 
623                 
624                 case COLLADAFW::Transformation::ROTATE:
625                         {
626                                 if (is_joint)
627                                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
628                                 else
629                                         BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
630                 std::vector<FCurve*>::iterator iter;
631                                 for (iter = curves->begin(); iter != curves->end(); iter++) {
632                                         FCurve* fcu = *iter;
633                                         
634                                         //if transform is rotation the fcurves values must be turned in to radian.
635                                         if (is_rotation)
636                                                 fcurve_deg_to_rad(fcu);          
637                                 }                                       
638                                 COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)transform;
639                                 COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
640                         
641                                 switch (binding->animationClass) {
642                                         case COLLADAFW::AnimationList::ANGLE:
643                                                 if (COLLADABU::Math::Vector3::UNIT_X == axis) {
644                                                         modify_fcurve(curves, rna_path, 0 );
645                                                 }
646                                                 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
647                                                         modify_fcurve(curves, rna_path, 1 );
648                                                 }
649                                                 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
650                                                         modify_fcurve(curves, rna_path, 2 );
651                                                 }
652                                                 break;
653                                         case COLLADAFW::AnimationList::AXISANGLE:
654                                                 // TODO convert axis-angle to quat? or XYZ?
655                                         default:
656                                                 fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
657                                                                 binding->animationClass);
658                                         }
659                         break;
660                         }
661                         
662                 case COLLADAFW::Transformation::MATRIX:
663                 case COLLADAFW::Transformation::SKEW:
664                 case COLLADAFW::Transformation::LOOKAT:
665                         fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
666                         break;
667                 }
668         
669 }
670
671 void AnimationImporter:: Assign_color_animations(const COLLADAFW::AnimationList::AnimationBinding * binding,
672                                                                                                  std::vector<FCurve*>* curves)
673 {
674         char rna_path[100];
675         BLI_strncpy(rna_path,"color", sizeof(rna_path));
676
677         switch (binding->animationClass) {
678                 case COLLADAFW::AnimationList::COLOR_R:
679                         modify_fcurve(curves, rna_path, 0 );
680                         break;
681                 case COLLADAFW::AnimationList::COLOR_G:
682                         modify_fcurve(curves, rna_path, 1 );
683                         break;
684                 case COLLADAFW::AnimationList::COLOR_B:
685                         modify_fcurve(curves, rna_path, 2 );
686                         break;
687                 case COLLADAFW::AnimationList::COLOR_RGB:
688                 case COLLADAFW::AnimationList::COLOR_RGBA:
689                         modify_fcurve(curves, rna_path, -1 );
690                         break;
691                         
692                 default:
693                         fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
694                                         binding->animationClass, "COLOR" );
695                 }
696 }
697
698 void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, char * anim_type)
699 {
700         char rna_path[100];
701         if (animlist_map.find(listid) == animlist_map.end()) return ;
702         else 
703         {
704                 //transformation has animations
705                 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
706                 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
707                 //all the curves belonging to the current binding
708                 std::vector<FCurve*> animcurves;    
709                 for (unsigned int j = 0; j < bindings.getCount(); j++) {
710                          animcurves = curve_map[bindings[j].animation];
711                         //calculate rnapaths and array index of fcurves according to transformation and animation class
712                          BLI_strncpy(rna_path, anim_type , sizeof(rna_path));
713                          modify_fcurve(&animcurves, rna_path, 0 );
714                          std::vector<FCurve*>::iterator iter;
715                                 //Add the curves of the current animation to the object
716                                 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
717                                         FCurve * fcu = *iter;
718                                         BLI_addtail(AnimCurves, fcu);   
719                                 }                               
720                 }
721         }
722         
723 }
724
725 void AnimationImporter::translate_Animations_NEW ( COLLADAFW::Node * node , 
726                                                                                                    std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
727                                                                                                    std::map<COLLADAFW::UniqueId, Object*>& object_map,
728                                                                                                    std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map)
729 {
730         AnimationImporter::AnimMix* animType = get_animation_type(node, FW_object_map );
731
732         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
733         COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
734         Object *ob = is_joint ? armature_importer->get_armature_for_joint(root) : object_map[node->getUniqueId()];
735         if (!ob)
736         {
737                 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
738                 return;
739         }
740
741         bAction * act;
742         bActionGroup *grp = NULL;
743     
744         //if ( (animType & NODE_TRANSFORM) != 0 )
745         if ( (animType->transform) != 0 )
746         {
747         const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
748         char joint_path[200];
749
750                 if ( is_joint ) 
751                 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
752                 
753         
754                 if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1);
755                                         else act = ob->adt->action;
756                                         //Get the list of animation curves of the object
757             
758                 ListBase *AnimCurves = &(act->curves);
759
760                 const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
761         
762                 //for each transformation in node 
763                 for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
764                         COLLADAFW::Transformation *transform = nodeTransforms[i];
765                         COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
766
767                         bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
768                         bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
769                                 
770                         const COLLADAFW::UniqueId& listid = transform->getAnimationList();
771                 
772                         //check if transformation has animations    
773                         if (animlist_map.find(listid) == animlist_map.end()) continue ; 
774                         else 
775                         {
776                                 //transformation has animations
777                                 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
778                                 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
779                                 //all the curves belonging to the current binding
780                                 std::vector<FCurve*> animcurves;    
781                                 for (unsigned int j = 0; j < bindings.getCount(); j++) {
782                                          animcurves = curve_map[bindings[j].animation];
783                                         //calculate rnapaths and array index of fcurves according to transformation and animation class
784                                          Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path ); 
785                                         
786                                          std::vector<FCurve*>::iterator iter;
787                                                 //Add the curves of the current animation to the object
788                                                 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
789                                                         FCurve * fcu = *iter;
790                                                          if (ob->type == OB_ARMATURE) 
791                                                                 add_bone_fcurve( ob, node , fcu );
792                                                          else 
793                                                          BLI_addtail(AnimCurves, fcu);  
794                                                 }                               
795                                 }
796                         }
797                         if (is_rotation || is_matrix) {
798                                 if (is_joint) 
799                                 {
800                                         bPoseChannel *chan = get_pose_channel(ob->pose, bone_name);
801                                         chan->rotmode = ROT_MODE_EUL;
802                                 }
803                                 else 
804                                 {
805                                         ob->rotmode = ROT_MODE_EUL;
806                                 }
807                         }
808                 }
809         }
810
811         //if ( ((animType & LIGHT_COLOR) != 0)|| ((animType & LIGHT_FOA) != 0) || ((animType & LIGHT_FOE) != 0) )
812         if ((animType->light) != 0)
813         {
814                 Lamp * lamp  = (Lamp*) ob->data;
815
816                 if (!lamp->adt || !lamp->adt->action) act = verify_adt_action((ID*)&lamp->id, 1);
817                                         else act = lamp->adt->action;
818
819                 ListBase *AnimCurves = &(act->curves);
820                 const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights();
821
822                 for (unsigned int i = 0; i < nodeLights.getCount(); i++) {
823                         const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
824
825                         if ((animType->light & LIGHT_COLOR) != 0)
826                         {
827                                 const COLLADAFW::Color *col =  &(light->getColor());
828                                 const COLLADAFW::UniqueId& listid = col->getAnimationList();
829                                 //transformation has animations
830                                 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
831                                 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
832                                 //all the curves belonging to the current binding
833                                 std::vector<FCurve*> animcurves;    
834                                 for (unsigned int j = 0; j < bindings.getCount(); j++) {
835                                          animcurves = curve_map[bindings[j].animation];
836                                         //calculate rnapaths and array index of fcurves according to transformation and animation class
837                                          Assign_color_animations( &bindings[j], &animcurves); 
838                                         
839                                          std::vector<FCurve*>::iterator iter;
840                                                 //Add the curves of the current animation to the object
841                                                 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
842                                                         FCurve * fcu = *iter;
843                                                         BLI_addtail(AnimCurves, fcu);   
844                                                 }                               
845                                 }
846                                 
847                         }
848                         if ((animType->light & LIGHT_FOA) != 0 )
849                         {
850                                 const COLLADAFW::AnimatableFloat *foa =  &(light->getFallOffAngle());
851                                 const COLLADAFW::UniqueId& listid = foa->getAnimationList();
852                                 Assign_float_animations( listid ,AnimCurves, "spot_size"); 
853                         }
854                         if ( (animType->light & LIGHT_FOE) != 0 )
855                         {
856                                 const COLLADAFW::AnimatableFloat *foe =  &(light->getFallOffExponent());
857                                 const COLLADAFW::UniqueId& listid = foe->getAnimationList();
858                                 Assign_float_animations( listid ,AnimCurves, "spot_blend"); 
859                         
860                         }
861                 }
862         }
863
864         //if ( ((animType & CAMERA_XFOV) != 0) || (animType & CAMERA_XMAG) != 0 )
865         if ( (animType->camera) != 0) 
866         {
867                 Camera * camera  = (Camera*) ob->data;
868
869                 if (!camera->adt || !camera->adt->action) act = verify_adt_action((ID*)&camera->id, 1);
870                                         else act = camera->adt->action;
871
872                 ListBase *AnimCurves = &(act->curves);
873                 const COLLADAFW::InstanceCameraPointerArray& nodeCameras= node->getInstanceCameras();
874
875                 for (unsigned int i = 0; i < nodeCameras.getCount(); i++) {
876                         const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
877
878                         if ((animType->camera & CAMERA_XFOV) != 0 )
879                         {
880                                 const COLLADAFW::AnimatableFloat *xfov =  &(camera->getXFov());
881                                 const COLLADAFW::UniqueId& listid = xfov->getAnimationList();
882                                 Assign_float_animations( listid ,AnimCurves, "lens"); 
883                         }
884
885                         else if ((animType->camera & CAMERA_XMAG) != 0 )
886                         {
887                                 const COLLADAFW::AnimatableFloat *xmag =  &(camera->getXMag());
888                                 const COLLADAFW::UniqueId& listid = xmag->getAnimationList();
889                                 Assign_float_animations( listid ,AnimCurves, "ortho_scale"); 
890                         }
891
892                         if ((animType->camera & CAMERA_ZFAR) != 0 )
893                         {
894                                 const COLLADAFW::AnimatableFloat *zfar =  &(camera->getFarClippingPlane());
895                                 const COLLADAFW::UniqueId& listid = zfar->getAnimationList();
896                                 Assign_float_animations( listid ,AnimCurves, "clipend"); 
897                         }
898
899                         if ((animType->camera & CAMERA_ZNEAR) != 0 )
900                         {
901                                 const COLLADAFW::AnimatableFloat *znear =  &(camera->getNearClippingPlane());
902                                 const COLLADAFW::UniqueId& listid = znear->getAnimationList();
903                                 Assign_float_animations( listid ,AnimCurves, "clipsta"); 
904                         }
905
906                 }
907         }
908 }
909
910 //Check if object is animated by checking if animlist_map holds the animlist_id of node transforms
911 AnimationImporter::AnimMix* AnimationImporter::get_animation_type ( const COLLADAFW::Node * node , 
912                                                                                         std::map<COLLADAFW::UniqueId, const COLLADAFW::Object*> FW_object_map) 
913 {
914         AnimMix *types = new AnimMix();
915         //types->transform = INANIMATE ;
916         //types->light = INANIMATE;
917         //types->camera = INANIMATE;
918         //types->material = INANIMATE;
919         //types->texture = INANIMATE;
920         
921         const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
922         
923         //for each transformation in node 
924         for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
925                 COLLADAFW::Transformation *transform = nodeTransforms[i];
926                 const COLLADAFW::UniqueId& listid = transform->getAnimationList();
927                 
928                 //check if transformation has animations    
929                 if (animlist_map.find(listid) == animlist_map.end()) continue ;
930                 else 
931                 {
932                         types->transform = types->transform|NODE_TRANSFORM;
933                         break;
934                 }
935         }
936         const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights();
937
938         for (unsigned int i = 0; i < nodeLights.getCount(); i++) {
939                 const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
940                 types->light = setAnimType(&(light->getColor()),(types->light), LIGHT_COLOR);
941                 types->light = setAnimType(&(light->getFallOffAngle()),(types->light), LIGHT_FOA);
942                 types->light = setAnimType(&(light->getFallOffExponent()),(types->light), LIGHT_FOE);
943                 
944                 if ( types->light != 0) break;
945                 
946         }
947
948         const COLLADAFW::InstanceCameraPointerArray& nodeCameras = node->getInstanceCameras();
949         for (unsigned int i = 0; i < nodeCameras.getCount(); i++) {
950                 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
951         
952
953                 if ( camera->getCameraType() == COLLADAFW::Camera::PERSPECTIVE )
954                 {
955                     types->camera = setAnimType(&(camera->getXMag()),(types->camera), CAMERA_XFOV);
956                 }
957                 else 
958                 {
959                         types->camera = setAnimType(&(camera->getXMag()),(types->camera), CAMERA_XMAG);
960                 }
961                         
962                 types->camera = setAnimType(&(camera->getFarClippingPlane()),(types->camera), CAMERA_ZFAR);
963                 types->camera = setAnimType(&(camera->getNearClippingPlane()),(types->camera), CAMERA_ZNEAR);
964
965                 //if ( type != 0) break;
966                 if ( types->camera != 0) break;
967
968         }
969         return types;
970 }
971
972 int AnimationImporter::setAnimType ( const COLLADAFW::Animatable * prop , int types, int addition)
973 {
974                 const COLLADAFW::UniqueId& listid =  prop->getAnimationList();
975                 if (animlist_map.find(listid) != animlist_map.end()) 
976                                 return types|addition;
977                 else return types;
978 }               
979
980 //XXX Is not used anymore.
981 void AnimationImporter::find_frames_old(std::vector<float> * frames, COLLADAFW::Node * node , COLLADAFW::Transformation::TransformationType tm_type)
982 {
983         bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
984         bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
985         // for each <rotate>, <translate>, etc. there is a separate Transformation
986         const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
987
988         unsigned int i;
989         // find frames at which to sample plus convert all rotation keys to radians
990         for (i = 0; i < nodeTransforms.getCount(); i++) {
991                 COLLADAFW::Transformation *transform = nodeTransforms[i];
992                 COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType();
993
994
995                 if (nodeTmType == tm_type) {
996                         //get animation bindings for the current transformation
997                         const COLLADAFW::UniqueId& listid = transform->getAnimationList();
998                         //if transform is animated its animlist must exist.
999                         if (animlist_map.find(listid) != animlist_map.end()) {
1000                                 
1001                                 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1002                                 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
1003                 
1004                                 if (bindings.getCount()) {
1005                                         //for each AnimationBinding get the fcurves which animate the transform
1006                                         for (unsigned int j = 0; j < bindings.getCount(); j++) {
1007                                                 std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
1008                                                 bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || nodeTmType == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
1009
1010                                                 if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) {
1011                                                         std::vector<FCurve*>::iterator iter;
1012
1013                                                         for (iter = curves.begin(); iter != curves.end(); iter++) {
1014                                                                 FCurve *fcu = *iter;
1015                                 
1016                                                                 //if transform is rotation the fcurves values must be turned in to radian.
1017                                                                 if (is_rotation)
1018                                                                         fcurve_deg_to_rad(fcu);
1019
1020                                                                 for (unsigned int k = 0; k < fcu->totvert; k++) {
1021                                                                         //get frame value from bezTriple
1022                                                                         float fra = fcu->bezt[k].vec[1][0];
1023                                                                         //if frame already not added add frame to frames
1024                                                                         if (std::find(frames->begin(), frames->end(), fra) == frames->end())
1025                                                                                 frames->push_back(fra);
1026                                                                 }
1027                                                         }
1028                                                 }
1029                                                 else {
1030                                                         fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size());
1031                                                 }
1032                                         }
1033                                 }
1034                         }
1035                 }
1036         }
1037 }
1038
1039
1040 // prerequisites:
1041 // animlist_map - map animlist id -> animlist
1042 // curve_map - map anim id -> curve(s)
1043 Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
1044                                                         std::map<COLLADAFW::UniqueId, Object*>& object_map,
1045                                                         std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
1046                                                         COLLADAFW::Transformation::TransformationType tm_type,
1047                                                         Object *par_job)
1048 {
1049         
1050         bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
1051         bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
1052         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
1053         
1054         COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
1055         Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
1056         const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
1057         if (!ob) {
1058                 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
1059                 return NULL;
1060         }
1061
1062         // frames at which to sample
1063         std::vector<float> frames;
1064         
1065         find_frames_old(&frames, node , tm_type);
1066         
1067         unsigned int i;
1068         
1069         float irest_dae[4][4];
1070         float rest[4][4], irest[4][4];
1071
1072         if (is_joint) {
1073                 get_joint_rest_mat(irest_dae, root, node);
1074                 invert_m4(irest_dae);
1075
1076                 Bone *bone = get_named_bone((bArmature*)ob->data, bone_name);
1077                 if (!bone) {
1078                         fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
1079                         return NULL;
1080                 }
1081
1082                 unit_m4(rest);
1083                 copy_m4_m4(rest, bone->arm_mat);
1084                 invert_m4_m4(irest, rest);
1085         }
1086
1087         Object *job = NULL;
1088
1089 #ifdef ARMATURE_TEST
1090         FCurve *job_curves[10];
1091         job = get_joint_object(root, node, par_job);
1092 #endif
1093
1094         if (frames.size() == 0)
1095                 return job;
1096
1097         std::sort(frames.begin(), frames.end());
1098
1099         const char *tm_str = NULL;
1100         switch (tm_type) {
1101         case COLLADAFW::Transformation::ROTATE:
1102                 tm_str = "rotation_quaternion";
1103                 break;
1104         case COLLADAFW::Transformation::SCALE:
1105                 tm_str = "scale";
1106                 break;
1107         case COLLADAFW::Transformation::TRANSLATE:
1108                 tm_str = "location";
1109                 break;
1110         case COLLADAFW::Transformation::MATRIX:
1111                 break;
1112         default:
1113                 return job;
1114         }
1115
1116         char rna_path[200];
1117         char joint_path[200];
1118
1119         if (is_joint)
1120                 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
1121
1122         // new curves
1123         FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale
1124         unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3);
1125
1126         for (i = 0; i < totcu; i++) {
1127
1128                 int axis = i;
1129
1130                 if (is_matrix) {
1131                         if (i < 4) {
1132                                 tm_str = "rotation_quaternion";
1133                                 axis = i;
1134                         }
1135                         else if (i < 7) {
1136                                 tm_str = "location";
1137                                 axis = i - 4;
1138                         }
1139                         else {
1140                                 tm_str = "scale";
1141                                 axis = i - 7;
1142                         }
1143                 }
1144
1145                 if (is_joint)
1146                         BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
1147                 else
1148                         strcpy(rna_path, tm_str);
1149                 newcu[i] = create_fcurve(axis, rna_path);
1150
1151 #ifdef ARMATURE_TEST
1152                 if (is_joint)
1153                         job_curves[i] = create_fcurve(axis, tm_str);
1154 #endif
1155         }
1156
1157         std::vector<float>::iterator it;
1158
1159         // sample values at each frame
1160         for (it = frames.begin(); it != frames.end(); it++) {
1161                 float fra = *it;
1162
1163                 float mat[4][4];
1164                 float matfra[4][4];
1165
1166                 unit_m4(matfra);
1167
1168                 // calc object-space mat
1169                 evaluate_transform_at_frame(matfra, node, fra);
1170
1171                 // for joints, we need a special matrix
1172                 if (is_joint) {
1173                         // special matrix: iR * M * iR_dae * R
1174                         // where R, iR are bone rest and inverse rest mats in world space (Blender bones),
1175                         // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE)
1176                         float temp[4][4], par[4][4];
1177
1178                         // calc M
1179                         calc_joint_parent_mat_rest(par, NULL, root, node);
1180                         mul_m4_m4m4(temp, matfra, par);
1181
1182                         // evaluate_joint_world_transform_at_frame(temp, NULL, , node, fra);
1183
1184                         // calc special matrix
1185                         mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
1186                 }
1187                 else {
1188                         copy_m4_m4(mat, matfra);
1189                 }
1190
1191                 float val[4], rot[4], loc[3], scale[3];
1192
1193                 switch (tm_type) {
1194                 case COLLADAFW::Transformation::ROTATE:
1195                         mat4_to_quat(val, mat);
1196                         break;
1197                 case COLLADAFW::Transformation::SCALE:
1198                         mat4_to_size(val, mat);
1199                         break;
1200                 case COLLADAFW::Transformation::TRANSLATE:
1201                         copy_v3_v3(val, mat[3]);
1202                         break;
1203                 case COLLADAFW::Transformation::MATRIX:
1204                         mat4_to_quat(rot, mat);
1205                         copy_v3_v3(loc, mat[3]);
1206                         mat4_to_size(scale, mat);
1207                         break;
1208                 default:
1209                         break;
1210                 }
1211
1212                 // add keys
1213                 for (i = 0; i < totcu; i++) {
1214                         if (is_matrix) {
1215                                 if (i < 4)
1216                                         add_bezt(newcu[i], fra, rot[i]);
1217                                 else if (i < 7)
1218                                         add_bezt(newcu[i], fra, loc[i - 4]);
1219                                 else
1220                                         add_bezt(newcu[i], fra, scale[i - 7]);
1221                         }
1222                         else {
1223                                 add_bezt(newcu[i], fra, val[i]);
1224                         }
1225                 }
1226
1227 #ifdef ARMATURE_TEST
1228                 if (is_joint) {
1229                         switch (tm_type) {
1230                         case COLLADAFW::Transformation::ROTATE:
1231                                 mat4_to_quat(val, matfra);
1232                                 break;
1233                         case COLLADAFW::Transformation::SCALE:
1234                                 mat4_to_size(val, matfra);
1235                                 break;
1236                         case COLLADAFW::Transformation::TRANSLATE:
1237                                 copy_v3_v3(val, matfra[3]);
1238                                 break;
1239                         case MATRIX:
1240                                 mat4_to_quat(rot, matfra);
1241                                 copy_v3_v3(loc, matfra[3]);
1242                                 mat4_to_size(scale, matfra);
1243                                 break;
1244                         default:
1245                                 break;
1246                         }
1247
1248                         for (i = 0; i < totcu; i++) {
1249                                 if (is_matrix) {
1250                                         if (i < 4)
1251                                                 add_bezt(job_curves[i], fra, rot[i]);
1252                                         else if (i < 7)
1253                                                 add_bezt(job_curves[i], fra, loc[i - 4]);
1254                                         else
1255                                                 add_bezt(job_curves[i], fra, scale[i - 7]);
1256                                 }
1257                                 else {
1258                                         add_bezt(job_curves[i], fra, val[i]);
1259                                 }
1260                         }
1261                 }
1262 #endif
1263         }
1264
1265         verify_adt_action((ID*)&ob->id, 1);
1266
1267         ListBase *curves = &ob->adt->action->curves;
1268
1269         // add curves
1270         for (i = 0; i < totcu; i++) {
1271                 if (is_joint)
1272                         add_bone_fcurve(ob, node, newcu[i]);
1273                 else
1274                         BLI_addtail(curves, newcu[i]);
1275
1276 #ifdef ARMATURE_TEST
1277                 if (is_joint)
1278                         BLI_addtail(&job->adt->action->curves, job_curves[i]);
1279 #endif
1280         }
1281
1282         if (is_rotation || is_matrix) {
1283                 if (is_joint) {
1284                         bPoseChannel *chan = get_pose_channel(ob->pose, bone_name);
1285                         chan->rotmode = ROT_MODE_QUAT;
1286                 }
1287                 else {
1288                         ob->rotmode = ROT_MODE_QUAT;
1289                 }
1290         }
1291
1292         return job;
1293 }
1294
1295 // internal, better make it private
1296 // warning: evaluates only rotation
1297 // prerequisites: animlist_map, curve_map
1298 void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra)
1299 {
1300         const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
1301
1302         unit_m4(mat);
1303
1304         for (unsigned int i = 0; i < tms.getCount(); i++) {
1305                 COLLADAFW::Transformation *tm = tms[i];
1306                 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1307                 float m[4][4];
1308
1309                 unit_m4(m);
1310
1311                 std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
1312                 if (!evaluate_animation(tm, m, fra, nodename.c_str())) {
1313                         switch (type) {
1314                         case COLLADAFW::Transformation::ROTATE:
1315                                 dae_rotate_to_mat4(tm, m);
1316                                 break;
1317                         case COLLADAFW::Transformation::TRANSLATE:
1318                                 dae_translate_to_mat4(tm, m);
1319                                 break;
1320                         case COLLADAFW::Transformation::SCALE:
1321                                 dae_scale_to_mat4(tm, m);
1322                                 break;
1323                         case COLLADAFW::Transformation::MATRIX:
1324                                 dae_matrix_to_mat4(tm, m);
1325                                 break;
1326                         default:
1327                                 fprintf(stderr, "unsupported transformation type %d\n", type);
1328                         }
1329                 }
1330
1331                 float temp[4][4];
1332                 copy_m4_m4(temp, mat);
1333
1334                 mul_m4_m4m4(mat, m, temp);
1335         }
1336 }
1337
1338 // return true to indicate that mat contains a sane value
1339 bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id)
1340 {
1341         const COLLADAFW::UniqueId& listid = tm->getAnimationList();
1342         COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1343
1344         if (type != COLLADAFW::Transformation::ROTATE &&
1345             type != COLLADAFW::Transformation::SCALE &&
1346             type != COLLADAFW::Transformation::TRANSLATE &&
1347             type != COLLADAFW::Transformation::MATRIX) {
1348                 fprintf(stderr, "animation of transformation %d is not supported yet\n", type);
1349                 return false;
1350         }
1351
1352         if (animlist_map.find(listid) == animlist_map.end())
1353                 return false;
1354
1355         const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1356         const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
1357
1358         if (bindings.getCount()) {
1359                 float vec[3];
1360
1361                 bool is_scale = (type == COLLADAFW::Transformation::SCALE);
1362                 bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE);
1363
1364                 if (type == COLLADAFW::Transformation::SCALE)
1365                         dae_scale_to_v3(tm, vec);
1366                 else if (type == COLLADAFW::Transformation::TRANSLATE)
1367                         dae_translate_to_v3(tm, vec);
1368
1369                 for (unsigned int j = 0; j < bindings.getCount(); j++) {
1370                         const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[j];
1371                         std::vector<FCurve*>& curves = curve_map[binding.animation];
1372                         COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass;
1373                         char path[100];
1374
1375                         switch (type) {
1376                         case COLLADAFW::Transformation::ROTATE:
1377                                 BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, j);
1378                                 break;
1379                         case COLLADAFW::Transformation::SCALE:
1380                                 BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, j);
1381                                 break;
1382                         case COLLADAFW::Transformation::TRANSLATE:
1383                                 BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, j);
1384                                 break;
1385                         case COLLADAFW::Transformation::MATRIX:
1386                                 BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, j);
1387                                 break;
1388                         default:
1389                                 break;
1390                         }
1391
1392                         if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) {
1393                                 fprintf(stderr, "%s: UNKNOWN animation class\n", path);
1394                                 continue;
1395                         }
1396
1397                         if (type == COLLADAFW::Transformation::ROTATE) {
1398                                 if (curves.size() != 1) {
1399                                         fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size());
1400                                         return false;
1401                                 }
1402
1403                                 // TODO support other animclasses
1404                                 if (animclass != COLLADAFW::AnimationList::ANGLE) {
1405                                         fprintf(stderr, "%s: animation class %d is not supported yet\n", path, animclass);
1406                                         return false;
1407                                 }
1408
1409                                 COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis();
1410                                 float ax[3] = {axis[0], axis[1], axis[2]};
1411                                 float angle = evaluate_fcurve(curves[0], fra);
1412                                 axis_angle_to_mat4(mat, ax, angle);
1413
1414                                 return true;
1415                         }
1416                         else if (is_scale || is_translate) {
1417                                 bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ;
1418
1419                                 if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) {
1420                                         if (is_xyz)
1421                                                 fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size());
1422                                         else
1423                                                 fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size());
1424                                         return false;
1425                                 }
1426                                 
1427                                 switch (animclass) {
1428                                 case COLLADAFW::AnimationList::POSITION_X:
1429                                         vec[0] = evaluate_fcurve(curves[0], fra);
1430                                         break;
1431                                 case COLLADAFW::AnimationList::POSITION_Y:
1432                                         vec[1] = evaluate_fcurve(curves[0], fra);
1433                                         break;
1434                                 case COLLADAFW::AnimationList::POSITION_Z:
1435                                         vec[2] = evaluate_fcurve(curves[0], fra);
1436                                         break;
1437                                 case COLLADAFW::AnimationList::POSITION_XYZ:
1438                                         vec[0] = evaluate_fcurve(curves[0], fra);
1439                                         vec[1] = evaluate_fcurve(curves[1], fra);
1440                                         vec[2] = evaluate_fcurve(curves[2], fra);
1441                                         break;
1442                                 default:
1443                                         fprintf(stderr, "%s: animation class %d is not supported yet\n", path, animclass);
1444                                         break;
1445                                 }
1446                         }
1447                         else if (type == COLLADAFW::Transformation::MATRIX) {
1448                                 // for now, of matrix animation, support only the case when all values are packed into one animation
1449                                 if (curves.size() != 16) {
1450                                         fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size());
1451                                         return false;
1452                                 }
1453
1454                                 COLLADABU::Math::Matrix4 matrix;
1455                                 int i = 0, j = 0;
1456
1457                                 for (std::vector<FCurve*>::iterator it = curves.begin(); it != curves.end(); it++) {
1458                                         matrix.setElement(i, j, evaluate_fcurve(*it, fra));
1459                                         j++;
1460                                         if (j == 4) {
1461                                                 i++;
1462                                                 j = 0;
1463                                         }
1464                                 }
1465
1466                                 COLLADAFW::Matrix tm(matrix);
1467                                 dae_matrix_to_mat4(&tm, mat);
1468
1469                                 return true;
1470                         }
1471                 }
1472
1473                 if (is_scale)
1474                         size_to_mat4(mat, vec);
1475                 else
1476                         copy_v3_v3(mat[3], vec);
1477
1478                 return is_scale || is_translate;
1479         }
1480
1481         return false;
1482 }
1483
1484 // gives a world-space mat of joint at rest position
1485 void AnimationImporter::get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node)
1486 {
1487         // if bind mat is not available,
1488         // use "current" node transform, i.e. all those tms listed inside <node>
1489         if (!armature_importer->get_joint_bind_mat(mat, node)) {
1490                 float par[4][4], m[4][4];
1491
1492                 calc_joint_parent_mat_rest(par, NULL, root, node);
1493                 get_node_mat(m, node, NULL, NULL);
1494                 mul_m4_m4m4(mat, m, par);
1495         }
1496 }
1497
1498 // gives a world-space mat, end's mat not included
1499 bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end)
1500 {
1501         float m[4][4];
1502
1503         if (node == end) {
1504                 par ? copy_m4_m4(mat, par) : unit_m4(mat);
1505                 return true;
1506         }
1507
1508         // use bind matrix if available or calc "current" world mat
1509         if (!armature_importer->get_joint_bind_mat(m, node)) {
1510                 if (par) {
1511                         float temp[4][4];
1512                         get_node_mat(temp, node, NULL, NULL);
1513                         mul_m4_m4m4(m, temp, par);
1514                 }
1515                 else {
1516                         get_node_mat(m, node, NULL, NULL);
1517                 }
1518         }
1519
1520         COLLADAFW::NodePointerArray& children = node->getChildNodes();
1521         for (unsigned int i = 0; i < children.getCount(); i++) {
1522                 if (calc_joint_parent_mat_rest(mat, m, children[i], end))
1523                         return true;
1524         }
1525
1526         return false;
1527 }
1528
1529 #ifdef ARMATURE_TEST
1530 Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job)
1531 {
1532         if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) {
1533                 Object *job = add_object(scene, OB_EMPTY);
1534
1535                 rename_id((ID*)&job->id, (char*)get_joint_name(node));
1536
1537                 job->lay = object_in_scene(job, scene)->lay = 2;
1538
1539                 mul_v3_fl(job->size, 0.5f);
1540                 job->recalc |= OB_RECALC_OB;
1541
1542                 verify_adt_action((ID*)&job->id, 1);
1543
1544                 job->rotmode = ROT_MODE_QUAT;
1545
1546                 float mat[4][4];
1547                 get_joint_rest_mat(mat, root, node);
1548
1549                 if (par_job) {
1550                         float temp[4][4], ipar[4][4];
1551                         invert_m4_m4(ipar, par_job->obmat);
1552                         copy_m4_m4(temp, mat);
1553                         mul_m4_m4m4(mat, temp, ipar);
1554                 }
1555
1556                 TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size);
1557
1558                 if (par_job) {
1559                         job->parent = par_job;
1560
1561                         par_job->recalc |= OB_RECALC_OB;
1562                         job->parsubstr[0] = 0;
1563                 }
1564
1565                 where_is_object(scene, job);
1566
1567                 // after parenting and layer change
1568                 DAG_scene_sort(CTX_data_main(C), scene);
1569
1570                 joint_objects[node->getUniqueId()] = job;
1571         }
1572
1573         return joint_objects[node->getUniqueId()];
1574 }
1575 #endif
1576
1577 #if 0
1578 // recursively evaluates joint tree until end is found, mat then is world-space matrix of end
1579 // mat must be identity on enter, node must be root
1580 bool AnimationImporter::evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra)
1581 {
1582         float m[4][4];
1583         if (par) {
1584                 float temp[4][4];
1585                 evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f);
1586                 mul_m4_m4m4(m, temp, par);
1587         }
1588         else {
1589                 evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f);
1590         }
1591
1592         if (node == end) {
1593                 copy_m4_m4(mat, m);
1594                 return true;
1595         }
1596         else {
1597                 COLLADAFW::NodePointerArray& children = node->getChildNodes();
1598                 for (int i = 0; i < children.getCount(); i++) {
1599                         if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra))
1600                                 return true;
1601                 }
1602         }
1603
1604         return false;
1605 }
1606 #endif
1607
1608 void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu)
1609 {
1610         const char *bone_name = bc_get_joint_name(node);
1611         bAction *act = ob->adt->action;
1612                         
1613         /* try to find group */
1614         bActionGroup *grp = action_groups_find_named(act, bone_name);
1615
1616         /* no matching groups, so add one */
1617         if (grp == NULL) {
1618                 /* Add a new group, and make it active */
1619                 grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
1620                                         
1621                 grp->flag = AGRP_SELECTED;
1622                 BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
1623                                         
1624                 BLI_addtail(&act->groups, grp);
1625                 BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
1626         }
1627                                 
1628         /* add F-Curve to group */
1629         action_groups_add_channel(act, grp, fcu);
1630 }
1631
1632 void AnimationImporter::add_bezt(FCurve *fcu, float fra, float value)
1633 {
1634         BezTriple bez;
1635         memset(&bez, 0, sizeof(BezTriple));
1636         bez.vec[1][0] = fra;
1637         bez.vec[1][1] = value;
1638         bez.ipo = U.ipo_new; /* use default interpolation mode here... */
1639         bez.f1 = bez.f2 = bez.f3 = SELECT;
1640         bez.h1 = bez.h2 = HD_AUTO;
1641         insert_bezt_fcurve(fcu, &bez, 0);
1642         calchandles_fcurve(fcu);
1643 }