Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern/MOD_surfacedeform.c')
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c159
1 files changed, 127 insertions, 32 deletions
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 57e7e2fa98b..4169c76272e 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
+ * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright 2017, Blender Foundation.
@@ -36,6 +36,8 @@
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
+#include "BKE_deform.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -110,6 +112,8 @@ typedef struct SDefDeformData {
const SDefVert *const bind_verts;
float (*const targetCos)[3];
float (*const vertexCos)[3];
+ float *const weights;
+ float const strength;
} SDefDeformData;
/* Bind result values */
@@ -136,6 +140,19 @@ static void initData(ModifierData *md)
smd->verts = NULL;
smd->flags = 0;
smd->falloff = 4.0f;
+ smd->strength = 1.0f;
+}
+
+static void requiredDataMask(Object *UNUSED(ob),
+ ModifierData *md,
+ CustomData_MeshMasks *r_cddata_masks)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+
+ /* Ask for vertex groups if we need them. */
+ if (smd->defgrp_name[0] != '\0') {
+ r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
+ }
}
static void freeData(ModifierData *md)
@@ -163,7 +180,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
- modifier_copyData_generic(md, target, flag);
+ BKE_modifier_copydata_generic(md, target, flag);
if (smd->verts) {
tsmd->verts = MEM_dupallocN(smd->verts);
@@ -1000,20 +1017,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig,
vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap");
if (vert_edges == NULL) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
return false;
}
adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge");
if (adj_array == NULL) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
MEM_freeN(vert_edges);
return false;
}
edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap");
if (edge_polys == NULL) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
MEM_freeN(vert_edges);
MEM_freeN(adj_array);
return false;
@@ -1021,14 +1038,14 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig,
smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts");
if (smd_orig->verts == NULL) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
freeAdjacencyMap(vert_edges, adj_array, edge_polys);
return false;
}
BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2);
if (treeData.tree == NULL) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
freeAdjacencyMap(vert_edges, adj_array, edge_polys);
MEM_freeN(smd_orig->verts);
smd_orig->verts = NULL;
@@ -1039,7 +1056,8 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig,
mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
- modifier_setError((ModifierData *)smd_eval, "Target has edges with more than two polygons");
+ BKE_modifier_set_error((ModifierData *)smd_eval,
+ "Target has edges with more than two polygons");
freeAdjacencyMap(vert_edges, adj_array, edge_polys);
free_bvhtree_from_mesh(&treeData);
MEM_freeN(smd_orig->verts);
@@ -1066,7 +1084,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig,
};
if (data.targetCos == NULL) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
freeData((ModifierData *)smd_orig);
return false;
}
@@ -1085,19 +1103,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig,
MEM_freeN(data.targetCos);
if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
- modifier_setError((ModifierData *)smd_eval, "Out of memory");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory");
freeData((ModifierData *)smd_orig);
}
else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
- modifier_setError((ModifierData *)smd_eval, "Target has edges with more than two polygons");
+ BKE_modifier_set_error((ModifierData *)smd_eval,
+ "Target has edges with more than two polygons");
freeData((ModifierData *)smd_orig);
}
else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
- modifier_setError((ModifierData *)smd_eval, "Target contains concave polygons");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains concave polygons");
freeData((ModifierData *)smd_orig);
}
else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
- modifier_setError((ModifierData *)smd_eval, "Target contains overlapping verts");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains overlapping verts");
freeData((ModifierData *)smd_orig);
}
else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) {
@@ -1105,7 +1124,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig,
* to explain this with a reasonably sized message.
* Though it shouldn't really matter all that much,
* because this is very unlikely to occur */
- modifier_setError((ModifierData *)smd_eval, "Target contains invalid polygons");
+ BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains invalid polygons");
freeData((ModifierData *)smd_orig);
}
@@ -1123,9 +1142,16 @@ static void deformVert(void *__restrict userdata,
const SDefBind *sdbind = data->bind_verts[index].binds;
const int num_binds = data->bind_verts[index].numbinds;
float *const vertexCos = data->vertexCos[index];
- float norm[3], temp[3];
+ float norm[3], temp[3], offset[3];
+ const float weight = (data->weights != NULL) ? data->weights[index] : 1.0f;
- zero_v3(vertexCos);
+ /* Check if this vertex will be deformed. If it is not deformed we return and avoid
+ * unnecessary calculations. */
+ if (weight == 0.0f) {
+ return;
+ }
+
+ zero_v3(offset);
/* Allocate a `coords_buffer` that fits all the temp-data. */
int max_verts = 0;
@@ -1170,8 +1196,13 @@ static void deformVert(void *__restrict userdata,
/* Apply normal offset (generic for all modes) */
madd_v3_v3fl(temp, norm, sdbind->normal_dist);
- madd_v3_v3fl(vertexCos, temp, sdbind->influence);
+ madd_v3_v3fl(offset, temp, sdbind->influence);
}
+ /* Subtract the vertex coord to get the deformation offset. */
+ sub_v3_v3(offset, vertexCos);
+
+ /* Add the offset to start coord multiplied by the strength and weight values. */
+ madd_v3_v3fl(vertexCos, offset, data->strength * weight);
MEM_freeN(coords_buffer);
}
@@ -1179,7 +1210,8 @@ static void surfacedeformModifier_do(ModifierData *md,
const ModifierEvalContext *ctx,
float (*vertexCos)[3],
uint numverts,
- Object *ob)
+ Object *ob,
+ Mesh *mesh)
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
Mesh *target;
@@ -1189,10 +1221,10 @@ static void surfacedeformModifier_do(ModifierData *md,
if (!(smd->flags & MOD_SDEF_BIND)) {
if (smd->verts != NULL) {
if (!DEG_is_active(ctx->depsgraph)) {
- modifier_setError(md, "Attempt to bind from inactive dependency graph");
+ BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph");
return;
}
- ModifierData *md_orig = modifier_get_original(md);
+ ModifierData *md_orig = BKE_modifier_get_original(md);
freeData(md_orig);
}
return;
@@ -1201,7 +1233,7 @@ static void surfacedeformModifier_do(ModifierData *md,
Object *ob_target = smd->target;
target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false);
if (!target) {
- modifier_setError(md, "No valid target mesh");
+ BKE_modifier_set_error(md, "No valid target mesh");
return;
}
@@ -1211,11 +1243,12 @@ static void surfacedeformModifier_do(ModifierData *md,
/* If not bound, execute bind. */
if (smd->verts == NULL) {
if (!DEG_is_active(ctx->depsgraph)) {
- modifier_setError(md, "Attempt to unbind from inactive dependency graph");
+ BKE_modifier_set_error(md, "Attempt to unbind from inactive dependency graph");
return;
}
- SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)modifier_get_original(md);
+ SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)BKE_modifier_get_original(
+ md);
float tmp_mat[4][4];
invert_m4_m4(tmp_mat, ob->obmat);
@@ -1230,19 +1263,52 @@ static void surfacedeformModifier_do(ModifierData *md,
/* Poly count checks */
if (smd->numverts != numverts) {
- modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts);
+ BKE_modifier_set_error(md, "Verts changed from %u to %u", smd->numverts, numverts);
return;
}
else if (smd->numpoly != tnumpoly) {
- modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
+ BKE_modifier_set_error(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
+ return;
+ }
+
+ /* Early out if modifier would not affect input at all - still *after* the sanity checks (and
+ * potential binding) above.
+ */
+ if (smd->strength == 0.0f) {
return;
}
+ int defgrp_index;
+ MDeformVert *dvert;
+ MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index);
+ float *weights = NULL;
+ const bool invert_group = (smd->flags & MOD_SDEF_INVERT_VGROUP) != 0;
+
+ if (defgrp_index != -1) {
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
+ /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
+ if (dvert == NULL) {
+ /* Add a valid data layer! */
+ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, mesh->totvert);
+ }
+
+ if (dvert) {
+ weights = MEM_calloc_arrayN((size_t)numverts, sizeof(*weights), __func__);
+ MDeformVert *dv = dvert;
+ for (uint i = 0; i < numverts; i++, dv++) {
+ weights[i] = invert_group ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) :
+ BKE_defvert_find_weight(dv, defgrp_index);
+ }
+ }
+ }
+
/* Actual vertex location update starts here */
SDefDeformData data = {
.bind_verts = smd->verts,
.targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"),
.vertexCos = vertexCos,
+ .weights = weights,
+ .strength = smd->strength,
};
if (data.targetCos != NULL) {
@@ -1259,25 +1325,51 @@ static void surfacedeformModifier_do(ModifierData *md,
MEM_freeN(data.targetCos);
}
+
+ MEM_SAFE_FREE(weights);
}
static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
- Mesh *UNUSED(mesh),
+ Mesh *mesh,
float (*vertexCos)[3],
int numVerts)
{
- surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object);
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ Mesh *mesh_src = NULL;
+
+ if (smd->defgrp_name[0] != '\0') {
+ /* Only need to use mesh_src when a vgroup is used. */
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ }
+
+ surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src);
+
+ if (!ELEM(mesh_src, NULL, mesh)) {
+ BKE_id_free(NULL, mesh_src);
+ }
}
static void deformVertsEM(ModifierData *md,
const ModifierEvalContext *ctx,
- struct BMEditMesh *UNUSED(editData),
- Mesh *UNUSED(mesh),
+ struct BMEditMesh *em,
+ Mesh *mesh,
float (*vertexCos)[3],
int numVerts)
{
- surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object);
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ Mesh *mesh_src = NULL;
+
+ if (smd->defgrp_name[0] != '\0') {
+ /* Only need to use mesh_src when a vgroup is used. */
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ }
+
+ surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src);
+
+ if (!ELEM(mesh_src, NULL, mesh)) {
+ BKE_id_free(NULL, mesh_src);
+ }
}
static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
@@ -1306,10 +1398,13 @@ ModifierTypeInfo modifierType_SurfaceDeform = {
/* deformMatrices */ NULL,
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
- /* applyModifier */ NULL,
+ /* modifyMesh */ NULL,
+ /* modifyHair */ NULL,
+ /* modifyPointCloud */ NULL,
+ /* modifyVolume */ NULL,
/* initData */ initData,
- /* requiredDataMask */ NULL,
+ /* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,