svn merge ^/trunk/blender -r43564:43609
[blender.git] / source / blender / modifiers / intern / MOD_weightvgedit.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) 2011 by Bastien Montagne.
19  * All rights reserved.
20  *
21  * Contributor(s): None yet.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  */
26
27 /** \file blender/modifiers/intern/MOD_weightvgedit.c
28  *  \ingroup modifiers
29  */
30
31 #include "BLI_utildefines.h"
32 #include "BLI_math.h"
33 #include "BLI_string.h"
34
35 #include "DNA_color_types.h"      /* CurveMapping. */
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40
41 #include "BKE_cdderivedmesh.h"
42 #include "BKE_colortools.h"       /* CurveMapping. */
43 #include "BKE_deform.h"
44 #include "BKE_mesh.h"
45 #include "BKE_modifier.h"
46 #include "BKE_texture.h"          /* Texture masking. */
47
48 #include "depsgraph_private.h"
49 #include "MEM_guardedalloc.h"
50 #include "MOD_util.h"
51 #include "MOD_weightvg_util.h"
52
53 /**************************************
54  * Modifiers functions.               *
55  **************************************/
56 static void initData(ModifierData *md)
57 {
58         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
59         wmd->edit_flags             = 0;
60         wmd->falloff_type           = MOD_WVG_MAPPING_NONE;
61         wmd->default_weight         = 0.0f;
62
63         wmd->cmap_curve             = curvemapping_add(1, 0.0, 0.0, 1.0, 1.0);
64         curvemapping_initialize(wmd->cmap_curve);
65
66         wmd->rem_threshold          = 0.01f;
67         wmd->add_threshold          = 0.01f;
68
69         wmd->mask_constant          = 1.0f;
70         wmd->mask_tex_use_channel   = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */
71         wmd->mask_tex_mapping       = MOD_DISP_MAP_LOCAL;
72 }
73
74 static void freeData(ModifierData *md)
75 {
76         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
77         curvemapping_free(wmd->cmap_curve);
78 }
79
80 static void copyData(ModifierData *md, ModifierData *target)
81 {
82         WeightVGEditModifierData *wmd  = (WeightVGEditModifierData*) md;
83         WeightVGEditModifierData *twmd = (WeightVGEditModifierData*) target;
84
85         BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
86
87         twmd->edit_flags             = wmd->edit_flags;
88         twmd->falloff_type           = wmd->falloff_type;
89         twmd->default_weight         = wmd->default_weight;
90
91         twmd->cmap_curve             = curvemapping_copy(wmd->cmap_curve);
92
93         twmd->add_threshold          = wmd->add_threshold;
94         twmd->rem_threshold          = wmd->rem_threshold;
95
96         twmd->mask_constant          = wmd->mask_constant;
97         BLI_strncpy(twmd->mask_defgrp_name, wmd->mask_defgrp_name, sizeof(twmd->mask_defgrp_name));
98         twmd->mask_texture           = wmd->mask_texture;
99         twmd->mask_tex_use_channel   = wmd->mask_tex_use_channel;
100         twmd->mask_tex_mapping       = wmd->mask_tex_mapping;
101         twmd->mask_tex_map_obj       = wmd->mask_tex_map_obj;
102         BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name));
103 }
104
105 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
106 {
107         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
108         CustomDataMask dataMask = 0;
109
110         /* We need vertex groups! */
111         dataMask |= CD_MASK_MDEFORMVERT;
112
113         /* Ask for UV coordinates if we need them. */
114         if(wmd->mask_tex_mapping == MOD_DISP_MAP_UV)
115                 dataMask |= CD_MASK_MTFACE;
116
117         return dataMask;
118 }
119
120 static int dependsOnTime(ModifierData *md)
121 {
122         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
123
124         if(wmd->mask_texture)
125                 return BKE_texture_dependsOnTime(wmd->mask_texture);
126         return 0;
127 }
128
129 static void foreachObjectLink(ModifierData *md, Object *ob,
130                               void (*walk)(void *userData, Object *ob, Object **obpoin),
131                               void *userData)
132 {
133         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
134         walk(userData, ob, &wmd->mask_tex_map_obj);
135 }
136
137 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
138 {
139         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
140
141         walk(userData, ob, (ID **)&wmd->mask_texture);
142
143         foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
144 }
145
146 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
147 {
148         walk(userData, ob, md, "mask_texture");
149 }
150
151 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
152                            Object *UNUSED(ob), DagNode *obNode)
153 {
154         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
155         DagNode *curNode;
156
157         if(wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
158                 curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
159
160                 dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
161                                  "WeightVGEdit Modifier");
162         }
163
164         if(wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
165                 dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA,
166                                  "WeightVGEdit Modifier");
167 }
168
169 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
170 {
171         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
172         /* If no vertex group, bypass. */
173         return (wmd->defgrp_name[0] == '\0');
174 }
175
176 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
177                                   int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
178 {
179         WeightVGEditModifierData *wmd = (WeightVGEditModifierData*) md;
180         DerivedMesh *dm = derivedData;
181         MDeformVert *dvert = NULL;
182         MDeformWeight **dw = NULL;
183         float *org_w; /* Array original weights. */
184         float *new_w; /* Array new weights. */
185         int numVerts;
186         int defgrp_idx;
187         int i;
188         /* Flags. */
189         int do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0;
190         int do_rem = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0;
191
192         /* Get number of verts. */
193         numVerts = dm->getNumVerts(dm);
194
195         /* Check if we can just return the original mesh.
196          * Must have verts and therefore verts assigned to vgroups to do anything useful!
197          */
198         if ((numVerts == 0) || (ob->defbase.first == NULL))
199                 return dm;
200
201         /* Get vgroup idx from its name. */
202         defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name);
203         if (defgrp_idx < 0)
204                 return dm;
205
206         dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts);
207         /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
208         if(!dvert)
209                 /* If this modifier is not allowed to add vertices, just return. */
210                 if(!do_add)
211                         return dm;
212                 /* Else, add a valid data layer! */
213                 dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC,
214                                                    NULL, numVerts, wmd->defgrp_name);
215                 /* Ultimate security check. */
216                 if(!dvert)
217                         return dm;
218
219         /* Get org weights, assuming 0.0 for vertices not in given vgroup. */
220         org_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, org_w");
221         new_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, new_w");
222         dw = MEM_mallocN(sizeof(MDeformWeight*) * numVerts, "WeightVGEdit Modifier, dw");
223         for (i = 0; i < numVerts; i++) {
224                 dw[i] = defvert_find_index(&dvert[i], defgrp_idx);
225                 if(dw[i]) {
226                         org_w[i] = new_w[i] = dw[i]->weight;
227                 }
228                 else {
229                         org_w[i] = new_w[i] = wmd->default_weight;
230                 }
231         }
232
233         /* Do mapping. */
234         if (wmd->falloff_type != MOD_WVG_MAPPING_NONE) {
235                 weightvg_do_map(numVerts, new_w, wmd->falloff_type, wmd->cmap_curve);
236         }
237
238         /* Do masking. */
239         weightvg_do_mask(numVerts, NULL, org_w, new_w, ob, dm, wmd->mask_constant,
240                          wmd->mask_defgrp_name, wmd->mask_texture, wmd->mask_tex_use_channel,
241                          wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
242
243         /* Update/add/remove from vgroup. */
244         weightvg_update_vg(dvert, defgrp_idx, dw, numVerts, NULL, org_w, do_add, wmd->add_threshold,
245                            do_rem, wmd->rem_threshold);
246
247         /* Freeing stuff. */
248         MEM_freeN(org_w);
249         MEM_freeN(new_w);
250         MEM_freeN(dw);
251
252         /* Return the vgroup-modified mesh. */
253         return dm;
254 }
255
256 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
257                                     struct BMEditMesh *UNUSED(editData),
258                                     DerivedMesh *derivedData)
259 {
260         return applyModifier(md, ob, derivedData, 0, 1);
261 }
262
263
264 ModifierTypeInfo modifierType_WeightVGEdit = {
265         /* name */              "VertexWeightEdit",
266         /* structName */        "WeightVGEditModifierData",
267         /* structSize */        sizeof(WeightVGEditModifierData),
268         /* type */              eModifierTypeType_NonGeometrical,
269         /* flags */             eModifierTypeFlag_AcceptsMesh
270 /*                             |eModifierTypeFlag_SupportsMapping*/
271                                |eModifierTypeFlag_SupportsEditmode,
272
273         /* copyData */          copyData,
274         /* deformVerts */       NULL,
275         /* deformMatrices */    NULL,
276         /* deformVertsEM */     NULL,
277         /* deformMatricesEM */  NULL,
278         /* applyModifier */     applyModifier,
279         /* applyModifierEM */   applyModifierEM,
280         /* initData */          initData,
281         /* requiredDataMask */  requiredDataMask,
282         /* freeData */          freeData,
283         /* isDisabled */        isDisabled,
284         /* updateDepgraph */    updateDepgraph,
285         /* dependsOnTime */     dependsOnTime,
286         /* dependsOnNormals */  NULL,
287         /* foreachObjectLink */ foreachObjectLink,
288         /* foreachIDLink */     foreachIDLink,
289         /* foreachTexLink */    foreachTexLink,
290 };