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.c112
1 files changed, 83 insertions, 29 deletions
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index a80918b8d2b..9b0012e3890 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -1166,8 +1166,8 @@ static bool surfacedeformBind(Object *ob,
SurfaceDeformModifierData *smd_eval,
float (*vertexCos)[3],
uint verts_num,
- uint tpolys_num,
- uint tverts_num,
+ uint target_polys_num,
+ uint target_verts_num,
Mesh *target,
Mesh *mesh)
{
@@ -1182,7 +1182,7 @@ static bool surfacedeformBind(Object *ob,
SDefAdjacency *adj_array;
SDefEdgePolys *edge_polys;
- vert_edges = MEM_calloc_arrayN(tverts_num, sizeof(*vert_edges), "SDefVertEdgeMap");
+ vert_edges = MEM_calloc_arrayN(target_verts_num, sizeof(*vert_edges), "SDefVertEdgeMap");
if (vert_edges == NULL) {
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
return false;
@@ -1220,7 +1220,7 @@ static bool surfacedeformBind(Object *ob,
}
adj_result = buildAdjacencyMap(
- mpoly, medge, mloop, tpolys_num, tedges_num, vert_edges, adj_array, edge_polys);
+ mpoly, medge, mloop, target_polys_num, tedges_num, vert_edges, adj_array, edge_polys);
if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
BKE_modifier_set_error(
@@ -1233,7 +1233,8 @@ static bool surfacedeformBind(Object *ob,
}
smd_orig->mesh_verts_num = verts_num;
- smd_orig->polys_num = tpolys_num;
+ smd_orig->target_verts_num = target_verts_num;
+ smd_orig->target_polys_num = target_polys_num;
int defgrp_index;
MDeformVert *dvert;
@@ -1249,7 +1250,8 @@ static bool surfacedeformBind(Object *ob,
.medge = medge,
.mloop = mloop,
.looptri = BKE_mesh_runtime_looptri_ensure(target),
- .targetCos = MEM_malloc_arrayN(tverts_num, sizeof(float[3]), "SDefTargetBindVertArray"),
+ .targetCos = MEM_malloc_arrayN(
+ target_verts_num, sizeof(float[3]), "SDefTargetBindVertArray"),
.bind_verts = smd_orig->verts,
.vertexCos = vertexCos,
.falloff = smd_orig->falloff,
@@ -1268,7 +1270,7 @@ static bool surfacedeformBind(Object *ob,
invert_m4_m4(data.imat, smd_orig->mat);
- for (int i = 0; i < tverts_num; i++) {
+ for (int i = 0; i < target_verts_num; i++) {
mul_v3_m4v3(data.targetCos[i], smd_orig->mat, mvert[i].co);
}
@@ -1431,7 +1433,7 @@ static void surfacedeformModifier_do(ModifierData *md,
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
Mesh *target;
- uint tverts_num, tpolys_num;
+ uint target_verts_num, target_polys_num;
/* Exit function if bind flag is not set (free bind data if any). */
if (!(smd->flags & MOD_SDEF_BIND)) {
@@ -1453,8 +1455,8 @@ static void surfacedeformModifier_do(ModifierData *md,
return;
}
- tverts_num = BKE_mesh_wrapper_vert_len(target);
- tpolys_num = BKE_mesh_wrapper_poly_len(target);
+ target_verts_num = BKE_mesh_wrapper_vert_len(target);
+ target_polys_num = BKE_mesh_wrapper_poly_len(target);
/* If not bound, execute bind. */
if (smd->verts == NULL) {
@@ -1473,25 +1475,62 @@ static void surfacedeformModifier_do(ModifierData *md,
/* Avoid converting edit-mesh data, binding is an exception. */
BKE_mesh_wrapper_ensure_mdata(target);
- if (!surfacedeformBind(
- ob, smd_orig, smd, vertexCos, verts_num, tpolys_num, tverts_num, target, mesh)) {
+ if (!surfacedeformBind(ob,
+ smd_orig,
+ smd,
+ vertexCos,
+ verts_num,
+ target_polys_num,
+ target_verts_num,
+ target,
+ mesh)) {
smd->flags &= ~MOD_SDEF_BIND;
}
/* Early abort, this is binding 'call', no need to perform whole evaluation. */
return;
}
- /* Poly count checks */
+ /* Geometry count on the deforming mesh. */
if (smd->mesh_verts_num != verts_num) {
BKE_modifier_set_error(
ob, md, "Vertices changed from %u to %u", smd->mesh_verts_num, verts_num);
return;
}
- if (smd->polys_num != tpolys_num) {
+
+ /* Geometry count on the target mesh. */
+ if (smd->target_polys_num != target_polys_num && smd->target_verts_num == 0) {
+ /* Change in the number of polygons does not really imply change in the vertex count, but
+ * this is how the modifier worked before the vertex count was known. Follow the legacy
+ * logic without requirement to re-bind the mesh. */
BKE_modifier_set_error(
- ob, md, "Target polygons changed from %u to %u", smd->polys_num, tpolys_num);
+ ob, md, "Target polygons changed from %u to %u", smd->target_polys_num, target_polys_num);
return;
}
+ if (smd->target_verts_num != 0 && smd->target_verts_num != target_verts_num) {
+ if (smd->target_verts_num > target_verts_num) {
+ /* Number of vertices on the target did reduce. There is no usable recovery from this. */
+ BKE_modifier_set_error(ob,
+ md,
+ "Target vertices changed from %u to %u",
+ smd->target_verts_num,
+ target_verts_num);
+ return;
+ }
+
+ /* Assume the increase in the vertex count means that the "new" vertices in the target mesh are
+ * added after the original ones. This covers typical case when target was at the subdivision
+ * level 0 and then subdivision was increased (i.e. for the render purposes). */
+
+ BKE_modifier_set_error(ob,
+ md,
+ "Target vertices changed from %u to %u, continuing anyway",
+ smd->target_verts_num,
+ target_verts_num);
+
+ /* In theory we only need the `smd->verts_num` vertices in the `targetCos` for evaluation, but
+ * it is not currently possible to request a subset of coordinates: the API expects that the
+ * caller needs coordinates of all vertices and asserts for it. */
+ }
/* Early out if modifier would not affect input at all - still *after* the sanity checks
* (and potential binding) above. */
@@ -1507,7 +1546,7 @@ static void surfacedeformModifier_do(ModifierData *md,
/* Actual vertex location update starts here */
SDefDeformData data = {
.bind_verts = smd->verts,
- .targetCos = MEM_malloc_arrayN(tverts_num, sizeof(float[3]), "SDefTargetVertArray"),
+ .targetCos = MEM_malloc_arrayN(target_verts_num, sizeof(float[3]), "SDefTargetVertArray"),
.vertexCos = vertexCos,
.dvert = dvert,
.defgrp_index = defgrp_index,
@@ -1516,7 +1555,8 @@ static void surfacedeformModifier_do(ModifierData *md,
};
if (data.targetCos != NULL) {
- BKE_mesh_wrapper_vert_coords_copy_with_mat4(target, data.targetCos, tverts_num, smd->mat);
+ BKE_mesh_wrapper_vert_coords_copy_with_mat4(
+ target, data.targetCos, target_verts_num, smd->mat);
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@@ -1629,27 +1669,41 @@ static void panelRegister(ARegionType *region_type)
modifier_panel_register(region_type, eModifierType_SurfaceDeform, panel_draw);
}
-static void blendWrite(BlendWriter *writer, const ModifierData *md)
+static void blendWrite(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
{
- const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
+ SurfaceDeformModifierData smd = *(const SurfaceDeformModifierData *)md;
+
+ if (ID_IS_OVERRIDE_LIBRARY(id_owner)) {
+ BLI_assert(!ID_IS_LINKED(id_owner));
+ const bool is_local = (md->flag & eModifierFlag_OverrideLibrary_Local) != 0;
+ if (!is_local) {
+ /* Modifier coming from linked data cannot be bound from an override, so we can remove all
+ * binding data, can save a significant amount of memory. */
+ smd.bind_verts_num = 0;
+ smd.verts = NULL;
+ }
+ }
- BLO_write_struct_array(writer, SDefVert, smd->bind_verts_num, smd->verts);
+ BLO_write_struct_at_address(writer, SurfaceDeformModifierData, md, &smd);
- if (smd->verts) {
- for (int i = 0; i < smd->bind_verts_num; i++) {
- BLO_write_struct_array(writer, SDefBind, smd->verts[i].binds_num, smd->verts[i].binds);
+ if (smd.verts != NULL) {
+ SDefVert *bind_verts = smd.verts;
+ BLO_write_struct_array(writer, SDefVert, smd.bind_verts_num, bind_verts);
- if (smd->verts[i].binds) {
- for (int j = 0; j < smd->verts[i].binds_num; j++) {
+ for (int i = 0; i < smd.bind_verts_num; i++) {
+ BLO_write_struct_array(writer, SDefBind, bind_verts[i].binds_num, bind_verts[i].binds);
+
+ if (bind_verts[i].binds) {
+ for (int j = 0; j < bind_verts[i].binds_num; j++) {
BLO_write_uint32_array(
- writer, smd->verts[i].binds[j].verts_num, smd->verts[i].binds[j].vert_inds);
+ writer, bind_verts[i].binds[j].verts_num, bind_verts[i].binds[j].vert_inds);
- if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) {
- BLO_write_float3_array(writer, 1, smd->verts[i].binds[j].vert_weights);
+ if (ELEM(bind_verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) {
+ BLO_write_float3_array(writer, 1, bind_verts[i].binds[j].vert_weights);
}
else {
BLO_write_float_array(
- writer, smd->verts[i].binds[j].verts_num, smd->verts[i].binds[j].vert_weights);
+ writer, bind_verts[i].binds[j].verts_num, bind_verts[i].binds[j].vert_weights);
}
}
}