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