Merge branch 'master' into blender2.8
[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(EvaluationContext *eval_ctx, Scene *sce)
38 {
39         bool has_animations = hasAnimations(sce);
40         if (has_animations) {
41                 this->eval_ctx = eval_ctx;
42                 this->scene = sce;
43
44                 openLibrary();
45
46                 forEachObjectInExportSet(sce, *this, this->export_settings->export_set);
47
48                 closeLibrary();
49         }
50         return has_animations;
51 }
52
53 bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
54 {
55         for (int i = 0; i < values.size(); i += channel_count) {
56                 for (int j = 0; j < channel_count; j++) {
57                         if (!bc_in_range(values[j], values[i+j], 0.000001))
58                                 return false;
59                 }
60         }
61         return true;
62 }
63 /*
64  *  This function creates a complete LINEAR Collada <Animation> Entry with all needed 
65  *  <source>, <sampler>, and <channel> entries.
66  *  This is is used for creating sampled Transformation Animations for either:
67  *
68  *              1-axis animation:
69  *                  times contains the time points in seconds from within the timeline
70  *                      values contains the data (list of single floats)
71  *                      channel_count = 1
72  *                      axis_name = ['X' | 'Y' | 'Z']
73  *                      is_rot indicates if the animation is a rotation
74  *
75  *              3-axis animation:
76  *                      times contains the time points in seconds from within the timeline
77  *                      values contains the data (list of floats where each 3 entries are one vector)
78  *                      channel_count = 3
79  *                      axis_name = "" (actually not used)
80  *                      is_rot = false (see xxx below)
81  *
82  *      xxx: I tried to create a 3 axis rotation animation 
83  *               like for translation or scale. But i could not 
84  *               figure out how to setup the channel for this case.
85  *               So for now rotations are exported as 3 separate 1-axis collada animations
86  *               See export_sampled_animation() further down.
87  */
88 void AnimationExporter::create_sampled_animation(int channel_count,
89         std::vector<float> &times,
90         std::vector<float> &values,
91         std::string ob_name,
92         std::string label,
93         std::string axis_name,
94         bool is_rot)
95 {
96         char anim_id[200];
97
98         if (is_flat_line(values, channel_count))
99                 return;
100
101         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
102
103         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
104
105         /* create input source */
106         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
107
108         /* create output source */
109         std::string output_id;
110         if (channel_count == 1)
111                 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
112         else if (channel_count == 3)
113                 output_id = create_xyz_source(&values[0], times.size(), anim_id);
114         else if (channel_count == 16)
115                 output_id = create_4x4_source(times, values, anim_id);
116
117         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
118         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
119         std::string empty;
120         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
121         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
122
123         /* TODO create in/out tangents source (LINEAR) */
124         std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
125
126         /* Create Sampler */
127         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
128         addSampler(sampler);
129
130         /* Create channel */
131         std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
132         addChannel(COLLADABU::URI(empty, sampler_id), target);
133
134         closeAnimation();
135
136 }
137
138 /*
139  * Export all animation FCurves of an Object.
140  *
141  * Note: This uses the keyframes as sample points,
142  * and exports "baked keyframes" while keeping the tangent infromation
143  * of the FCurves intact. This works for simple cases, but breaks
144  * especially when negative scales are involved in the animation.
145  *
146  * If it is necessary to conserve the Animation precisely then
147  * use export_sampled_animation_set() instead.
148  */
149 void AnimationExporter::export_keyframed_animation_set(Object *ob)
150 {
151         FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
152         if (!fcu) {
153                 return; /* object has no animation */
154         }
155
156         if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
157
158                 std::vector<float> ctimes;
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(eval_ctx, 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(eval_ctx, 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(this->eval_ctx, 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(eval_ctx, 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(eval_ctx, 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(this->eval_ctx, 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(this->eval_ctx, 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(this->eval_ctx, 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(eval_ctx, scene, ctime);
1325                 if (is_bone_animation) {
1326
1327                         if (pchan->flag & POSE_CHAIN) {
1328                                 enable_fcurves(ob->adt->action, NULL);
1329                                 BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
1330                                 BKE_pose_where_is(eval_ctx, scene, ob);
1331                         }
1332                         else {
1333                                 BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
1334                         }
1335                         
1336                         // compute bone local mat
1337                         if (bone->parent) {
1338                                 invert_m4_m4(ipar, parchan->pose_mat);
1339                                 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1340                         }
1341                         else
1342                                 copy_m4_m4(mat, pchan->pose_mat);
1343                         
1344                         /* OPEN_SIM_COMPATIBILITY
1345                          * AFAIK animation to second life is via BVH, but no
1346                          * reason to not have the collada-animation be correct
1347                          */
1348                         if (export_settings->open_sim) {
1349                                 float temp[4][4];
1350                                 copy_m4_m4(temp, bone->arm_mat);
1351                                 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1352                                 invert_m4(temp);
1353
1354                                 mul_m4_m4m4(mat, mat, temp);
1355
1356                                 if (bone->parent) {
1357                                         copy_m4_m4(temp, bone->parent->arm_mat);
1358                                         temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
1359
1360                                         mul_m4_m4m4(mat, temp, mat);
1361                                 }
1362                         }
1363
1364                 }
1365                 else {
1366                         copy_m4_m4(mat, ob->obmat);
1367                 }
1368                 
1369                 UnitConverter converter;
1370
1371                 double outmat[4][4];
1372                 converter.mat4_to_dae_double(outmat, mat);
1373
1374                 if (this->export_settings->limit_precision)
1375                         bc_sanitize_mat(outmat, 6);
1376
1377                 source.appendValues(outmat);
1378
1379                 j++;
1380
1381                 BIK_release_tree(scene, ob, ctime);
1382         }
1383
1384         if (ob->adt) {
1385                 enable_fcurves(ob->adt->action, NULL);
1386         }
1387
1388         source.finish();
1389
1390         return source_id;
1391 }
1392
1393
1394 /*
1395  * only used for sources with OUTPUT semantic ( locations and scale)
1396  */
1397 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
1398 {
1399         COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
1400         std::string source_id = anim_id + get_semantic_suffix(semantic);
1401
1402         COLLADASW::FloatSourceF source(mSW);
1403         source.setId(source_id);
1404         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1405         source.setAccessorCount(tot);
1406         source.setAccessorStride(3);
1407
1408         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1409         add_source_parameters(param, semantic, false, NULL, false);
1410
1411         source.prepareToAppendValues();
1412
1413         for (int i = 0; i < tot; i++) {
1414                 source.appendValues(*v, *(v + 1), *(v + 2));
1415                 v += 3;
1416         }
1417
1418         source.finish();
1419
1420         return source_id;
1421 }
1422
1423 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
1424 {
1425         std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1426
1427         COLLADASW::NameSource source(mSW);
1428         source.setId(source_id);
1429         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1430         source.setAccessorCount(fcu->totvert);
1431         source.setAccessorStride(1);
1432
1433         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1434         param.push_back("INTERPOLATION");
1435
1436         source.prepareToAppendValues();
1437
1438         *has_tangents = false;
1439
1440         for (unsigned int i = 0; i < fcu->totvert; i++) {
1441                 if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
1442                         source.appendValues(BEZIER_NAME);
1443                         *has_tangents = true;
1444                 }
1445                 else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
1446                         source.appendValues(STEP_NAME);
1447                 }
1448                 else { // BEZT_IPO_LIN
1449                         source.appendValues(LINEAR_NAME);
1450                 }
1451         }
1452         // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
1453
1454         source.finish();
1455
1456         return source_id;
1457 }
1458
1459 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
1460 {
1461         std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
1462
1463         COLLADASW::NameSource source(mSW);
1464         source.setId(source_id);
1465         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
1466         source.setAccessorCount(tot);
1467         source.setAccessorStride(1);
1468
1469         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
1470         param.push_back("INTERPOLATION");
1471
1472         source.prepareToAppendValues();
1473
1474         for (int i = 0; i < tot; i++) {
1475                 source.appendValues(LINEAR_NAME);
1476         }
1477
1478         source.finish();
1479
1480         return source_id;
1481 }
1482
1483 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1484 {
1485         std::string tm_name;
1486         // when given rna_path, determine tm_type from it
1487         if (rna_path) {
1488                 char *name = extract_transform_name(rna_path);
1489
1490                 if (STREQ(name, "color"))
1491                         tm_type = 1;
1492                 else if (STREQ(name, "spot_size"))
1493                         tm_type = 2;
1494                 else if (STREQ(name, "spot_blend"))
1495                         tm_type = 3;
1496                 else if (STREQ(name, "distance"))
1497                         tm_type = 4;
1498                 else
1499                         tm_type = -1;
1500         }
1501
1502         switch (tm_type) {
1503                 case 1:
1504                         tm_name = "color";
1505                         break;
1506                 case 2:
1507                         tm_name = "fall_off_angle";
1508                         break;
1509                 case 3:
1510                         tm_name = "fall_off_exponent";
1511                         break;
1512                 case 4:
1513                         tm_name = "blender/blender_dist";
1514                         break;
1515
1516                 default:
1517                         tm_name = "";
1518                         break;
1519         }
1520
1521         if (tm_name.size()) {
1522                 if (axis_name[0])
1523                         return tm_name + "." + std::string(axis_name);
1524                 else 
1525                         return tm_name;
1526         }
1527
1528         return std::string("");
1529 }
1530
1531 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1532 {
1533         std::string tm_name;
1534         // when given rna_path, determine tm_type from it
1535         if (rna_path) {
1536                 char *name = extract_transform_name(rna_path);
1537
1538                 if (STREQ(name, "lens"))
1539                         tm_type = 0;
1540                 else if (STREQ(name, "ortho_scale"))
1541                         tm_type = 1;
1542                 else if (STREQ(name, "clip_end"))
1543                         tm_type = 2;
1544                 else if (STREQ(name, "clip_start"))
1545                         tm_type = 3;
1546
1547                 else
1548                         tm_type = -1;
1549         }
1550
1551         switch (tm_type) {
1552                 case 0:
1553                         tm_name = "xfov";
1554                         break;
1555                 case 1:
1556                         tm_name = "xmag";
1557                         break;
1558                 case 2:
1559                         tm_name = "zfar";
1560                         break;
1561                 case 3:
1562                         tm_name = "znear";
1563                         break;
1564
1565                 default:
1566                         tm_name = "";
1567                         break;
1568         }
1569
1570         if (tm_name.size()) {
1571                 if (axis_name[0])
1572                         return tm_name + "." + std::string(axis_name);
1573                 else 
1574                         return tm_name;
1575         }
1576
1577         return std::string("");
1578 }
1579
1580 /*
1581  * Assign sid of the animated parameter or transform for rotation, 
1582  * axis name is always appended and the value of append_axis is ignored
1583  */
1584 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
1585 {
1586         std::string tm_name;
1587         bool is_angle = false;
1588         // when given rna_path, determine tm_type from it
1589         if (rna_path) {
1590                 char *name = extract_transform_name(rna_path);
1591
1592                 if (STREQ(name, "rotation_euler"))
1593                         tm_type = 0;
1594                 else if (STREQ(name, "rotation_quaternion"))
1595                         tm_type = 1;
1596                 else if (STREQ(name, "scale"))
1597                         tm_type = 2;
1598                 else if (STREQ(name, "location"))
1599                         tm_type = 3;
1600                 else if (STREQ(name, "specular_hardness"))
1601                         tm_type = 4;
1602                 else if (STREQ(name, "specular_color"))
1603                         tm_type = 5;
1604                 else if (STREQ(name, "diffuse_color"))
1605                         tm_type = 6;
1606                 else if (STREQ(name, "alpha"))
1607                         tm_type = 7;
1608                 else if (STREQ(name, "ior"))
1609                         tm_type = 8;
1610
1611                 else
1612                         tm_type = -1;
1613         }
1614
1615         switch (tm_type) {
1616                 case 0:
1617                 case 1:
1618                         tm_name = "rotation";
1619                         is_angle = true;
1620                         break;
1621                 case 2:
1622                         tm_name = "scale";
1623                         break;
1624                 case 3:
1625                         tm_name = "location";
1626                         break;
1627                 case 4:
1628                         tm_name = "shininess";
1629                         break;
1630                 case 5:
1631                         tm_name = "specular";
1632                         break;
1633                 case 6:
1634                         tm_name = "diffuse";
1635                         break;
1636                 case 7:
1637                         tm_name = "transparency";
1638                         break;
1639                 case 8:
1640                         tm_name = "index_of_refraction";
1641                         break;
1642
1643                 default:
1644                         tm_name = "";
1645                         break;
1646         }
1647
1648         if (tm_name.size()) {
1649                 if (is_angle)
1650                         return tm_name + std::string(axis_name) + ".ANGLE";
1651                 else
1652                 if (axis_name[0])
1653                         return tm_name + "." + std::string(axis_name);
1654                 else
1655                         return tm_name;
1656         }
1657
1658         return std::string("");
1659 }
1660
1661 char *AnimationExporter::extract_transform_name(char *rna_path)
1662 {
1663         char *dot = strrchr(rna_path, '.');
1664         return dot ? (dot + 1) : rna_path;
1665 }
1666
1667 /*
1668  * enable fcurves driving a specific bone, disable all the rest
1669  * if bone_name = NULL enable all fcurves
1670  */
1671 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1672 {
1673         FCurve *fcu;
1674         char prefix[200];
1675
1676         if (bone_name)
1677                 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1678
1679         for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
1680                 if (bone_name) {
1681                         if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
1682                                 fcu->flag &= ~FCURVE_DISABLED;
1683                         else
1684                                 fcu->flag |= FCURVE_DISABLED;
1685                 }
1686                 else {
1687                         fcu->flag &= ~FCURVE_DISABLED;
1688                 }
1689         }
1690 }
1691
1692 bool AnimationExporter::hasAnimations(Scene *sce)
1693 {
1694         LinkNode *node;
1695
1696         for (node=this->export_settings->export_set; node; node=node->next) {
1697                 Object *ob = (Object *)node->link;
1698
1699                 FCurve *fcu = 0;
1700                 //Check for object transform animations
1701                 if (ob->adt && ob->adt->action)
1702                         fcu = (FCurve *)ob->adt->action->curves.first;
1703                 //Check for Lamp parameter animations
1704                 else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
1705                         fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
1706                 //Check for Camera parameter animations
1707                 else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
1708                         fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
1709
1710                 //Check Material Effect parameter animations.
1711                 for (int a = 0; a < ob->totcol; a++) {
1712                         Material *ma = give_current_material(ob, a + 1);
1713                         if (!ma) continue;
1714                         if (ma->adt && ma->adt->action) {
1715                                 fcu = (FCurve *)ma->adt->action->curves.first;
1716                         }
1717                 }
1718
1719                 //check shape key animation
1720                 if (!fcu) {
1721                         Key *key = BKE_key_from_object(ob);
1722                         if (key && key->adt && key->adt->action)
1723                                 fcu = (FCurve *)key->adt->action->curves.first;
1724                 }
1725                 if (fcu)
1726                         return true;
1727         }
1728         return false;
1729 }
1730
1731 //------------------------------- Not used in the new system.--------------------------------------------------------
1732 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1733 {
1734         if (rotmode > 0)
1735                 find_keyframes(ob, fra, prefix, "rotation_euler");
1736         else if (rotmode == ROT_MODE_QUAT)
1737                 find_keyframes(ob, fra, prefix, "rotation_quaternion");
1738         /*else if (rotmode == ROT_MODE_AXISANGLE)
1739            ;*/
1740 }
1741
1742 /* Take care to always have the first frame and the last frame in the animation
1743  * regardless of the sampling_rate setting
1744  */
1745 void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
1746 {
1747         int frame = scene->r.sfra;
1748         do {
1749                 float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
1750                 fra.push_back(ctime);
1751                 if (frame == scene->r.efra)
1752                         break;
1753                 frame += this->export_settings->sampling_rate;
1754                 if (frame > scene->r.efra)
1755                         frame = scene->r.efra; // make sure the last frame is always exported
1756
1757         } while (true);
1758 }
1759
1760 /* 
1761  * find keyframes of all the objects animations
1762  */
1763 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
1764 {
1765         if (ob->adt && ob->adt->action) {
1766                 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1767
1768                 for (; fcu; fcu = fcu->next) {
1769                         for (unsigned int i = 0; i < fcu->totvert; i++) {
1770                                 float f = fcu->bezt[i].vec[1][0];
1771                                 if (std::find(fra.begin(), fra.end(), f) == fra.end())
1772                                         fra.push_back(f);
1773                         }
1774                 }
1775
1776                 // keep the keys in ascending order
1777                 std::sort(fra.begin(), fra.end());
1778         }
1779 }
1780
1781 void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1782 {
1783         if (ob->adt && ob->adt->action) {
1784                 FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1785
1786                 for (; fcu; fcu = fcu->next) {
1787                         if (prefix && !STREQLEN(prefix, fcu->rna_path, strlen(prefix)))
1788                                 continue;
1789
1790                         char *name = extract_transform_name(fcu->rna_path);
1791                         if (STREQ(name, tm_name)) {
1792                                 for (unsigned int i = 0; i < fcu->totvert; i++) {
1793                                         float f = fcu->bezt[i].vec[1][0];
1794                                         if (std::find(fra.begin(), fra.end(), f) == fra.end())
1795                                                 fra.push_back(f);
1796                                 }
1797                         }
1798                 }
1799
1800                 // keep the keys in ascending order
1801                 std::sort(fra.begin(), fra.end());
1802         }
1803 }
1804
1805 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1806 {
1807         if (!ob_arm->adt)
1808                 return;
1809
1810         //write bone animations for 3 transform types
1811         //i=0 --> rotations
1812         //i=1 --> scale
1813         //i=2 --> location
1814         for (int i = 0; i < 3; i++)
1815                 sample_and_write_bone_animation(ob_arm, bone, i);
1816
1817         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
1818                 write_bone_animation(ob_arm, child);
1819 }
1820
1821 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1822 {
1823         bArmature *arm = (bArmature *)ob_arm->data;
1824         int flag = arm->flag;
1825         std::vector<float> fra;
1826         char prefix[256];
1827
1828         BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1829
1830         bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
1831         if (!pchan)
1832                 return;
1833         //Fill frame array with key frame values framed at \param:transform_type
1834         switch (transform_type) {
1835                 case 0:
1836                         find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1837                         break;
1838                 case 1:
1839                         find_keyframes(ob_arm, fra, prefix, "scale");
1840                         break;
1841                 case 2:
1842                         find_keyframes(ob_arm, fra, prefix, "location");
1843                         break;
1844                 default:
1845                         return;
1846         }
1847
1848         // exit rest position
1849         if (flag & ARM_RESTPOS) {
1850                 arm->flag &= ~ARM_RESTPOS;
1851                 BKE_pose_where_is(eval_ctx, scene, ob_arm);
1852         }
1853         //v array will hold all values which will be exported. 
1854         if (fra.size()) {
1855                 float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1856                 sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1857
1858                 if (transform_type == 0) {
1859                         // write x, y, z curves separately if it is rotation
1860                         float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
1861
1862                         for (int i = 0; i < 3; i++) {
1863                                 for (unsigned int j = 0; j < fra.size(); j++)
1864                                         axisValues[j] = values[j * 3 + i];
1865
1866                                 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1867                         }
1868                         MEM_freeN(axisValues);
1869                 }
1870                 else {
1871                         // write xyz at once if it is location or scale
1872                         dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1873                 }
1874
1875                 MEM_freeN(values);
1876         }
1877
1878         // restore restpos
1879         if (flag & ARM_RESTPOS) 
1880                 arm->flag = flag;
1881         BKE_pose_where_is(eval_ctx, scene, ob_arm);
1882 }
1883
1884 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1885 {
1886         bPoseChannel *parchan = NULL;
1887         bPose *pose = ob_arm->pose;
1888
1889         pchan = BKE_pose_channel_find_name(pose, bone->name);
1890
1891         if (!pchan)
1892                 return;
1893
1894         parchan = pchan->parent;
1895
1896         enable_fcurves(ob_arm->adt->action, bone->name);
1897
1898         std::vector<float>::iterator it;
1899         for (it = frames.begin(); it != frames.end(); it++) {
1900                 float mat[4][4], ipar[4][4];
1901
1902                 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
1903
1904
1905                 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1906                 BKE_pose_where_is_bone(eval_ctx, scene, ob_arm, pchan, ctime, 1);
1907
1908                 // compute bone local mat
1909                 if (bone->parent) {
1910                         invert_m4_m4(ipar, parchan->pose_mat);
1911                         mul_m4_m4m4(mat, ipar, pchan->pose_mat);
1912                 }
1913                 else
1914                         copy_m4_m4(mat, pchan->pose_mat);
1915
1916                 switch (type) {
1917                         case 0:
1918                                 mat4_to_eul(v, mat);
1919                                 break;
1920                         case 1:
1921                                 mat4_to_size(v, mat);
1922                                 break;
1923                         case 2:
1924                                 copy_v3_v3(v, mat[3]);
1925                                 break;
1926                 }
1927
1928                 v += 3;
1929         }
1930
1931         enable_fcurves(ob_arm->adt->action, NULL);
1932 }
1933
1934 bool AnimationExporter::validateConstraints(bConstraint *con)
1935 {
1936         bool valid = true;
1937         const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1938         /* these we can skip completely (invalid constraints...) */
1939         if (cti == NULL) valid = false;
1940         if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
1941         /* these constraints can't be evaluated anyway */
1942         if (cti->evaluate_constraint == NULL) valid = false;
1943         /* influence == 0 should be ignored */
1944         if (con->enforce == 0.0f) valid = false;
1945
1946         return valid;
1947 }
1948
1949 #if 0
1950 /*
1951  * Needed for sampled animations. 
1952  * This function calculates the object matrix at a given time,
1953  * also taking constraints into account.
1954  *
1955  * XXX: Why looking at the constraints here is necessary?
1956  *      Maybe this can be done better?
1957  */
1958 void AnimationExporter::calc_obmat_at_time(Object *ob, float ctime )
1959 {
1960 <<<<<<< HEAD
1961         ListBase *conlist = get_active_constraints(this->eval_ctx, ob);
1962 =======
1963         BKE_scene_frame_set(scene, ctime);
1964
1965         Main *bmain = bc_get_main();
1966         EvaluationContext *ev_context = bc_get_evaluation_context();
1967         BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
1968
1969         ListBase *conlist = get_active_constraints(ob);
1970 >>>>>>> master
1971         bConstraint *con;
1972         for (con = (bConstraint *)conlist->first; con; con = con->next) {
1973                 ListBase targets = {NULL, NULL};
1974                 
1975                 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
1976                 
1977                 if (cti && cti->get_constraint_targets) {
1978                         bConstraintTarget *ct;
1979                         Object *obtar;
1980                         cti->get_constraint_targets(con, &targets);
1981                         for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
1982                                 obtar = ct->tar;
1983
1984                                 if (obtar) {
1985                                         BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
1986                                         BKE_object_where_is_calc_time(eval_ctx, scene, obtar, ctime);
1987                                 }
1988                         }
1989
1990                         if (cti->flush_constraint_targets)
1991                                 cti->flush_constraint_targets(con, &targets, 1);
1992                 }
1993         }
1994 <<<<<<< HEAD
1995         BKE_object_where_is_calc_time(eval_ctx, scene, ob, ctime);
1996         copy_m4_m4(mat, ob->obmat);
1997 =======
1998         BKE_object_where_is_calc_time(scene, ob, ctime);
1999 >>>>>>> master
2000 }
2001 #endif
2002