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