Remove MinGW support
[blender-staging.git] / source / blender / collada / SkinInfo.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/SkinInfo.cpp
24  *  \ingroup collada
25  */
26
27
28 #include <algorithm>
29
30 #if !defined(WIN32)
31 #include <stdint.h>
32 #endif
33
34 /* COLLADABU_ASSERT, may be able to remove later */
35 #include "COLLADABUPlatform.h"
36
37 #include "BLI_listbase.h"
38 #include "BLI_math.h"
39 #include "BLI_compiler_attrs.h"
40
41 #include "DNA_armature_types.h"
42 #include "DNA_modifier_types.h"
43 #include "DNA_scene_types.h"
44
45 #include "BKE_action.h"
46 #include "BKE_object.h"
47 #include "BKE_object_deform.h"
48
49 #include "ED_mesh.h"
50 #include "ED_object.h"
51
52 #include "SkinInfo.h"
53 #include "collada_utils.h"
54
55 // use name, or fall back to original id if name not present (name is optional)
56 template<class T>
57 static const char *bc_get_joint_name(T *node)
58 {
59         const std::string& id = node->getName();
60         return id.size() ? id.c_str() : node->getOriginalId().c_str();
61 }
62
63 // This is used to store data passed in write_controller_data.
64 // Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members
65 // so that arrays don't get freed until we free them explicitly.
66 SkinInfo::SkinInfo()
67 {
68         /* pass */
69 }
70
71 SkinInfo::SkinInfo(const SkinInfo& skin) : weights(skin.weights),
72         joint_data(skin.joint_data),
73         unit_converter(skin.unit_converter),
74         ob_arm(skin.ob_arm),
75         controller_uid(skin.controller_uid),
76         parent(skin.parent)
77 {
78         copy_m4_m4(bind_shape_matrix, (float (*)[4])skin.bind_shape_matrix);
79
80         transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex);
81         transfer_uint_array_data_const(skin.weight_indices, weight_indices);
82         transfer_int_array_data_const(skin.joint_indices, joint_indices);
83 }
84
85 SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL), parent(NULL) {
86 }
87
88 // nobody owns the data after this, so it should be freed manually with releaseMemory
89 template <class T>
90 void SkinInfo::transfer_array_data(T& src, T& dest)
91 {
92         dest.setData(src.getData(), src.getCount());
93         src.yieldOwnerShip();
94         dest.yieldOwnerShip();
95 }
96
97 // when src is const we cannot src.yieldOwnerShip, this is used by copy constructor
98 void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray& src, COLLADAFW::IntValuesArray& dest)
99 {
100         dest.setData((int *)src.getData(), src.getCount());
101         dest.yieldOwnerShip();
102 }
103
104 void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray& src, COLLADAFW::UIntValuesArray& dest)
105 {
106         dest.setData((unsigned int *)src.getData(), src.getCount());
107         dest.yieldOwnerShip();
108 }
109
110 void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin)
111 {
112         transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getJointsPerVertex(), joints_per_vertex);
113         transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getWeightIndices(), weight_indices);
114         transfer_array_data((COLLADAFW::IntValuesArray &)skin->getJointIndices(), joint_indices);
115         // transfer_array_data(skin->getWeights(), weights);
116
117         // cannot transfer data for FloatOrDoubleArray, copy values manually
118         const COLLADAFW::FloatOrDoubleArray& weight = skin->getWeights();
119         for (unsigned int i = 0; i < weight.getValuesCount(); i++)
120                 weights.push_back(bc_get_float_value(weight, i));
121
122         unit_converter->dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix());
123 }
124         
125 void SkinInfo::free()
126 {
127         joints_per_vertex.releaseMemory();
128         weight_indices.releaseMemory();
129         joint_indices.releaseMemory();
130         // weights.releaseMemory();
131 }
132
133 // using inverse bind matrices to construct armature
134 // it is safe to invert them to get the original matrices
135 // because if they are inverse matrices, they can be inverted
136 void SkinInfo::add_joint(const COLLADABU::Math::Matrix4& matrix)
137 {
138         JointData jd;
139         unit_converter->dae_matrix_to_mat4_(jd.inv_bind_mat, matrix);
140         joint_data.push_back(jd);
141 }
142
143 void SkinInfo::set_controller(const COLLADAFW::SkinController *co)
144 {
145         controller_uid = co->getUniqueId();
146
147         // fill in joint UIDs
148         const COLLADAFW::UniqueIdArray& joint_uids = co->getJoints();
149         for (unsigned int i = 0; i < joint_uids.getCount(); i++) {
150                 joint_data[i].joint_uid = joint_uids[i];
151
152                 // // store armature pointer
153                 // JointData& jd = joint_index_to_joint_info_map[i];
154                 // jd.ob_arm = ob_arm;
155
156                 // now we'll be able to get inv bind matrix from joint id
157                 // joint_id_to_joint_index_map[joint_ids[i]] = i;
158         }
159 }
160
161 // called from write_controller
162 Object *SkinInfo::create_armature(Scene *scene)
163 {
164         ob_arm = bc_add_object(scene, OB_ARMATURE, NULL);
165         return ob_arm;
166 }
167
168 Object *SkinInfo::set_armature(Object *ob_arm)
169 {
170         if (this->ob_arm)
171                 return this->ob_arm;
172
173         this->ob_arm = ob_arm;
174         return ob_arm;
175 }
176
177 bool SkinInfo::get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node)
178 {
179         const COLLADAFW::UniqueId& uid = node->getUniqueId();
180         std::vector<JointData>::iterator it;
181         for (it = joint_data.begin(); it != joint_data.end(); it++) {
182                 if ((*it).joint_uid == uid) {
183                         copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat);
184                         return true;
185                 }
186         }
187
188         return false;
189 }
190
191 Object *SkinInfo::BKE_armature_from_object()
192 {
193         return ob_arm;
194 }
195
196 const COLLADAFW::UniqueId& SkinInfo::get_controller_uid()
197 {
198         return controller_uid;
199 }
200
201 // check if this skin controller references a joint or any descendant of it
202 // 
203 // some nodes may not be referenced by SkinController,
204 // in this case to determine if the node belongs to this armature,
205 // we need to search down the tree
206 bool SkinInfo::uses_joint_or_descendant(COLLADAFW::Node *node)
207 {
208         const COLLADAFW::UniqueId& uid = node->getUniqueId();
209         std::vector<JointData>::iterator it;
210         for (it = joint_data.begin(); it != joint_data.end(); it++) {
211                 if ((*it).joint_uid == uid)
212                         return true;
213         }
214
215         COLLADAFW::NodePointerArray& children = node->getChildNodes();
216         for (unsigned int i = 0; i < children.getCount(); i++) {
217                 if (uses_joint_or_descendant(children[i]))
218                         return true;
219         }
220
221         return false;
222 }
223
224 void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid,
225                              TransformReader *tm)
226 {
227         Main *bmain = CTX_data_main(C);
228         Scene *scene = CTX_data_scene(C);
229
230         ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
231         ArmatureModifierData *amd = (ArmatureModifierData *)md;
232         amd->object = ob_arm;
233
234 #if 1
235         bc_set_parent(ob, ob_arm, C);
236 #else
237         Object workob;
238         ob->parent = ob_arm;
239         ob->partype = PAROBJECT;
240
241         BKE_object_workob_calc_parent(scene, ob, &workob);
242         invert_m4_m4(ob->parentinv, workob.obmat);
243
244         DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
245
246         DAG_relations_tag_update(bmain);
247         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
248 #endif
249         copy_m4_m4(ob->obmat, bind_shape_matrix);
250         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
251
252         amd->deformflag = ARM_DEF_VGROUP;
253
254         // create all vertex groups
255         std::vector<JointData>::iterator it;
256         int joint_index;
257         for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
258                 const char *name = "Group";
259
260                 // skip joints that have invalid UID
261                 if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue;
262                 
263                 // name group by joint node name
264                 
265                 if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
266                         name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
267                 }
268
269                 BKE_object_defgroup_add_name(ob, name);
270         }
271
272         // <vcount> - number of joints per vertex - joints_per_vertex
273         // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
274         // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?
275
276         // for each vertex in weight indices
277         //      for each bone index in vertex
278         //              add vertex to group at group index
279         //              treat group index -1 specially
280
281         // get def group by index with BLI_findlink
282
283         for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {
284
285                 unsigned int limit = weight + joints_per_vertex[vertex];
286                 for (; weight < limit; weight++) {
287                         int joint = joint_indices[weight], joint_weight = weight_indices[weight];
288
289                         // -1 means "weight towards the bind shape", we just don't assign it to any group
290                         if (joint != -1) {
291                                 bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint);
292
293                                 ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
294                         }
295                 }
296         }
297 }
298
299 bPoseChannel *SkinInfo::get_pose_channel_from_node(COLLADAFW::Node *node)
300 {
301         return BKE_pose_channel_find_name(ob_arm->pose, bc_get_joint_name(node));
302 }
303
304 void SkinInfo::set_parent(Object *_parent)
305 {
306         parent = _parent;
307 }
308
309 Object *SkinInfo::get_parent()
310 {
311         return parent;
312 }
313
314 void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node *> &root_joints,
315                                 std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid,
316                                 std::vector<COLLADAFW::Node *>& result)
317 {
318         std::vector<COLLADAFW::Node *>::const_iterator it;
319         // for each root_joint
320         for (it = root_joints.begin(); it != root_joints.end(); it++) {
321                 COLLADAFW::Node *root = *it;
322                 std::vector<JointData>::iterator ji;
323                 //for each joint_data in this skin
324                 for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
325                         if (joint_by_uid.find((*ji).joint_uid) != joint_by_uid.end()) {
326                                 //get joint node from joint map
327                                 COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
328
329                                 //find if joint node is in the tree belonging to the root_joint
330                                 if (find_node_in_tree(joint, root)) {
331                                         if (std::find(result.begin(), result.end(), root) == result.end())
332                                                 result.push_back(root);
333                                 }
334                         }
335                 }
336         }
337 }
338
339 bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
340 {
341         if (node == tree_root)
342                 return true;
343
344         COLLADAFW::NodePointerArray& children = tree_root->getChildNodes();
345         for (unsigned int i = 0; i < children.getCount(); i++) {
346                 if (find_node_in_tree(node, children[i]))
347                         return true;
348         }
349
350         return false;
351 }