Blender  V3.3
AnimationExporter.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "AnimationExporter.h"
9 #include "BCAnimationSampler.h"
10 #include "GeometryExporter.h"
11 #include "MaterialExporter.h"
12 #include "collada_utils.h"
13 
14 std::string EMPTY_STRING;
15 
16 std::string AnimationExporter::get_axis_name(std::string channel_type, int id)
17 {
18 
19  static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = {
20  {"color", {"R", "G", "B"}},
21  {"specular_color", {"R", "G", "B"}},
22  {"diffuse_color", {"R", "G", "B"}},
23  {"alpha", {"R", "G", "B"}},
24  {"scale", {"X", "Y", "Z"}},
25  {"location", {"X", "Y", "Z"}},
26  {"rotation_euler", {"X", "Y", "Z"}}};
27 
28  std::map<std::string, std::vector<std::string>>::const_iterator it;
29 
30  it = BC_COLLADA_AXIS_FROM_TYPE.find(channel_type);
31  if (it == BC_COLLADA_AXIS_FROM_TYPE.end()) {
32  return "";
33  }
34 
35  const std::vector<std::string> &subchannel = it->second;
36  if (id >= subchannel.size()) {
37  return "";
38  }
39  return subchannel[id];
40 }
41 
43 {
44  if (!has_container) {
45  char anim_id[200];
46  sprintf(anim_id, "action_container-%s", translate_id(id_name(ob)).c_str());
47  openAnimation(anim_id, encode_xml(id_name(ob)));
48  }
49  return true;
50 }
51 
52 void AnimationExporter::openAnimationWithClip(std::string action_id, std::string action_name)
53 {
54  std::vector<std::string> anim_meta_entry;
55  anim_meta_entry.push_back(translate_id(action_id));
56  anim_meta_entry.push_back(action_name);
57  anim_meta.push_back(anim_meta_entry);
58 
59  openAnimation(translate_id(action_id), action_name);
60 }
61 
63 {
64  if (has_container) {
65  closeAnimation();
66  }
67 }
68 
70 {
71  Scene *sce = export_settings.get_scene();
72 
73  LinkNode *export_set = this->export_settings.get_export_set();
74  bool has_anim_data = bc_has_animations(sce, export_set);
75  int animation_count = 0;
76  if (has_anim_data) {
77 
78  BCObjectSet animated_subset;
79  BCAnimationSampler::get_animated_from_export_set(animated_subset, *export_set);
80  animation_count = animated_subset.size();
81  BCAnimationSampler animation_sampler(export_settings, animated_subset);
82 
83  try {
84  animation_sampler.sample_scene(export_settings, /*keyframe_at_end = */ true);
85 
86  openLibrary();
87 
88  BCObjectSet::iterator it;
89  for (it = animated_subset.begin(); it != animated_subset.end(); ++it) {
90  Object *ob = *it;
91  exportAnimation(ob, animation_sampler);
92  }
93  }
94  catch (std::invalid_argument &iae) {
95  fprintf(stderr, "Animation export interrupted");
96  fprintf(stderr, "Exception was: %s", iae.what());
97  }
98 
99  closeLibrary();
100 
101 #if 0
102  /* TODO: If all actions shall be exported, we need to call the
103  * AnimationClipExporter which will figure out which actions
104  * need to be exported for which objects
105  */
106  if (this->export_settings->include_all_actions) {
107  AnimationClipExporter ace(eval_ctx, sw, export_settings, anim_meta);
108  ace.exportAnimationClips(sce);
109  }
110 #endif
111  }
112  return animation_count;
113 }
114 
116 {
117  bool container_is_open = false;
118 
119  /* Transform animations (trans, rot, scale). */
120  container_is_open = open_animation_container(container_is_open, ob);
121 
122  /* Now take care of the Object Animations
123  * NOTE: For Armatures the skeletal animation has already been exported (see above)
124  * However Armatures also can have Object animation.
125  */
126  bool export_as_matrix = this->export_settings.get_animation_transformation_type() ==
128 
129  if (export_as_matrix) {
130  /* export all transform_curves as one single matrix animation */
132  }
133 
134  export_curve_animation_set(ob, sampler, export_as_matrix);
135 
136  if (ob->type == OB_ARMATURE && export_as_matrix) {
137 
138 #ifdef WITH_MORPH_ANIMATION
139  /* TODO: This needs to be handled by extra profiles, postponed for now */
141 #endif
142 
143  /* Export skeletal animation (if any) */
144  bArmature *arm = (bArmature *)ob->data;
145  for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) {
147  }
148  }
149 
150  close_animation_container(container_is_open);
151 }
152 
155  bool export_as_matrix)
156 {
157  BCAnimationCurveMap *curves = sampler.get_curves(ob);
158  bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
159 
160  BCAnimationCurveMap::iterator it;
161  for (it = curves->begin(); it != curves->end(); ++it) {
162  BCAnimationCurve &curve = *it->second;
163  std::string channel_type = curve.get_channel_type();
164  if (channel_type == "rotation_quaternion") {
165  /* Can not export Quaternion animation in Collada as far as i know)
166  * Maybe automatically convert to euler rotation?
167  * Discard for now. */
168  continue;
169  }
170 
171  if (export_as_matrix && curve.is_transform_curve()) {
172  /* All Transform curves will be exported within a single matrix animation,
173  * see export_matrix_animation()
174  * No need to export the curves here again.
175  */
176  continue;
177  }
178 
179  if (!keep_flat_curves && !curve.is_animated()) {
180  continue;
181  }
182 
184  if (mcurve) {
185  export_curve_animation(ob, *mcurve);
186  delete mcurve;
187  }
188  else {
190  }
191  }
192 }
193 
195 {
196  bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
197 
198  std::vector<float> frames;
199  sampler.get_object_frames(frames, ob);
200  if (!frames.empty()) {
201  BCMatrixSampleMap samples;
202  bool is_animated = sampler.get_object_samples(samples, ob);
203  if (keep_flat_curves || is_animated) {
204  bAction *action = bc_getSceneObjectAction(ob);
205  std::string name = encode_xml(id_name(ob));
206  std::string action_name = (action == nullptr) ? name + "-action" : id_name(action);
207  std::string channel_type = "transform";
208  std::string axis;
209  std::string id = bc_get_action_id(action_name, name, channel_type, axis);
210 
211  std::string target = translate_id(name) + '/' + channel_type;
212 
213  BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
215  id, name, target, frames, samples, global_rotation_type, ob->parentinv);
216  }
217  }
218 }
219 
220 BC_global_rotation_type AnimationExporter::get_global_rotation_type(Object *ob)
221 {
222  bool is_export_root = this->export_settings.is_export_root(ob);
223  if (!is_export_root) {
224  return BC_NO_ROTATION;
225  }
226 
227  bool apply_global_rotation = this->export_settings.get_apply_global_orientation();
228 
229  return (apply_global_rotation) ? BC_DATA_ROTATION : BC_OBJECT_ROTATION;
230 }
231 
233  Bone *bone,
235 {
236  bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
237 
238  std::vector<float> frames;
239  sampler.get_bone_frames(frames, ob, bone);
240 
241  if (!frames.empty()) {
242  BCMatrixSampleMap samples;
243  bool is_animated = sampler.get_bone_samples(samples, ob, bone);
244  if (keep_flat_curves || is_animated) {
245  export_bone_animation(ob, bone, frames, samples);
246  }
247  }
248 
249  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
251  }
252 }
253 
257 {
258  std::string channel_type = curve.get_channel_type();
259  BCAnimationCurve *mcurve = nullptr;
260  if (channel_type == "lens") {
261 
262  /* Create an xfov curve */
263 
264  BCCurveKey key(BC_ANIMATION_TYPE_CAMERA, "xfov", 0);
265  mcurve = new BCAnimationCurve(key, ob);
266 
267  /* now tricky part: transform the fcurve */
268  BCValueMap lens_values;
269  curve.get_value_map(lens_values);
270 
271  BCAnimationCurve *sensor_curve = nullptr;
272  BCCurveKey sensor_key(BC_ANIMATION_TYPE_CAMERA, "sensor_width", 0);
273  BCAnimationCurveMap::iterator cit = curves.find(sensor_key);
274  if (cit != curves.end()) {
275  sensor_curve = cit->second;
276  }
277 
278  BCValueMap::const_iterator vit;
279  for (vit = lens_values.begin(); vit != lens_values.end(); ++vit) {
280  int frame = vit->first;
281  float lens_value = vit->second;
282 
283  float sensor_value;
284  if (sensor_curve) {
285  sensor_value = sensor_curve->get_value(frame);
286  }
287  else {
288  sensor_value = ((Camera *)ob->data)->sensor_x;
289  }
290  float value = RAD2DEGF(focallength_to_fov(lens_value, sensor_value));
291  mcurve->add_value(value, frame);
292  }
293  /* to reset the handles */
294  mcurve->clean_handles();
295  }
296  return mcurve;
297 }
298 
300 {
301  std::string channel_target = curve.get_channel_target();
302 
303  /*
304  * Some curves can not be exported as is and need some conversion
305  * For more information see implementation of get_modified_export_curve()
306  * NOTE: if mcurve is not NULL then it must be deleted at end of this method;
307  */
308 
309  int channel_index = curve.get_channel_index();
310  /* RGB or XYZ or "" */
311  std::string channel_type = curve.get_channel_type();
312  std::string axis = get_axis_name(channel_type, channel_index);
313 
314  std::string action_name;
315  bAction *action = bc_getSceneObjectAction(ob);
316  action_name = (action) ? id_name(action) : "constraint_anim";
317 
318  const std::string curve_name = encode_xml(curve.get_animation_name(ob));
319  std::string id = bc_get_action_id(action_name, curve_name, channel_target, axis, ".");
320 
321  std::string collada_target = translate_id(curve_name);
322 
323  if (curve.is_of_animation_type(BC_ANIMATION_TYPE_MATERIAL)) {
324  int material_index = curve.get_subindex();
325  Material *ma = BKE_object_material_get(ob, material_index + 1);
326  if (ma) {
327  collada_target = translate_id(id_name(ma)) + "-effect/common/" +
328  get_collada_sid(curve, axis);
329  }
330  }
331  else {
332  collada_target += "/" + get_collada_sid(curve, axis);
333  }
334 
335  BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
337  id, curve_name, collada_target, axis, curve, global_rotation_type);
338 }
339 
341  Bone *bone,
342  BCFrames &frames,
343  BCMatrixSampleMap &samples)
344 {
345  bAction *action = bc_getSceneObjectAction(ob);
346  std::string bone_name(bone->name);
347  std::string name = encode_xml(id_name(ob));
348  std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix");
349  std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform";
350 
351  BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
353  id, name, target, frames, samples, global_rotation_type, ob->parentinv);
354 }
355 
357 {
358  bool is_def;
359  /* Check if current bone is deform */
360  if ((bone->flag & BONE_NO_DEFORM) == 0) {
361  return true;
362  }
363  /* Check child bones */
364 
365  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
366  /* loop through all the children until deform bone is found, and then return */
367  is_def = is_bone_deform_group(child);
368  if (is_def) {
369  return true;
370  }
371  }
372 
373  /* no deform bone found in children also */
374  return false;
375 }
376 
378  std::string id,
379  std::string name,
380  std::string collada_target,
381  std::string axis,
383  BC_global_rotation_type global_rotation_type)
384 {
385  BCFrames frames;
386  BCValues values;
387  curve.get_frames(frames);
388  curve.get_values(values);
389  std::string channel_target = curve.get_channel_target();
390 
391  fprintf(
392  stdout, "Export animation curve %s (%d control points)\n", id.c_str(), int(frames.size()));
393  openAnimation(id, name);
394  BC_animation_source_type source_type = (curve.is_rotation_curve()) ? BC_SOURCE_TYPE_ANGLE :
396 
397  std::string input_id = collada_source_from_values(
398  BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, axis);
399  std::string output_id = collada_source_from_values(
400  source_type, COLLADASW::InputSemantic::OUTPUT, values, id, axis);
401 
402  bool has_tangents = false;
403  std::string interpolation_id;
404  if (this->export_settings.get_keep_smooth_curves()) {
405  interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents);
406  }
407  else {
408  interpolation_id = collada_linear_interpolation_source(frames.size(), id);
409  }
410 
411  std::string intangent_id;
412  std::string outtangent_id;
413  if (has_tangents) {
414  intangent_id = collada_tangent_from_curve(
415  COLLADASW::InputSemantic::IN_TANGENT, curve, id, axis);
416  outtangent_id = collada_tangent_from_curve(
417  COLLADASW::InputSemantic::OUT_TANGENT, curve, id, axis);
418  }
419 
420  std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
421 
422  COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
423 
424  sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
425  sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
426  sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION,
427  COLLADABU::URI(EMPTY_STRING, interpolation_id));
428 
429  if (has_tangents) {
430  sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT,
431  COLLADABU::URI(EMPTY_STRING, intangent_id));
432  sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT,
433  COLLADABU::URI(EMPTY_STRING, outtangent_id));
434  }
435 
436  addSampler(sampler);
437  addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), collada_target);
438 
439  closeAnimation();
440 }
441 
443  std::string id,
444  std::string name,
445  std::string target,
446  BCFrames &frames,
447  BCMatrixSampleMap &samples,
448  BC_global_rotation_type global_rotation_type,
449  Matrix &parentinv)
450 {
451  fprintf(
452  stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size()));
453 
454  openAnimationWithClip(id, name);
455 
456  std::string input_id = collada_source_from_values(
457  BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, "");
458  std::string output_id = collada_source_from_values(samples, id, global_rotation_type, parentinv);
459  std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id);
460 
461  std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
462  COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
463 
464  sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(EMPTY_STRING, input_id));
465  sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(EMPTY_STRING, output_id));
466  sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION,
467  COLLADABU::URI(EMPTY_STRING, interpolation_id));
468 
469  /* Matrix animation has no tangents */
470 
471  addSampler(sampler);
472  addChannel(COLLADABU::URI(EMPTY_STRING, sampler_id), target);
473 
474  closeAnimation();
475 }
476 
477 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
478 {
479  switch (semantic) {
480  case COLLADASW::InputSemantic::INPUT:
481  return INPUT_SOURCE_ID_SUFFIX;
482  case COLLADASW::InputSemantic::OUTPUT:
483  return OUTPUT_SOURCE_ID_SUFFIX;
484  case COLLADASW::InputSemantic::INTERPOLATION:
485  return INTERPOLATION_SOURCE_ID_SUFFIX;
486  case COLLADASW::InputSemantic::IN_TANGENT:
487  return INTANGENT_SOURCE_ID_SUFFIX;
488  case COLLADASW::InputSemantic::OUT_TANGENT:
489  return OUTTANGENT_SOURCE_ID_SUFFIX;
490  default:
491  break;
492  }
493  return "";
494 }
495 
496 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList &param,
497  COLLADASW::InputSemantic::Semantics semantic,
498  bool is_rot,
499  const std::string axis,
500  bool transform)
501 {
502  switch (semantic) {
503  case COLLADASW::InputSemantic::INPUT:
504  param.push_back("TIME");
505  break;
506  case COLLADASW::InputSemantic::OUTPUT:
507  if (is_rot) {
508  param.push_back("ANGLE");
509  }
510  else {
511  if (!axis.empty()) {
512  param.push_back(axis);
513  }
514  else if (transform) {
515  param.push_back("TRANSFORM");
516  }
517  else {
518  /* assumes if axis isn't specified all axes are added */
519  param.push_back("X");
520  param.push_back("Y");
521  param.push_back("Z");
522  }
523  }
524  break;
525  case COLLADASW::InputSemantic::IN_TANGENT:
526  case COLLADASW::InputSemantic::OUT_TANGENT:
527  param.push_back("X");
528  param.push_back("Y");
529  break;
530  default:
531  break;
532  }
533 }
534 
536  COLLADASW::InputSemantic::Semantics semantic,
538  const std::string &anim_id,
539  std::string axis_name)
540 {
541  Scene *scene = this->export_settings.get_scene();
542 
543  std::string channel = curve.get_channel_target();
544 
545  const std::string source_id = anim_id + get_semantic_suffix(semantic);
546 
547  bool is_angle = (bc_startswith(channel, "rotation") || channel == "spot_size");
548 
549  COLLADASW::FloatSourceF source(mSW);
550  source.setId(source_id);
551  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
552  source.setAccessorCount(curve.sample_count());
553  source.setAccessorStride(2);
554 
555  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
556  add_source_parameters(param, semantic, is_angle, axis_name, false);
557 
558  source.prepareToAppendValues();
559 
560  const FCurve *fcu = curve.get_fcurve();
561  int tangent = (semantic == COLLADASW::InputSemantic::IN_TANGENT) ? 0 : 2;
562 
563  for (int i = 0; i < fcu->totvert; i++) {
564  BezTriple &bezt = fcu->bezt[i];
565 
566  float sampled_time = bezt.vec[tangent][0];
567  float sampled_val = bezt.vec[tangent][1];
568 
569  if (is_angle) {
570  sampled_val = RAD2DEGF(sampled_val);
571  }
572 
573  source.appendValues(FRA2TIME(sampled_time));
574  source.appendValues(sampled_val);
575  }
576  source.finish();
577  return source_id;
578 }
579 
581  BC_animation_source_type source_type,
582  COLLADASW::InputSemantic::Semantics semantic,
583  std::vector<float> &values,
584  const std::string &anim_id,
585  const std::string axis_name)
586 {
587  BlenderContext &blender_context = this->export_settings.get_blender_context();
588  Scene *scene = blender_context.get_scene();
589  /* T can be float, int or double */
590 
591  int stride = 1;
592  int entry_count = values.size() / stride;
593  std::string source_id = anim_id + get_semantic_suffix(semantic);
594 
595  COLLADASW::FloatSourceF source(mSW);
596  source.setId(source_id);
597  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
598  source.setAccessorCount(entry_count);
599  source.setAccessorStride(stride);
600 
601  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
602  add_source_parameters(param, semantic, source_type == BC_SOURCE_TYPE_ANGLE, axis_name, false);
603 
604  source.prepareToAppendValues();
605 
606  for (int i = 0; i < entry_count; i++) {
607  float val = values[i];
608  switch (source_type) {
610  val = FRA2TIME(val);
611  break;
613  val = RAD2DEGF(val);
614  break;
615  default:
616  break;
617  }
618  source.appendValues(val);
619  }
620 
621  source.finish();
622 
623  return source_id;
624 }
625 
627  BCMatrixSampleMap &samples,
628  const std::string &anim_id,
629  BC_global_rotation_type global_rotation_type,
630  Matrix &parentinv)
631 {
632  COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
633  std::string source_id = anim_id + get_semantic_suffix(semantic);
634 
635  COLLADASW::Float4x4Source source(mSW);
636  source.setId(source_id);
637  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
638  source.setAccessorCount(samples.size());
639  source.setAccessorStride(16);
640 
641  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
642  add_source_parameters(param, semantic, false, "", true);
643 
644  source.prepareToAppendValues();
645 
646  BCMatrixSampleMap::iterator it;
647  /* could be made configurable */
648  int precision = (this->export_settings.get_limit_precision()) ? 6 : -1;
649  for (it = samples.begin(); it != samples.end(); it++) {
650  BCMatrix sample = BCMatrix(*it->second);
651  BCMatrix global_transform = this->export_settings.get_global_transform();
652  DMatrix daemat;
653  if (this->export_settings.get_apply_global_orientation()) {
654  sample.apply_transform(global_transform);
655  }
656  else {
657  sample.add_transform(global_transform);
658  }
659  sample.get_matrix(daemat, true, precision);
660  source.appendValues(daemat);
661  }
662 
663  source.finish();
664  return source_id;
665 }
666 
668  const std::string &anim_id,
669  const std::string axis,
670  bool *has_tangents)
671 {
672  std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
673 
674  COLLADASW::NameSource source(mSW);
675  source.setId(source_id);
676  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
677  source.setAccessorCount(curve.sample_count());
678  source.setAccessorStride(1);
679 
680  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
681  param.push_back("INTERPOLATION");
682 
683  source.prepareToAppendValues();
684 
685  *has_tangents = false;
686 
687  std::vector<float> frames;
688  curve.get_frames(frames);
689 
690  for (unsigned int i = 0; i < curve.sample_count(); i++) {
691  float frame = frames[i];
692  int ipo = curve.get_interpolation_type(frame);
693  if (ipo == BEZT_IPO_BEZ) {
694  source.appendValues(BEZIER_NAME);
695  *has_tangents = true;
696  }
697  else if (ipo == BEZT_IPO_CONST) {
698  source.appendValues(STEP_NAME);
699  }
700  else {
701  /* BEZT_IPO_LIN */
702  source.appendValues(LINEAR_NAME);
703  }
704  }
705  /* unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS */
706 
707  source.finish();
708 
709  return source_id;
710 }
711 
713  const std::string &anim_id)
714 {
715  std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
716 
717  COLLADASW::NameSource source(mSW);
718  source.setId(source_id);
719  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
720  source.setAccessorCount(tot);
721  source.setAccessorStride(1);
722 
723  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
724  param.push_back("INTERPOLATION");
725 
726  source.prepareToAppendValues();
727 
728  for (int i = 0; i < tot; i++) {
729  source.appendValues(LINEAR_NAME);
730  }
731 
732  source.finish();
733 
734  return source_id;
735 }
736 
737 std::string AnimationExporter::get_collada_name(std::string channel_type) const
738 {
739  /*
740  * Translation table to map FCurve animation types to Collada animation.
741  * TODO: Maybe we can keep the names from the fcurves here instead of
742  * mapping. However this is what i found in the old code. So keep
743  * this map for now.
744  */
745  static std::map<std::string, std::string> BC_CHANNEL_BLENDER_TO_COLLADA = {
746  {"rotation", "rotation"},
747  {"rotation_euler", "rotation"},
748  {"rotation_quaternion", "rotation"},
749  {"scale", "scale"},
750  {"location", "location"},
751 
752  /* Materials */
753  {"specular_color", "specular"},
754  {"diffuse_color", "diffuse"},
755  {"ior", "index_of_refraction"},
756  {"specular_hardness", "specular_hardness"},
757  {"alpha", "alpha"},
758 
759  /* Lights */
760  {"color", "color"},
761  {"fall_off_angle", "falloff_angle"},
762  {"spot_size", "falloff_angle"},
763  {"fall_off_exponent", "falloff_exponent"},
764  {"spot_blend", "falloff_exponent"},
765  /* Special blender profile (TODO: make this more elegant). */
766  {"blender/blender_dist", "blender/blender_dist"},
767  /* Special blender profile (TODO: make this more elegant). */
768  {"distance", "blender/blender_dist"},
769 
770  /* Cameras */
771  {"lens", "xfov"},
772  {"xfov", "xfov"},
773  {"xmag", "xmag"},
774  {"zfar", "zfar"},
775  {"znear", "znear"},
776  {"ortho_scale", "xmag"},
777  {"clip_end", "zfar"},
778  {"clip_start", "znear"}};
779 
780  std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(
781  channel_type);
782  if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end()) {
783  return "";
784  }
785  std::string tm_name = name_it->second;
786  return tm_name;
787 }
788 
790  const std::string axis_name)
791 {
792  std::string channel_target = curve.get_channel_target();
793  std::string channel_type = curve.get_channel_type();
794  std::string tm_name = get_collada_name(channel_type);
795 
796  bool is_angle = curve.is_rotation_curve();
797 
798  if (!tm_name.empty()) {
799  if (is_angle) {
800  return tm_name + std::string(axis_name) + ".ANGLE";
801  }
802  if (!axis_name.empty()) {
803  return tm_name + "." + std::string(axis_name);
804  }
805 
806  return tm_name;
807  }
808 
809  return tm_name;
810 }
811 
812 #ifdef WITH_MORPH_ANIMATION
813 /* TODO: This function needs to be implemented similar to the material animation export
814  * So we have to update BCSample for this to work. */
816 {
817  FCurve *fcu;
818  Key *key = BKE_key_from_object(ob);
819  if (!key) {
820  return;
821  }
822 
823  if (key->adt && key->adt->action) {
824  fcu = (FCurve *)key->adt->action->curves.first;
825 
826  while (fcu) {
827  BC_animation_transform_type tm_type = get_transform_type(fcu->rna_path);
828 
829  create_keyframed_animation(ob, fcu, tm_type, true, sampler);
830 
831  fcu = fcu->next;
832  }
833  }
834 }
835 #endif
std::string EMPTY_STRING
BC_animation_source_type
@ BC_SOURCE_TYPE_TIMEFRAME
@ BC_SOURCE_TYPE_VALUE
@ BC_SOURCE_TYPE_ANGLE
BC_global_rotation_type
@ BC_DATA_ROTATION
@ BC_OBJECT_ROTATION
@ BC_NO_ROTATION
std::vector< float > BCValues
std::map< int, float > BCValueMap
@ BC_ANIMATION_TYPE_MATERIAL
@ BC_ANIMATION_TYPE_CAMERA
std::map< BCCurveKey, BCAnimationCurve * > BCAnimationCurveMap
std::vector< float > BCFrames
std::map< int, const BCMatrix * > BCMatrixSampleMap
Definition: BCSampleData.h:48
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
#define RAD2DEGF(_rad)
float focallength_to_fov(float focal_length, float sensor)
@ BONE_NO_DEFORM
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ OB_ARMATURE
#define FRA2TIME(a)
@ BC_TRANSFORMATION_TYPE_MATRIX
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void exportAnimationClips(Scene *sce)
void export_collada_matrix_animation(std::string id, std::string name, std::string target, BCFrames &frames, BCMatrixSampleMap &samples, BC_global_rotation_type global_rotation_type, Matrix &parentinv)
std::string get_axis_name(std::string channel, int id)
std::string collada_interpolation_source(const BCAnimationCurve &curve, const std::string &anim_id, std::string axis_name, bool *has_tangents)
void add_source_parameters(COLLADASW::SourceBase::ParameterNameList &param, COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const std::string axis, bool transform)
void close_animation_container(bool has_container)
void openAnimationWithClip(std::string id, std::string name)
bool open_animation_container(bool has_container, Object *ob)
void export_collada_curve_animation(std::string id, std::string name, std::string target, std::string axis, BCAnimationCurve &curve, BC_global_rotation_type global_rotation_type)
void exportAnimation(Object *ob, BCAnimationSampler &sampler)
void export_matrix_animation(Object *ob, BCAnimationSampler &sampler)
void export_curve_animation_set(Object *ob, BCAnimationSampler &sampler, bool export_as_matrix)
bool is_bone_deform_group(Bone *bone)
void export_bone_animations_recursive(Object *ob_arm, Bone *bone, BCAnimationSampler &sampler)
void export_bone_animation(Object *ob, Bone *bone, BCFrames &frames, BCMatrixSampleMap &samples)
BCAnimationCurve * get_modified_export_curve(Object *ob, BCAnimationCurve &curve, BCAnimationCurveMap &curves)
void export_curve_animation(Object *ob, BCAnimationCurve &curve)
void export_morph_animation(Object *ob)
std::string get_collada_name(std::string channel_type) const
std::string collada_linear_interpolation_source(int tot, const std::string &anim_id)
std::string get_collada_sid(const BCAnimationCurve &curve, const std::string axis_name)
std::vector< std::vector< std::string > > anim_meta
std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
std::string collada_tangent_from_curve(COLLADASW::InputSemantic::Semantics semantic, BCAnimationCurve &curve, const std::string &anim_id, const std::string axis_name)
std::string collada_source_from_values(BC_animation_source_type source_type, COLLADASW::InputSemantic::Semantics semantic, std::vector< float > &values, const std::string &anim_id, const std::string axis_name)
float get_value(float frame)
void add_value(float val, int frame)
static void get_animated_from_export_set(std::set< Object * > &animated_objects, LinkNode &export_set)
void sample_scene(BCExportSettings &export_settings, bool keyframe_at_end)
std::string translate_id(const char *idString)
std::string encode_xml(std::string xml)
std::string id_name(void *id)
bool bc_has_animations(Object *ob)
std::string bc_get_action_id(std::string action_name, std::string ob_name, std::string channel_type, std::string axis_name, std::string axis_separator)
std::set< Object * > BCObjectSet
Definition: collada_utils.h:58
bAction * bc_getSceneObjectAction(Object *ob)
Definition: collada_utils.h:68
bool bc_startswith(std::string const &value, std::string const &starting)
Scene scene
Curve curve
depth_tx sampler(1, ImageType::FLOAT_2D, "combined_tx") .sampler(2
bAction * action
float vec[3][3]
char name[64]
ListBase childbase
struct FCurve * next
char * rna_path
BezTriple * bezt
unsigned int totvert
struct AnimData * adt
Definition: DNA_key_types.h:65
void * first
Definition: DNA_listBase.h:31
float parentinv[4][4]
void * data
ListBase curves
ListBase bonebase