Armature object animations export.
[blender-staging.git] / source / blender / collada / AnimationExporter.cpp
1 /*
2  * $Id: DocumentExporter.cpp 36898 2011-05-25 17:14:31Z phabtar $
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, Jan Diederich, Tod Liverseed.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include "GeometryExporter.h"
26 #include "AnimationExporter.h"
27 #include "MaterialExporter.h"
28
29 template<class Functor>
30 void forEachObjectInScene(Scene *sce, Functor &f)
31 {
32         Base *base= (Base*) sce->base.first;
33         
34         while(base) {
35                 Object *ob = base->object;
36                         
37                 f(ob);
38
39                 base= base->next;
40         }
41 }
42
43 void AnimationExporter::exportAnimations(Scene *sce)
44         {
45                 if(hasAnimations(sce)) {
46                         this->scene = sce;
47
48                         openLibrary();
49
50                         forEachObjectInScene(sce, *this);
51
52                         closeLibrary();
53                 }
54         }
55
56         // called for each exported object
57         void AnimationExporter::operator() (Object *ob) 
58         {
59                 FCurve *fcu;
60                 char * transformName ;
61                 bool isMatAnim = false;
62
63                 //Export transform animations
64                 if(ob->adt && ob->adt->action)      
65                 {
66                         fcu = (FCurve*)ob->adt->action->curves.first;
67
68                         //transform matrix export for bones are temporarily disabled here.
69                         if ( ob->type == OB_ARMATURE )
70                         {
71                                 if (!ob->data) return;
72                                 bArmature *arm = (bArmature*)ob->data;
73                                 for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
74                                         write_bone_animation_matrix(ob, bone);
75                                 
76                                 transformName = fcu->rna_path;
77                         }
78                         else 
79                                 transformName = extract_transform_name( fcu->rna_path );
80                         
81                         while (fcu) {
82                                 transformName = extract_transform_name( fcu->rna_path );
83                                 if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
84                                         (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)||
85                                         (!strcmp(transformName, "rotation_quaternion"))) 
86                                         dae_animation(ob ,fcu, transformName, false);
87                                 fcu = fcu->next;
88                         }
89                 
90                 }
91
92                 //Export Lamp parameter animations
93                 if( (ob->type == OB_LAMP ) && ((Lamp*)ob ->data)->adt && ((Lamp*)ob ->data)->adt->action )
94                 {
95                         fcu = (FCurve*)(((Lamp*)ob ->data)->adt->action->curves.first);
96                         while (fcu) {
97                         transformName = extract_transform_name( fcu->rna_path );
98                                 
99                                 if ((!strcmp(transformName, "color")) || (!strcmp(transformName, "spot_size"))|| (!strcmp(transformName, "spot_blend"))||
100                                         (!strcmp(transformName, "distance")) ) 
101                                         dae_animation(ob , fcu, transformName, true );
102                                 fcu = fcu->next;
103                         }
104                 }
105
106                 //Export Camera parameter animations
107                 if( (ob->type == OB_CAMERA ) && ((Camera*)ob ->data)->adt && ((Camera*)ob ->data)->adt->action )
108                 {               
109                         fcu = (FCurve*)(((Camera*)ob ->data)->adt->action->curves.first);
110                         while (fcu) {
111                         transformName = extract_transform_name( fcu->rna_path );
112                                 
113                                 if ((!strcmp(transformName, "lens"))||
114                                         (!strcmp(transformName, "ortho_scale"))||
115                                         (!strcmp(transformName, "clip_end"))||(!strcmp(transformName, "clip_start"))) 
116                                         dae_animation(ob , fcu, transformName, true );
117                                 fcu = fcu->next;
118                         }
119                 }
120
121                 //Export Material parameter animations.
122                 for(int a = 0; a < ob->totcol; a++)
123                 {
124                         Material *ma = give_current_material(ob, a+1);
125                         if (!ma) continue;
126                         if(ma->adt && ma->adt->action)
127                         {
128                                 isMatAnim = true;
129                                 fcu = (FCurve*)ma->adt->action->curves.first;
130                                 while (fcu) {
131                                         transformName = extract_transform_name( fcu->rna_path );
132                                         
133                                         if ((!strcmp(transformName, "specular_hardness"))||(!strcmp(transformName, "specular_color"))
134                                                 ||(!strcmp(transformName, "diffuse_color"))||(!strcmp(transformName, "alpha"))||
135                                                 (!strcmp(transformName, "ior"))) 
136                                                 dae_animation(ob ,fcu, transformName, true, ma );
137                                         fcu = fcu->next;
138                                 }
139                         }
140                         
141                 }
142                 /* Old System
143                 if (!ob->adt || !ob->adt->action) 
144                         fcu = (FCurve*)((Lamp*)ob->data)->adt->action->curves.first;  //this is already checked in hasAnimations()
145                 else
146                         fcu = (FCurve*)ob->adt->action->curves.first;
147                                                                 
148                 if (ob->type == OB_ARMATURE) {
149                         if (!ob->data) return;
150                         bArmature *arm = (bArmature*)ob->data;
151                         while(fcu)
152                         {               
153                                 transformName = extract_transform_name( fcu->rna_path );
154                         //      std::string ob_name =  getObjectBoneName( ob , fcu);
155                         //      for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
156                         //              write_bone_animation(ob, bone);
157                                 dae_animation(ob, fcu, ob_name, transformName);
158                                 fcu = fcu->next;
159                         }
160                 }
161                 else {*/
162                 
163         }
164
165         //euler sources from quternion sources
166         float * AnimationExporter::get_eul_source_for_quat(Object *ob )
167         {
168                 FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
169                 const int keys = fcu->totvert;  
170                 float *quat = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");  
171                 float *eul = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
172                 float temp_quat[4];
173                 float temp_eul[3];
174                         while(fcu)
175                         {
176                                 char * transformName = extract_transform_name( fcu->rna_path );
177                                 
178                                 if( !strcmp(transformName, "rotation_quaternion") )     { 
179                                         for ( int i = 0 ; i < fcu->totvert ; i++){
180                                                 *(quat + ( i * 4 ) + fcu->array_index) = fcu->bezt[i].vec[1][1];
181                                         }
182                                 }
183                                         fcu = fcu->next;
184                         }
185
186                         for ( int i = 0 ; i < keys ; i++){
187                                 for ( int j = 0;j<4;j++)
188                                         temp_quat[j] = quat[(i*4)+j];
189
190                                 quat_to_eul(temp_eul,temp_quat);
191
192                                 for (int k = 0;k<3;k++)
193                                         eul[i*3 + k] = temp_eul[k];
194
195                         }
196
197                 return eul;
198
199         }
200
201         //Get proper name for bones
202         std::string AnimationExporter::getObjectBoneName( Object* ob,const FCurve* fcu ) 
203         {
204                 //hard-way to derive the bone name from rna_path. Must find more compact method
205                 std::string rna_path = std::string(fcu->rna_path);
206
207                 char* boneName = strtok((char *)rna_path.c_str(), "\"");
208                 boneName = strtok(NULL,"\"");
209                 
210                 if( boneName != NULL )
211                         return /*id_name(ob) + "_" +*/ std::string(boneName);
212                 else            
213                         return id_name(ob);
214         }
215
216         //convert f-curves to animation curves and write
217         void AnimationExporter::dae_animation(Object* ob, FCurve *fcu, char* transformName , bool is_param, Material * ma )
218         {
219                 const char *axis_name = NULL;
220                 char anim_id[200];
221                 
222                 bool has_tangents = false;
223                 bool quatRotation = false;
224                 
225                 if ( !strcmp(transformName, "rotation_quaternion") )
226                 {
227                         fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
228                         quatRotation = true;
229                         return;
230                 }
231                 
232                 //axis names for colors
233                 else if ( !strcmp(transformName, "color")||!strcmp(transformName, "specular_color")||!strcmp(transformName, "diffuse_color")||
234                                   (!strcmp(transformName, "alpha")))
235                 {
236                         const char *axis_names[] = {"R", "G", "B"};
237                         if (fcu->array_index < 3)
238                         axis_name = axis_names[fcu->array_index];
239                 }
240
241                 //axis names for transforms
242                 else if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
243                                 (!strcmp(transformName, "rotation_euler"))||(!strcmp(transformName, "rotation_quaternion")))
244                 {
245                         const char *axis_names[] = {"X", "Y", "Z"};
246                         if (fcu->array_index < 3)
247                         axis_name = axis_names[fcu->array_index];
248                 }
249
250                 //no axis name. single parameter.
251                 else{
252                         axis_name = "";
253                 }
254                 
255                 std::string ob_name = std::string("null");
256
257                 //Create anim Id
258                 if (ob->type == OB_ARMATURE) 
259                 {   
260                         ob_name =  getObjectBoneName( ob , fcu);
261                         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char*)translate_id(ob_name).c_str(),
262                                 transformName, axis_name);
263                 }
264                 else 
265                 {
266                         if (ma)
267                                 ob_name = id_name(ob) + "_material";
268                         else
269                                 ob_name = id_name(ob);
270                         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
271                                  fcu->rna_path, axis_name);
272                 }
273                 
274                 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
275
276                 // create input source
277                 std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
278
279                 // create output source
280                 std::string output_id ;
281                 
282                 //quat rotations are skipped for now, because of complications with determining axis.
283                 if(quatRotation) 
284                 {
285                         float * eul  = get_eul_source_for_quat(ob);
286                         float * eul_axis = (float*)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
287                                 for ( int i = 0 ; i< fcu->totvert ; i++)
288                                         eul_axis[i] = eul[i*3 + fcu->array_index];
289                         output_id= create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis , fcu->totvert, quatRotation, anim_id, axis_name);
290                 }
291                 else 
292                 {
293                         output_id= create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
294                 }
295                 // create interpolations source
296                 std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
297
298                 // handle tangents (if required)
299                 std::string intangent_id;
300                 std::string outtangent_id;
301                 
302                 if (has_tangents) {
303                         // create in_tangent source
304                         intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
305
306                         // create out_tangent source
307                         outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
308                 }
309
310                 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
311                 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
312                 std::string empty;
313                 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
314                 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
315
316                 // this input is required
317                 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
318
319                 if (has_tangents) {
320                         sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
321                         sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
322                 }
323
324                 addSampler(sampler);
325
326                 std::string target ;
327
328                 if ( !is_param )
329                         target = translate_id(ob_name)
330                         + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
331                 else 
332                 {
333                         if ( ob->type == OB_LAMP )
334                                 target = get_light_id(ob)
335                                 + "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
336
337                         if ( ob->type == OB_CAMERA )
338                                 target = get_camera_id(ob)
339                                 + "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
340
341                         if( ma ) 
342                                 target = translate_id(id_name(ma)) + "-effect"
343                                                 +"/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
344                 }
345                 addChannel(COLLADABU::URI(empty, sampler_id), target);
346
347                 closeAnimation();
348         }
349
350
351         
352         //write bone animations in transform matrix sources
353         void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
354         {
355                 if (!ob_arm->adt)
356                         return;
357                 
358                 //This will only export animations of bones in deform group.
359                 /*if(!is_bone_deform_group(bone))
360                         return;*/
361                 
362                 sample_and_write_bone_animation_matrix(ob_arm, bone);
363
364                 for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
365                         write_bone_animation_matrix(ob_arm, child);
366         }
367
368         bool AnimationExporter::is_bone_deform_group(Bone * bone)
369         {   
370                 bool is_def;
371                 //Check if current bone is deform
372                 if((bone->flag & BONE_NO_DEFORM) == 0 ) return true;
373                 //Check child bones
374                 else 
375                 {   
376                         for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next){
377                                 //loop through all the children until deform bone is found, and then return
378                                 is_def = is_bone_deform_group(child);
379                                 if (is_def) return true;
380                         }
381                 }
382         //no deform bone found in children also
383                 return false;
384         }
385
386         void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
387         {
388                 bArmature *arm = (bArmature*)ob_arm->data;
389                 int flag = arm->flag;
390                 std::vector<float> fra;
391                 //char prefix[256];
392
393                 FCurve* fcu = (FCurve*)ob_arm->adt->action->curves.first;
394                 while(fcu)
395                 {
396                         std::string bone_name = getObjectBoneName(ob_arm,fcu);
397                         int val = BLI_strcasecmp((char*)bone_name.c_str(),bone->name);
398                         if(val==0) break;
399                         fcu = fcu->next;
400                 }
401
402                 if(!(fcu)) return; 
403                 bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
404                 if (!pchan)
405                         return;
406         
407                 find_frames(ob_arm, fra);
408
409                 if (flag & ARM_RESTPOS) {
410                         arm->flag &= ~ARM_RESTPOS;
411                         where_is_pose(scene, ob_arm);
412                 }
413
414                 if (fra.size()) {
415                         dae_baked_animation(fra ,ob_arm, bone );
416                 }
417
418                 if (flag & ARM_RESTPOS) 
419                         arm->flag = flag;
420                 where_is_pose(scene, ob_arm);
421         }
422
423         void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm , Bone *bone)
424         {
425                 std::string ob_name = id_name(ob_arm);
426                 std::string bone_name = bone->name;
427                 char anim_id[200];
428                 
429                 if (!fra.size())
430                         return;
431
432                 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
433                                          (char*)translate_id(bone_name).c_str(), "pose_matrix");
434
435                 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
436
437                 // create input source
438                 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
439
440                 // create output source
441                 std::string output_id;
442                 output_id = create_4x4_source( fra, ob_arm , bone ,  anim_id);
443
444                 // create interpolations source
445                 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
446
447                 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
448                 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
449                 std::string empty;
450                 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
451                 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
452
453                 // TODO create in/out tangents source
454
455                 // this input is required
456                 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
457
458                 addSampler(sampler);
459
460                 std::string target = translate_id(bone_name) + "/transform";
461                 addChannel(COLLADABU::URI(empty, sampler_id), target);
462
463                 closeAnimation();
464         }
465
466         // dae_bone_animation -> add_bone_animation
467         // (blend this into dae_bone_animation)
468         void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
469         {
470                 const char *axis_names[] = {"X", "Y", "Z"};
471                 const char *axis_name = NULL;
472                 char anim_id[200];
473                 bool is_rot = tm_type == 0;
474                 
475                 if (!fra.size())
476                         return;
477
478                 char rna_path[200];
479                 BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
480                                          tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
481
482                 if (axis > -1)
483                         axis_name = axis_names[axis];
484                 
485                 std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
486                 
487                 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
488                                          (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
489
490                 openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
491
492                 // create input source
493                 std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
494
495                 // create output source
496                 std::string output_id;
497                 if (axis == -1)
498                         output_id = create_xyz_source(values, fra.size(), anim_id);
499                 else
500                         output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
501
502                 // create interpolations source
503                 std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
504
505                 std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
506                 COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
507                 std::string empty;
508                 sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
509                 sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
510
511                 // TODO create in/out tangents source
512
513                 // this input is required
514                 sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
515
516                 addSampler(sampler);
517
518                 std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
519                 addChannel(COLLADABU::URI(empty, sampler_id), target);
520
521                 closeAnimation();
522         }
523
524         float AnimationExporter::convert_time(float frame)
525         {
526                 return FRA2TIME(frame);
527         }
528
529         float AnimationExporter::convert_angle(float angle)
530         {
531                 return COLLADABU::Math::Utils::radToDegF(angle);
532         }
533
534         std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
535         {
536                 switch(semantic) {
537                 case COLLADASW::InputSemantic::INPUT:
538                         return INPUT_SOURCE_ID_SUFFIX;
539                 case COLLADASW::InputSemantic::OUTPUT:
540                         return OUTPUT_SOURCE_ID_SUFFIX;
541                 case COLLADASW::InputSemantic::INTERPOLATION:
542                         return INTERPOLATION_SOURCE_ID_SUFFIX;
543                 case COLLADASW::InputSemantic::IN_TANGENT:
544                         return INTANGENT_SOURCE_ID_SUFFIX;
545                 case COLLADASW::InputSemantic::OUT_TANGENT:
546                         return OUTTANGENT_SOURCE_ID_SUFFIX;
547                 default:
548                         break;
549                 }
550                 return "";
551         }
552
553         void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
554                                                            COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
555         {
556                 switch(semantic) {
557                 case COLLADASW::InputSemantic::INPUT:
558                         param.push_back("TIME");
559                         break;
560                 case COLLADASW::InputSemantic::OUTPUT:
561                         if (is_rot) {
562                                 param.push_back("ANGLE");
563                         }
564                         else {
565                                 if (axis) {
566                                         param.push_back(axis);
567                                 }
568                                 else 
569                                 if ( transform )
570                                 {
571                                         param.push_back("TRANSFORM");  
572                                 }else{                           //assumes if axis isn't specified all axises are added
573                                         param.push_back("X");
574                                         param.push_back("Y");
575                                         param.push_back("Z");
576                                 }
577                         }
578                         break;
579                 case COLLADASW::InputSemantic::IN_TANGENT:
580                 case COLLADASW::InputSemantic::OUT_TANGENT:
581                         param.push_back("X");
582                         param.push_back("Y");
583                         break;
584                 default:
585                         break;
586                 }
587         }
588
589         void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length)
590         {
591                 switch (semantic) {
592                 case COLLADASW::InputSemantic::INPUT:
593                         *length = 1;
594                         values[0] = convert_time(bezt->vec[1][0]);
595                         break;
596                 case COLLADASW::InputSemantic::OUTPUT:
597                         *length = 1;
598                         if (rotation) {
599                                 values[0] = (bezt->vec[1][1]) * 180.0f/M_PI;
600                         }
601                         else {
602                                 values[0] = bezt->vec[1][1];
603                         }
604                         break;
605                 
606                 case COLLADASW::InputSemantic::IN_TANGENT:
607                 *length = 2;
608                         values[0] = convert_time(bezt->vec[0][0]);
609                         if (bezt->ipo != BEZT_IPO_BEZ) {
610                                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
611                                 values[0] = 0;  
612                                 values[1] = 0;  
613                         }
614                         else if (rotation) {
615                                 values[1] = (bezt->vec[0][1]) * 180.0f/M_PI;
616                         } else {
617                                 values[1] = bezt->vec[0][1];
618                         }
619                         break;
620                 
621                 case COLLADASW::InputSemantic::OUT_TANGENT:
622                         *length = 2;
623                         values[0] = convert_time(bezt->vec[2][0]);
624                         if (bezt->ipo != BEZT_IPO_BEZ) {
625                                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
626                                 values[0] = 0;  
627                                 values[1] = 0;  
628                         }
629                         else if (rotation) {
630                                 values[1] = (bezt->vec[2][1]) * 180.0f/M_PI;
631                         } else {
632                                 values[1] = bezt->vec[2][1];
633                         }
634                         break;
635                         break;
636                 default:
637                         *length = 0;
638                         break;
639                 }
640         }
641
642         std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
643         {
644                 std::string source_id = anim_id + get_semantic_suffix(semantic);
645
646                 //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
647                 bool is_angle = false;
648                 
649                 if (strstr(fcu->rna_path, "rotation")) is_angle = true;
650                 
651                 COLLADASW::FloatSourceF source(mSW);
652                 source.setId(source_id);
653                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
654                 source.setAccessorCount(fcu->totvert);
655                 
656                 switch (semantic) {
657                 case COLLADASW::InputSemantic::INPUT:
658                 case COLLADASW::InputSemantic::OUTPUT:
659                 source.setAccessorStride(1);                    
660                         break;
661                 case COLLADASW::InputSemantic::IN_TANGENT:
662                 case COLLADASW::InputSemantic::OUT_TANGENT:
663                 source.setAccessorStride(2);                    
664                         break;
665                 }
666                 
667                 
668                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
669                 add_source_parameters(param, semantic, is_angle, axis_name, false);
670
671                 source.prepareToAppendValues();
672
673                 for (unsigned int i = 0; i < fcu->totvert; i++) {
674                         float values[3]; // be careful!
675                         int length = 0;
676                         get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length);
677                                 for (int j = 0; j < length; j++)
678                                 source.appendValues(values[j]);
679                 }
680
681                 source.finish();
682
683                 return source_id;
684         }
685
686         //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified )
687         std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
688         {
689                 std::string source_id = anim_id + get_semantic_suffix(semantic);
690
691                 COLLADASW::FloatSourceF source(mSW);
692                 source.setId(source_id);
693                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
694                 source.setAccessorCount(tot);
695                 source.setAccessorStride(1);
696                 
697                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
698                 add_source_parameters(param, semantic, is_rot, axis_name,  false);
699
700                 source.prepareToAppendValues();
701
702                 for (int i = 0; i < tot; i++) {
703                         float val = v[i];
704                         ////if (semantic == COLLADASW::InputSemantic::INPUT)
705                         //      val = convert_time(val);
706                         //else
707                                 if (is_rot)                       
708                                 val *= 180.0f / M_PI;
709                         source.appendValues(val);
710                 }
711
712                 source.finish();
713
714                 return source_id;
715         }
716 // only used for sources with INPUT semantic
717         std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
718         {
719                 std::string source_id = anim_id + get_semantic_suffix(semantic);
720
721                 COLLADASW::FloatSourceF source(mSW);
722                 source.setId(source_id);
723                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
724                 source.setAccessorCount(fra.size());
725                 source.setAccessorStride(1);
726                 
727                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
728                 add_source_parameters(param, semantic, is_rot, axis_name, false);
729
730                 source.prepareToAppendValues();
731
732                 std::vector<float>::iterator it;
733                 for (it = fra.begin(); it != fra.end(); it++) {
734                         float val = *it;
735                         //if (semantic == COLLADASW::InputSemantic::INPUT)
736                                 val = convert_time(val);
737                         /*else if (is_rot)
738                                 val = convert_angle(val);*/
739                         source.appendValues(val);
740                 }
741
742                 source.finish();
743
744                 return source_id;
745         }
746
747         std::string AnimationExporter::create_4x4_source(std::vector<float> &frames , Object * ob_arm, Bone *bone , const std::string& anim_id)
748         {
749                 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
750                 std::string source_id = anim_id + get_semantic_suffix(semantic);
751
752                 COLLADASW::Float4x4Source source(mSW);
753                 source.setId(source_id);
754                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
755                 source.setAccessorCount(frames.size());
756                 source.setAccessorStride(16);
757                 
758                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
759                 add_source_parameters(param, semantic, false, NULL, true);
760
761                 source.prepareToAppendValues();
762                 
763                 bPoseChannel *parchan = NULL;
764                 bPoseChannel *pchan = NULL;
765                 bPose *pose = ob_arm->pose;
766
767                 pchan = get_pose_channel(pose, bone->name);
768
769                 if (!pchan)
770                         return "";
771
772                 parchan = pchan->parent;
773
774                 enable_fcurves(ob_arm->adt->action, bone->name);
775
776                 std::vector<float>::iterator it;
777                 int j = 0;
778                 for (it = frames.begin(); it != frames.end(); it++) {
779                         float mat[4][4], ipar[4][4];
780
781                         float ctime = bsystem_time(scene, ob_arm, *it, 0.0f);
782
783                         BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
784                         where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
785
786                         // compute bone local mat
787                         if (bone->parent) {
788                                 invert_m4_m4(ipar, parchan->pose_mat);
789                                 mul_m4_m4m4(mat, pchan->pose_mat, ipar);
790                         }
791                         else
792                                 copy_m4_m4(mat, pchan->pose_mat);
793                         UnitConverter converter;
794
795                         float outmat[4][4];
796                         converter.mat4_to_dae(outmat,mat);
797
798
799                         source.appendValues(outmat);
800                         
801
802                         j++;
803                 }
804
805                 enable_fcurves(ob_arm->adt->action, NULL);
806
807                 source.finish();
808
809                 return source_id;
810         }
811         // only used for sources with OUTPUT semantic ( locations and scale)
812         std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
813         {
814                 COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
815                 std::string source_id = anim_id + get_semantic_suffix(semantic);
816
817                 COLLADASW::FloatSourceF source(mSW);
818                 source.setId(source_id);
819                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
820                 source.setAccessorCount(tot);
821                 source.setAccessorStride(3);
822                 
823                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
824                 add_source_parameters(param, semantic, false, NULL, false);
825
826                 source.prepareToAppendValues();
827
828                 for (int i = 0; i < tot; i++) {
829                         source.appendValues(*v, *(v + 1), *(v + 2));
830                         v += 3;
831                 }
832
833                 source.finish();
834
835                 return source_id;
836         }
837
838         std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
839         {
840                 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
841
842                 COLLADASW::NameSource source(mSW);
843                 source.setId(source_id);
844                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
845                 source.setAccessorCount(fcu->totvert);
846                 source.setAccessorStride(1);
847                 
848                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
849                 param.push_back("INTERPOLATION");
850
851                 source.prepareToAppendValues();
852
853                 *has_tangents = false;
854
855                 for (unsigned int i = 0; i < fcu->totvert; i++) {
856                         if (fcu->bezt[i].ipo==BEZT_IPO_BEZ) {
857                                 source.appendValues(BEZIER_NAME);
858                                 *has_tangents = true;
859                         } else if (fcu->bezt[i].ipo==BEZT_IPO_CONST) {
860                                 source.appendValues(STEP_NAME);
861                         } else { // BEZT_IPO_LIN
862                                 source.appendValues(LINEAR_NAME);
863                         }
864                 }
865                 // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
866
867                 source.finish();
868
869                 return source_id;
870         }
871
872         std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
873         {
874                 std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
875
876                 COLLADASW::NameSource source(mSW);
877                 source.setId(source_id);
878                 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
879                 source.setAccessorCount(tot);
880                 source.setAccessorStride(1);
881                 
882                 COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
883                 param.push_back("INTERPOLATION");
884
885                 source.prepareToAppendValues();
886
887                 for (int i = 0; i < tot; i++) {
888                         source.appendValues(LINEAR_NAME);
889                 }
890
891                 source.finish();
892
893                 return source_id;
894         }
895
896         std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
897         {
898                 std::string tm_name;
899                 // when given rna_path, determine tm_type from it
900                 if (rna_path) {
901                         char *name = extract_transform_name(rna_path);
902
903                         if (!strcmp(name, "color"))
904                                 tm_type = 1;
905                         else if (!strcmp(name, "spot_size"))
906                                 tm_type = 2;
907                         else if (!strcmp(name, "spot_blend"))
908                                 tm_type = 3;
909                         else if (!strcmp(name, "distance"))
910                                 tm_type = 4;
911                         else
912                                 tm_type = -1;
913                 }
914
915                 switch (tm_type) {
916                 case 1:
917                         tm_name = "color";
918                         break;
919                 case 2:
920                         tm_name = "fall_off_angle";
921                         break;
922                 case 3:
923                         tm_name = "fall_off_exponent";
924                         break;
925                 case 4:
926                         tm_name = "blender/blender_dist";
927                         break;
928                 
929                 default:
930                         tm_name = "";
931                         break;
932                 }
933            
934                 if (tm_name.size()) {
935                         if (axis_name != "")
936                                 return tm_name + "." + std::string(axis_name);
937                         else 
938                                 return tm_name;
939                 }
940
941                 return std::string("");
942         }
943         
944         std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
945         {
946                 std::string tm_name;
947                 // when given rna_path, determine tm_type from it
948                 if (rna_path) {
949                         char *name = extract_transform_name(rna_path);
950
951                         if (!strcmp(name, "lens"))
952                                 tm_type = 0;
953                         else if (!strcmp(name, "ortho_scale"))
954                                 tm_type = 1;
955                         else if (!strcmp(name, "clip_end"))
956                                 tm_type = 2;
957                         else if (!strcmp(name, "clip_start"))
958                                 tm_type = 3;
959                         
960                         else
961                                 tm_type = -1;
962                 }
963
964                 switch (tm_type) {
965                 case 0:
966                         tm_name = "xfov";
967                         break;
968                 case 1:
969                         tm_name = "xmag";
970                         break;
971                 case 2:
972                         tm_name = "zfar";
973                         break;
974                 case 3:
975                         tm_name = "znear";
976                         break;
977                 
978                 default:
979                         tm_name = "";
980                         break;
981                 }
982            
983                 if (tm_name.size()) {
984                         if (axis_name != "")
985                                 return tm_name + "." + std::string(axis_name);
986                         else 
987                                 return tm_name;
988                 }
989
990                 return std::string("");
991         }
992
993         // Assign sid of the animated parameter or transform 
994         // for rotation, axis name is always appended and the value of append_axis is ignored
995         std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
996         {
997                 std::string tm_name;
998                 bool is_rotation =false;
999                 // when given rna_path, determine tm_type from it
1000                 if (rna_path) {
1001                         char *name = extract_transform_name(rna_path);
1002
1003                         if (!strcmp(name, "rotation_euler"))
1004                                 tm_type = 0;
1005                         else if (!strcmp(name, "rotation_quaternion"))
1006                                 tm_type = 1;
1007                         else if (!strcmp(name, "scale"))
1008                                 tm_type = 2;
1009                         else if (!strcmp(name, "location"))
1010                                 tm_type = 3;
1011                         else if (!strcmp(name, "specular_hardness"))
1012                                 tm_type = 4;
1013                         else if (!strcmp(name, "specular_color"))
1014                                 tm_type = 5;
1015                         else if (!strcmp(name, "diffuse_color"))
1016                                 tm_type = 6;
1017                         else if (!strcmp(name, "alpha"))
1018                                 tm_type = 7;
1019                         else if (!strcmp(name, "ior"))
1020                                 tm_type = 8;
1021                         
1022                         else
1023                                 tm_type = -1;
1024                 }
1025
1026                 switch (tm_type) {
1027                 case 0:
1028                 case 1:
1029                         tm_name = "rotation";
1030                         is_rotation = true;
1031                         break;
1032                 case 2:
1033                         tm_name = "scale";
1034                         break;
1035                 case 3:
1036                         tm_name = "location";
1037                         break;
1038                 case 4:
1039                         tm_name = "shininess";
1040                         break;
1041                 case 5:
1042                         tm_name = "specular";
1043                         break;
1044                 case 6:
1045                         tm_name = "diffuse";
1046                         break;  
1047                 case 7:
1048                         tm_name = "transparency";
1049                         break;  
1050                 case 8:
1051                         tm_name = "index_of_refraction";
1052                         break;  
1053                 
1054                 default:
1055                         tm_name = "";
1056                         break;
1057                 }
1058            
1059                 if (tm_name.size()) {
1060                         if (is_rotation)
1061                                 return tm_name + std::string(axis_name) + ".ANGLE";
1062                         else
1063                                 if (axis_name != "")
1064                                         return tm_name + "." + std::string(axis_name);
1065                                 else 
1066                                         return tm_name;
1067                 }
1068
1069                 return std::string("");
1070         }
1071
1072         char* AnimationExporter::extract_transform_name(char *rna_path)
1073         {
1074                 char *dot = strrchr(rna_path, '.');
1075                 return dot ? (dot + 1) : rna_path;
1076         }
1077
1078         //find keyframes of all the objects animations
1079         void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra)
1080         {
1081                 FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
1082
1083                 for (; fcu; fcu = fcu->next) {
1084                         
1085                         for (unsigned int i = 0; i < fcu->totvert; i++) {
1086                                 float f = fcu->bezt[i].vec[1][0];     //
1087                                 if (std::find(fra.begin(), fra.end(), f) == fra.end())   
1088                                         fra.push_back(f);
1089                         }
1090                 }
1091
1092                 // keep the keys in ascending order
1093                 std::sort(fra.begin(), fra.end());
1094         }
1095
1096                 
1097
1098         // enable fcurves driving a specific bone, disable all the rest
1099         // if bone_name = NULL enable all fcurves
1100         void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1101         {
1102                 FCurve *fcu;
1103                 char prefix[200];
1104
1105                 if (bone_name)
1106                         BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1107
1108                 for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) {
1109                         if (bone_name) {
1110                                 if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
1111                                         fcu->flag &= ~FCURVE_DISABLED;
1112                                 else
1113                                         fcu->flag |= FCURVE_DISABLED;
1114                         }
1115                         else {
1116                                 fcu->flag &= ~FCURVE_DISABLED;
1117                         }
1118                 }
1119         }
1120         
1121         bool AnimationExporter::hasAnimations(Scene *sce)
1122         {
1123                 Base *base= (Base*) sce->base.first;
1124                 
1125                 while(base) {
1126                         Object *ob = base->object;
1127                         
1128                         FCurve *fcu = 0;
1129                         //Check for object transform animations
1130                         if(ob->adt && ob->adt->action)      
1131                                 fcu = (FCurve*)ob->adt->action->curves.first;
1132                         //Check for Lamp parameter animations
1133                         else if( (ob->type == OB_LAMP ) && ((Lamp*)ob ->data)->adt && ((Lamp*)ob ->data)->adt->action )
1134                                 fcu = (FCurve*)(((Lamp*)ob ->data)->adt->action->curves.first);
1135                         //Check for Camera parameter animations
1136                         else if( (ob->type == OB_CAMERA ) && ((Camera*)ob ->data)->adt && ((Camera*)ob ->data)->adt->action )
1137                                 fcu = (FCurve*)(((Camera*)ob ->data)->adt->action->curves.first);
1138                         
1139                         //Check Material Effect parameter animations.
1140                         for(int a = 0; a < ob->totcol; a++)
1141                         {
1142                                 Material *ma = give_current_material(ob, a+1);
1143                                 if (!ma) continue;
1144                                 if(ma->adt && ma->adt->action)
1145                                 {
1146                                         fcu = (FCurve*)ma->adt->action->curves.first;   
1147                                 }
1148                         }
1149
1150                         if ( fcu) 
1151                                 return true;
1152                         base= base->next;
1153                 }
1154                 return false;
1155         }
1156
1157         //------------------------------- Not used in the new system.--------------------------------------------------------
1158         void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1159         {
1160                 if (rotmode > 0)
1161                         find_frames(ob, fra, prefix, "rotation_euler");
1162                 else if (rotmode == ROT_MODE_QUAT)
1163                         find_frames(ob, fra, prefix, "rotation_quaternion");
1164                 /*else if (rotmode == ROT_MODE_AXISANGLE)
1165                         ;*/
1166         }
1167
1168         void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1169         {
1170                 FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
1171
1172                 for (; fcu; fcu = fcu->next) {
1173                         if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
1174                                 continue;
1175
1176                         char *name = extract_transform_name(fcu->rna_path);
1177                         if (!strcmp(name, tm_name)) {
1178                                 for (unsigned int i = 0; i < fcu->totvert; i++) {
1179                                         float f = fcu->bezt[i].vec[1][0];     //
1180                                         if (std::find(fra.begin(), fra.end(), f) == fra.end())   
1181                                                 fra.push_back(f);
1182                                 }
1183                         }
1184                 }
1185
1186                 // keep the keys in ascending order
1187                 std::sort(fra.begin(), fra.end());
1188         }
1189
1190         void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1191         {
1192                 if (!ob_arm->adt)
1193                         return;
1194                 
1195                 //write bone animations for 3 transform types
1196                 //i=0 --> rotations
1197                 //i=1 --> scale
1198                 //i=2 --> location
1199                 for (int i = 0; i < 3; i++)
1200                         sample_and_write_bone_animation(ob_arm, bone, i);
1201                 
1202                 for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
1203                         write_bone_animation(ob_arm, child);
1204         }
1205
1206         void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1207         {
1208                 bArmature *arm = (bArmature*)ob_arm->data;
1209                 int flag = arm->flag;
1210                 std::vector<float> fra;
1211                 char prefix[256];
1212
1213                 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1214
1215                 bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
1216                 if (!pchan)
1217                         return;
1218                 //Fill frame array with key frame values framed at @param:transform_type
1219                 switch (transform_type) {
1220                 case 0:
1221                         find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1222                         break;
1223                 case 1:
1224                         find_frames(ob_arm, fra, prefix, "scale");
1225                         break;
1226                 case 2:
1227                         find_frames(ob_arm, fra, prefix, "location");
1228                         break;
1229                 default:
1230                         return;
1231                 }
1232
1233                 // exit rest position
1234                 if (flag & ARM_RESTPOS) {
1235                         arm->flag &= ~ARM_RESTPOS;
1236                         where_is_pose(scene, ob_arm);
1237                 }
1238                 //v array will hold all values which will be exported. 
1239                 if (fra.size()) {
1240                         float *values = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1241                         sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1242
1243                         if (transform_type == 0) {
1244                                 // write x, y, z curves separately if it is rotation
1245                                 float *axisValues = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");   
1246                         
1247                                 for (int i = 0; i < 3; i++) {
1248                                         for (unsigned int j = 0; j < fra.size(); j++)
1249                                                 axisValues[j] = values[j * 3 + i];
1250
1251                                         dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1252                                 }
1253                                 MEM_freeN(axisValues);
1254                         }
1255                         else {
1256                                 // write xyz at once if it is location or scale
1257                                 dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1258                         }
1259
1260                         MEM_freeN(values);
1261                 }
1262
1263                 // restore restpos
1264                 if (flag & ARM_RESTPOS) 
1265                         arm->flag = flag;
1266                 where_is_pose(scene, ob_arm);
1267         }
1268
1269         void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1270         {
1271                 bPoseChannel *parchan = NULL;
1272                 bPose *pose = ob_arm->pose;
1273
1274                 pchan = get_pose_channel(pose, bone->name);
1275
1276                 if (!pchan)
1277                         return;
1278
1279                 parchan = pchan->parent;
1280
1281                 enable_fcurves(ob_arm->adt->action, bone->name);
1282
1283                 std::vector<float>::iterator it;
1284                 for (it = frames.begin(); it != frames.end(); it++) {
1285                         float mat[4][4], ipar[4][4];
1286
1287                         float ctime = bsystem_time(scene, ob_arm, *it, 0.0f);
1288
1289
1290                         BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1291                         where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
1292
1293                         // compute bone local mat
1294                         if (bone->parent) {
1295                                 invert_m4_m4(ipar, parchan->pose_mat);
1296                                 mul_m4_m4m4(mat, pchan->pose_mat, ipar);
1297                         }
1298                         else
1299                                 copy_m4_m4(mat, pchan->pose_mat);
1300
1301                         switch (type) {
1302                         case 0:
1303                                 mat4_to_eul(v, mat);
1304                                 break;
1305                         case 1:
1306                                 mat4_to_size(v, mat);
1307                                 break;
1308                         case 2:
1309                                 copy_v3_v3(v, mat[3]);
1310                                 break;
1311                         }
1312
1313                         v += 3;
1314                 }
1315
1316                 enable_fcurves(ob_arm->adt->action, NULL);
1317         }
1318
1319