57829f777c583885f83030d6b250f318c06363f8
[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 void AnimationExporter::exportAnimations(Scene *sce)
38 {
39         if (hasAnimations(sce)) {
40                 this->scene = sce;
41
42                 openLibrary();
43
44                 forEachObjectInExportSet(sce, *this, this->export_settings->export_set);
45
46                 closeLibrary();
47         }
48 }
49
50 // called for each exported object
51 void AnimationExporter::operator()(Object *ob)
52 {
53         FCurve *fcu;
54         char *transformName;
55         /* bool isMatAnim = false; */ /* UNUSED */
56
57         //Export transform animations
58         if (ob->adt && ob->adt->action) {
59                 fcu = (FCurve *)ob->adt->action->curves.first;
60
61                 //transform matrix export for bones are temporarily disabled here.
62                 if (ob->type == OB_ARMATURE) {
63                         bArmature *arm = (bArmature *)ob->data;
64                         for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
65                                 write_bone_animation_matrix(ob, bone);
66                 }
67
68                 while (fcu) {
69                         //for armature animations as objects
70                         if (ob->type == OB_ARMATURE)
71                                 transformName =  fcu->rna_path;
72                         else 
73                                 transformName = extract_transform_name(fcu->rna_path);
74
75                         if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
76                             (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
77                             (!strcmp(transformName, "rotation_quaternion")))
78                         {
79                                 dae_animation(ob, fcu, transformName, false);
80                         }
81                         fcu = fcu->next;
82                 }
83
84         }
85
86         //Export Lamp parameter animations
87         if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
88                 fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
89                 while (fcu) {
90                         transformName = extract_transform_name(fcu->rna_path);
91
92                         if ((!strcmp(transformName, "color")) || (!strcmp(transformName, "spot_size")) ||
93                             (!strcmp(transformName, "spot_blend")) || (!strcmp(transformName, "distance")))
94                         {
95                                 dae_animation(ob, fcu, transformName, true);
96                         }
97                         fcu = fcu->next;
98                 }
99         }
100
101         //Export Camera parameter animations
102         if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
103                 fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
104                 while (fcu) {
105                         transformName = extract_transform_name(fcu->rna_path);
106
107                         if ((!strcmp(transformName, "lens")) ||
108                             (!strcmp(transformName, "ortho_scale")) ||
109                             (!strcmp(transformName, "clip_end")) || (!strcmp(transformName, "clip_start")))
110                         {
111                                 dae_animation(ob, fcu, transformName, true);
112                         }
113                         fcu = fcu->next;
114                 }
115         }
116
117         //Export Material parameter animations.
118         for (int a = 0; a < ob->totcol; a++) {
119                 Material *ma = give_current_material(ob, a + 1);
120                 if (!ma) continue;
121                 if (ma->adt && ma->adt->action) {
122                         /* isMatAnim = true; */
123                         fcu = (FCurve *)ma->adt->action->curves.first;
124                         while (fcu) {
125                                 transformName = extract_transform_name(fcu->rna_path);
126
127                                 if ((!strcmp(transformName, "specular_hardness")) || (!strcmp(transformName, "specular_color")) ||
128                                     (!strcmp(transformName, "diffuse_color")) || (!strcmp(transformName, "alpha")) ||
129                                     (!strcmp(transformName, "ior")))
130                                 {
131                                         dae_animation(ob, fcu, transformName, true, ma);
132                                 }
133                                 fcu = fcu->next;
134                         }
135                 }
136
137         }
138 }
139
140 //euler sources from quternion sources
141 float *AnimationExporter::get_eul_source_for_quat(Object *ob)
142 {
143         FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
144         const int keys = fcu->totvert;  
145         float *quat = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
146         float *eul = (float *)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
147         float temp_quat[4];
148         float temp_eul[3];
149         while (fcu) {
150                 char *transformName = extract_transform_name(fcu->rna_path);
151
152                 if (!strcmp(transformName, "rotation_quaternion") ) {
153                         for (int i = 0; i < fcu->totvert; i++) {
154                                 *(quat + (i * 4) + fcu->array_index) = fcu->bezt[i].vec[1][1];
155                         }
156                 }
157                 fcu = fcu->next;
158         }
159
160         for (int i = 0; i < keys; i++) {
161                 for (int j = 0; j < 4; j++)
162                         temp_quat[j] = quat[(i * 4) + j];
163
164                 quat_to_eul(temp_eul, temp_quat);
165
166                 for (int k = 0; k < 3; k++)
167                         eul[i * 3 + k] = temp_eul[k];
168
169         }
170         MEM_freeN(quat);
171         return eul;
172
173 }
174
175 //Get proper name for bones
176 std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
177 {
178         //hard-way to derive the bone name from rna_path. Must find more compact method
179         std::string rna_path = std::string(fcu->rna_path);
180
181         char *boneName = strtok((char *)rna_path.c_str(), "\"");
182         boneName = strtok(NULL, "\"");
183
184         if (boneName != NULL)
185                 return /*id_name(ob) + "_" +*/ std::string(boneName);
186         else            
187                 return id_name(ob);
188 }
189
190 //convert f-curves to animation curves and write
191 void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
192 {
193         const char *axis_name = NULL;
194         char anim_id[200];
195
196         bool has_tangents = false;
197         bool quatRotation = false;
198
199         if (!strcmp(transformName, "rotation_quaternion") ) {
200                 fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
201                 quatRotation = true;
202                 return;
203         }
204
205         //axis names for colors
206         else if (!strcmp(transformName, "color") || !strcmp(transformName, "specular_color") || !strcmp(transformName, "diffuse_color") ||
207                  (!strcmp(transformName, "alpha")))
208         {
209                 const char *axis_names[] = {"R", "G", "B"};
210                 if (fcu->array_index < 3)
211                         axis_name = axis_names[fcu->array_index];
212         }
213
214         //axis names for transforms
215         else if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
216                  (!strcmp(transformName, "rotation_euler")) || (!strcmp(transformName, "rotation_quaternion")))
217         {
218                 const char *axis_names[] = {"X", "Y", "Z"};
219                 if (fcu->array_index < 3)
220                         axis_name = axis_names[fcu->array_index];
221         }
222         else {
223                 /* no axis name. single parameter */
224                 axis_name = "";
225         }
226
227         std::string ob_name = std::string("null");
228
229         //Create anim Id
230         if (ob->type == OB_ARMATURE) {
231                 ob_name =  getObjectBoneName(ob, fcu);
232                 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char *)translate_id(ob_name).c_str(),
233                              transformName, axis_name);
234         }
235         else {
236                 if (ma)
237                         ob_name = id_name(ob) + "_material";
238                 else
239                         ob_name = id_name(ob);
240                 BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
241                              fcu->rna_path, axis_name);
242         }
243
244         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
245
246         // create input source
247         std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
248
249         // create output source
250         std::string output_id;
251
252         //quat rotations are skipped for now, because of complications with determining axis.
253         if (quatRotation) {
254                 float *eul  = get_eul_source_for_quat(ob);
255                 float *eul_axis = (float *)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
256                 for (int i = 0; i < fcu->totvert; i++) {
257                         eul_axis[i] = eul[i * 3 + fcu->array_index];
258                 }
259                 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis, fcu->totvert, quatRotation, anim_id, axis_name);
260                 MEM_freeN(eul);
261                 MEM_freeN(eul_axis);
262         }
263         else {
264                 output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
265         }
266         // create interpolations source
267         std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
268
269         // handle tangents (if required)
270         std::string intangent_id;
271         std::string outtangent_id;
272
273         if (has_tangents) {
274                 // create in_tangent source
275                 intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
276
277                 // create out_tangent source
278                 outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
279         }
280
281         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
282         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
283         std::string empty;
284         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
285         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
286
287         // this input is required
288         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
289
290         if (has_tangents) {
291                 sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
292                 sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
293         }
294
295         addSampler(sampler);
296
297         std::string target;
298
299         if (!is_param)
300                 target = translate_id(ob_name) +
301                          "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
302         else {
303                 if (ob->type == OB_LAMP)
304                         target = get_light_id(ob) +
305                                  "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
306
307                 if (ob->type == OB_CAMERA)
308                         target = get_camera_id(ob) +
309                                  "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
310
311                 if (ma)
312                         target = translate_id(id_name(ma)) + "-effect" +
313                                  "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
314         }
315         addChannel(COLLADABU::URI(empty, sampler_id), target);
316
317         closeAnimation();
318 }
319
320
321
322 //write bone animations in transform matrix sources
323 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
324 {
325         if (!ob_arm->adt)
326                 return;
327
328         //This will only export animations of bones in deform group.
329         /* if (!is_bone_deform_group(bone)) return; */
330
331         sample_and_write_bone_animation_matrix(ob_arm, bone);
332
333         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
334                 write_bone_animation_matrix(ob_arm, child);
335 }
336
337 bool AnimationExporter::is_bone_deform_group(Bone *bone)
338 {   
339         bool is_def;
340         //Check if current bone is deform
341         if ((bone->flag & BONE_NO_DEFORM) == 0) return true;
342         //Check child bones
343         else {
344                 for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
345                         //loop through all the children until deform bone is found, and then return
346                         is_def = is_bone_deform_group(child);
347                         if (is_def) return true;
348                 }
349         }
350         //no deform bone found in children also
351         return false;
352 }
353
354 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
355 {
356         bArmature *arm = (bArmature *)ob_arm->data;
357         int flag = arm->flag;
358         std::vector<float> fra;
359         //char prefix[256];
360
361         FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
362         while (fcu) {
363                 std::string bone_name = getObjectBoneName(ob_arm, fcu);
364                 int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
365                 if (val == 0) break;
366                 fcu = fcu->next;
367         }
368
369         if (!(fcu)) return; 
370         bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
371         if (!pchan)
372                 return;
373
374         find_frames(ob_arm, fra);
375
376         if (flag & ARM_RESTPOS) {
377                 arm->flag &= ~ARM_RESTPOS;
378                 BKE_pose_where_is(scene, ob_arm);
379         }
380
381         if (fra.size()) {
382                 dae_baked_animation(fra, ob_arm, bone);
383         }
384
385         if (flag & ARM_RESTPOS) 
386                 arm->flag = flag;
387         BKE_pose_where_is(scene, ob_arm);
388 }
389
390 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
391 {
392         std::string ob_name = id_name(ob_arm);
393         std::string bone_name = bone->name;
394         char anim_id[200];
395
396         if (!fra.size())
397                 return;
398
399         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
400                      (char *)translate_id(bone_name).c_str(), "pose_matrix");
401
402         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
403
404         // create input source
405         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
406
407         // create output source
408         std::string output_id;
409         output_id = create_4x4_source(fra, ob_arm, bone,  anim_id);
410
411         // create interpolations source
412         std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
413
414         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
415         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
416         std::string empty;
417         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
418         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
419
420         // TODO create in/out tangents source
421
422         // this input is required
423         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
424
425         addSampler(sampler);
426
427         std::string target = translate_id(bone_name) + "/transform";
428         addChannel(COLLADABU::URI(empty, sampler_id), target);
429
430         closeAnimation();
431 }
432
433 // dae_bone_animation -> add_bone_animation
434 // (blend this into dae_bone_animation)
435 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
436 {
437         const char *axis_names[] = {"X", "Y", "Z"};
438         const char *axis_name = NULL;
439         char anim_id[200];
440         bool is_rot = tm_type == 0;
441
442         if (!fra.size())
443                 return;
444
445         char rna_path[200];
446         BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
447                      tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
448
449         if (axis > -1)
450                 axis_name = axis_names[axis];
451
452         std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
453
454         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
455                      (char *)translate_id(bone_name).c_str(), (char *)transform_sid.c_str());
456
457         openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
458
459         // create input source
460         std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
461
462         // create output source
463         std::string output_id;
464         if (axis == -1)
465                 output_id = create_xyz_source(values, fra.size(), anim_id);
466         else
467                 output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
468
469         // create interpolations source
470         std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
471
472         std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
473         COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
474         std::string empty;
475         sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
476         sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
477
478         // TODO create in/out tangents source
479
480         // this input is required
481         sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
482
483         addSampler(sampler);
484
485         std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
486         addChannel(COLLADABU::URI(empty, sampler_id), target);
487
488         closeAnimation();
489 }
490
491 float AnimationExporter::convert_time(float frame)
492 {
493         return FRA2TIME(frame);
494 }
495
496 float AnimationExporter::convert_angle(float angle)
497 {
498         return COLLADABU::Math::Utils::radToDegF(angle);
499 }
500
501 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
502 {
503         switch (semantic) {
504                 case COLLADASW::InputSemantic::INPUT:
505                         return INPUT_SOURCE_ID_SUFFIX;
506                 case COLLADASW::InputSemantic::OUTPUT:
507                         return OUTPUT_SOURCE_ID_SUFFIX;
508                 case COLLADASW::InputSemantic::INTERPOLATION:
509                         return INTERPOLATION_SOURCE_ID_SUFFIX;
510                 case COLLADASW::InputSemantic::IN_TANGENT:
511                         return INTANGENT_SOURCE_ID_SUFFIX;
512                 case COLLADASW::InputSemantic::OUT_TANGENT:
513                         return OUTTANGENT_SOURCE_ID_SUFFIX;
514                 default:
515                         break;
516         }
517         return "";
518 }
519
520 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
521                                               COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
522 {
523         switch (semantic) {
524                 case COLLADASW::InputSemantic::INPUT:
525                         param.push_back("TIME");
526                         break;
527                 case COLLADASW::InputSemantic::OUTPUT:
528                         if (is_rot) {
529                                 param.push_back("ANGLE");
530                         }
531                         else {
532                                 if (axis) {
533                                         param.push_back(axis);
534                                 }
535                                 else 
536                                 if (transform) {
537                                         param.push_back("TRANSFORM");
538                                 }
539                                 else {     //assumes if axis isn't specified all axises are added
540                                         param.push_back("X");
541                                         param.push_back("Y");
542                                         param.push_back("Z");
543                                 }
544                         }
545                         break;
546                 case COLLADASW::InputSemantic::IN_TANGENT:
547                 case COLLADASW::InputSemantic::OUT_TANGENT:
548                         param.push_back("X");
549                         param.push_back("Y");
550                         break;
551                 default:
552                         break;
553         }
554 }
555
556 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length)
557 {
558         switch (semantic) {
559                 case COLLADASW::InputSemantic::INPUT:
560                         *length = 1;
561                         values[0] = convert_time(bezt->vec[1][0]);
562                         break;
563                 case COLLADASW::InputSemantic::OUTPUT:
564                         *length = 1;
565                         if (rotation) {
566                                 values[0] = RAD2DEGF(bezt->vec[1][1]);
567                         }
568                         else {
569                                 values[0] = bezt->vec[1][1];
570                         }
571                         break;
572
573                 case COLLADASW::InputSemantic::IN_TANGENT:
574                         *length = 2;
575                         values[0] = convert_time(bezt->vec[0][0]);
576                         if (bezt->ipo != BEZT_IPO_BEZ) {
577                                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
578                                 values[0] = 0;  
579                                 values[1] = 0;  
580                         }
581                         else if (rotation) {
582                                 values[1] = RAD2DEGF(bezt->vec[0][1]);
583                         }
584                         else {
585                                 values[1] = bezt->vec[0][1];
586                         }
587                         break;
588
589                 case COLLADASW::InputSemantic::OUT_TANGENT:
590                         *length = 2;
591                         values[0] = convert_time(bezt->vec[2][0]);
592                         if (bezt->ipo != BEZT_IPO_BEZ) {
593                                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
594                                 values[0] = 0;  
595                                 values[1] = 0;  
596                         }
597                         else if (rotation) {
598                                 values[1] = RAD2DEGF(bezt->vec[2][1]);
599                         }
600                         else {
601                                 values[1] = bezt->vec[2][1];
602                         }
603                         break;
604                         break;
605                 default:
606                         *length = 0;
607                         break;
608         }
609 }
610
611 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
612 {
613         std::string source_id = anim_id + get_semantic_suffix(semantic);
614
615         //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
616         bool is_angle = false;
617
618         if (strstr(fcu->rna_path, "rotation")) is_angle = true;
619
620         COLLADASW::FloatSourceF source(mSW);
621         source.setId(source_id);
622         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
623         source.setAccessorCount(fcu->totvert);
624
625         switch (semantic) {
626                 case COLLADASW::InputSemantic::INPUT:
627                 case COLLADASW::InputSemantic::OUTPUT:
628                         source.setAccessorStride(1);                    
629                         break;
630                 case COLLADASW::InputSemantic::IN_TANGENT:
631                 case COLLADASW::InputSemantic::OUT_TANGENT:
632                         source.setAccessorStride(2);                    
633                         break;
634                 default:
635                         break;
636         }
637
638
639         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
640         add_source_parameters(param, semantic, is_angle, axis_name, false);
641
642         source.prepareToAppendValues();
643
644         for (unsigned int i = 0; i < fcu->totvert; i++) {
645                 float values[3]; // be careful!
646                 int length = 0;
647                 get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length);
648                 for (int j = 0; j < length; j++)
649                         source.appendValues(values[j]);
650         }
651
652         source.finish();
653
654         return source_id;
655 }
656
657 //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified )
658 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)
659 {
660         std::string source_id = anim_id + get_semantic_suffix(semantic);
661
662         COLLADASW::FloatSourceF source(mSW);
663         source.setId(source_id);
664         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
665         source.setAccessorCount(tot);
666         source.setAccessorStride(1);
667
668         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
669         add_source_parameters(param, semantic, is_rot, axis_name,  false);
670
671         source.prepareToAppendValues();
672
673         for (int i = 0; i < tot; i++) {
674                 float val = v[i];
675                 ////if (semantic == COLLADASW::InputSemantic::INPUT)
676                 //      val = convert_time(val);
677                 //else
678                 if (is_rot)
679                         val = RAD2DEGF(val);
680                 source.appendValues(val);
681         }
682
683         source.finish();
684
685         return source_id;
686 }
687 // only used for sources with INPUT semantic
688 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)
689 {
690         std::string source_id = anim_id + get_semantic_suffix(semantic);
691
692         COLLADASW::FloatSourceF source(mSW);
693         source.setId(source_id);
694         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
695         source.setAccessorCount(fra.size());
696         source.setAccessorStride(1);
697
698         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
699         add_source_parameters(param, semantic, is_rot, axis_name, false);
700
701         source.prepareToAppendValues();
702
703         std::vector<float>::iterator it;
704         for (it = fra.begin(); it != fra.end(); it++) {
705                 float val = *it;
706                 //if (semantic == COLLADASW::InputSemantic::INPUT)
707                 val = convert_time(val);
708                 /*else if (is_rot)
709                    val = convert_angle(val);*/
710                 source.appendValues(val);
711         }
712
713         source.finish();
714
715         return source_id;
716 }
717
718 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob_arm, Bone *bone, const std::string& anim_id)
719 {
720         COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
721         std::string source_id = anim_id + get_semantic_suffix(semantic);
722
723         COLLADASW::Float4x4Source source(mSW);
724         source.setId(source_id);
725         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
726         source.setAccessorCount(frames.size());
727         source.setAccessorStride(16);
728
729         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
730         add_source_parameters(param, semantic, false, NULL, true);
731
732         source.prepareToAppendValues();
733
734         bPoseChannel *parchan = NULL;
735         bPoseChannel *pchan = NULL;
736         bPose *pose = ob_arm->pose;
737
738         pchan = BKE_pose_channel_find_name(pose, bone->name);
739
740         if (!pchan)
741                 return "";
742
743         parchan = pchan->parent;
744
745         enable_fcurves(ob_arm->adt->action, bone->name);
746
747         std::vector<float>::iterator it;
748         int j = 0;
749         for (it = frames.begin(); it != frames.end(); it++) {
750                 float mat[4][4], ipar[4][4];
751
752                 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
753
754                 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
755                 BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
756
757                 // compute bone local mat
758                 if (bone->parent) {
759                         invert_m4_m4(ipar, parchan->pose_mat);
760                         mult_m4_m4m4(mat, ipar, pchan->pose_mat);
761                 }
762                 else
763                         copy_m4_m4(mat, pchan->pose_mat);
764                 UnitConverter converter;
765
766                 // SECOND_LIFE_COMPATIBILITY
767                 // AFAIK animation to second life is via BVH, but no
768                 // reason to not have the collada-animation be correct
769                 if (export_settings->second_life) {
770                         float temp[4][4];
771                         copy_m4_m4(temp, bone->arm_mat);
772                         temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
773                         invert_m4(temp);
774
775                         mult_m4_m4m4(mat, mat, temp);
776
777                         if (bone->parent) {
778                                 copy_m4_m4(temp, bone->parent->arm_mat);
779                                 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
780
781                                 mult_m4_m4m4(mat, temp, mat);
782                         }
783                 }
784
785                 float outmat[4][4];
786                 converter.mat4_to_dae(outmat, mat);
787
788
789                 source.appendValues(outmat);
790
791
792                 j++;
793         }
794
795         enable_fcurves(ob_arm->adt->action, NULL);
796
797         source.finish();
798
799         return source_id;
800 }
801 // only used for sources with OUTPUT semantic ( locations and scale)
802 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
803 {
804         COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
805         std::string source_id = anim_id + get_semantic_suffix(semantic);
806
807         COLLADASW::FloatSourceF source(mSW);
808         source.setId(source_id);
809         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
810         source.setAccessorCount(tot);
811         source.setAccessorStride(3);
812
813         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
814         add_source_parameters(param, semantic, false, NULL, false);
815
816         source.prepareToAppendValues();
817
818         for (int i = 0; i < tot; i++) {
819                 source.appendValues(*v, *(v + 1), *(v + 2));
820                 v += 3;
821         }
822
823         source.finish();
824
825         return source_id;
826 }
827
828 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
829 {
830         std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
831
832         COLLADASW::NameSource source(mSW);
833         source.setId(source_id);
834         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
835         source.setAccessorCount(fcu->totvert);
836         source.setAccessorStride(1);
837
838         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
839         param.push_back("INTERPOLATION");
840
841         source.prepareToAppendValues();
842
843         *has_tangents = false;
844
845         for (unsigned int i = 0; i < fcu->totvert; i++) {
846                 if (fcu->bezt[i].ipo == BEZT_IPO_BEZ) {
847                         source.appendValues(BEZIER_NAME);
848                         *has_tangents = true;
849                 }
850                 else if (fcu->bezt[i].ipo == BEZT_IPO_CONST) {
851                         source.appendValues(STEP_NAME);
852                 }
853                 else { // BEZT_IPO_LIN
854                         source.appendValues(LINEAR_NAME);
855                 }
856         }
857         // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
858
859         source.finish();
860
861         return source_id;
862 }
863
864 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
865 {
866         std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
867
868         COLLADASW::NameSource source(mSW);
869         source.setId(source_id);
870         source.setArrayId(source_id + ARRAY_ID_SUFFIX);
871         source.setAccessorCount(tot);
872         source.setAccessorStride(1);
873
874         COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
875         param.push_back("INTERPOLATION");
876
877         source.prepareToAppendValues();
878
879         for (int i = 0; i < tot; i++) {
880                 source.appendValues(LINEAR_NAME);
881         }
882
883         source.finish();
884
885         return source_id;
886 }
887
888 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
889 {
890         std::string tm_name;
891         // when given rna_path, determine tm_type from it
892         if (rna_path) {
893                 char *name = extract_transform_name(rna_path);
894
895                 if (!strcmp(name, "color"))
896                         tm_type = 1;
897                 else if (!strcmp(name, "spot_size"))
898                         tm_type = 2;
899                 else if (!strcmp(name, "spot_blend"))
900                         tm_type = 3;
901                 else if (!strcmp(name, "distance"))
902                         tm_type = 4;
903                 else
904                         tm_type = -1;
905         }
906
907         switch (tm_type) {
908                 case 1:
909                         tm_name = "color";
910                         break;
911                 case 2:
912                         tm_name = "fall_off_angle";
913                         break;
914                 case 3:
915                         tm_name = "fall_off_exponent";
916                         break;
917                 case 4:
918                         tm_name = "blender/blender_dist";
919                         break;
920
921                 default:
922                         tm_name = "";
923                         break;
924         }
925
926         if (tm_name.size()) {
927                 if (axis_name[0])
928                         return tm_name + "." + std::string(axis_name);
929                 else 
930                         return tm_name;
931         }
932
933         return std::string("");
934 }
935
936 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
937 {
938         std::string tm_name;
939         // when given rna_path, determine tm_type from it
940         if (rna_path) {
941                 char *name = extract_transform_name(rna_path);
942
943                 if (!strcmp(name, "lens"))
944                         tm_type = 0;
945                 else if (!strcmp(name, "ortho_scale"))
946                         tm_type = 1;
947                 else if (!strcmp(name, "clip_end"))
948                         tm_type = 2;
949                 else if (!strcmp(name, "clip_start"))
950                         tm_type = 3;
951
952                 else
953                         tm_type = -1;
954         }
955
956         switch (tm_type) {
957                 case 0:
958                         tm_name = "xfov";
959                         break;
960                 case 1:
961                         tm_name = "xmag";
962                         break;
963                 case 2:
964                         tm_name = "zfar";
965                         break;
966                 case 3:
967                         tm_name = "znear";
968                         break;
969
970                 default:
971                         tm_name = "";
972                         break;
973         }
974
975         if (tm_name.size()) {
976                 if (axis_name[0])
977                         return tm_name + "." + std::string(axis_name);
978                 else 
979                         return tm_name;
980         }
981
982         return std::string("");
983 }
984
985 // Assign sid of the animated parameter or transform 
986 // for rotation, axis name is always appended and the value of append_axis is ignored
987 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
988 {
989         std::string tm_name;
990         bool is_rotation = false;
991         // when given rna_path, determine tm_type from it
992         if (rna_path) {
993                 char *name = extract_transform_name(rna_path);
994
995                 if (!strcmp(name, "rotation_euler"))
996                         tm_type = 0;
997                 else if (!strcmp(name, "rotation_quaternion"))
998                         tm_type = 1;
999                 else if (!strcmp(name, "scale"))
1000                         tm_type = 2;
1001                 else if (!strcmp(name, "location"))
1002                         tm_type = 3;
1003                 else if (!strcmp(name, "specular_hardness"))
1004                         tm_type = 4;
1005                 else if (!strcmp(name, "specular_color"))
1006                         tm_type = 5;
1007                 else if (!strcmp(name, "diffuse_color"))
1008                         tm_type = 6;
1009                 else if (!strcmp(name, "alpha"))
1010                         tm_type = 7;
1011                 else if (!strcmp(name, "ior"))
1012                         tm_type = 8;
1013
1014                 else
1015                         tm_type = -1;
1016         }
1017
1018         switch (tm_type) {
1019                 case 0:
1020                 case 1:
1021                         tm_name = "rotation";
1022                         is_rotation = true;
1023                         break;
1024                 case 2:
1025                         tm_name = "scale";
1026                         break;
1027                 case 3:
1028                         tm_name = "location";
1029                         break;
1030                 case 4:
1031                         tm_name = "shininess";
1032                         break;
1033                 case 5:
1034                         tm_name = "specular";
1035                         break;
1036                 case 6:
1037                         tm_name = "diffuse";
1038                         break;  
1039                 case 7:
1040                         tm_name = "transparency";
1041                         break;  
1042                 case 8:
1043                         tm_name = "index_of_refraction";
1044                         break;  
1045
1046                 default:
1047                         tm_name = "";
1048                         break;
1049         }
1050
1051         if (tm_name.size()) {
1052                 if (is_rotation)
1053                         return tm_name + std::string(axis_name) + ".ANGLE";
1054                 else
1055                 if (axis_name[0])
1056                         return tm_name + "." + std::string(axis_name);
1057                 else
1058                         return tm_name;
1059         }
1060
1061         return std::string("");
1062 }
1063
1064 char *AnimationExporter::extract_transform_name(char *rna_path)
1065 {
1066         char *dot = strrchr(rna_path, '.');
1067         return dot ? (dot + 1) : rna_path;
1068 }
1069
1070 //find keyframes of all the objects animations
1071 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra)
1072 {
1073         FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1074
1075         for (; fcu; fcu = fcu->next) {
1076
1077                 for (unsigned int i = 0; i < fcu->totvert; i++) {
1078                         float f = fcu->bezt[i].vec[1][0];
1079                         if (std::find(fra.begin(), fra.end(), f) == fra.end())   
1080                                 fra.push_back(f);
1081                 }
1082         }
1083
1084         // keep the keys in ascending order
1085         std::sort(fra.begin(), fra.end());
1086 }
1087
1088
1089
1090 // enable fcurves driving a specific bone, disable all the rest
1091 // if bone_name = NULL enable all fcurves
1092 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
1093 {
1094         FCurve *fcu;
1095         char prefix[200];
1096
1097         if (bone_name)
1098                 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
1099
1100         for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
1101                 if (bone_name) {
1102                         if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
1103                                 fcu->flag &= ~FCURVE_DISABLED;
1104                         else
1105                                 fcu->flag |= FCURVE_DISABLED;
1106                 }
1107                 else {
1108                         fcu->flag &= ~FCURVE_DISABLED;
1109                 }
1110         }
1111 }
1112
1113 bool AnimationExporter::hasAnimations(Scene *sce)
1114 {
1115         LinkNode *node;
1116
1117         for (node=this->export_settings->export_set; node; node=node->next) {
1118                 Object *ob = (Object *)node->link;
1119
1120                 FCurve *fcu = 0;
1121                 //Check for object transform animations
1122                 if (ob->adt && ob->adt->action)
1123                         fcu = (FCurve *)ob->adt->action->curves.first;
1124                 //Check for Lamp parameter animations
1125                 else if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action)
1126                         fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
1127                 //Check for Camera parameter animations
1128                 else if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action)
1129                         fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
1130
1131                 //Check Material Effect parameter animations.
1132                 for (int a = 0; a < ob->totcol; a++) {
1133                         Material *ma = give_current_material(ob, a + 1);
1134                         if (!ma) continue;
1135                         if (ma->adt && ma->adt->action) {
1136                                 fcu = (FCurve *)ma->adt->action->curves.first;
1137                         }
1138                 }
1139
1140                 if (fcu)
1141                         return true;
1142         }
1143         return false;
1144 }
1145
1146 //------------------------------- Not used in the new system.--------------------------------------------------------
1147 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
1148 {
1149         if (rotmode > 0)
1150                 find_frames(ob, fra, prefix, "rotation_euler");
1151         else if (rotmode == ROT_MODE_QUAT)
1152                 find_frames(ob, fra, prefix, "rotation_quaternion");
1153         /*else if (rotmode == ROT_MODE_AXISANGLE)
1154            ;*/
1155 }
1156
1157 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
1158 {
1159         FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
1160
1161         for (; fcu; fcu = fcu->next) {
1162                 if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
1163                         continue;
1164
1165                 char *name = extract_transform_name(fcu->rna_path);
1166                 if (!strcmp(name, tm_name)) {
1167                         for (unsigned int i = 0; i < fcu->totvert; i++) {
1168                                 float f = fcu->bezt[i].vec[1][0];
1169                                 if (std::find(fra.begin(), fra.end(), f) == fra.end())   
1170                                         fra.push_back(f);
1171                         }
1172                 }
1173         }
1174
1175         // keep the keys in ascending order
1176         std::sort(fra.begin(), fra.end());
1177 }
1178
1179 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
1180 {
1181         if (!ob_arm->adt)
1182                 return;
1183
1184         //write bone animations for 3 transform types
1185         //i=0 --> rotations
1186         //i=1 --> scale
1187         //i=2 --> location
1188         for (int i = 0; i < 3; i++)
1189                 sample_and_write_bone_animation(ob_arm, bone, i);
1190
1191         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next)
1192                 write_bone_animation(ob_arm, child);
1193 }
1194
1195 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
1196 {
1197         bArmature *arm = (bArmature *)ob_arm->data;
1198         int flag = arm->flag;
1199         std::vector<float> fra;
1200         char prefix[256];
1201
1202         BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
1203
1204         bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
1205         if (!pchan)
1206                 return;
1207         //Fill frame array with key frame values framed at \param:transform_type
1208         switch (transform_type) {
1209                 case 0:
1210                         find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
1211                         break;
1212                 case 1:
1213                         find_frames(ob_arm, fra, prefix, "scale");
1214                         break;
1215                 case 2:
1216                         find_frames(ob_arm, fra, prefix, "location");
1217                         break;
1218                 default:
1219                         return;
1220         }
1221
1222         // exit rest position
1223         if (flag & ARM_RESTPOS) {
1224                 arm->flag &= ~ARM_RESTPOS;
1225                 BKE_pose_where_is(scene, ob_arm);
1226         }
1227         //v array will hold all values which will be exported. 
1228         if (fra.size()) {
1229                 float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
1230                 sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
1231
1232                 if (transform_type == 0) {
1233                         // write x, y, z curves separately if it is rotation
1234                         float *axisValues = (float *)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
1235
1236                         for (int i = 0; i < 3; i++) {
1237                                 for (unsigned int j = 0; j < fra.size(); j++)
1238                                         axisValues[j] = values[j * 3 + i];
1239
1240                                 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
1241                         }
1242                         MEM_freeN(axisValues);
1243                 }
1244                 else {
1245                         // write xyz at once if it is location or scale
1246                         dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
1247                 }
1248
1249                 MEM_freeN(values);
1250         }
1251
1252         // restore restpos
1253         if (flag & ARM_RESTPOS) 
1254                 arm->flag = flag;
1255         BKE_pose_where_is(scene, ob_arm);
1256 }
1257
1258 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
1259 {
1260         bPoseChannel *parchan = NULL;
1261         bPose *pose = ob_arm->pose;
1262
1263         pchan = BKE_pose_channel_find_name(pose, bone->name);
1264
1265         if (!pchan)
1266                 return;
1267
1268         parchan = pchan->parent;
1269
1270         enable_fcurves(ob_arm->adt->action, bone->name);
1271
1272         std::vector<float>::iterator it;
1273         for (it = frames.begin(); it != frames.end(); it++) {
1274                 float mat[4][4], ipar[4][4];
1275
1276                 float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
1277
1278
1279                 BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
1280                 BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
1281
1282                 // compute bone local mat
1283                 if (bone->parent) {
1284                         invert_m4_m4(ipar, parchan->pose_mat);
1285                         mult_m4_m4m4(mat, ipar, pchan->pose_mat);
1286                 }
1287                 else
1288                         copy_m4_m4(mat, pchan->pose_mat);
1289
1290                 switch (type) {
1291                         case 0:
1292                                 mat4_to_eul(v, mat);
1293                                 break;
1294                         case 1:
1295                                 mat4_to_size(v, mat);
1296                                 break;
1297                         case 2:
1298                                 copy_v3_v3(v, mat[3]);
1299                                 break;
1300                 }
1301
1302                 v += 3;
1303         }
1304
1305         enable_fcurves(ob_arm->adt->action, NULL);
1306 }