Blender  V3.3
BCAnimationSampler.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
4 #include <algorithm> /* std::find */
5 #include <map>
6 #include <vector>
7 
8 #include "BCAnimationCurve.h"
9 #include "BCAnimationSampler.h"
10 #include "BCMath.h"
11 #include "ExportSettings.h"
12 #include "collada_utils.h"
13 
14 #include "BKE_action.h"
15 #include "BKE_constraint.h"
16 #include "BKE_key.h"
17 #include "BKE_lib_id.h"
18 #include "BKE_main.h"
19 #include "BKE_material.h"
20 
21 #include "BLI_listbase.h"
22 
23 #include "DNA_anim_types.h"
24 #include "DNA_constraint_types.h"
25 #include "DNA_key_types.h"
26 #include "DNA_scene_types.h"
27 
28 #include "ED_object.h"
29 
30 static std::string EMPTY_STRING;
32 
33 BCAnimationSampler::BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &object_set)
34  : export_settings(export_settings)
35 {
36  BCObjectSet::iterator it;
37  for (it = object_set.begin(); it != object_set.end(); ++it) {
38  Object *ob = *it;
39  add_object(ob);
40  }
41 }
42 
44 {
45  BCAnimationObjectMap::iterator it;
46  for (it = objects.begin(); it != objects.end(); ++it) {
47  BCAnimation *animation = it->second;
48  delete animation;
49  }
50 }
51 
53 {
54  BlenderContext blender_context = export_settings.get_blender_context();
55  BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob);
56  objects[ob] = animation;
57 
58  initialize_keyframes(animation->frame_set, ob);
59  initialize_curves(animation->curve_map, ob);
60 }
61 
63 {
64  BCAnimation &animation = *objects[ob];
65  if (animation.curve_map.empty()) {
66  initialize_curves(animation.curve_map, ob);
67  }
68  return &animation.curve_map;
69 }
70 
71 static void get_sample_frames(BCFrameSet &sample_frames,
72  int sampling_rate,
73  bool keyframe_at_end,
74  Scene *scene)
75 {
76  sample_frames.clear();
77 
78  if (sampling_rate < 1) {
79  return; /* no sample frames in this case */
80  }
81 
82  float sfra = scene->r.sfra;
83  float efra = scene->r.efra;
84 
85  int frame_index;
86  for (frame_index = nearbyint(sfra); frame_index < efra; frame_index += sampling_rate) {
87  sample_frames.insert(frame_index);
88  }
89 
90  if (frame_index >= efra && keyframe_at_end) {
91  sample_frames.insert(efra);
92  }
93 }
94 
95 static bool is_object_keyframe(Object *ob, int frame_index)
96 {
97  return false;
98 }
99 
100 static void add_keyframes_from(bAction *action, BCFrameSet &frameset)
101 {
102  if (action) {
103  FCurve *fcu = nullptr;
104  for (fcu = (FCurve *)action->curves.first; fcu; fcu = fcu->next) {
105  BezTriple *bezt = fcu->bezt;
106  for (int i = 0; i < fcu->totvert; bezt++, i++) {
107  int frame_index = nearbyint(bezt->vec[1][0]);
108  frameset.insert(frame_index);
109  }
110  }
111  }
112 }
113 
114 void BCAnimationSampler::check_property_is_animated(
115  BCAnimation &animation, float *ref, float *val, std::string data_path, int length)
116 {
117  for (int array_index = 0; array_index < length; array_index++) {
118  if (!bc_in_range(ref[length], val[length], 0.00001)) {
119  BCCurveKey key(BC_ANIMATION_TYPE_OBJECT, data_path, array_index);
120  BCAnimationCurveMap::iterator it = animation.curve_map.find(key);
121  if (it == animation.curve_map.end()) {
122  animation.curve_map[key] = new BCAnimationCurve(key, animation.get_reference());
123  }
124  }
125  }
126 }
127 
128 void BCAnimationSampler::update_animation_curves(BCAnimation &animation,
129  BCSample &sample,
130  Object *ob,
131  int frame)
132 {
133  BCAnimationCurveMap::iterator it;
134  for (it = animation.curve_map.begin(); it != animation.curve_map.end(); ++it) {
135  BCAnimationCurve *curve = it->second;
136  if (curve->is_transform_curve()) {
137  curve->add_value_from_matrix(sample, frame);
138  }
139  else {
140  curve->add_value_from_rna(frame);
141  }
142  }
143 }
144 
145 BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool for_opensim)
146 {
147  BCSample &ob_sample = sample_data.add(ob, frame_index);
148 #if 0
149  if (export_settings.get_apply_global_orientation()) {
150  const BCMatrix &global_transform = export_settings.get_global_transform();
151  ob_sample.get_matrix(global_transform);
152  }
153 #endif
154 
155  if (ob->type == OB_ARMATURE) {
156  bPoseChannel *pchan;
157  for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
158  Bone *bone = pchan->bone;
159  Matrix bmat;
160  if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) {
161 
162  ob_sample.add_bone_matrix(bone, bmat);
163  }
164  }
165  }
166  return ob_sample;
167 }
168 
169 void BCAnimationSampler::sample_scene(BCExportSettings &export_settings, bool keyframe_at_end)
170 {
171  BlenderContext blender_context = export_settings.get_blender_context();
172  int sampling_rate = export_settings.get_sampling_rate();
173  bool for_opensim = export_settings.get_open_sim();
174  bool keep_keyframes = export_settings.get_keep_keyframes();
175  BC_export_animation_type export_animation_type = export_settings.get_export_animation_type();
176 
177  Scene *scene = blender_context.get_scene();
178  BCFrameSet scene_sample_frames;
179  get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene);
180  BCFrameSet::iterator it;
181 
182  int startframe = scene->r.sfra;
183  int endframe = scene->r.efra;
184 
185  for (int frame_index = startframe; frame_index <= endframe; frame_index++) {
186  /* Loop over all frames and decide for each frame if sampling is necessary */
187  bool is_scene_sample_frame = false;
188  bool needs_update = true;
189  if (scene_sample_frames.find(frame_index) != scene_sample_frames.end()) {
190  bc_update_scene(blender_context, frame_index);
191  needs_update = false;
192  is_scene_sample_frame = true;
193  }
194 
195  bool needs_sampling = is_scene_sample_frame || keep_keyframes ||
196  export_animation_type == BC_ANIMATION_EXPORT_KEYS;
197  if (!needs_sampling) {
198  continue;
199  }
200 
201  BCAnimationObjectMap::iterator obit;
202  for (obit = objects.begin(); obit != objects.end(); ++obit) {
203  Object *ob = obit->first;
204  BCAnimation *animation = obit->second;
205  BCFrameSet &object_keyframes = animation->frame_set;
206  if (is_scene_sample_frame || object_keyframes.find(frame_index) != object_keyframes.end()) {
207 
208  if (needs_update) {
209  bc_update_scene(blender_context, frame_index);
210  needs_update = false;
211  }
212 
213  BCSample &sample = sample_object(ob, frame_index, for_opensim);
214  update_animation_curves(*animation, sample, ob, frame_index);
215  }
216  }
217  }
218 }
219 
221  ListBase *conlist,
222  std::set<Object *> &animated_objects)
223 {
224  bConstraint *con;
225  for (con = (bConstraint *)conlist->first; con; con = con->next) {
226  ListBase targets = {nullptr, nullptr};
227 
228  if (!bc_validateConstraints(con)) {
229  continue;
230  }
231 
232  if (BKE_constraint_targets_get(con, &targets)) {
233  bConstraintTarget *ct;
234  Object *obtar;
235  bool found = false;
236 
237  for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
238  obtar = ct->tar;
239  if (obtar) {
240  if (animated_objects.find(obtar) != animated_objects.end()) {
241  found = true;
242  break;
243  }
244  }
245  }
246  BKE_constraint_targets_flush(con, &targets, true);
247  return found;
248  }
249  }
250  return false;
251 }
252 
253 void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_objects,
254  std::set<Object *> &candidates)
255 {
256  bool found_more;
257  do {
258  found_more = false;
259  std::set<Object *>::iterator it;
260  for (it = candidates.begin(); it != candidates.end(); ++it) {
261  Object *cob = *it;
263  if (is_animated_by_constraint(cob, conlist, animated_objects)) {
264  animated_objects.insert(cob);
265  candidates.erase(cob);
266  found_more = true;
267  break;
268  }
269  }
270  } while (found_more && !candidates.empty());
271 }
272 
273 void BCAnimationSampler::get_animated_from_export_set(std::set<Object *> &animated_objects,
274  LinkNode &export_set)
275 {
276  /* Check if this object is animated. That is: Check if it has its own action, or:
277  *
278  * - Check if it has constraints to other objects.
279  * - at least one of the other objects is animated as well.
280  */
281 
282  animated_objects.clear();
283  std::set<Object *> static_objects;
284  std::set<Object *> candidates;
285 
286  LinkNode *node;
287  for (node = &export_set; node; node = node->next) {
288  Object *cob = (Object *)node->link;
289  if (bc_has_animations(cob)) {
290  animated_objects.insert(cob);
291  }
292  else {
293  ListBase conlist = cob->constraints;
294  if (conlist.first) {
295  candidates.insert(cob);
296  }
297  }
298  }
299  find_depending_animated(animated_objects, candidates);
300 }
301 
303 {
304  sample_data.get_frames(ob, frames);
305 }
306 
308 {
309  sample_data.get_frames(ob, bone, frames);
310 }
311 
313 {
314  sample_data.get_matrices(ob, bone, samples);
315  return bc_is_animated(samples);
316 }
317 
319 {
320  sample_data.get_matrices(ob, samples);
321  return bc_is_animated(samples);
322 }
323 
324 #if 0
337 void BCAnimationSampler::add_value_set(BCAnimationCurve &curve,
338  BCFrameSampleMap &samples,
339  BC_export_animation_type animation_type)
340 {
341  int array_index = curve.get_array_index();
342  const BC_animation_transform_type tm_type = curve.get_transform_type();
343 
344  BCFrameSampleMap::iterator it;
345  for (it = samples.begin(); it != samples.end(); ++it) {
346  const int frame_index = nearbyint(it->first);
347  if (animation_type == BC_ANIMATION_EXPORT_SAMPLES || curve.is_keyframe(frame_index)) {
348 
349  const BCSample *sample = it->second;
350  float val = 0;
351 
352  int subindex = curve.get_subindex();
353  bool good;
354  if (subindex == -1) {
355  good = sample->get_value(tm_type, array_index, &val);
356  }
357  else {
358  good = sample->get_value(tm_type, array_index, &val, subindex);
359  }
360 
361  if (good) {
362  curve.add_value(val, frame_index);
363  }
364  }
365  }
366  curve.remove_unused_keyframes();
367  curve.calchandles();
368 }
369 #endif
370 
371 void BCAnimationSampler::generate_transform(Object *ob,
372  const BCCurveKey &key,
374 {
375  BCAnimationCurveMap::const_iterator it = curves.find(key);
376  if (it == curves.end()) {
377  curves[key] = new BCAnimationCurve(key, ob);
378  }
379 }
380 
381 void BCAnimationSampler::generate_transforms(Object *ob,
382  const std::string prep,
383  const BC_animation_type type,
385 {
386  generate_transform(ob, BCCurveKey(type, prep + "location", 0), curves);
387  generate_transform(ob, BCCurveKey(type, prep + "location", 1), curves);
388  generate_transform(ob, BCCurveKey(type, prep + "location", 2), curves);
389  generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 0), curves);
390  generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 1), curves);
391  generate_transform(ob, BCCurveKey(type, prep + "rotation_euler", 2), curves);
392  generate_transform(ob, BCCurveKey(type, prep + "scale", 0), curves);
393  generate_transform(ob, BCCurveKey(type, prep + "scale", 1), curves);
394  generate_transform(ob, BCCurveKey(type, prep + "scale", 2), curves);
395 }
396 
397 void BCAnimationSampler::generate_transforms(Object *ob, Bone *bone, BCAnimationCurveMap &curves)
398 {
399  std::string prep = "pose.bones[\"" + std::string(bone->name) + "\"].";
400  generate_transforms(ob, prep, BC_ANIMATION_TYPE_BONE, curves);
401 
402  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
403  generate_transforms(ob, child, curves);
404  }
405 }
406 
407 void BCAnimationSampler::initialize_keyframes(BCFrameSet &frameset, Object *ob)
408 {
409  frameset.clear();
413 
414  for (int a = 0; a < ob->totcol; a++) {
415  Material *ma = BKE_object_material_get(ob, a + 1);
417  }
418 }
419 
420 void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object *ob)
421 {
423 
424  bAction *action = bc_getSceneObjectAction(ob);
425  if (action) {
426  FCurve *fcu = (FCurve *)action->curves.first;
427 
428  for (; fcu; fcu = fcu->next) {
429  object_type = BC_ANIMATION_TYPE_OBJECT;
430  if (ob->type == OB_ARMATURE) {
431  char boneName[MAXBONENAME];
432  if (BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", boneName, sizeof(boneName))) {
433  object_type = BC_ANIMATION_TYPE_BONE;
434  }
435  }
436 
437  /* Adding action curves on object */
438  BCCurveKey key(object_type, fcu->rna_path, fcu->array_index);
439  curves[key] = new BCAnimationCurve(key, ob, fcu);
440  }
441  }
442 
443  /* Add missing curves */
444  object_type = BC_ANIMATION_TYPE_OBJECT;
445  generate_transforms(ob, EMPTY_STRING, object_type, curves);
446  if (ob->type == OB_ARMATURE) {
447  bArmature *arm = (bArmature *)ob->data;
448  for (Bone *root_bone = (Bone *)arm->bonebase.first; root_bone; root_bone = root_bone->next) {
449  generate_transforms(ob, root_bone, curves);
450  }
451  }
452 
453  /* Add curves on Object->data actions */
454  action = nullptr;
455  if (ob->type == OB_CAMERA) {
456  action = bc_getSceneCameraAction(ob);
457  object_type = BC_ANIMATION_TYPE_CAMERA;
458  }
459  else if (ob->type == OB_LAMP) {
460  action = bc_getSceneLightAction(ob);
461  object_type = BC_ANIMATION_TYPE_LIGHT;
462  }
463 
464  if (action) {
465  /* Add light action or Camera action */
466  FCurve *fcu = (FCurve *)action->curves.first;
467  for (; fcu; fcu = fcu->next) {
468  BCCurveKey key(object_type, fcu->rna_path, fcu->array_index);
469  curves[key] = new BCAnimationCurve(key, ob, fcu);
470  }
471  }
472 
473  /* Add curves on Object->material actions. */
474  object_type = BC_ANIMATION_TYPE_MATERIAL;
475  for (int a = 0; a < ob->totcol; a++) {
476  /* Export Material parameter animations. */
477  Material *ma = BKE_object_material_get(ob, a + 1);
478  if (ma) {
479  action = bc_getSceneMaterialAction(ma);
480  if (action) {
481  /* isMatAnim = true; */
482  FCurve *fcu = (FCurve *)action->curves.first;
483  for (; fcu; fcu = fcu->next) {
484  BCCurveKey key(object_type, fcu->rna_path, fcu->array_index, a);
485  curves[key] = new BCAnimationCurve(key, ob, fcu);
486  }
487  }
488  }
489  }
490 }
491 
492 /* ==================================================================== */
493 
495 {
496  BCSample *sample = new BCSample(ob);
497  sampleMap[ob] = sample;
498  return *sample;
499 }
500 
502 {
503  BCSampleMap::const_iterator it = sampleMap.find(ob);
504  if (it == sampleMap.end()) {
505  return nullptr;
506  }
507  return it->second;
508 }
509 
511 {
512  BCSampleMap::const_iterator it = sampleMap.find(ob);
513  if (it == sampleMap.end()) {
514  return nullptr;
515  }
516  BCSample *sample = it->second;
517  return &sample->get_matrix();
518 }
519 
521 {
522  BCSampleMap::const_iterator it = sampleMap.find(ob);
523  if (it == sampleMap.end()) {
524  return nullptr;
525  }
526 
527  BCSample *sample = it->second;
528  const BCMatrix *bc_bone = sample->get_matrix(bone);
529  return bc_bone;
530 }
531 
533 {
534  return sampleMap.find(ob) != sampleMap.end();
535 }
536 
538 {
539  const BCMatrix *bc_bone = get_sample_matrix(ob, bone);
540  return bc_bone;
541 }
542 
543 /* ==================================================================== */
544 
546 {
547  BCSampleFrame &frame = sample_frames[frame_index];
548  return frame.add(ob);
549 }
550 
551 /* ====================================================== */
552 /* Below are the getters which we need to export the data */
553 /* ====================================================== */
554 
556 {
557  BCSampleFrameMap::iterator it = sample_frames.find(frame_index);
558  BCSampleFrame *frame = (it == sample_frames.end()) ? nullptr : &it->second;
559  return frame;
560 }
561 
562 int BCSampleFrameContainer::get_frames(std::vector<int> &frames) const
563 {
564  frames.clear(); /* safety; */
565  BCSampleFrameMap::const_iterator it;
566  for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
567  frames.push_back(it->first);
568  }
569  return frames.size();
570 }
571 
573 {
574  frames.clear(); /* safety; */
575  BCSampleFrameMap::const_iterator it;
576  for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
577  const BCSampleFrame &frame = it->second;
578  if (frame.has_sample_for(ob)) {
579  frames.push_back(it->first);
580  }
581  }
582  return frames.size();
583 }
584 
586 {
587  frames.clear(); /* safety; */
588  BCSampleFrameMap::const_iterator it;
589  for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
590  const BCSampleFrame &frame = it->second;
591  if (frame.has_sample_for(ob, bone)) {
592  frames.push_back(it->first);
593  }
594  }
595  return frames.size();
596 }
597 
599 {
600  samples.clear(); /* safety; */
601  BCSampleFrameMap::const_iterator it;
602  for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
603  const BCSampleFrame &frame = it->second;
604  const BCSample *sample = frame.get_sample(ob);
605  if (sample) {
606  samples[it->first] = sample;
607  }
608  }
609  return samples.size();
610 }
611 
613 {
614  samples.clear(); /* safety; */
615  BCSampleFrameMap::const_iterator it;
616  for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
617  const BCSampleFrame &frame = it->second;
618  const BCMatrix *matrix = frame.get_sample_matrix(ob);
619  if (matrix) {
620  samples[it->first] = matrix;
621  }
622  }
623  return samples.size();
624 }
625 
627 {
628  samples.clear(); /* safety; */
629  BCSampleFrameMap::const_iterator it;
630  for (it = sample_frames.begin(); it != sample_frames.end(); ++it) {
631  const BCSampleFrame &frame = it->second;
632  const BCMatrix *sample = frame.get_sample_matrix(ob, bone);
633  if (sample) {
634  samples[it->first] = sample;
635  }
636  }
637  return samples.size();
638 }
BC_animation_type
@ BC_ANIMATION_TYPE_MATERIAL
@ BC_ANIMATION_TYPE_LIGHT
@ BC_ANIMATION_TYPE_OBJECT
@ BC_ANIMATION_TYPE_BONE
@ BC_ANIMATION_TYPE_CAMERA
std::map< BCCurveKey, BCAnimationCurve * > BCAnimationCurveMap
std::vector< float > BCFrames
std::set< float > BCFrameSet
static BCAnimationCurveMap BCEmptyAnimationCurves
static bool is_object_keyframe(Object *ob, int frame_index)
static void add_keyframes_from(bAction *action, BCFrameSet &frameset)
static void get_sample_frames(BCFrameSet &sample_frames, int sampling_rate, bool keyframe_at_end, Scene *scene)
static std::string EMPTY_STRING
std::map< int, const BCSample * > BCFrameSampleMap
Definition: BCSampleData.h:47
std::map< int, const BCMatrix * > BCMatrixSampleMap
Definition: BCSampleData.h:48
Blender kernel action and pose functionality.
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
Definition: constraint.c:6186
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
Definition: constraint.c:6157
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
bool bool BLI_str_quoted_substr(const char *__restrict str, const char *__restrict prefix, char *result, size_t result_maxlen)
Definition: string.c:424
#define MAXBONENAME
@ OB_CAMERA
@ OB_ARMATURE
@ OB_LAMP
struct ListBase * ED_object_constraint_active_list(struct Object *ob)
BC_export_animation_type
@ BC_ANIMATION_EXPORT_KEYS
@ BC_ANIMATION_EXPORT_SAMPLES
_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 type
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
void get_object_frames(BCFrames &frames, Object *ob)
static void find_depending_animated(std::set< Object * > &animated_objects, std::set< Object * > &candidates)
bool get_bone_samples(BCMatrixSampleMap &samples, Object *ob, Bone *bone)
static void get_animated_from_export_set(std::set< Object * > &animated_objects, LinkNode &export_set)
void get_bone_frames(BCFrames &frames, Object *ob, Bone *bone)
BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &object_set)
void add_object(Object *ob)
void sample_scene(BCExportSettings &export_settings, bool keyframe_at_end)
static bool is_animated_by_constraint(Object *ob, ListBase *conlist, std::set< Object * > &animated_objects)
bool get_object_samples(BCMatrixSampleMap &samples, Object *ob)
BCAnimationCurveMap * get_curves(Object *ob)
Object * get_reference()
BCFrameSet frame_set
BCAnimationCurveMap curve_map
BCSample & add(Object *ob, int frame_index)
int get_frames(std::vector< int > &frames) const
BCSampleFrame * get_frame(int frame_index)
int get_samples(Object *ob, BCFrameSampleMap &samples) const
int get_matrices(Object *ob, BCMatrixSampleMap &samples) const
const BCMatrix * get_sample_matrix(Object *ob) const
bool has_sample_for(Object *ob) const
const BCSample * get_sample(Object *ob) const
BCSample & add(Object *ob)
const BCMatrix & get_matrix() const
void add_bone_matrix(Bone *bone, Matrix &mat)
bool bc_has_animations(Object *ob)
bool bc_is_animated(BCMatrixSampleMap &values)
bool bc_validateConstraints(bConstraint *con)
void bc_update_scene(BlenderContext &blender_context, float ctime)
bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
std::set< Object * > BCObjectSet
Definition: collada_utils.h:58
bAction * bc_getSceneObjectAction(Object *ob)
Definition: collada_utils.h:68
bool bc_in_range(float a, float b, float range)
bAction * bc_getSceneLightAction(Object *ob)
Definition: collada_utils.h:74
bAction * bc_getSceneMaterialAction(Material *ma)
Definition: collada_utils.h:96
bAction * bc_getSceneCameraAction(Object *ob)
Definition: collada_utils.h:85
OperationNode * node
Scene scene
Curve curve
static unsigned a[3]
Definition: RandGen.cpp:78
T length(const vec_base< T, Size > &a)
float vec[3][3]
char name[64]
ListBase childbase
struct FCurve * next
char * rna_path
BezTriple * bezt
int array_index
unsigned int totvert
void * first
Definition: DNA_listBase.h:31
ListBase constraints
struct bPose * pose
void * data
struct RenderData r
ListBase curves
ListBase bonebase
struct bConstraintTarget * next
struct bConstraint * next
struct Bone * bone
struct bPoseChannel * next
ListBase chanbase