Blender  V3.3
SkinInfo.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <algorithm>
8 
9 #if !defined(WIN32)
10 # include <cstdint>
11 #endif
12 
13 /* COLLADABU_ASSERT, may be able to remove later */
14 #include "COLLADABUPlatform.h"
15 
16 #include "BLI_compiler_attrs.h"
17 #include "BLI_listbase.h"
18 #include "BLI_math.h"
19 
20 #include "DNA_armature_types.h"
21 #include "DNA_modifier_types.h"
22 #include "DNA_scene_types.h"
23 
24 #include "BKE_action.h"
25 #include "BKE_deform.h"
26 #include "BKE_object.h"
27 #include "BKE_object_deform.h"
28 
29 #include "ED_mesh.h"
30 #include "ED_object.h"
31 
32 #include "SkinInfo.h"
33 #include "collada_utils.h"
34 
35 /* use name, or fall back to original id if name not present (name is optional) */
36 template<class T> static const char *bc_get_joint_name(T *node)
37 {
38  const std::string &id = node->getName();
39  return id.empty() ? node->getOriginalId().c_str() : id.c_str();
40 }
41 
42 SkinInfo::SkinInfo() = default;
43 
45  : weights(skin.weights),
46  joint_data(skin.joint_data),
47  unit_converter(skin.unit_converter),
48  ob_arm(skin.ob_arm),
49  controller_uid(skin.controller_uid),
50  parent(skin.parent)
51 {
52  copy_m4_m4(bind_shape_matrix, (float(*)[4])skin.bind_shape_matrix);
53 
54  transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex);
55  transfer_uint_array_data_const(skin.weight_indices, weight_indices);
56  transfer_int_array_data_const(skin.joint_indices, joint_indices);
57 }
58 
59 SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(nullptr), parent(nullptr)
60 {
61 }
62 
63 template<class T> void SkinInfo::transfer_array_data(T &src, T &dest)
64 {
65  dest.setData(src.getData(), src.getCount());
66  src.yieldOwnerShip();
67  dest.yieldOwnerShip();
68 }
69 
70 void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray &src,
71  COLLADAFW::IntValuesArray &dest)
72 {
73  dest.setData((int *)src.getData(), src.getCount());
74  dest.yieldOwnerShip();
75 }
76 
77 void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src,
78  COLLADAFW::UIntValuesArray &dest)
79 {
80  dest.setData((unsigned int *)src.getData(), src.getCount());
81  dest.yieldOwnerShip();
82 }
83 
84 void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin)
85 {
86  transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getJointsPerVertex(), joints_per_vertex);
87  transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getWeightIndices(), weight_indices);
88  transfer_array_data((COLLADAFW::IntValuesArray &)skin->getJointIndices(), joint_indices);
89  // transfer_array_data(skin->getWeights(), weights);
90 
91  /* cannot transfer data for FloatOrDoubleArray, copy values manually */
92  const COLLADAFW::FloatOrDoubleArray &weight = skin->getWeights();
93  for (unsigned int i = 0; i < weight.getValuesCount(); i++) {
94  weights.push_back(bc_get_float_value(weight, i));
95  }
96 
97  UnitConverter::dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix());
98 }
99 
101 {
102  joints_per_vertex.releaseMemory();
103  weight_indices.releaseMemory();
104  joint_indices.releaseMemory();
105  // weights.releaseMemory();
106 }
107 
108 void SkinInfo::add_joint(const COLLADABU::Math::Matrix4 &matrix)
109 {
110  JointData jd;
111  UnitConverter::dae_matrix_to_mat4_(jd.inv_bind_mat, matrix);
112  joint_data.push_back(jd);
113 }
114 
115 void SkinInfo::set_controller(const COLLADAFW::SkinController *co)
116 {
117  controller_uid = co->getUniqueId();
118 
119  /* fill in joint UIDs */
120  const COLLADAFW::UniqueIdArray &joint_uids = co->getJoints();
121  for (unsigned int i = 0; i < joint_uids.getCount(); i++) {
122  joint_data[i].joint_uid = joint_uids[i];
123 
124  /* store armature pointer */
125  // JointData& jd = joint_index_to_joint_info_map[i];
126  // jd.ob_arm = ob_arm;
127 
128  /* now we'll be able to get inv bind matrix from joint id */
129  // joint_id_to_joint_index_map[joint_ids[i]] = i;
130  }
131 }
132 
134 {
135  ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, nullptr);
136  return ob_arm;
137 }
138 
140 {
141  if (this->ob_arm) {
142  return this->ob_arm;
143  }
144 
145  this->ob_arm = ob_arm;
146  return ob_arm;
147 }
148 
149 bool SkinInfo::get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node)
150 {
151  const COLLADAFW::UniqueId &uid = node->getUniqueId();
152  std::vector<JointData>::iterator it;
153  for (it = joint_data.begin(); it != joint_data.end(); it++) {
154  if ((*it).joint_uid == uid) {
155  copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat);
156  return true;
157  }
158  }
159 
160  return false;
161 }
162 
164 {
165  return ob_arm;
166 }
167 
168 const COLLADAFW::UniqueId &SkinInfo::get_controller_uid()
169 {
170  return controller_uid;
171 }
172 
174 {
175  const COLLADAFW::UniqueId &uid = node->getUniqueId();
176  std::vector<JointData>::iterator it;
177  for (it = joint_data.begin(); it != joint_data.end(); it++) {
178  if ((*it).joint_uid == uid) {
179  return true;
180  }
181  }
182 
183  COLLADAFW::NodePointerArray &children = node->getChildNodes();
184  for (unsigned int i = 0; i < children.getCount(); i++) {
185  if (uses_joint_or_descendant(children[i])) {
186  return true;
187  }
188  }
189 
190  return false;
191 }
192 
194  Object *ob,
195  std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid,
196  TransformReader *tm)
197 {
198  Main *bmain = CTX_data_main(C);
200 
202  nullptr, bmain, scene, ob, nullptr, eModifierType_Armature);
204  amd->object = ob_arm;
205 
206 #if 1
207  /* XXX Why do we enforce objects to be children of Armatures if they weren't so before? */
208  if (!BKE_object_is_child_recursive(ob_arm, ob)) {
209  bc_set_parent(ob, ob_arm, C);
210  }
211 #else
212  Object workob;
213  ob->parent = ob_arm;
214  ob->partype = PAROBJECT;
215 
216  BKE_object_workob_calc_parent(scene, ob, &workob);
217  invert_m4_m4(ob->parentinv, workob.obmat);
218 
220 #endif
221  copy_m4_m4(ob->obmat, bind_shape_matrix);
222  BKE_object_apply_mat4(ob, ob->obmat, false, false);
223 
224  amd->deformflag = ARM_DEF_VGROUP;
225 
226  /* create all vertex groups */
227  std::vector<JointData>::iterator it;
228  int joint_index;
229  for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
230  const char *name = "Group";
231 
232  /* skip joints that have invalid UID */
233  if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) {
234  continue;
235  }
236 
237  /* name group by joint node name */
238 
239  if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
240  name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
241  }
242 
244  }
245 
246  /* <vcount> - number of joints per vertex - joints_per_vertex
247  * <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
248  * ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?
249  *
250  * for each vertex in weight indices
251  * for each bone index in vertex
252  * add vertex to group at group index
253  * treat group index -1 specially
254  *
255  * get def group by index with BLI_findlink */
256 
257  for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {
258 
259  unsigned int limit = weight + joints_per_vertex[vertex];
260  for (; weight < limit; weight++) {
261  int joint = joint_indices[weight], joint_weight = weight_indices[weight];
262 
263  /* -1 means "weight towards the bind shape", we just don't assign it to any group */
264  if (joint != -1) {
265  const ListBase *defbase = BKE_object_defgroup_list(ob);
266  bDeformGroup *def = (bDeformGroup *)BLI_findlink(defbase, joint);
267 
268  ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
269  }
270  }
271  }
272 }
273 
275 {
277 }
278 
280 {
281  parent = _parent;
282 }
283 
285 {
286  return parent;
287 }
288 
289 void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node *> &root_joints,
290  std::map<COLLADAFW::UniqueId, COLLADAFW::Node *> &joint_by_uid,
291  std::vector<COLLADAFW::Node *> &result)
292 {
293  std::vector<COLLADAFW::Node *>::const_iterator it;
294  /* for each root_joint */
295  for (it = root_joints.begin(); it != root_joints.end(); it++) {
296  COLLADAFW::Node *root = *it;
297  std::vector<JointData>::iterator ji;
298  /* for each joint_data in this skin */
299  for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
300  if (joint_by_uid.find((*ji).joint_uid) != joint_by_uid.end()) {
301  /* get joint node from joint map */
302  COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
303 
304  /* find if joint node is in the tree belonging to the root_joint */
305  if (find_node_in_tree(joint, root)) {
306  if (std::find(result.begin(), result.end(), root) == result.end()) {
307  result.push_back(root);
308  }
309  }
310  }
311  }
312  }
313 }
314 
315 bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
316 {
317  if (node == tree_root) {
318  return true;
319  }
320 
321  COLLADAFW::NodePointerArray &children = tree_root->getChildNodes();
322  for (unsigned int i = 0; i < children.getCount(); i++) {
323  if (find_node_in_tree(node, children[i])) {
324  return true;
325  }
326  }
327 
328  return false;
329 }
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:1090
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
support for deformation groups and hooks.
const struct ListBase * BKE_object_defgroup_list(const struct Object *ob)
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_apply_mat4(struct Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Definition: object.cc:3575
void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *workob)
Definition: object.cc:3501
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)
Definition: object_deform.c:95
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:1287
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ ARM_DEF_VGROUP
@ eModifierType_Armature
@ OB_ARMATURE
@ PAROBJECT
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode)
#define WEIGHT_REPLACE
Definition: ED_mesh.h:449
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:25
static const char * bc_get_joint_name(T *node)
Definition: SkinInfo.cpp:36
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:289
const COLLADAFW::UniqueId & get_controller_uid()
Definition: SkinInfo.cpp:168
void transfer_int_array_data_const(const COLLADAFW::IntValuesArray &src, COLLADAFW::IntValuesArray &dest)
Definition: SkinInfo.cpp:70
void set_controller(const COLLADAFW::SkinController *co)
Definition: SkinInfo.cpp:115
void link_armature(bContext *C, Object *ob, std::map< COLLADAFW::UniqueId, COLLADAFW::Node * > &joint_by_uid, TransformReader *tm)
Definition: SkinInfo.cpp:193
Object * set_armature(Object *ob_arm)
Definition: SkinInfo.cpp:139
void borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin)
Definition: SkinInfo.cpp:84
bool uses_joint_or_descendant(COLLADAFW::Node *node)
Definition: SkinInfo.cpp:173
Object * BKE_armature_from_object()
Definition: SkinInfo.cpp:163
bool get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node)
Definition: SkinInfo.cpp:149
void add_joint(const COLLADABU::Math::Matrix4 &matrix)
Definition: SkinInfo.cpp:108
void transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src, COLLADAFW::UIntValuesArray &dest)
Definition: SkinInfo.cpp:77
void set_parent(Object *_parent)
Definition: SkinInfo.cpp:279
Object * get_parent()
Definition: SkinInfo.cpp:284
bool find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
Definition: SkinInfo.cpp:315
void transfer_array_data(T &src, T &dest)
Definition: SkinInfo.cpp:63
bPoseChannel * get_pose_channel_from_node(COLLADAFW::Node *node)
Definition: SkinInfo.cpp:274
Object * create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition: SkinInfo.cpp:133
void free()
Definition: SkinInfo.cpp:100
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
SyclQueue void void * src
SyclQueue void * dest
#define T
Definition: BKE_main.h:121
short partype
struct bPose * pose
float parentinv[4][4]
float obmat[4][4]
struct Object * parent