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