Blender  V2.93
ArmatureExporter.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_mesh.h"
34 
35 #include "ED_armature.h"
36 
37 #include "BLI_listbase.h"
38 
39 #include "ArmatureExporter.h"
40 #include "GeometryExporter.h"
41 #include "SceneExporter.h"
42 
43 /* write bone nodes */
45  ViewLayer *view_layer,
46  SceneExporter *se,
47  std::vector<Object *> &child_objects)
48 
49 {
50  /* write bone nodes */
51 
52  bArmature *armature = (bArmature *)ob_arm->data;
53  bool is_edited = armature->edbo != nullptr;
54 
55  if (!is_edited) {
56  ED_armature_to_edit(armature);
57  }
58 
59  for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) {
60  add_bone_node(bone, ob_arm, se, child_objects);
61  }
62 
63  if (!is_edited) {
64  ED_armature_edit_free(armature);
65  }
66 }
67 
68 void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins,
69  Object *ob_arm,
70  Bone *bone)
71 {
72  if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) {
73  std::string joint_id = translate_id(id_name(ob_arm) + "_" + bone->name);
74  ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, joint_id));
75  }
76  else {
77  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
78  write_bone_URLs(ins, ob_arm, child);
79  }
80  }
81 }
82 
84 {
85  Object *ob_arm = bc_get_assigned_armature(ob);
86  bArmature *arm = (bArmature *)ob_arm->data;
87 
88  const std::string &controller_id = get_controller_id(ob_arm, ob);
89 
90  COLLADASW::InstanceController ins(mSW);
91  ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
92 
93  Mesh *me = (Mesh *)ob->data;
94  if (!me->dvert) {
95  return false;
96  }
97 
98  /* write root bone URLs */
99  Bone *bone;
100  for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
101  write_bone_URLs(ins, ob_arm, bone);
102  }
103 
105  ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
106 
107  ins.add();
108  return true;
109 }
110 
111 #if 0
113 {
114  Object *ob_arm = bc_get_assigned_armature(ob);
115 }
116 
117 bool ArmatureExporter::already_written(Object *ob_arm)
118 {
119  return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) !=
120  written_armatures.end();
121 }
122 
123 void ArmatureExporter::wrote(Object *ob_arm)
124 {
125  written_armatures.push_back(ob_arm);
126 }
127 
128 void ArmatureExporter::find_objects_using_armature(Object *ob_arm,
129  std::vector<Object *> &objects,
130  Scene *sce)
131 {
132  objects.clear();
133 
134  Base *base = (Base *)sce->base.first;
135  while (base) {
136  Object *ob = base->object;
137 
138  if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
139  objects.push_back(ob);
140  }
141 
142  base = base->next;
143  }
144 }
145 #endif
146 
147 /* parent_mat is armature-space */
148 void ArmatureExporter::add_bone_node(Bone *bone,
149  Object *ob_arm,
150  SceneExporter *se,
151  std::vector<Object *> &child_objects)
152 {
153  if (can_export(bone)) {
154  std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
155  std::string node_name = std::string(bone->name);
156  std::string node_sid = get_joint_sid(bone);
157 
158  COLLADASW::Node node(mSW);
159 
160  node.setType(COLLADASW::Node::JOINT);
161  node.setNodeId(node_id);
162  node.setNodeName(node_name);
163  node.setNodeSid(node_sid);
164 
165  if (this->export_settings.get_use_blender_profile()) {
166  if (!is_export_root(bone)) {
167  if (bone->flag & BONE_CONNECTED) {
168  node.addExtraTechniqueParameter("blender", "connect", true);
169  }
170  }
171  std::string layers = BoneExtended::get_bone_layers(bone->layer);
172  node.addExtraTechniqueParameter("blender", "layer", layers);
173 
174  bArmature *armature = (bArmature *)ob_arm->data;
175  EditBone *ebone = bc_get_edit_bone(armature, bone->name);
176  if (ebone && ebone->roll != 0) {
177  node.addExtraTechniqueParameter("blender", "roll", ebone->roll);
178  }
179  if (bc_is_leaf_bone(bone)) {
180  Vector head, tail;
181  const BCMatrix &global_transform = this->export_settings.get_global_transform();
182  if (this->export_settings.get_apply_global_orientation()) {
183  bc_add_global_transform(head, bone->arm_head, global_transform);
184  bc_add_global_transform(tail, bone->arm_tail, global_transform);
185  }
186  else {
187  copy_v3_v3(head, bone->arm_head);
188  copy_v3_v3(tail, bone->arm_tail);
189  }
190  node.addExtraTechniqueParameter("blender", "tip_x", tail[0] - head[0]);
191  node.addExtraTechniqueParameter("blender", "tip_y", tail[1] - head[1]);
192  node.addExtraTechniqueParameter("blender", "tip_z", tail[2] - head[2]);
193  }
194  }
195 
196  node.start();
197 
198  add_bone_transform(ob_arm, bone, node);
199 
200  /* Write nodes of child-objects, remove written objects from list. */
201  std::vector<Object *>::iterator iter = child_objects.begin();
202 
203  while (iter != child_objects.end()) {
204  Object *ob = *iter;
205  if (ob->partype == PARBONE && STREQ(ob->parsubstr, bone->name)) {
206  float backup_parinv[4][4];
207  copy_m4_m4(backup_parinv, ob->parentinv);
208 
209  /* Crude, temporary change to parentinv
210  * so transform gets exported correctly. */
211 
212  /* Add bone tail- translation... don't know why
213  * bone parenting is against the tail of a bone
214  * and not its head, seems arbitrary. */
215  ob->parentinv[3][1] += bone->length;
216 
217  /* OPEN_SIM_COMPATIBILITY
218  * TODO: when such objects are animated as
219  * single matrix the tweak must be applied
220  * to the result. */
221  if (export_settings.get_open_sim()) {
222  /* Tweak objects parent-inverse to match compatibility. */
223  float temp[4][4];
224 
225  copy_m4_m4(temp, bone->arm_mat);
226  temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
227 
228  mul_m4_m4m4(ob->parentinv, temp, ob->parentinv);
229  }
230 
231  se->writeNode(ob);
232  copy_m4_m4(ob->parentinv, backup_parinv);
233  iter = child_objects.erase(iter);
234  }
235  else {
236  iter++;
237  }
238  }
239 
240  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
241  add_bone_node(child, ob_arm, se, child_objects);
242  }
243  node.end();
244  }
245  else {
246  for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
247  add_bone_node(child, ob_arm, se, child_objects);
248  }
249  }
250 }
251 
252 bool ArmatureExporter::is_export_root(Bone *bone)
253 {
254  Bone *entry = bone->parent;
255  while (entry) {
256  if (can_export(entry)) {
257  return false;
258  }
259  entry = entry->parent;
260  }
261  return can_export(bone);
262 }
263 
264 void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node)
265 {
266  // bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
267 
268  float mat[4][4];
269  float bone_rest_mat[4][4]; /* derived from bone->arm_mat */
270  float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */
271 
272  bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat);
273 
274  if (!has_restmat) {
275 
276  /* Have no restpose matrix stored, try old style <= Blender 2.78 */
277 
278  bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true);
279 
280  if (is_export_root(bone)) {
281  copy_m4_m4(mat, bone_rest_mat);
282  }
283  else {
284  Matrix parent_inverse;
286  this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true);
287 
288  invert_m4_m4(parent_inverse, parent_rest_mat);
289  mul_m4_m4m4(mat, parent_inverse, bone_rest_mat);
290  }
291 
292  /* OPEN_SIM_COMPATIBILITY */
293 
294  if (export_settings.get_open_sim()) {
295  /* Remove rotations vs armature from transform
296  * parent_rest_rot * mat * irest_rot */
297  Matrix workmat;
298  copy_m4_m4(workmat, bone_rest_mat);
299 
300  workmat[3][0] = workmat[3][1] = workmat[3][2] = 0.0f;
301  invert_m4(workmat);
302 
303  mul_m4_m4m4(mat, mat, workmat);
304 
305  if (!is_export_root(bone)) {
306  copy_m4_m4(workmat, parent_rest_mat);
307  workmat[3][0] = workmat[3][1] = workmat[3][2] = 0.0f;
308 
309  mul_m4_m4m4(mat, workmat, mat);
310  }
311  }
312  }
313 
314  if (this->export_settings.get_limit_precision()) {
316  }
317 
318  TransformWriter::add_joint_transform(node, mat, nullptr, this->export_settings, has_restmat);
319 }
320 
321 std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
322 {
323  return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) +
324  SKIN_CONTROLLER_ID_SUFFIX;
325 }
std::string EMPTY_STRING
Blender kernel action and pose functionality.
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1187
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define STREQ(a, b)
@ BONE_CONNECTED
@ PARBONE
@ OB_MESH
void ED_armature_edit_free(struct bArmature *arm)
void ED_armature_to_edit(bArmature *arm)
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition: btTransform.h:90
bool add_instance_controller(Object *ob)
void add_armature_bones(Object *ob_arm, ViewLayer *view_layer, SceneExporter *se, std::vector< Object * > &child_objects)
static void sanitize(Matrix &matrix, int precision)
Definition: BCMath.cpp:158
void add_material_bindings(COLLADASW::BindMaterial &bind_material, Object *ob, bool active_uv_only)
void add_joint_transform(COLLADASW::Node &node, float mat[4][4], float parent_mat[4][4], BCExportSettings &export_settings, bool has_restmat)
std::string get_joint_sid(Bone *bone)
std::string translate_id(const char *idString)
std::string id_name(void *id)
bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
void bc_add_global_transform(Matrix &to_mat, const Matrix &from_mat, const BCMatrix &global_transform, const bool invert)
EditBone * bc_get_edit_bone(bArmature *armature, char *name)
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)
bool bc_is_leaf_bone(Bone *bone)
constexpr int LIMITTED_PRECISION
Definition: collada_utils.h:67
OperationNode * node
@ Vector
Vector data type.
struct Base * next
struct Object * object
struct Bone * parent
float arm_head[3]
char name[64]
float arm_tail[3]
float length
float arm_mat[4][4]
struct Bone * next
ListBase childbase
void * first
Definition: DNA_listBase.h:47
struct MDeformVert * dvert
short partype
float parentinv[4][4]
void * data
char parsubstr[64]
ListBase bonebase
ListBase * edbo