Fix build error on Windows 32 bit.
[blender-staging.git] / source / blender / modifiers / intern / MOD_mask.c
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  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_mask.c
32  *  \ingroup modifiers
33  */
34
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_utildefines.h"
39 #include "BLI_listbase.h"
40 #include "BLI_ghash.h"
41
42 #include "DNA_armature_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_modifier_types.h"
45 #include "DNA_object_types.h"
46
47 #include "BKE_action.h" /* BKE_pose_channel_find_name */
48 #include "BKE_cdderivedmesh.h"
49 #include "BKE_library_query.h"
50 #include "BKE_modifier.h"
51 #include "BKE_deform.h"
52
53 #include "depsgraph_private.h"
54 #include "DEG_depsgraph_build.h"
55
56 #include "MOD_modifiertypes.h"
57
58 #include "BLI_strict_flags.h"
59
60 static void copyData(ModifierData *md, ModifierData *target)
61 {
62 #if 0
63         MaskModifierData *mmd = (MaskModifierData *) md;
64         MaskModifierData *tmmd = (MaskModifierData *) target;
65 #endif
66         modifier_copyData_generic(md, target);
67 }
68
69 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
70 {
71         return CD_MASK_MDEFORMVERT;
72 }
73
74 static void foreachObjectLink(
75         ModifierData *md, Object *ob,
76         ObjectWalkFunc walk, void *userData)
77 {
78         MaskModifierData *mmd = (MaskModifierData *)md;
79         walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP);
80 }
81
82 static void updateDepgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
83 {
84         MaskModifierData *mmd = (MaskModifierData *)md;
85
86         if (mmd->ob_arm) {
87                 bArmature *arm = (bArmature *)mmd->ob_arm->data;
88                 DagNode *armNode = dag_get_node(ctx->forest, mmd->ob_arm);
89                 
90                 /* tag relationship in depsgraph, but also on the armature */
91                 dag_add_relation(ctx->forest, armNode, ctx->obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
92                 arm->flag |= ARM_HAS_VIZ_DEPS;
93         }
94 }
95
96 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
97 {
98         MaskModifierData *mmd = (MaskModifierData *)md;
99         if (mmd->ob_arm) {
100                 bArmature *arm = (bArmature *)mmd->ob_arm->data;
101                 /* Tag relationship in depsgraph, but also on the armature. */
102                 /* TODO(sergey): Is it a proper relation here? */
103                 DEG_add_object_relation(ctx->node, mmd->ob_arm, DEG_OB_COMP_TRANSFORM, "Mask Modifier");
104                 arm->flag |= ARM_HAS_VIZ_DEPS;
105         }
106 }
107
108 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
109                                   DerivedMesh *dm,
110                                   ModifierApplyFlag UNUSED(flag))
111 {
112         MaskModifierData *mmd = (MaskModifierData *)md;
113         const bool found_test = (mmd->flag & MOD_MASK_INV) == 0;
114         DerivedMesh *result = NULL;
115         GHash *vertHash = NULL, *edgeHash, *polyHash;
116         GHashIterator gh_iter;
117         MDeformVert *dvert, *dv;
118         int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0;
119         int maxVerts, maxEdges, maxPolys;
120         int i;
121
122         const MVert *mvert_src;
123         const MEdge *medge_src;
124         const MPoly *mpoly_src;
125         const MLoop *mloop_src;
126
127         MPoly *mpoly_dst;
128         MLoop *mloop_dst;
129         MEdge *medge_dst;
130         MVert *mvert_dst;
131
132         int *loop_mapping;
133
134         dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
135         if (dvert == NULL) {
136                 return found_test ? CDDM_from_template(dm, 0, 0, 0, 0, 0) : dm;
137         }
138
139         /* Overview of Method:
140          *      1. Get the vertices that are in the vertexgroup of interest 
141          *      2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
142          *      3. Make a new mesh containing only the mapping data
143          */
144         
145         /* get original number of verts, edges, and faces */
146         maxVerts = dm->getNumVerts(dm);
147         maxEdges = dm->getNumEdges(dm);
148         maxPolys = dm->getNumPolys(dm);
149         
150         /* check if we can just return the original mesh 
151          *      - must have verts and therefore verts assigned to vgroups to do anything useful
152          */
153         if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
154             (maxVerts == 0) || BLI_listbase_is_empty(&ob->defbase))
155         {
156                 return dm;
157         }
158         
159         /* if mode is to use selected armature bones, aggregate the bone groups */
160         if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */
161                 Object *oba = mmd->ob_arm;
162                 bPoseChannel *pchan;
163                 bDeformGroup *def;
164                 bool *bone_select_array;
165                 int bone_select_tot = 0;
166                 const int defbase_tot = BLI_listbase_count(&ob->defbase);
167                 
168                 /* check that there is armature object with bones to use, otherwise return original mesh */
169                 if (ELEM(NULL, oba, oba->pose, ob->defbase.first))
170                         return dm;
171                 
172                 /* determine whether each vertexgroup is associated with a selected bone or not 
173                  * - each cell is a boolean saying whether bone corresponding to the ith group is selected
174                  * - groups that don't match a bone are treated as not existing (along with the corresponding ungrouped verts)
175                  */
176                 bone_select_array = MEM_malloc_arrayN((size_t)defbase_tot, sizeof(char), "mask array");
177                 
178                 for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
179                         pchan = BKE_pose_channel_find_name(oba->pose, def->name);
180                         if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
181                                 bone_select_array[i] = true;
182                                 bone_select_tot++;
183                         }
184                         else {
185                                 bone_select_array[i] = false;
186                         }
187                 }
188
189                 /* verthash gives mapping from original vertex indices to the new indices (including selected matches only)
190                  * key = oldindex, value = newindex
191                  */
192                 vertHash = BLI_ghash_int_new_ex("mask vert gh", (unsigned int)maxVerts);
193                 
194                 /* add vertices which exist in vertexgroups into vertHash for filtering 
195                  * - dv = for each vertex, what vertexgroups does it belong to
196                  * - dw = weight that vertex was assigned to a vertexgroup it belongs to
197                  */
198                 for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
199                         MDeformWeight *dw = dv->dw;
200                         bool found = false;
201                         int j;
202                         
203                         /* check the groups that vertex is assigned to, and see if it was any use */
204                         for (j = 0; j < dv->totweight; j++, dw++) {
205                                 if (dw->def_nr < defbase_tot) {
206                                         if (bone_select_array[dw->def_nr]) {
207                                                 if (dw->weight != 0.0f) {
208                                                         found = true;
209                                                         break;
210                                                 }
211                                         }
212                                 }
213                         }
214                         
215                         if (found_test != found) {
216                                 continue;
217                         }
218                         
219                         /* add to ghash for verts (numVerts acts as counter for mapping) */
220                         BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
221                         numVerts++;
222                 }
223                 
224                 /* free temp hashes */
225                 MEM_freeN(bone_select_array);
226         }
227         else {  /* --- Using Nominated VertexGroup only --- */
228                 int defgrp_index = defgroup_name_index(ob, mmd->vgroup);
229
230                 /* if no vgroup (i.e. dverts) found, return the initial mesh */
231                 if (defgrp_index == -1)
232                         return dm;
233                         
234                 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
235                 vertHash = BLI_ghash_int_new_ex("mask vert2 bh", (unsigned int)maxVerts);
236                 
237                 /* add vertices which exist in vertexgroup into ghash for filtering */
238                 for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
239                         const bool found = defvert_find_weight(dv, defgrp_index) != 0.0f;
240                         if (found_test != found) {
241                                 continue;
242                         }
243
244                         /* add to ghash for verts (numVerts acts as counter for mapping) */
245                         BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
246                         numVerts++;
247                 }
248         }
249
250         /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
251         edgeHash = BLI_ghash_int_new_ex("mask ed2 gh", (unsigned int)maxEdges);
252         polyHash = BLI_ghash_int_new_ex("mask fa2 gh", (unsigned int)maxPolys);
253
254         mvert_src = dm->getVertArray(dm);
255         medge_src = dm->getEdgeArray(dm);
256         mpoly_src = dm->getPolyArray(dm);
257         mloop_src = dm->getLoopArray(dm);
258
259         /* overalloc, assume all polys are seen */
260         loop_mapping = MEM_malloc_arrayN((size_t)maxPolys, sizeof(int), "mask loopmap");
261
262         /* loop over edges and faces, and do the same thing to 
263          * ensure that they only reference existing verts 
264          */
265         for (i = 0; i < maxEdges; i++) {
266                 const MEdge *me = &medge_src[i];
267                 
268                 /* only add if both verts will be in new mesh */
269                 if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) &&
270                     BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
271                 {
272                         BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
273                         numEdges++;
274                 }
275         }
276         for (i = 0; i < maxPolys; i++) {
277                 const MPoly *mp_src = &mpoly_src[i];
278                 const MLoop *ml_src = &mloop_src[mp_src->loopstart];
279                 bool ok = true;
280                 int j;
281                 
282                 for (j = 0; j < mp_src->totloop; j++, ml_src++) {
283                         if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml_src->v))) {
284                                 ok = false;
285                                 break;
286                         }
287                 }
288                 
289                 /* all verts must be available */
290                 if (ok) {
291                         BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys));
292                         loop_mapping[numPolys] = numLoops;
293                         numPolys++;
294                         numLoops += mp_src->totloop;
295                 }
296         }
297         
298         
299         /* now we know the number of verts, edges and faces, 
300          * we can create the new (reduced) mesh
301          */
302         result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys);
303         
304         mpoly_dst = CDDM_get_polys(result);
305         mloop_dst = CDDM_get_loops(result);
306         medge_dst = CDDM_get_edges(result);
307         mvert_dst = CDDM_get_verts(result);
308
309         /* using ghash-iterators, map data into new mesh */
310         /* vertices */
311         GHASH_ITER (gh_iter, vertHash) {
312                 const MVert *v_src;
313                 MVert *v_dst;
314                 const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
315                 const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
316                 
317                 v_src = &mvert_src[i_src];
318                 v_dst = &mvert_dst[i_dst];
319
320                 *v_dst = *v_src;
321                 DM_copy_vert_data(dm, result, i_src, i_dst, 1);
322         }
323                 
324         /* edges */
325         GHASH_ITER (gh_iter, edgeHash) {
326                 const MEdge *e_src;
327                 MEdge *e_dst;
328                 const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
329                 const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
330                 
331                 e_src = &medge_src[i_src];
332                 e_dst = &medge_dst[i_dst];
333
334                 DM_copy_edge_data(dm, result, i_src, i_dst, 1);
335                 *e_dst = *e_src;
336                 e_dst->v1 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v1)));
337                 e_dst->v2 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v2)));
338         }
339         
340         /* faces */
341         GHASH_ITER (gh_iter, polyHash) {
342                 const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
343                 const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
344                 const MPoly *mp_src = &mpoly_src[i_src];
345                 MPoly *mp_dst = &mpoly_dst[i_dst];
346                 const int i_ml_src = mp_src->loopstart;
347                 const int i_ml_dst = loop_mapping[i_dst];
348                 const MLoop *ml_src = &mloop_src[i_ml_src];
349                 MLoop *ml_dst = &mloop_dst[i_ml_dst];
350                 
351                 DM_copy_poly_data(dm, result, i_src, i_dst, 1);
352                 DM_copy_loop_data(dm, result, i_ml_src, i_ml_dst, mp_src->totloop);
353
354                 *mp_dst = *mp_src;
355                 mp_dst->loopstart = i_ml_dst;
356                 for (i = 0; i < mp_src->totloop; i++) {
357                         ml_dst[i].v = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(ml_src[i].v)));
358                         ml_dst[i].e = GET_UINT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_UINT_IN_POINTER(ml_src[i].e)));
359                 }
360         }
361
362         MEM_freeN(loop_mapping);
363
364         /* why is this needed? - campbell */
365         /* recalculate normals */
366         result->dirty |= DM_DIRTY_NORMALS;
367         
368         /* free hashes */
369         BLI_ghash_free(vertHash, NULL, NULL);
370         BLI_ghash_free(edgeHash, NULL, NULL);
371         BLI_ghash_free(polyHash, NULL, NULL);
372
373         /* return the new mesh */
374         return result;
375 }
376
377
378 ModifierTypeInfo modifierType_Mask = {
379         /* name */              "Mask",
380         /* structName */        "MaskModifierData",
381         /* structSize */        sizeof(MaskModifierData),
382         /* type */              eModifierTypeType_Nonconstructive,
383         /* flags */             eModifierTypeFlag_AcceptsMesh |
384                                 eModifierTypeFlag_SupportsMapping |
385                                 eModifierTypeFlag_SupportsEditmode,
386
387         /* copyData */          copyData,
388         /* deformVerts */       NULL,
389         /* deformMatrices */    NULL,
390         /* deformVertsEM */     NULL,
391         /* deformMatricesEM */  NULL,
392         /* applyModifier */     applyModifier,
393         /* applyModifierEM */   NULL,
394         /* initData */          NULL,
395         /* requiredDataMask */  requiredDataMask,
396         /* freeData */          NULL,
397         /* isDisabled */        NULL,
398         /* updateDepgraph */    updateDepgraph,
399         /* updateDepsgraph */   updateDepsgraph,
400         /* dependsOnTime */     NULL,
401         /* dependsOnNormals */  NULL,
402         /* foreachObjectLink */ foreachObjectLink,
403         /* foreachIDLink */     NULL,
404         /* foreachTexLink */    NULL,
405 };