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