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