c891414f088ae6183a8177deac34db9a982b7734
[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 bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
53 {
54         for (int i = 0; i < values.size(); i += channel_count) {
55                 for (int j = 0; j < channel_count; j++) {
56                         if (!bc_in_range(values[j], values[i+j], 0.000001))
57                                 return false;
58                 }
59         }
60         return true;
61 }
62 /*
63  *  This function creates a complete LINEAR Collada <Animation> Entry with all needed
64  *  <source>, <sampler>, and <channel> entries.
65  *  This is is used for creating sampled Transformation Animations for either:
66  *
67  *              1-axis animation:
68  *                  times contains the time points in seconds from within the timeline
69  *                      values contains the data (list of single floats)
70  *                      channel_count = 1
71  *                      axis_name = ['X' | 'Y' | 'Z']
72  *                      is_rot indicates if the animation is a rotation
73  *
74  *              3-axis animation:
75  *                      times contains the time points in seconds from within the timeline
76  *                      values contains the data (list of floats where each 3 entries are one vector)
77  *                      channel_count = 3
78  *                      axis_name = "" (actually not used)
79  *                      is_rot = false (see xxx below)
80  *
81  *      xxx: I tried to create a 3 axis rotation animation
82  *               like for translation or scale. But i could not
83  *               figure out how to setup the channel for this case.
84  *               So for now rotations are exported as 3 separate 1-axis collada animations
85  *               See export_sampled_animation() further down.
86  */
87 void AnimationExporter::create_sampled_animation(int channel_count,
88         std::vector<float> &times,
89         std::vector<float> &values,
90         std::string ob_name,
91         std::string label,
92         std::string axis_name,
93         bool is_rot)
94 {
95         char anim_id[200];
96
97         if (is_flat_line(values, channel_count))
98                 return;
99
100         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
101
102         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
103
104         /* create input source */
105         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
106
107         /* create output source */
108         std::string output_id;
109         if (channel_count == 1)
110                 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
111         else if (channel_count == 3)
112                 output_id = create_xyz_source(&values[0], times.size(), anim_id);
113         else if (channel_count == 16)
114                 output_id = create_4x4_source(times, values, anim_id);
115
116         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
117         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
118         std::string empty;
119         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
120         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
121
122         /* TODO create in/out tangents source (LINEAR) */
123         std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
124
125         /* Create Sampler */
126         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
127         addSampler(sampler);
128
129         /* Create channel */
130         std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
131         addChannel(COLLADABU::URI(empty, sampler_id), target);
132
133         closeAnimation();
134
135 }
136
137 /*
138  * Export all animation FCurves of an Object.
139  *
140  * Note: This uses the keyframes as sample points,
141  * and exports "baked keyframes" while keeping the tangent infromation
142  * of the FCurves intact. This works for simple cases, but breaks
143  * especially when negative scales are involved in the animation.
144  *
145  * If it is necessary to conserve the Animation precisely then
146  * use export_sampled_animation_set() instead.
147  */
148 void AnimationExporter::export_keyframed_animation_set(Object *ob)
149 {
150         FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
151         if (!fcu) {
152                 return; /* object has no animation */
153         }
154
155         if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
156
157                 std::vector<float> ctimes;
158                 find_keyframes(ob, ctimes);
159                 if (ctimes.size() > 0)
160                         export_sampled_matrix_animation(ob, ctimes);
161         }
162         else {
163                 char *transformName;
164                 while (fcu) {
165                         //for armature animations as objects
166                         if (ob->type == OB_ARMATURE)
167                                 transformName = fcu->rna_path;
168                         else
169                                 transformName = extract_transform_name(fcu->rna_path);
170
171                         if (
172                                 STREQ(transformName, "location") ||
173                                 STREQ(transformName, "scale") ||
174                                 (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
175                                 STREQ(transformName, "rotation_quaternion"))
176                         {
177                                 create_keyframed_animation(ob, fcu, transformName, false);
178                         }
179                         fcu = fcu->next;
180                 }
181         }
182 }
183
184 /*
185  * Export the sampled animation of an Object.
186  *
187  * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
188  * and then evaluates the transformation,
189  * and exports "baked samples" This works always, however currently the interpolation type is set
190  * to LINEAR for now. (maybe later this can be changed to BEZIER)
191  *
192  * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
193  * However be aware that exporting keyframed animation may modify the animation slightly.
194  * Also keyframed animation exports tend to break when negative scales are involved.
195  */
196 void AnimationExporter::export_sampled_animation_set(Object *ob)
197 {
198         std::vector<float>ctimes;
199         find_sampleframes(ob, ctimes);
200         if (ctimes.size() > 0) {
201                 if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
202                         export_sampled_matrix_animation(ob, ctimes);
203                 else
204                         export_sampled_transrotloc_animation(ob, ctimes);
205         }
206 }
207
208 void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
209 {
210         UnitConverter converter;
211
212         std::vector<float> values;
213
214         for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
215                 float fmat[4][4];
216
217                 bc_update_scene(scene, *ctime);
218                 BKE_object_matrix_local_get(ob, fmat);
219                 if (this->export_settings->limit_precision)
220                         bc_sanitize_mat(fmat, 6);
221
222                 for (int i = 0; i < 4; i++)
223                         for (int j = 0; j < 4; j++)
224                                 values.push_back(fmat[i][j]);
225         }
226
227         std::string ob_name = id_name(ob);
228
229         create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
230 }
231
232 void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
233 {
234         static int LOC   = 0;
235         static int EULX  = 1;
236         static int EULY  = 2;
237         static int EULZ  = 3;
238         static int SCALE = 4;
239
240         std::vector<float> baked_curves[5];
241
242         for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
243                 float fmat[4][4];
244                 float floc[3];
245                 float fquat[4];
246                 float fsize[3];
247                 float feul[3];
248
249                 bc_update_scene(scene, *ctime);
250                 BKE_object_matrix_local_get(ob, fmat);
251                 mat4_decompose(floc, fquat, fsize, fmat);
252                 quat_to_eul(feul, fquat);
253
254                 baked_curves[LOC].push_back(floc[0]);
255                 baked_curves[LOC].push_back(floc[1]);
256                 baked_curves[LOC].push_back(floc[2]);
257
258                 baked_curves[EULX].push_back(feul[0]);
259                 baked_curves[EULY].push_back(feul[1]);
260                 baked_curves[EULZ].push_back(feul[2]);
261
262                 baked_curves[SCALE].push_back(fsize[0]);
263                 baked_curves[SCALE].push_back(fsize[1]);
264                 baked_curves[SCALE].push_back(fsize[2]);
265
266         }
267
268         std::string ob_name = id_name(ob);
269
270         create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale",   "", false);
271         create_sampled_animation(3, ctimes, baked_curves[LOC],  ob_name, "location", "", false);
272
273         /* Not sure how to export rotation as a 3channel animation, 
274          * so separate into 3 single animations for now:
275          */
276
277         create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
278         create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
279         create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
280
281         fprintf(stdout, "Animation Export: Baked %d frames for %s (sampling rate: %d)\n",
282                 (int)baked_curves[0].size(),
283                 ob->id.name,
284                 this->export_settings->sampling_rate);
285 }
286
287 /* called for each exported object */
288 void AnimationExporter::operator()(Object *ob)
289 {
290         char *transformName;
291
292         /* bool isMatAnim = false; */ /* UNUSED */
293
294         //Export transform animations
295         if (ob->adt && ob->adt->action) {
296
297                 if (ob->type == OB_ARMATURE) {
298                         /* Export skeletal animation (if any)*/
299                         bArmature *arm = (bArmature *)ob->data;
300                         for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
301                                 write_bone_animation_matrix(ob, bone);
302                 }
303
304                 /* Armatures can have object animation and skeletal animation*/
305                 if (this->export_settings->sampling_rate < 1) {
306                         export_keyframed_animation_set(ob);
307                 }
308                 else {
309                         export_sampled_animation_set(ob);
310                 }
311         }
312
313         export_object_constraint_animation(ob);
314
315         //This needs to be handled by extra profiles, so postponed for now
316         //export_morph_animation(ob);
317                 
318         //Export Lamp parameter animations
319         if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
320                 FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
321                 while (fcu) {
322                         transformName = extract_transform_name(fcu->rna_path);
323
324                         if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
325                             (STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
326                         {
327                                 create_keyframed_animation(ob, fcu, transformName, true);
328                         }
329                         fcu = fcu->next;
330                 }
331         }
332
333         //Export Camera parameter animations
334         if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
335                 FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
336                 while (fcu) {
337                         transformName = extract_transform_name(fcu->rna_path);
338
339                         if ((STREQ(transformName, "lens")) ||
340                             (STREQ(transformName, "ortho_scale")) ||
341                             (STREQ(transformName, "clip_end")) || 
342                                 (STREQ(transformName, "clip_start")))
343                         {
344                                 create_keyframed_animation(ob, fcu, transformName, true);
345                         }
346                         fcu = fcu->next;
347                 }
348         }
349
350         //Export Material parameter animations.
351         for (int a = 0; a < ob->totcol; a++) {
352                 Material *ma = give_current_material(ob, a + 1);
353                 if (!ma) continue;
354                 if (ma->adt && ma->adt->action) {
355                         /* isMatAnim = true; */
356                         FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
357                         while (fcu) {
358                                 transformName = extract_transform_name(fcu->rna_path);
359
360                                 if ((STREQ(transformName, "specular_hardness")) || (STREQ(transformName, "specular_color")) ||
361                                     (STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
362                                     (STREQ(transformName, "ior")))
363                                 {
364                                         create_keyframed_animation(ob, fcu, transformName, true, ma);
365                                 }
366                                 fcu = fcu->next;
367                         }
368                 }
369         }
370 }
371
372 void AnimationExporter::export_object_constraint_animation(Object *ob)
373 {
374         std::vector<float> fra;
375         //Takes frames of target animations
376         make_anim_frames_from_targets(ob, fra);
377
378         if (fra.size())
379                 dae_baked_object_animation(fra, ob);
380 }
381
382 void AnimationExporter::export_morph_animation(Object *ob)
383
384         FCurve *fcu;
385         char *transformName;
386         Key *key = BKE_key_from_object(ob);
387         if (!key) return;
388
389         if (key->adt && key->adt->action) {
390                 fcu = (FCurve *)key->adt->action->curves.first;
391                 
392                 while (fcu) {
393                         transformName = extract_transform_name(fcu->rna_path);
394
395                         create_keyframed_animation(ob, fcu, transformName, true);
396                         
397                         fcu = fcu->next;
398                 }
399         }
400
401 }
402
403 void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
404 {
405         ListBase *conlist = get_active_constraints(ob);
406         if (conlist == NULL) return;
407         bConstraint *con;
408         for (con = (bConstraint *)conlist->first; con; con = con->next) {
409                 ListBase targets = {NULL, NULL};
410                 
411                 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
412                 
413                 if (!validateConstraints(con)) continue;
414
415                 if (cti && cti->get_constraint_targets) {
416                         bConstraintTarget *ct;
417                         Object *obtar;
418                         /* get targets 
419                          *  - constraints should use ct->matrix, not directly accessing values
420                          *      - ct->matrix members have not yet been calculated here! 
421                          */
422                         cti->get_constraint_targets(con, &targets);
423
424                         for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
425                                 obtar = ct->tar;
426
427                                 if (obtar)
428                                         find_keyframes(obtar, frames);
429                         }
430
431                         if (cti->flush_constraint_targets)
432                                 cti->flush_constraint_targets(con, &targets, 1);
433                 }
434         }
435 }
436
437 //euler sources from quternion sources
438 float *AnimationExporter::get_eul_source_for_quat(Object *ob)
439 {
440         FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
441         const int keys = fcu->totvert;  
442         float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
443         float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
444         float temp_quat[4];
445         float temp_eul[3];
446         while (fcu) {
447                 char *transformName = extract_transform_name(fcu->rna_path);
448
449                 if (STREQ(transformName, "rotation_quaternion") ) {
450                         for (int i = 0; i < fcu->totvert; i++) {
451                                 *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
452                         }
453                 }
454                 fcu = fcu->next;
455         }
456
457         for (int i = 0; i < keys; i++) {
458                 for (int j = 0; j < 4; j++)
459                         temp_quat[j] = quat[(i * 4) + j];
460
461                 quat_to_eul(temp_eul, temp_quat);
462
463                 for (int k = 0; k < 3; k++)
464                         eul[i * 3 + k] = temp_eul[k];
465
466         }
467         MEM_freeN(quat);
468         return eul;
469
470 }
471
472 //Get proper name for bones
473 std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
474 {
475         //hard-way to derive the bone name from rna_path. Must find more compact method
476         std::string rna_path = std::string(fcu->rna_path);
477
478         char *boneName = strtok((char *)rna_path.c_str(), "\"");
479         boneName = strtok(NULL, "\"");
480
481         if (boneName != NULL)
482                 return /*id_name(ob) + "_" +*/ std::string(boneName);
483         else
484                 return id_name(ob);
485 }
486
487 std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
488 {
489         std::string rna_path = std::string(fcu->rna_path);
490         return translate_id(rna_path);
491 }
492
493 /* convert f-curves to animation curves and write */
494 void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
495 {
496         const char *axis_name = NULL;
497         char anim_id[200];
498
499         bool has_tangents = false;
500         bool quatRotation = false;
501
502         Object *obj = NULL;
503
504         if (STREQ(transformName, "rotation_quaternion") ) {
505                 fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
506                 quatRotation = true;
507                 return;
508         }
509
510         //axis names for colors
511         else if (STREQ(transformName, "color") ||
512                  STREQ(transformName, "specular_color") ||
513                  STREQ(transformName, "diffuse_color") ||
514                  STREQ(transformName, "alpha"))
515         {
516                 const char *axis_names[] = {"R", "G", "B"};
517                 if (fcu->array_index < 3)
518                         axis_name = axis_names[fcu->array_index];
519         }
520
521         /*
522          * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
523          * We will use the object to evaluate the animation on all keyframes and calculate the 
524          * resulting object matrix. We need this to incorporate the
525          * effects of the parent inverse matrix (when it contains a rotation component)
526          *
527          * TODO: try to combine exported fcurves into 3 channel animations like done 
528          * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
529          */
530
531         else if (
532                 STREQ(transformName, "scale") ||
533                 STREQ(transformName, "location") ||
534                 STREQ(transformName, "rotation_euler"))
535         {
536                 const char *axis_names[] = {"X", "Y", "Z"};
537                 if (fcu->array_index < 3) {
538                         axis_name = axis_names[fcu->array_index];
539                         obj = ob;
540                 }
541         }
542         else {
543                 /* no axis name. single parameter */
544                 axis_name = "";
545         }
546
547         std::string ob_name = std::string("null");
548
549         /* Create anim Id */
550         if (ob->type == OB_ARMATURE) {
551                 ob_name =  getObjectBoneName(ob, fcu);
552                 BLI_snprintf(
553                         anim_id,
554                         sizeof(anim_id),
555                         "%s_%s.%s",
556                         (char *)translate_id(ob_name).c_str(),
557                         (char *)translate_id(transformName).c_str(),
558                         axis_name);
559         }
560         else {
561                 if (ma)
562                         ob_name = id_name(ob) + "_material";
563                 else
564                         ob_name = id_name(ob);
565
566                 BLI_snprintf(
567                         anim_id,
568                         sizeof(anim_id),
569                         "%s_%s_%s",
570                         (char *)translate_id(ob_name).c_str(),
571                         (char *)getAnimationPathId(fcu).c_str(),
572                         axis_name);
573         }
574
575         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
576
577         // create input source
578         std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
579
580         // create output source
581         std::string output_id;
582
583         //quat rotations are skipped for now, because of complications with determining axis.
584         if (quatRotation) {
585                 float *eul  = get_eul_source_for_quat(ob);
586                 float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
587                 for (int i = 0; i < fcu->totvert; i++) {
588                         eul_axis[i] = eul[i * 3 + fcu->array_index];
589                 }
590                 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
591                 MEM_freeN(eul);
592                 MEM_freeN(eul_axis);
593         }
594         else if (STREQ(transformName, "lens") && (ob->type == OB_CAMERA)) {
595                 output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
596         }
597         else {
598                 output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
599         }
600
601         // create interpolations source
602         std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
603
604         // handle tangents (if required)
605         std::string intangent_id;
606         std::string outtangent_id;
607
608         if (has_tangents) {
609                 // create in_tangent source
610                 intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
611
612                 // create out_tangent source
613                 outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
614         }
615
616         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
617         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
618         std::string empty;
619         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
620         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
621
622         // this input is required
623         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
624
625         if (has_tangents) {
626                 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
627                 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
628         }
629
630         addSampler(sampler);
631
632         std::string target;
633
634         if (!is_param)
635                 target = translate_id(ob_name) +
636                          "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
637         else {
638                 if (ob->type == OB_LAMP)
639                         target = get_light_id(ob) +
640                                  "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
641
642                 if (ob->type == OB_CAMERA)
643                         target = get_camera_id(ob) +
644                                  "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
645
646                 if (ma)
647                         target = translate_id(id_name(ma)) + "-effect" +
648                                  "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
649                 //if shape key animation, this is the main problem, how to define the channel targets.
650                 /*target = get_morph_id(ob) +
651                                  "/value" +*/ 
652         }
653         addChannel(COLLADABU::URI(empty, sampler_id), target);
654
655         closeAnimation();
656 }
657
658
659
660 //write bone animations in transform matrix sources
661 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
662 {
663         if (!ob_arm->adt)
664                 return;
665
666         //This will only export animations of bones in deform group.
667         /* if (!is_bone_deform_group(bone)) return; */
668
669         sample_and_write_bone_animation_matrix(ob_arm, bone);
670
671         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
672                 write_bone_animation_matrix(ob_arm, child);
673 }
674
675 bool AnimationExporter::is_bone_deform_group(Bone *bone)
676 {   
677         bool is_def;
678         //Check if current bone is deform
679         if ((bone->flag & BONE_NO_DEFORM) == 0) return true;
680         //Check child bones
681         else {
682                 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
683                         //loop through all the children until deform bone is found, and then return
684                         is_def = is_bone_deform_group(child);
685                         if (is_def) return true;
686                 }
687         }
688         //no deform bone found in children also
689         return false;
690 }
691
692 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
693 {
694         bArmature *arm = (bArmature *)ob_arm->data;
695         int flag = arm->flag;
696         std::vector<float> fra;
697         //char prefix[256];
698
699         //Check if there is a fcurve in the armature for the bone in param
700         //when baking this check is not needed, solve every bone for every frame.
701         /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
702
703         while (fcu) {
704                 std::string bone_name = getObjectBoneName(ob_arm, fcu);
705                 int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
706                 if (val == 0) break;
707                 fcu = fcu->next;
708         }
709
710         if (!(fcu)) return;*/ 
711
712         bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
713         if (!pchan)
714                 return;
715
716
717         if (this->export_settings->sampling_rate < 1)
718                 find_keyframes(ob_arm, fra);
719         else
720                 find_sampleframes(ob_arm, fra);
721
722         if (flag & ARM_RESTPOS) {
723                 arm->flag &= ~ARM_RESTPOS;
724                 BKE_pose_where_is(scene, ob_arm);
725         }
726
727         if (fra.size()) {
728                 dae_baked_animation(fra, ob_arm, bone);
729         }
730
731         if (flag & ARM_RESTPOS) 
732                 arm->flag = flag;
733         BKE_pose_where_is(scene, ob_arm);
734 }
735
736 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
737 {
738         std::string ob_name = id_name(ob_arm);
739         std::string bone_name = bone->name;
740         char anim_id[200];
741
742         if (!fra.size())
743                 return;
744
745         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
746                      (char *)translate_id(bone_name).c_str(), "pose_matrix");
747
748         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
749
750         // create input source
751         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
752
753         // create output source
754         std::string output_id;
755
756         output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
757
758         // create interpolations source
759         std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
760
761         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
762         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
763         std::string empty;
764         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
765         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
766
767         // TODO create in/out tangents source
768
769         // this input is required
770         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
771
772         addSampler(sampler);
773
774         std::string target = get_joint_id(ob_arm, bone) + "/transform";
775         addChannel(COLLADABU::URI(empty, sampler_id), target);
776
777         closeAnimation();
778 }
779
780 void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
781 {
782         std::string ob_name = id_name(ob);
783         char anim_id[200];
784
785         if (!fra.size())
786                 return;
787
788         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
789                      "object_matrix");
790
791         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
792
793         // create input source
794         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
795
796         // create output source
797         std::string output_id;
798         output_id = create_4x4_source( fra, ob, NULL, anim_id);
799
800         // create interpolations source
801         std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
802
803         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
804         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
805         std::string empty;
806         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
807         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
808
809         // TODO create in/out tangents source
810
811         // this input is required
812         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
813
814         addSampler(sampler);
815
816         std::string target = translate_id(ob_name) + "/transform";
817         addChannel(COLLADABU::URI(empty, sampler_id), target);
818
819         closeAnimation();
820 }
821
822 // dae_bone_animation -> add_bone_animation
823 // (blend this into dae_bone_animation)
824 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
825 {
826         const char *axis_names[] = {"X", "Y", "Z"};
827         const char *axis_name = NULL;
828         char anim_id[200];
829         bool is_rot = tm_type == 0;
830
831         if (!fra.size())
832                 return;
833
834         char rna_path[200];
835         BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
836                      tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
837
838         if (axis > -1)
839                 axis_name = axis_names[axis];
840
841         std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
842
843         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
844                      (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
845
846         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
847
848         // create input source
849         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
850
851         // create output source
852         std::string output_id;
853         if (axis == -1)
854                 output_id = create_xyz_source(values, fra.size(), anim_id);
855         else
856                 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
857
858         // create interpolations source
859         std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
860
861         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
862         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
863         std::string empty;
864         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
865         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
866
867         // TODO create in/out tangents source
868
869         // this input is required
870         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
871
872         addSampler(sampler);
873
874         std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
875         addChannel(COLLADABU::URI(empty, sampler_id), target);
876
877         closeAnimation();
878 }
879
880 float AnimationExporter::convert_time(float frame)
881 {
882         return FRA2TIME(frame);
883 }
884
885 float AnimationExporter::convert_angle(float angle)
886 {
887         return COLLADABU::Math::Utils::radToDegF(angle);
888 }
889
890 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
891 {
892         switch (semantic) {
893                 case COLLADASW::InputSemantic::INPUT:
894                         return INPUT_SOURCE_ID_SUFFIX;
895                 case COLLADASW::InputSemantic::OUTPUT:
896                         return OUTPUT_SOURCE_ID_SUFFIX;
897                 case COLLADASW::InputSemantic::INTERPOLATION:
898                         return INTERPOLATION_SOURCE_ID_SUFFIX;
899                 case COLLADASW::InputSemantic::IN_TANGENT:
900                         return INTANGENT_SOURCE_ID_SUFFIX;
901                 case COLLADASW::InputSemantic::OUT_TANGENT:
902                         return OUTTANGENT_SOURCE_ID_SUFFIX;
903                 default:
904                         break;
905         }
906         return "";
907 }
908
909 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
910                                               COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
911 {
912         switch (semantic) {
913                 case COLLADASW::InputSemantic::INPUT:
914                         param.push_back("TIME");
915                         break;
916                 case COLLADASW::InputSemantic::OUTPUT:
917                         if (is_rot) {
918                                 param.push_back("ANGLE");
919                         }
920                         else {
921                                 if (axis) {
922                                         param.push_back(axis);
923                                 }
924                                 else 
925                                 if (transform) {
926                                         param.push_back("TRANSFORM");
927                                 }
928                                 else {     //assumes if axis isn't specified all axises are added
929                                         param.push_back("X");
930                                         param.push_back("Y");
931                                         param.push_back("Z");
932                                 }
933                         }
934                         break;
935                 case COLLADASW::InputSemantic::IN_TANGENT:
936                 case COLLADASW::InputSemantic::OUT_TANGENT:
937                         param.push_back("X");
938                         param.push_back("Y");
939                         break;
940                 default:
941                         break;
942         }
943 }
944
945 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_angle, float *values, int *length)
946 {
947         switch (semantic) {
948                 case COLLADASW::InputSemantic::INPUT:
949                         *length = 1;
950                         values[0] = convert_time(bezt->vec[1][0]);
951                         break;
952                 case COLLADASW::InputSemantic::OUTPUT:
953                         *length = 1;
954                         if (is_angle) {
955                                 values[0] = RAD2DEGF(bezt->vec[1][1]);
956                         }
957                         else {
958                                 values[0] = bezt->vec[1][1];
959                         }
960                         break;
961
962                 case COLLADASW::InputSemantic::IN_TANGENT:
963                         *length = 2;
964                         values[0] = convert_time(bezt->vec[0][0]);
965                         if (bezt->ipo != BEZT_IPO_BEZ) {
966                                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
967                                 values[0] = 0;
968                                 values[1] = 0;
969                         }
970                         else if (is_angle) {
971                                 values[1] = RAD2DEGF(bezt->vec[0][1]);
972                         }
973                         else {
974                                 values[1] = bezt->vec[0][1];
975                         }
976                         break;
977
978                 case COLLADASW::InputSemantic::OUT_TANGENT:
979                         *length = 2;
980                         values[0] = convert_time(bezt->vec[2][0]);
981                         if (bezt->ipo != BEZT_IPO_BEZ) {
982                                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
983                                 values[0] = 0;
984                                 values[1] = 0;
985                         }
986                         else if (is_angle) {
987                                 values[1] = RAD2DEGF(bezt->vec[2][1]);
988                         }
989                         else {
990                                 values[1] = bezt->vec[2][1];
991                         }
992                         break;
993                 default:
994                         *length = 0;
995                         break;
996         }
997 }
998
999 // old function to keep compatibility for calls where offset and object are not needed
1000 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
1001 {
1002         return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
1003 }
1004
1005 void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
1006 {
1007         BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1008         ListBase *conlist = get_active_constraints(ob);
1009         bConstraint *con;
1010         for (con = (bConstraint *)conlist->first; con; con = con->next) {
1011                 ListBase targets = { NULL, NULL };
1012
1013                 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1014
1015                 if (cti && cti->get_constraint_targets) {
1016                         bConstraintTarget *ct;
1017                         Object *obtar;
1018                         cti->get_constraint_targets(con, &targets);
1019                         for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1020                                 obtar = ct->tar;
1021
1022                                 if (obtar) {
1023                                         BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1024                                         BKE_object_where_is_calc_time(scene, obtar, ctime);
1025                                 }
1026                         }
1027
1028                         if (cti->flush_constraint_targets)
1029                                 cti->flush_constraint_targets(con, &targets, 1);
1030                 }
1031         }
1032         BKE_object_where_is_calc_time(scene, ob, ctime);
1033 }
1034
1035 /*
1036  * ob is needed to aply parent inverse information to fcurve.
1037  * TODO: Here we have to step over all keyframes for each object and for each fcurve.
1038  * Instead of processing each fcurve one by one,
1039  * step over the animation from keyframe to keyframe,
1040  * then create adjusted fcurves (and entries) for all affected objects.
1041  * Then we would need to step through the scene only once.
1042  */
1043 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
1044 {
1045         std::string source_id = anim_id + get_semantic_suffix(semantic);
1046
1047         bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
1048         bool is_euler = strstr(fcu->rna_path, "rotation_euler");
1049         bool is_translation = strstr(fcu->rna_path, "location");
1050         bool is_scale = strstr(fcu->rna_path, "scale");
1051         bool is_tangent = false;
1052         int offset_index = 0;
1053
1054         COLLADASW::FloatSourceF source(mSW);
1055         source.setId(source_id);
1056         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1057         source.setAccessorCount(fcu->totvert);
1058
1059         switch (semantic) {
1060                 case COLLADASW::InputSemantic::INPUT:
1061                 case COLLADASW::InputSemantic::OUTPUT:
1062                         source.setAccessorStride(1);
1063                         offset_index = 0;
1064                         break;
1065                 case COLLADASW::InputSemantic::IN_TANGENT:
1066                 case COLLADASW::InputSemantic::OUT_TANGENT:
1067                         source.setAccessorStride(2);
1068                         offset_index = 1;
1069                         is_tangent = true;
1070                         break;
1071                 default:
1072                         break;
1073         }
1074
1075         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1076         add_source_parameters(param, semantic, is_angle, axis_name, false);
1077
1078         source.prepareToAppendValues();
1079
1080         for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
1081                 float fixed_val = 0;
1082                 if (ob) {
1083                         float fmat[4][4];
1084                         float frame = fcu->bezt[frame_index].vec[1][0];
1085                         float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1086
1087                         evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
1088
1089                         BKE_object_matrix_local_get(ob, fmat);
1090                         float floc[3];
1091                         float fquat[4];
1092                         float fsize[3];
1093                         mat4_decompose(floc, fquat, fsize, fmat);
1094
1095                         if (is_euler) {
1096                                 float eul[3];
1097                                 quat_to_eul(eul, fquat);
1098                                 fixed_val = RAD2DEGF(eul[fcu->array_index]);
1099                         }
1100                         else if (is_translation) {
1101                                 fixed_val = floc[fcu->array_index];
1102                         }
1103                         else if (is_scale) {
1104                                 fixed_val = fsize[fcu->array_index];
1105                         }
1106                 }
1107
1108                 float values[3]; // be careful!
1109                 float offset = 0;
1110                 int length = 0;
1111                 get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
1112                 if (is_tangent) {
1113                         float bases[3];
1114                         int len = 0;
1115                         get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
1116                         offset = values[offset_index] - bases[0];
1117                 }
1118
1119                 for (int j = 0; j < length; j++) {
1120                         float val;
1121                         if (j == offset_index) {
1122                                 if (ob) {
1123                                         val = fixed_val + offset;
1124                                 }
1125                                 else {
1126                                         val = values[j] + offset;
1127                                 }
1128                         } else {
1129                                 val = values[j];
1130                         }
1131                         source.appendValues(val);
1132                 }
1133         }
1134
1135         source.finish();
1136
1137         return source_id;
1138 }
1139
1140 /*
1141  * Similar to create_source_from_fcurve, but adds conversion of lens
1142  * animation data from focal length to FOV.
1143  */
1144 std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id)
1145 {
1146         std::string source_id = anim_id + get_semantic_suffix(semantic);
1147
1148         COLLADASW::FloatSourceF source(mSW);
1149         source.setId(source_id);
1150         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1151         source.setAccessorCount(fcu->totvert);
1152
1153         source.setAccessorStride(1);
1154
1155         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1156         add_source_parameters(param, semantic, false, "", false);
1157
1158         source.prepareToAppendValues();
1159
1160         for (unsigned int i = 0; i < fcu->totvert; i++) {
1161                 float values[3]; // be careful!
1162                 int length = 0;
1163                 get_source_values(&fcu->bezt[i], semantic, false, values, &length);
1164                 for (int j = 0; j < length; j++)
1165                 {
1166                         float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x));
1167                         source.appendValues(val);
1168                 }
1169         }
1170
1171         source.finish();
1172
1173         return source_id;
1174 }
1175
1176 /*
1177  * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
1178  */
1179 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)
1180 {
1181         std::string source_id = anim_id + get_semantic_suffix(semantic);
1182
1183         COLLADASW::FloatSourceF source(mSW);
1184         source.setId(source_id);
1185         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1186         source.setAccessorCount(tot);
1187         source.setAccessorStride(1);
1188
1189         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1190         add_source_parameters(param, semantic, is_rot, axis_name,  false);
1191
1192         source.prepareToAppendValues();
1193
1194         for (int i = 0; i < tot; i++) {
1195                 float val = v[i];
1196                 ////if (semantic == COLLADASW::InputSemantic::INPUT)
1197                 //      val = convert_time(val);
1198                 //else
1199                 if (is_rot)
1200                         val = RAD2DEGF(val);
1201                 source.appendValues(val);
1202         }
1203
1204         source.finish();
1205
1206         return source_id;
1207 }
1208
1209 /*
1210  * only used for sources with INPUT semantic
1211  */
1212 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)
1213 {
1214         std::string source_id = anim_id + get_semantic_suffix(semantic);
1215
1216         COLLADASW::FloatSourceF source(mSW);
1217         source.setId(source_id);
1218         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1219         source.setAccessorCount(fra.size());
1220         source.setAccessorStride(1);
1221
1222         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1223         add_source_parameters(param, semantic, is_rot, axis_name, false);
1224
1225         source.prepareToAppendValues();
1226
1227         std::vector<float>::iterator it;
1228         for (it = fra.begin(); it != fra.end(); it++) {
1229                 float val = *it;
1230                 //if (semantic == COLLADASW::InputSemantic::INPUT)
1231                 val = convert_time(val);
1232                 /*else if (is_rot)
1233                    val = convert_angle(val);*/
1234                 source.appendValues(val);
1235         }
1236
1237         source.finish();
1238
1239         return source_id;
1240 }
1241
1242 std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
1243 {
1244         COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1245         std::string source_id = anim_id + get_semantic_suffix(semantic);
1246
1247         COLLADASW::Float4x4Source source(mSW);
1248         source.setId(source_id);
1249         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1250         source.setAccessorCount(ctimes.size());
1251         source.setAccessorStride(16);
1252
1253         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1254         add_source_parameters(param, semantic, false, NULL, true);
1255
1256         source.prepareToAppendValues();
1257
1258         std::vector<float>::iterator it;
1259
1260         for (it = values.begin(); it != values.end(); it+=16) {
1261                 float mat[4][4];
1262
1263                 bc_copy_m4_farray(mat, &*it);
1264
1265                 UnitConverter converter;
1266                 double outmat[4][4];
1267                 converter.mat4_to_dae_double(outmat, mat);
1268
1269                 if (this->export_settings->limit_precision)
1270                         bc_sanitize_mat(outmat, 6);
1271
1272                 source.appendValues(outmat);
1273         }
1274
1275         source.finish();
1276         return source_id;
1277 }
1278
1279 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
1280 {
1281         bool is_bone_animation = ob->type == OB_ARMATURE && bone;
1282
1283         COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1284         std::string source_id = anim_id + get_semantic_suffix(semantic);
1285
1286         COLLADASW::Float4x4Source source(mSW);
1287         source.setId(source_id);
1288         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1289         source.setAccessorCount(frames.size());
1290         source.setAccessorStride(16);
1291
1292         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1293         add_source_parameters(param, semantic, false, NULL, true);
1294
1295         source.prepareToAppendValues();
1296
1297         bPoseChannel *parchan = NULL;
1298         bPoseChannel *pchan = NULL;
1299
1300         if (is_bone_animation) {
1301                 bPose *pose = ob->pose;
1302                 pchan = BKE_pose_channel_find_name(pose, bone->name);
1303                 if (!pchan)
1304                         return "";
1305
1306                 parchan = pchan->parent;
1307
1308                 enable_fcurves(ob->adt->action, bone->name);
1309         }
1310         
1311         std::vector<float>::iterator it;
1312         int j = 0;
1313         for (it = frames.begin(); it != frames.end(); it++) {
1314                 float mat[4][4], ipar[4][4];
1315                 float frame = *it;
1316
1317                 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1318                 bc_update_scene(scene, ctime);
1319                 if (is_bone_animation) {
1320                         if (pchan->flag & POSE_CHAIN) {
1321                                 enable_fcurves(ob->adt->action, NULL);
1322                                 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1323                                 BKE_pose_where_is(scene, ob);
1324                         }
1325                         else {
1326                                 BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
1327                         }
1328                         
1329                         // compute bone local mat
1330                         if (bone->parent) {
1331                                 invert_m4_m4(ipar, parchan->pose_mat);
1332                                 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1333                         }
1334                         else
1335                                 copy_m4_m4(mat, pchan->pose_mat);
1336                         
1337                         /* OPEN_SIM_COMPATIBILITY
1338                          * AFAIK animation to second life is via BVH, but no
1339                          * reason to not have the collada-animation be correct
1340                          */
1341                         if (export_settings->open_sim) {
1342                                 float temp[4][4];
1343                                 copy_m4_m4(temp, bone->arm_mat);
1344                                 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1345                                 invert_m4(temp);
1346
1347                                 mul_m4_m4m4(mat, mat, temp);
1348
1349                                 if (bone->parent) {
1350                                         copy_m4_m4(temp, bone->parent->arm_mat);
1351                                         temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1352
1353                                         mul_m4_m4m4(mat, temp, mat);
1354                                 }
1355                         }
1356
1357                 }
1358                 else {
1359                         copy_m4_m4(mat, ob->obmat);
1360                 }
1361                 
1362                 UnitConverter converter;
1363
1364                 double outmat[4][4];
1365                 converter.mat4_to_dae_double(outmat, mat);
1366
1367                 if (this->export_settings->limit_precision)
1368                         bc_sanitize_mat(outmat, 6);
1369
1370                 source.appendValues(outmat);
1371
1372                 j++;
1373
1374                 BIK_release_tree(scene, ob, ctime);
1375         }
1376
1377         if (ob->adt) {
1378                 enable_fcurves(ob->adt->action, NULL);
1379         }
1380
1381         source.finish();
1382
1383         return source_id;
1384 }
1385
1386
1387 /*
1388  * only used for sources with OUTPUT semantic ( locations and scale)
1389  */
1390 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
1391 {
1392         COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1393         std::string source_id = anim_id + get_semantic_suffix(semantic);
1394
1395         COLLADASW::FloatSourceF source(mSW);
1396         source.setId(source_id);
1397         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1398         source.setAccessorCount(tot);
1399         source.setAccessorStride(3);
1400
1401         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1402         add_source_parameters(param, semantic, false, NULL, false);
1403
1404         source.prepareToAppendValues();
1405
1406         for (int i = 0; i < tot; i++) {
1407                 source.appendValues(*v, *(v + 1), *(v + 2));
1408                 v += 3;
1409         }
1410
1411         source.finish();
1412
1413         return source_id;
1414 }
1415
1416 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
1417 {
1418         std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1419
1420         COLLADASW::NameSource source(mSW);
1421         source.setId(source_id);
1422         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1423         source.setAccessorCount(fcu->totvert);
1424         source.setAccessorStride(1);
1425
1426         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1427         param.push_back("INTERPOLATION");
1428
1429         source.prepareToAppendValues();
1430
1431         *has_tangents = false;
1432
1433         for (unsigned int i = 0; i < fcu->totvert; i++) {
1434                 if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
1435                         source.appendValues(BEZIER_NAME);
1436                         *has_tangents = true;
1437                 }
1438                 else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
1439                         source.appendValues(STEP_NAME);
1440                 }
1441                 else { // BEZT_IPO_LIN
1442                         source.appendValues(LINEAR_NAME);
1443                 }
1444         }
1445         // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
1446
1447         source.finish();
1448
1449         return source_id;
1450 }
1451
1452 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
1453 {
1454         std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1455
1456         COLLADASW::NameSource source(mSW);
1457         source.setId(source_id);
1458         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1459         source.setAccessorCount(tot);
1460         source.setAccessorStride(1);
1461
1462         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1463         param.push_back("INTERPOLATION");
1464
1465         source.prepareToAppendValues();
1466
1467         for (int i = 0; i < tot; i++) {
1468                 source.appendValues(LINEAR_NAME);
1469         }
1470
1471         source.finish();
1472
1473         return source_id;
1474 }
1475
1476 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1477 {
1478         std::string tm_name;
1479         // when given rna_path, determine tm_type from it
1480         if (rna_path) {
1481                 char *name = extract_transform_name(rna_path);
1482
1483                 if (STREQ(name, "color"))
1484                         tm_type = 1;
1485                 else if (STREQ(name, "spot_size"))
1486                         tm_type = 2;
1487                 else if (STREQ(name, "spot_blend"))
1488                         tm_type = 3;
1489                 else if (STREQ(name, "distance"))
1490                         tm_type = 4;
1491                 else
1492                         tm_type = -1;
1493         }
1494
1495         switch (tm_type) {
1496                 case 1:
1497                         tm_name = "color";
1498                         break;
1499                 case 2:
1500                         tm_name = "fall_off_angle";
1501                         break;
1502                 case 3:
1503                         tm_name = "fall_off_exponent";
1504                         break;
1505                 case 4:
1506                         tm_name = "blender/blender_dist";
1507                         break;
1508
1509                 default:
1510                         tm_name = "";
1511                         break;
1512         }
1513
1514         if (tm_name.size()) {
1515                 if (axis_name[0])
1516                         return tm_name + "." + std::string(axis_name);
1517                 else 
1518                         return tm_name;
1519         }
1520
1521         return std::string("");
1522 }
1523
1524 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1525 {
1526         std::string tm_name;
1527         // when given rna_path, determine tm_type from it
1528         if (rna_path) {
1529                 char *name = extract_transform_name(rna_path);
1530
1531                 if (STREQ(name, "lens"))
1532                         tm_type = 0;
1533                 else if (STREQ(name, "ortho_scale"))
1534                         tm_type = 1;
1535                 else if (STREQ(name, "clip_end"))
1536                         tm_type = 2;
1537                 else if (STREQ(name, "clip_start"))
1538                         tm_type = 3;
1539
1540                 else
1541                         tm_type = -1;
1542         }
1543
1544         switch (tm_type) {
1545                 case 0:
1546                         tm_name = "xfov";
1547                         break;
1548                 case 1:
1549                         tm_name = "xmag";
1550                         break;
1551                 case 2:
1552                         tm_name = "zfar";
1553                         break;
1554                 case 3:
1555                         tm_name = "znear";
1556                         break;
1557
1558                 default:
1559                         tm_name = "";
1560                         break;
1561         }
1562
1563         if (tm_name.size()) {
1564                 if (axis_name[0])
1565                         return tm_name + "." + std::string(axis_name);
1566                 else 
1567                         return tm_name;
1568         }
1569
1570         return std::string("");
1571 }
1572
1573 /*
1574  * Assign sid of the animated parameter or transform for rotation,
1575  * axis name is always appended and the value of append_axis is ignored
1576  */
1577 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1578 {
1579         std::string tm_name;
1580         bool is_angle = false;
1581         // when given rna_path, determine tm_type from it
1582         if (rna_path) {
1583                 char *name = extract_transform_name(rna_path);
1584
1585                 if (STREQ(name, "rotation_euler"))
1586                         tm_type = 0;
1587                 else if (STREQ(name, "rotation_quaternion"))
1588                         tm_type = 1;
1589                 else if (STREQ(name, "scale"))
1590                         tm_type = 2;
1591                 else if (STREQ(name, "location"))
1592                         tm_type = 3;
1593                 else if (STREQ(name, "specular_hardness"))
1594                         tm_type = 4;
1595                 else if (STREQ(name, "specular_color"))
1596                         tm_type = 5;
1597                 else if (STREQ(name, "diffuse_color"))
1598                         tm_type = 6;
1599                 else if (STREQ(name, "alpha"))
1600                         tm_type = 7;
1601                 else if (STREQ(name, "ior"))
1602                         tm_type = 8;
1603
1604                 else
1605                         tm_type = -1;
1606         }
1607
1608         switch (tm_type) {
1609                 case 0:
1610                 case 1:
1611                         tm_name = "rotation";
1612                         is_angle = true;
1613                         break;
1614                 case 2:
1615                         tm_name = "scale";
1616                         break;
1617                 case 3:
1618                         tm_name = "location";
1619                         break;
1620                 case 4:
1621                         tm_name = "shininess";
1622                         break;
1623                 case 5:
1624                         tm_name = "specular";
1625                         break;
1626                 case 6:
1627                         tm_name = "diffuse";
1628                         break;
1629                 case 7:
1630                         tm_name = "transparency";
1631                         break;
1632                 case 8:
1633                         tm_name = "index_of_refraction";
1634                         break;
1635
1636                 default:
1637                         tm_name = "";
1638                         break;
1639         }
1640
1641         if (tm_name.size()) {
1642                 if (is_angle)
1643                         return tm_name + std::string(axis_name) + ".ANGLE";
1644                 else
1645                 if (axis_name[0])
1646                         return tm_name + "." + std::string(axis_name);
1647                 else
1648                         return tm_name;
1649         }
1650
1651         return std::string("");
1652 }
1653
1654 char *AnimationExporter::extract_transform_name(char *rna_path)
1655 {
1656         char *dot = strrchr(rna_path, '.');
1657         return dot ? (dot + 1) : rna_path;
1658 }
1659
1660 /*
1661  * enable fcurves driving a specific bone, disable all the rest
1662  * if bone_name = NULL enable all fcurves
1663  */
1664 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1665 {
1666         FCurve *fcu;
1667         char prefix[200];
1668
1669         if (bone_name)
1670                 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1671
1672         for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
1673                 if (bone_name) {
1674                         if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
1675                                 fcu->flag &= ~FCURVE_DISABLED;
1676                         else
1677                                 fcu->flag |= FCURVE_DISABLED;
1678                 }
1679                 else {
1680                         fcu->flag &= ~FCURVE_DISABLED;
1681                 }
1682         }
1683 }
1684
1685 bool AnimationExporter::hasAnimations(Scene *sce)
1686 {
1687         LinkNode *node;
1688
1689         for (node=this->export_settings->export_set; node; node=node->next) {
1690                 Object *ob = (Object *)node->link;
1691
1692                 FCurve *fcu = 0;
1693                 //Check for object transform animations
1694                 if (ob->adt && ob->adt->action)
1695                         fcu = (FCurve *)ob->adt->action->curves.first;
1696                 //Check for Lamp parameter animations
1697                 else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
1698                         fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
1699                 //Check for Camera parameter animations
1700                 else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
1701                         fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
1702
1703                 //Check Material Effect parameter animations.
1704                 for (int a = 0; a < ob->totcol; a++) {
1705                         Material *ma = give_current_material(ob, a + 1);
1706                         if (!ma) continue;
1707                         if (ma->adt && ma->adt->action) {
1708                                 fcu = (FCurve *)ma->adt->action->curves.first;
1709                         }
1710                 }
1711
1712                 //check shape key animation
1713                 if (!fcu) {
1714                         Key *key = BKE_key_from_object(ob);
1715                         if (key && key->adt && key->adt->action)
1716                                 fcu = (FCurve *)key->adt->action->curves.first;
1717                 }
1718                 if (fcu)
1719                         return true;
1720         }
1721         return false;
1722 }
1723
1724 //------------------------------- Not used in the new system.--------------------------------------------------------
1725 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1726 {
1727         if (rotmode > 0)
1728                 find_keyframes(ob, fra, prefix, "rotation_euler");
1729         else if (rotmode == ROT_MODE_QUAT)
1730                 find_keyframes(ob, fra, prefix, "rotation_quaternion");
1731         /*else if (rotmode == ROT_MODE_AXISANGLE)
1732            ;*/
1733 }
1734
1735 /* Take care to always have the first frame and the last frame in the animation
1736  * regardless of the sampling_rate setting
1737  */
1738 void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
1739 {
1740         int frame = scene->r.sfra;
1741         do {
1742                 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1743                 fra.push_back(ctime);
1744                 if (frame == scene->r.efra)
1745                         break;
1746                 frame += this->export_settings->sampling_rate;
1747                 if (frame > scene->r.efra)
1748                         frame = scene->r.efra; // make sure the last frame is always exported
1749
1750         } while (true);
1751 }
1752
1753 /* 
1754  * find keyframes of all the objects animations
1755  */
1756 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
1757 {
1758         if (ob->adt && ob->adt->action) {
1759                 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1760
1761                 for (; fcu; fcu = fcu->next) {
1762                         for (unsigned int i = 0; i < fcu->totvert; i++) {
1763                                 float f = fcu->bezt[i].vec[1][0];
1764                                 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1765                                         fra.push_back(f);
1766                         }
1767                 }
1768
1769                 // keep the keys in ascending order
1770                 std::sort(fra.begin(), fra.end());
1771         }
1772 }
1773
1774 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1775 {
1776         if (ob->adt && ob->adt->action) {
1777                 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1778
1779                 for (; fcu; fcu = fcu->next) {
1780                         if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
1781                                 continue;
1782
1783                         char *name = extract_transform_name(fcu->rna_path);
1784                         if (STREQ(name, tm_name)) {
1785                                 for (unsigned int i = 0; i < fcu->totvert; i++) {
1786                                         float f = fcu->bezt[i].vec[1][0];
1787                                         if (std::find(fra.begin(), fra.end(), f) == fra.end())
1788                                                 fra.push_back(f);
1789                                 }
1790                         }
1791                 }
1792
1793                 // keep the keys in ascending order
1794                 std::sort(fra.begin(), fra.end());
1795         }
1796 }
1797
1798 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1799 {
1800         if (!ob_arm->adt)
1801                 return;
1802
1803         //write bone animations for 3 transform types
1804         //i=0 --> rotations
1805         //i=1 --> scale
1806         //i=2 --> location
1807         for (int i = 0; i < 3; i++)
1808                 sample_and_write_bone_animation(ob_arm, bone, i);
1809
1810         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
1811                 write_bone_animation(ob_arm, child);
1812 }
1813
1814 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1815 {
1816         bArmature *arm = (bArmature *)ob_arm->data;
1817         int flag = arm->flag;
1818         std::vector<float> fra;
1819         char prefix[256];
1820
1821         BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1822
1823         bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
1824         if (!pchan)
1825                 return;
1826         //Fill frame array with key frame values framed at \param:transform_type
1827         switch (transform_type) {
1828                 case 0:
1829                         find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1830                         break;
1831                 case 1:
1832                         find_keyframes(ob_arm, fra, prefix, "scale");
1833                         break;
1834                 case 2:
1835                         find_keyframes(ob_arm, fra, prefix, "location");
1836                         break;
1837                 default:
1838                         return;
1839         }
1840
1841         // exit rest position
1842         if (flag & ARM_RESTPOS) {
1843                 arm->flag &= ~ARM_RESTPOS;
1844                 BKE_pose_where_is(scene, ob_arm);
1845         }
1846         //v array will hold all values which will be exported. 
1847         if (fra.size()) {
1848                 float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1849                 sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1850
1851                 if (transform_type == 0) {
1852                         // write x, y, z curves separately if it is rotation
1853                         float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
1854
1855                         for (int i = 0; i < 3; i++) {
1856                                 for (unsigned int j = 0; j < fra.size(); j++)
1857                                         axisValues[j] = values[j * 3 + i];
1858
1859                                 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1860                         }
1861                         MEM_freeN(axisValues);
1862                 }
1863                 else {
1864                         // write xyz at once if it is location or scale
1865                         dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1866                 }
1867
1868                 MEM_freeN(values);
1869         }
1870
1871         // restore restpos
1872         if (flag & ARM_RESTPOS) 
1873                 arm->flag = flag;
1874         BKE_pose_where_is(scene, ob_arm);
1875 }
1876
1877 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1878 {
1879         bPoseChannel *parchan = NULL;
1880         bPose *pose = ob_arm->pose;
1881
1882         pchan = BKE_pose_channel_find_name(pose, bone->name);
1883
1884         if (!pchan)
1885                 return;
1886
1887         parchan = pchan->parent;
1888
1889         enable_fcurves(ob_arm->adt->action, bone->name);
1890
1891         std::vector<float>::iterator it;
1892         for (it = frames.begin(); it != frames.end(); it++) {
1893                 float mat[4][4], ipar[4][4];
1894
1895                 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
1896
1897
1898                 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1899                 BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
1900
1901                 // compute bone local mat
1902                 if (bone->parent) {
1903                         invert_m4_m4(ipar, parchan->pose_mat);
1904                         mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1905                 }
1906                 else
1907                         copy_m4_m4(mat, pchan->pose_mat);
1908
1909                 switch (type) {
1910                         case 0:
1911                                 mat4_to_eul(v, mat);
1912                                 break;
1913                         case 1:
1914                                 mat4_to_size(v, mat);
1915                                 break;
1916                         case 2:
1917                                 copy_v3_v3(v, mat[3]);
1918                                 break;
1919                 }
1920
1921                 v += 3;
1922         }
1923
1924         enable_fcurves(ob_arm->adt->action, NULL);
1925 }
1926
1927 bool AnimationExporter::validateConstraints(bConstraint *con)
1928 {
1929         const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1930         /* these we can skip completely (invalid constraints...) */
1931         if (cti == NULL)
1932                 return false;
1933         if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
1934                 return false;
1935
1936         /* these constraints can't be evaluated anyway */
1937         if (cti->evaluate_constraint == NULL)
1938                 return false;
1939
1940         /* influence == 0 should be ignored */
1941         if (con->enforce == 0.0f)
1942                 return false;
1943
1944         /* validation passed */
1945         return true;
1946 }