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