Blender  V2.93
SkinInfo.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 <algorithm>
22 
23 #if !defined(WIN32)
24 # include <cstdint>
25 #endif
26 
27 /* COLLADABU_ASSERT, may be able to remove later */
28 #include "COLLADABUPlatform.h"
29 
30 #include "BLI_compiler_attrs.h"
31 #include "BLI_listbase.h"
32 #include "BLI_math.h"
33 
34 #include "DNA_armature_types.h"
35 #include "DNA_modifier_types.h"
36 #include "DNA_scene_types.h"
37 
38 #include "BKE_action.h"
39 #include "BKE_object.h"
40 #include "BKE_object_deform.h"
41 
42 #include "ED_mesh.h"
43 #include "ED_object.h"
44 
45 #include "SkinInfo.h"
46 #include "collada_utils.h"
47 
48 /* use name, or fall back to original id if name not present (name is optional) */
49 template<class T> static const char *bc_get_joint_name(T *node)
50 {
51  const std::string &id = node->getName();
52  return id.empty() ? node->getOriginalId().c_str() : id.c_str();
53 }
54 
55 /* This is used to store data passed in write_controller_data.
56  * Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members
57  * so that arrays don't get freed until we free them explicitly. */
58 SkinInfo::SkinInfo() = default;
59 
61  : weights(skin.weights),
62  joint_data(skin.joint_data),
63  unit_converter(skin.unit_converter),
64  ob_arm(skin.ob_arm),
65  controller_uid(skin.controller_uid),
66  parent(skin.parent)
67 {
68  copy_m4_m4(bind_shape_matrix, (float(*)[4])skin.bind_shape_matrix);
69 
70  transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex);
71  transfer_uint_array_data_const(skin.weight_indices, weight_indices);
72  transfer_int_array_data_const(skin.joint_indices, joint_indices);
73 }
74 
75 SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(nullptr), parent(nullptr)
76 {
77 }
78 
79 /* nobody owns the data after this, so it should be freed manually with releaseMemory */
80 template<class T> void SkinInfo::transfer_array_data(T &src, T &dest)
81 {
82  dest.setData(src.getData(), src.getCount());
83  src.yieldOwnerShip();
84  dest.yieldOwnerShip();
85 }
86 
87 /* when src is const we cannot src.yieldOwnerShip, this is used by copy constructor */
88 void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray &src,
89  COLLADAFW::IntValuesArray &dest)
90 {
91  dest.setData((int *)src.getData(), src.getCount());
92  dest.yieldOwnerShip();
93 }
94 
95 void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src,
96  COLLADAFW::UIntValuesArray &dest)
97 {
98  dest.setData((unsigned int *)src.getData(), src.getCount());
99  dest.yieldOwnerShip();
100 }
101 
102 void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin)
103 {
104  transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getJointsPerVertex(), joints_per_vertex);
105  transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getWeightIndices(), weight_indices);
106  transfer_array_data((COLLADAFW::IntValuesArray &)skin->getJointIndices(), joint_indices);
107  // transfer_array_data(skin->getWeights(), weights);
108 
109  /* cannot transfer data for FloatOrDoubleArray, copy values manually */
110  const COLLADAFW::FloatOrDoubleArray &weight = skin->getWeights();
111  for (unsigned int i = 0; i < weight.getValuesCount(); i++) {
112  weights.push_back(bc_get_float_value(weight, i));
113  }
114 
115  UnitConverter::dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix());
116 }
117 
119 {
120  joints_per_vertex.releaseMemory();
121  weight_indices.releaseMemory();
122  joint_indices.releaseMemory();
123  // weights.releaseMemory();
124 }
125 
126 /* using inverse bind matrices to construct armature
127  * it is safe to invert them to get the original matrices
128  * because if they are inverse matrices, they can be inverted */
129 void SkinInfo::add_joint(const COLLADABU::Math::Matrix4 &matrix)
130 {
131  JointData jd;
132  UnitConverter::dae_matrix_to_mat4_(jd.inv_bind_mat, matrix);
133  joint_data.push_back(jd);
134 }
135 
136 void SkinInfo::set_controller(const COLLADAFW::SkinController *co)
137 {
138  controller_uid = co->getUniqueId();
139 
140  /* fill in joint UIDs */
141  const COLLADAFW::UniqueIdArray &joint_uids = co->getJoints();
142  for (unsigned int i = 0; i < joint_uids.getCount(); i++) {
143  joint_data[i].joint_uid = joint_uids[i];
144 
145  /* store armature pointer */
146  // JointData& jd = joint_index_to_joint_info_map[i];
147  // jd.ob_arm = ob_arm;
148 
149  /* now we'll be able to get inv bind matrix from joint id */
150  // joint_id_to_joint_index_map[joint_ids[i]] = i;
151  }
152 }
153 
154 /* called from write_controller */
156 {
157  ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, nullptr);
158  return ob_arm;
159 }
160 
162 {
163  if (this->ob_arm) {
164  return this->ob_arm;
165  }
166 
167  this->ob_arm = ob_arm;
168  return ob_arm;
169 }
170 
171 bool SkinInfo::get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node)
172 {
173  const COLLADAFW::UniqueId &uid = node->getUniqueId();
174  std::vector<JointData>::iterator it;
175  for (it = joint_data.begin(); it != joint_data.end(); it++) {
176  if ((*it).joint_uid == uid) {
177  copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat);
178  return true;
179  }
180  }
181 
182  return false;
183 }
184 
186 {
187  return ob_arm;
188 }
189 
190 const COLLADAFW::UniqueId &SkinInfo::get_controller_uid()
191 {
192  return controller_uid;
193 }
194 
195 /* check if this skin controller references a joint or any descendant of it
196  *
197  * some nodes may not be referenced by SkinController,
198  * in this case to determine if the node belongs to this armature,
199  * we need to search down the tree */
201 {
202  const COLLADAFW::UniqueId &uid = node->getUniqueId();
203  std::vector<JointData>::iterator it;
204  for (it = joint_data.begin(); it != joint_data.end(); it++) {
205  if ((*it).joint_uid == uid) {
206  return true;
207  }
208  }
209 
210  COLLADAFW::NodePointerArray &children = node->getChildNodes();
211  for (unsigned int i = 0; i < children.getCount(); i++) {
212  if (uses_joint_or_descendant(children[i])) {
213  return true;
214  }
215  }
216 
217  return false;
218 }
219 
221  Object *ob,
222  std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid,
223  TransformReader *tm)
224 {
225  Main *bmain = CTX_data_main(C);
227 
229  nullptr, bmain, scene, ob, nullptr, eModifierType_Armature);
231  amd->object = ob_arm;
232 
233 #if 1
234  /* XXX Why do we enforce objects to be children of Armatures if they weren't so before ?*/
235  if (!BKE_object_is_child_recursive(ob_arm, ob)) {
236  bc_set_parent(ob, ob_arm, C);
237  }
238 #else
239  Object workob;
240  ob->parent = ob_arm;
241  ob->partype = PAROBJECT;
242 
243  BKE_object_workob_calc_parent(scene, ob, &workob);
244  invert_m4_m4(ob->parentinv, workob.obmat);
245 
247 #endif
248  copy_m4_m4(ob->obmat, bind_shape_matrix);
249  BKE_object_apply_mat4(ob, ob->obmat, false, false);
250 
251  amd->deformflag = ARM_DEF_VGROUP;
252 
253  /* create all vertex groups */
254  std::vector<JointData>::iterator it;
255  int joint_index;
256  for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
257  const char *name = "Group";
258 
259  /* skip joints that have invalid UID */
260  if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) {
261  continue;
262  }
263 
264  /* name group by joint node name */
265 
266  if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
267  name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
268  }
269 
271  }
272 
273  /* <vcount> - number of joints per vertex - joints_per_vertex
274  * <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
275  * ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?
276  *
277  * for each vertex in weight indices
278  * for each bone index in vertex
279  * add vertex to group at group index
280  * treat group index -1 specially
281  *
282  * get def group by index with BLI_findlink */
283 
284  for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {
285 
286  unsigned int limit = weight + joints_per_vertex[vertex];
287  for (; weight < limit; weight++) {
288  int joint = joint_indices[weight], joint_weight = weight_indices[weight];
289 
290  /* -1 means "weight towards the bind shape", we just don't assign it to any group */
291  if (joint != -1) {
292  bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint);
293 
294  ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
295  }
296  }
297  }
298 }
299 
301 {
303 }
304 
306 {
307  parent = _parent;
308 }
309 
311 {
312  return parent;
313 }
314 
315 void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node *> &root_joints,
316  std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid,
317  std::vector<COLLADAFW::Node *> &result)
318 {
319  std::vector<COLLADAFW::Node *>::const_iterator it;
320  /* for each root_joint */
321  for (it = root_joints.begin(); it != root_joints.end(); it++) {
322  COLLADAFW::Node *root = *it;
323  std::vector<JointData>::iterator ji;
324  /* for each joint_data in this skin */
325  for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
326  if (joint_by_uid.find((*ji).joint_uid) != joint_by_uid.end()) {
327  /* get joint node from joint map */
328  COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
329 
330  /* find if joint node is in the tree belonging to the root_joint */
331  if (find_node_in_tree(joint, root)) {
332  if (std::find(result.begin(), result.end(), root) == result.end()) {
333  result.push_back(root);
334  }
335  }
336  }
337  }
338  }
339 }
340 
341 bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
342 {
343  if (node == tree_root) {
344  return true;
345  }
346 
347  COLLADAFW::NodePointerArray &children = tree_root->getChildNodes();
348  for (unsigned int i = 0; i < children.getCount(); i++) {
349  if (find_node_in_tree(node, children[i])) {
350  return true;
351  }
352  }
353 
354  return false;
355 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
General operations, lookup, etc. for blender objects.
bool BKE_object_is_child_recursive(const struct Object *ob_parent, const struct Object *ob_child)
void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *workob)
Definition: object.c:3667
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], const bool use_compat, const bool use_parent)
Definition: object.c:3754
Functions for dealing with objects and deform verts, used by painting and tools.
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ ARM_DEF_VGROUP
@ eModifierType_Armature
@ PAROBJECT
@ OB_ARMATURE
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode)
#define WEIGHT_REPLACE
Definition: ED_mesh.h:345
struct ModifierData * ED_object_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type)
#define C
Definition: RandGen.cpp:39
static const char * bc_get_joint_name(T *node)
Definition: SkinInfo.cpp:49
void find_root_joints(const std::vector< COLLADAFW::Node * > &root_joints, std::map< COLLADAFW::UniqueId, COLLADAFW::Node * > &joint_by_uid, std::vector< COLLADAFW::Node * > &result)
Definition: SkinInfo.cpp:315
const COLLADAFW::UniqueId & get_controller_uid()
Definition: SkinInfo.cpp:190
void transfer_int_array_data_const(const COLLADAFW::IntValuesArray &src, COLLADAFW::IntValuesArray &dest)
Definition: SkinInfo.cpp:88
void set_controller(const COLLADAFW::SkinController *co)
Definition: SkinInfo.cpp:136
void link_armature(bContext *C, Object *ob, std::map< COLLADAFW::UniqueId, COLLADAFW::Node * > &joint_by_uid, TransformReader *tm)
Definition: SkinInfo.cpp:220
Object * set_armature(Object *ob_arm)
Definition: SkinInfo.cpp:161
void borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin)
Definition: SkinInfo.cpp:102
bool uses_joint_or_descendant(COLLADAFW::Node *node)
Definition: SkinInfo.cpp:200
Object * BKE_armature_from_object()
Definition: SkinInfo.cpp:185
bool get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node)
Definition: SkinInfo.cpp:171
void add_joint(const COLLADABU::Math::Matrix4 &matrix)
Definition: SkinInfo.cpp:129
void transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src, COLLADAFW::UIntValuesArray &dest)
Definition: SkinInfo.cpp:95
void set_parent(Object *_parent)
Definition: SkinInfo.cpp:305
Object * get_parent()
Definition: SkinInfo.cpp:310
bool find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
Definition: SkinInfo.cpp:341
void transfer_array_data(T &src, T &dest)
Definition: SkinInfo.cpp:80
bPoseChannel * get_pose_channel_from_node(COLLADAFW::Node *node)
Definition: SkinInfo.cpp:300
Object * create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: SkinInfo.cpp:155
void free()
Definition: SkinInfo.cpp:118
static void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4 &in)
bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
Object * bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index)
OperationNode * node
Scene scene
#define T
Definition: BKE_main.h:116
short partype
ListBase defbase
struct bPose * pose
float parentinv[4][4]
float obmat[4][4]
struct Object * parent