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