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