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