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