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