Blender  V3.3
ControllerExporter.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "COLLADASWBaseInputElement.h"
8 #include "COLLADASWInstanceController.h"
9 #include "COLLADASWPrimitves.h"
10 #include "COLLADASWSource.h"
11 
12 #include "DNA_action_types.h"
13 #include "DNA_meshdata_types.h"
14 #include "DNA_modifier_types.h"
15 
16 #include "BKE_action.h"
17 #include "BKE_armature.h"
18 #include "BKE_deform.h"
19 #include "BKE_global.h"
20 #include "BKE_idprop.h"
21 #include "BKE_lib_id.h"
22 #include "BKE_mesh.h"
23 
24 #include "ED_armature.h"
25 
26 #include "BLI_listbase.h"
27 
28 #include "ArmatureExporter.h"
29 #include "ControllerExporter.h"
30 #include "GeometryExporter.h"
31 #include "SceneExporter.h"
32 
33 #include "collada_utils.h"
34 
36 {
37  return bc_get_assigned_armature(ob) != nullptr;
38 }
39 
40 void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins,
41  Object *ob_arm,
42  Bone *bone)
43 {
44  if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) {
45  std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
46  ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id));
47  }
48  else {
49  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
50  write_bone_URLs(ins, ob_arm, child);
51  }
52  }
53 }
54 
56 {
57  Object *ob_arm = bc_get_assigned_armature(ob);
58  bArmature *arm = (bArmature *)ob_arm->data;
59 
60  const std::string &controller_id = get_controller_id(ob_arm, ob);
61 
62  COLLADASW::InstanceController ins(mSW);
63  ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
64 
65  Mesh *me = (Mesh *)ob->data;
66  if (!me->dvert) {
67  return false;
68  }
69 
70  /* write root bone URLs */
71  Bone *bone;
72  for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
73  write_bone_URLs(ins, ob_arm, bone);
74  }
75 
77  ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
78 
79  ins.add();
80  return true;
81 }
82 
84 {
85  Scene *sce = blender_context.get_scene();
86  openLibrary();
87 
88  GeometryFunctor gf;
90  sce, *this, this->export_settings.get_export_set());
91 
92  closeLibrary();
93 }
94 
96 {
97  Object *ob_arm = bc_get_assigned_armature(ob);
98  Key *key = BKE_key_from_object(ob);
99 
100  if (ob_arm) {
101  export_skin_controller(ob, ob_arm);
102  }
103  if (key && this->export_settings.get_include_shapekeys()) {
104  export_morph_controller(ob, key);
105  }
106 }
107 #if 0
108 
109 bool ArmatureExporter::already_written(Object *ob_arm)
110 {
111  return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) !=
112  written_armatures.end();
113 }
114 
115 void ArmatureExporter::wrote(Object *ob_arm)
116 {
117  written_armatures.push_back(ob_arm);
118 }
119 
120 void ArmatureExporter::find_objects_using_armature(Object *ob_arm,
121  std::vector<Object *> &objects,
122  Scene *sce)
123 {
124  objects.clear();
125 
126  Base *base = (Base *)sce->base.first;
127  while (base) {
128  Object *ob = base->object;
129 
130  if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
131  objects.push_back(ob);
132  }
133 
134  base = base->next;
135  }
136 }
137 #endif
138 
139 std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
140 {
141  return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) +
142  SKIN_CONTROLLER_ID_SUFFIX;
143 }
144 
145 std::string ControllerExporter::get_controller_id(Key *key, Object *ob)
146 {
147  return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX;
148 }
149 
150 void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
151 {
152  /* joint names
153  * joint inverse bind matrices
154  * vertex weights */
155 
156  /* input:
157  * joint names: ob -> vertex group names
158  * vertex group weights: me->dvert -> groups -> index, weight */
159 
160  bool use_instantiation = this->export_settings.get_use_object_instantiation();
161  Mesh *me;
162 
163  if (((Mesh *)ob->data)->dvert == nullptr) {
164  return;
165  }
166 
167  me = bc_get_mesh_copy(blender_context,
168  ob,
169  this->export_settings.get_export_mesh_type(),
170  this->export_settings.get_apply_modifiers(),
171  this->export_settings.get_triangulate());
172 
173  std::string controller_name = id_name(ob_arm);
174  std::string controller_id = get_controller_id(ob_arm, ob);
175 
176  openSkin(controller_id,
177  controller_name,
178  COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
179 
180  add_bind_shape_mat(ob);
181 
182  const ListBase *defbase = BKE_object_defgroup_list(ob);
183  std::string joints_source_id = add_joints_source(ob_arm, defbase, controller_id);
184  std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, defbase, controller_id);
185 
186  std::list<int> vcounts;
187  std::list<int> joints;
188  std::list<float> weights;
189 
190  {
191  int i, j;
192 
193  /* def group index -> joint index */
194  std::vector<int> joint_index_by_def_index;
195  const bDeformGroup *def;
196 
197  for (def = (const bDeformGroup *)defbase->first, i = 0, j = 0; def; def = def->next, i++) {
198  if (is_bone_defgroup(ob_arm, def)) {
199  joint_index_by_def_index.push_back(j++);
200  }
201  else {
202  joint_index_by_def_index.push_back(-1);
203  }
204  }
205 
206  int oob_counter = 0;
207  for (i = 0; i < me->totvert; i++) {
208  MDeformVert *vert = &me->dvert[i];
209  std::map<int, float> jw;
210 
211  /* We're normalizing the weights later */
212  float sumw = 0.0f;
213 
214  for (j = 0; j < vert->totweight; j++) {
215  uint idx = vert->dw[j].def_nr;
216  if (idx >= joint_index_by_def_index.size()) {
217  /* XXX: Maybe better find out where and
218  * why the Out Of Bound indexes get created? */
219  oob_counter += 1;
220  }
221  else {
222  int joint_index = joint_index_by_def_index[idx];
223  if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
224  jw[joint_index] += vert->dw[j].weight;
225  sumw += vert->dw[j].weight;
226  }
227  }
228  }
229 
230  if (sumw > 0.0f) {
231  float invsumw = 1.0f / sumw;
232  vcounts.push_back(jw.size());
233  for (auto &index_and_weight : jw) {
234  joints.push_back(index_and_weight.first);
235  weights.push_back(invsumw * index_and_weight.second);
236  }
237  }
238  else {
239  vcounts.push_back(0);
240 #if 0
241  vcounts.push_back(1);
242  joints.push_back(-1);
243  weights.push_back(1.0f);
244 #endif
245  }
246  }
247 
248  if (oob_counter > 0) {
249  fprintf(stderr,
250  "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n",
251  oob_counter,
252  joint_index_by_def_index.size());
253  }
254  }
255 
256  std::string weights_source_id = add_weights_source(me, controller_id, weights);
257  add_joints_element(defbase, joints_source_id, inv_bind_mat_source_id);
258  add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
259 
260  BKE_id_free(nullptr, me);
261 
262  closeSkin();
263  closeController();
264 }
265 
266 void ControllerExporter::export_morph_controller(Object *ob, Key *key)
267 {
268  bool use_instantiation = this->export_settings.get_use_object_instantiation();
269  Mesh *me;
270 
271  me = bc_get_mesh_copy(blender_context,
272  ob,
273  this->export_settings.get_export_mesh_type(),
274  this->export_settings.get_apply_modifiers(),
275  this->export_settings.get_triangulate());
276 
277  std::string controller_name = id_name(ob) + "-morph";
278  std::string controller_id = get_controller_id(key, ob);
279 
280  openMorph(
281  controller_id,
282  controller_name,
283  COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
284 
285  std::string targets_id = add_morph_targets(key, ob);
286  std::string morph_weights_id = add_morph_weights(key, ob);
287 
288  COLLADASW::TargetsElement targets(mSW);
289 
290  COLLADASW::InputList &input = targets.getInputList();
291 
292  input.push_back(COLLADASW::Input(
293  COLLADASW::InputSemantic::MORPH_TARGET, /* constant declared in COLLADASWInputList.h */
294  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id)));
295  input.push_back(
296  COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT,
297  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id)));
298  targets.add();
299 
300  BKE_id_free(nullptr, me);
301 
302  /* support for animations
303  * can also try the base element and param alternative */
304  add_weight_extras(key);
305  closeMorph();
306  closeController();
307 }
308 
309 std::string ControllerExporter::add_morph_targets(Key *key, Object *ob)
310 {
311  std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX;
312 
313  COLLADASW::IdRefSource source(mSW);
314  source.setId(source_id);
315  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
316  source.setAccessorCount(key->totkey - 1);
317  source.setAccessorStride(1);
318 
319  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
320  param.push_back("IDREF");
321 
322  source.prepareToAppendValues();
323 
324  KeyBlock *kb = (KeyBlock *)key->block.first;
325  /* skip the basis */
326  kb = kb->next;
327  for (; kb; kb = kb->next) {
328  std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
329  source.appendValues(geom_id);
330  }
331 
332  source.finish();
333 
334  return source_id;
335 }
336 
337 std::string ControllerExporter::add_morph_weights(Key *key, Object *ob)
338 {
339  std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX;
340 
341  COLLADASW::FloatSourceF source(mSW);
342  source.setId(source_id);
343  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
344  source.setAccessorCount(key->totkey - 1);
345  source.setAccessorStride(1);
346 
347  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
348  param.push_back("MORPH_WEIGHT");
349 
350  source.prepareToAppendValues();
351 
352  KeyBlock *kb = (KeyBlock *)key->block.first;
353  /* skip the basis */
354  kb = kb->next;
355  for (; kb; kb = kb->next) {
356  float weight = kb->curval;
357  source.appendValues(weight);
358  }
359  source.finish();
360 
361  return source_id;
362 }
363 
364 void ControllerExporter::add_weight_extras(Key *key)
365 {
366  /* can also try the base element and param alternative */
367  COLLADASW::BaseExtraTechnique extra;
368 
369  KeyBlock *kb = (KeyBlock *)key->block.first;
370  /* skip the basis */
371  kb = kb->next;
372  for (; kb; kb = kb->next) {
373  /* XXX why is the weight not used here and set to 0.0?
374  * float weight = kb->curval; */
375  extra.addExtraTechniqueParameter("KHR", "morph_weights", 0.000, "MORPH_WEIGHT_TO_TARGET");
376  }
377 }
378 
379 void ControllerExporter::add_joints_element(const ListBase *defbase,
380  const std::string &joints_source_id,
381  const std::string &inv_bind_mat_source_id)
382 {
383  COLLADASW::JointsElement joints(mSW);
384  COLLADASW::InputList &input = joints.getInputList();
385 
386  input.push_back(COLLADASW::Input(
387  COLLADASW::InputSemantic::JOINT, /* constant declared in COLLADASWInputList.h */
388  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
389  input.push_back(
390  COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
391  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
392  joints.add();
393 }
394 
395 void ControllerExporter::add_bind_shape_mat(Object *ob)
396 {
397  double bind_mat[4][4];
398  float f_obmat[4][4];
399  BKE_object_matrix_local_get(ob, f_obmat);
400 
401  if (export_settings.get_apply_global_orientation()) {
402  /* do nothing, rotation is going to be applied to the Data */
403  }
404  else {
405  bc_add_global_transform(f_obmat, export_settings.get_global_transform());
406  }
407 
408  // UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat);
409  UnitConverter::mat4_to_dae_double(bind_mat, f_obmat);
410  if (this->export_settings.get_limit_precision()) {
412  }
413 
414  addBindShapeTransform(bind_mat);
415 }
416 
417 std::string ControllerExporter::add_joints_source(Object *ob_arm,
418  const ListBase *defbase,
419  const std::string &controller_id)
420 {
421  std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
422 
423  int totjoint = 0;
424  bDeformGroup *def;
425  for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
426  if (is_bone_defgroup(ob_arm, def)) {
427  totjoint++;
428  }
429  }
430 
431  COLLADASW::NameSource source(mSW);
432  source.setId(source_id);
433  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
434  source.setAccessorCount(totjoint);
435  source.setAccessorStride(1);
436 
437  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
438  param.push_back("JOINT");
439 
440  source.prepareToAppendValues();
441 
442  for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
443  Bone *bone = get_bone_from_defgroup(ob_arm, def);
444  if (bone) {
445  source.appendValues(get_joint_sid(bone));
446  }
447  }
448 
449  source.finish();
450 
451  return source_id;
452 }
453 
454 std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
455  const ListBase *defbase,
456  const std::string &controller_id)
457 {
458  std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
459 
460  int totjoint = 0;
461  for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
462  if (is_bone_defgroup(ob_arm, def)) {
463  totjoint++;
464  }
465  }
466 
467  COLLADASW::FloatSourceF source(mSW);
468  source.setId(source_id);
469  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
470  source.setAccessorCount(totjoint); // BLI_listbase_count(defbase));
471  source.setAccessorStride(16);
472 
473  source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
474  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
475  param.push_back("TRANSFORM");
476 
477  source.prepareToAppendValues();
478 
479  bPose *pose = ob_arm->pose;
480  bArmature *arm = (bArmature *)ob_arm->data;
481 
482  int flag = arm->flag;
483 
484  /* put armature in rest position */
485  if (!(arm->flag & ARM_RESTPOS)) {
486  Depsgraph *depsgraph = blender_context.get_depsgraph();
487  Scene *scene = blender_context.get_scene();
488 
489  arm->flag |= ARM_RESTPOS;
491  }
492 
493  for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
494  if (is_bone_defgroup(ob_arm, def)) {
495  bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);
496 
497  float mat[4][4];
498  float world[4][4];
499  float inv_bind_mat[4][4];
500 
501  float bind_mat[4][4]; /* derived from bone->arm_mat */
502 
503  bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat);
504 
505  if (!has_bindmat) {
506 
507  /* Have no bind matrix stored, try old style <= Blender 2.78 */
508 
510  this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true);
511 
512  /* SL/OPEN_SIM COMPATIBILITY */
513  if (export_settings.get_open_sim()) {
514  float loc[3];
515  float rot[3] = {0, 0, 0};
516  float scale[3];
517  bc_decompose(bind_mat, loc, nullptr, nullptr, scale);
518 
519  /* Only translations, no rotation vs armature */
520  loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6);
521  }
522  }
523 
524  /* make world-space matrix (bind_mat is armature-space) */
525  mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
526 
527  if (!has_bindmat) {
528  if (export_settings.get_apply_global_orientation()) {
529  bc_apply_global_transform(world, export_settings.get_global_transform());
530  }
531  }
532 
533  invert_m4_m4(mat, world);
534  UnitConverter::mat4_to_dae(inv_bind_mat, mat);
535  if (this->export_settings.get_limit_precision()) {
536  BCMatrix::sanitize(inv_bind_mat, LIMITTED_PRECISION);
537  }
538  source.appendValues(inv_bind_mat);
539  }
540  }
541 
542  /* back from rest position */
543  if (!(flag & ARM_RESTPOS)) {
544  Depsgraph *depsgraph = blender_context.get_depsgraph();
545  Scene *scene = blender_context.get_scene();
546  arm->flag = flag;
548  }
549 
550  source.finish();
551 
552  return source_id;
553 }
554 
555 Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, const bDeformGroup *def)
556 {
557  bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
558  return pchan ? pchan->bone : nullptr;
559 }
560 
561 bool ControllerExporter::is_bone_defgroup(Object *ob_arm, const bDeformGroup *def)
562 {
563  return get_bone_from_defgroup(ob_arm, def) != nullptr;
564 }
565 
566 std::string ControllerExporter::add_weights_source(Mesh *me,
567  const std::string &controller_id,
568  const std::list<float> &weights)
569 {
570  std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
571 
572  COLLADASW::FloatSourceF source(mSW);
573  source.setId(source_id);
574  source.setArrayId(source_id + ARRAY_ID_SUFFIX);
575  source.setAccessorCount(weights.size());
576  source.setAccessorStride(1);
577 
578  COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
579  param.push_back("WEIGHT");
580 
581  source.prepareToAppendValues();
582 
583  for (float weight : weights) {
584  source.appendValues(weight);
585  }
586 
587  source.finish();
588 
589  return source_id;
590 }
591 
592 void ControllerExporter::add_vertex_weights_element(const std::string &weights_source_id,
593  const std::string &joints_source_id,
594  const std::list<int> &vcounts,
595  const std::list<int> &joints)
596 {
597  COLLADASW::VertexWeightsElement weightselem(mSW);
598  COLLADASW::InputList &input = weightselem.getInputList();
599 
600  int offset = 0;
601  input.push_back(COLLADASW::Input(
602  COLLADASW::InputSemantic::JOINT, /* constant declared in COLLADASWInputList.h */
603  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id),
604  offset++));
605  input.push_back(
606  COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
607  COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id),
608  offset++));
609 
610  weightselem.setCount(vcounts.size());
611 
612  /* write number of deformers per vertex */
613  COLLADASW::PrimitivesBase::VCountList vcountlist;
614 
615  vcountlist.resize(vcounts.size());
616  std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
617 
618  weightselem.prepareToAppendVCountValues();
619  weightselem.appendVertexCount(vcountlist);
620 
621  weightselem.CloseVCountAndOpenVElement();
622 
623  /* write deformer index - weight index pairs */
624  int weight_index = 0;
625  for (int joint_index : joints) {
626  weightselem.appendValues(joint_index, weight_index++);
627  }
628 
629  weightselem.finish();
630 }
std::string EMPTY_STRING
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: armature.c:2538
support for deformation groups and hooks.
const struct ListBase * BKE_object_defgroup_list(const struct Object *ob)
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4])
Definition: object.cc:3093
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void loc_eulO_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3], short order)
Definition: math_matrix.c:2571
unsigned int uint
Definition: BLI_sys_types.h:67
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ ARM_RESTPOS
@ OB_MESH
static void sanitize(Matrix &matrix, int precision)
Definition: BCMath.cpp:139
bool add_instance_controller(Object *ob)
void operator()(Object *ob)
bool is_skinned_mesh(Object *ob)
void add_material_bindings(COLLADASW::BindMaterial &bind_material, Object *ob, bool active_uv_only)
static void mat4_to_dae(float out[4][4], float in[4][4])
static void mat4_to_dae_double(double out[4][4], float in[4][4])
std::string get_joint_sid(Bone *bone)
std::string translate_id(const char *idString)
std::string get_geometry_id(Object *ob)
std::string id_name(void *id)
bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
Mesh * bc_get_mesh_copy(BlenderContext &blender_context, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
void bc_add_global_transform(Matrix &to_mat, const Matrix &from_mat, const BCMatrix &global_transform, const bool invert)
void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
void bc_create_restpose_mat(BCExportSettings &export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
Object * bc_get_assigned_armature(Object *ob)
void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
constexpr int LIMITTED_PRECISION
Definition: collada_utils.h:53
Scene scene
World world
const Depsgraph * depsgraph
#define rot(x, k)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_global KernelShaderEvalInput * input
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
struct Base * next
struct Object * object
char name[64]
float arm_mat[4][4]
struct Bone * next
ListBase childbase
void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
char name[64]
Definition: DNA_key_types.h:52
float curval
Definition: DNA_key_types.h:34
struct KeyBlock * next
Definition: DNA_key_types.h:25
int totkey
Definition: DNA_key_types.h:91
ListBase block
Definition: DNA_key_types.h:84
void * first
Definition: DNA_listBase.h:31
struct MDeformWeight * dw
unsigned int def_nr
struct MDeformVert * dvert
int totvert
struct bPose * pose
float obmat[4][4]
void * data
ListBase bonebase
struct bDeformGroup * next
struct Bone * bone