[Bf-blender-cvs] [619c55027f7] blender2.8: Multires: Fix reshaping from object at lower level

Sergey Sharybin noreply at git.blender.org
Fri Sep 21 11:48:09 CEST 2018


Commit: 619c55027f718c1018051da41bcd89943445e663
Author: Sergey Sharybin
Date:   Fri Sep 21 11:18:37 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB619c55027f718c1018051da41bcd89943445e663

Multires: Fix reshaping from object at lower level

This brings basic implementation of displacement propagation
to a higher levels. Currently does linear interpolation between
grid points at which reshape happened. It makes results a bit
choppy, proper solution would be to use some interpolation
weights from the limit patch.

===================================================================

M	source/blender/blenkernel/intern/multires_reshape.c

===================================================================

diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index 7687506e9a7..63def8055b0 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -330,7 +330,224 @@ static void multires_reshape_vertex_from_final_coord(
 }
 
 /* =============================================================================
- * Reshape from deformed veretx coordinates.
+ * Helpers to propagate displacement to higher levels.
+ */
+
+typedef struct MultiresPropagateData {
+	int reshape_level;
+	int top_level;
+	int num_grids;
+	int reshape_grid_size;
+	int top_grid_size;
+	MDisps *old_displacement_grids;
+	MDisps *new_displacement_grids;
+} MultiresPropagateData;
+
+static void multires_reshape_propagate_prepare(
+        MultiresPropagateData *data,
+        Object *object,
+        const int reshape_level,
+        const int top_level)
+{
+	BLI_assert(reshape_level <= top_level);
+	data->old_displacement_grids = NULL;
+	if (reshape_level == top_level) {
+		/* Nothing to do, reshape will happen on the whole grid conent. */
+		return;
+	}
+	Mesh *coarse_mesh = object->data;
+	const int num_grids = coarse_mesh->totloop;
+	MDisps *mdisps = CustomData_get_layer(&coarse_mesh->ldata, CD_MDISPS);
+	MDisps *old_mdisps = MEM_dupallocN(mdisps);
+	for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+		MDisps *displacement_grid = &mdisps[grid_index];
+		MDisps *old_displacement_grid = &old_mdisps[grid_index];
+		old_displacement_grid->totdisp = displacement_grid->totdisp;
+		old_displacement_grid->level = displacement_grid->level;
+		if (displacement_grid->disps) {
+			displacement_grid->disps = MEM_dupallocN(displacement_grid->disps);
+		}
+		else {
+			old_displacement_grid->disps = NULL;
+		}
+		/* TODO(sergey): This might be needed for proper propagation. */
+		old_displacement_grid->hidden = NULL;
+	}
+	data->reshape_level = reshape_level;
+	data->top_level = top_level;
+	data->num_grids = num_grids;
+	/* TODO(sergey): use grid_size_for_level_get(). */
+	data->reshape_grid_size = (1 << (reshape_level - 1)) + 1;
+	data->top_grid_size = (1 << (top_level - 1)) + 1;
+	data->old_displacement_grids = old_mdisps;
+	data->new_displacement_grids = mdisps;
+}
+
+static void multires_reshape_propagate_prepare_from_mmd(
+        MultiresPropagateData *data,
+        struct Depsgraph *depsgraph,
+        Object *object,
+        const MultiresModifierData *mmd,
+        const bool use_render_params)
+{
+	Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+	const int level = multires_get_level(
+	        scene_eval, object, mmd, use_render_params, true);
+	multires_reshape_propagate_prepare(data, object, level, mmd->totlvl);
+}
+
+static void multires_reshape_propagate_calc_simple_delta(
+        float r_delta[3],
+        const MDisps *old_displacement_grid,
+        const MDisps *new_displacement_grid,
+        const int grid_size,
+        const int x, const int y)
+{
+	copy_v3_v3(r_delta, new_displacement_grid->disps[y * grid_size + x]);
+	if (old_displacement_grid->disps != NULL) {
+		sub_v3_v3(r_delta, old_displacement_grid->disps[y * grid_size + x]);
+	}
+}
+
+static void multires_reshape_propagate_calc_reshape_delta(
+        float r_delta[3],
+        const MDisps *old_displacement_grid,
+        const MDisps *new_displacement_grid,
+        const int grid_size,
+        const int grid_skip,
+        const int reshape_x, const int reshape_y)
+{
+	const int x = reshape_x * grid_skip;
+	const int y = reshape_y * grid_skip;
+	multires_reshape_propagate_calc_simple_delta(
+	        r_delta,
+	        old_displacement_grid, new_displacement_grid,
+	        grid_size,
+	        x, y);
+}
+
+static void multires_reshape_propagate_grid(
+        MultiresPropagateData *data,
+        const MDisps *old_displacement_grid,
+		MDisps *new_displacement_grid)
+{
+	const int reshape_grid_size = data->reshape_grid_size;
+	const int top_grid_size = data->top_grid_size;
+	const int grid_skip = (top_grid_size - 1) / (reshape_grid_size - 1);
+	const float grid_skip_inv = 1.0f / (float)grid_skip;
+	for (int reshape_y = 0;
+	     reshape_y < reshape_grid_size - 1;
+	     reshape_y++)
+	{
+		for (int reshape_x = 0;
+		     reshape_x < reshape_grid_size - 1;
+		     reshape_x++)
+		{
+			/* Calculate delta from the reshape. */
+			float delta_corners[4][3];
+			multires_reshape_propagate_calc_reshape_delta(
+			        delta_corners[0],
+			        old_displacement_grid, new_displacement_grid,
+			        top_grid_size,
+			        grid_skip,
+			        reshape_x, reshape_y);
+			multires_reshape_propagate_calc_reshape_delta(
+			        delta_corners[1],
+			        old_displacement_grid, new_displacement_grid,
+			        top_grid_size,
+			        grid_skip,
+			        reshape_x + 1, reshape_y);
+			multires_reshape_propagate_calc_reshape_delta(
+			        delta_corners[2],
+			        old_displacement_grid, new_displacement_grid,
+			        top_grid_size,
+			        grid_skip,
+			        reshape_x + 1, reshape_y + 1);
+			multires_reshape_propagate_calc_reshape_delta(
+			        delta_corners[3],
+			        old_displacement_grid, new_displacement_grid,
+			        top_grid_size,
+			        grid_skip,
+			        reshape_x, reshape_y + 1);
+			/* Propagate to higher levels. */
+			for (int y = 0; y <= grid_skip; y++) {
+				const float v = (float)y * grid_skip_inv;
+				for (int x = 0; x <= grid_skip; x++) {
+					/* Ignorevalues at the exact locations of grid which was
+					 * reshape. Those points already have proper displacement.
+					 */
+					if ((x == 0 && y == 0) ||
+					    (x == grid_skip && y == 0) ||
+					    (x == grid_skip && y == grid_skip) ||
+					    (x == 0 && y == grid_skip))
+					{
+						continue;
+					}
+					/* Ignore right-most column and top-most row, unless this
+					 * is a boundary of the grid, to prevent displacement
+					 * being affected twice.
+					 */
+					if (x == grid_skip && reshape_x != reshape_grid_size - 2) {
+						continue;
+					}
+					if (y == grid_skip && reshape_y != reshape_grid_size - 2) {
+						continue;
+					}
+					const float u = (float)x * grid_skip_inv;
+					const float weights[4] = {(1.0f - u) * (1.0f - v),
+					                          u * (1.0f - v),
+					                          u * v,
+					                          (1.0f - u) * v};
+					float delta[3];
+					interp_v3_v3v3v3v3(
+					        delta,
+					        delta_corners[0], delta_corners[1],
+					        delta_corners[2], delta_corners[3],
+					        weights);
+					float *new_displacement = new_displacement_grid->disps[
+					        (reshape_y * grid_skip + y) * top_grid_size +
+					        (reshape_x * grid_skip) + x];
+					add_v3_v3(new_displacement, delta);
+				}
+			}
+		}
+	}
+}
+
+static void multires_reshape_propagate(MultiresPropagateData *data) {
+	if (data->old_displacement_grids == NULL) {
+		return;
+	}
+	const int num_grids = data->num_grids;
+	for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+		const MDisps *old_displacement_grid =
+		        &data->old_displacement_grids[grid_index];
+		MDisps *new_displacement_grid =
+		        &data->new_displacement_grids[grid_index];
+		if (old_displacement_grid->level != new_displacement_grid->level) {
+			continue;
+		}
+		multires_reshape_propagate_grid(
+		        data, old_displacement_grid, new_displacement_grid);
+	}
+}
+
+static void multires_reshape_propagate_free(MultiresPropagateData *data) {
+	if (data->old_displacement_grids != NULL) {
+		const int num_grids = data->num_grids;
+		MDisps *old_mdisps = data->old_displacement_grids;
+		for (int grid_index = 0; grid_index < num_grids; grid_index++) {
+			MDisps *old_displacement_grid = &old_mdisps[grid_index];
+			if (old_displacement_grid->disps) {
+				MEM_freeN(old_displacement_grid->disps);
+			}
+		}
+		MEM_freeN(data->old_displacement_grids);
+	}
+}
+
+/* =============================================================================
+ * Reshape from deformed vertex coordinates.
  */
 
 typedef struct MultiresReshapeFromDeformedVertsContext {
@@ -487,6 +704,10 @@ static bool multires_reshape_from_vertcos(
 	SubdivToMeshSettings mesh_settings;
 	BKE_multires_subdiv_mesh_settings_init(
         &mesh_settings, scene_eval, object, mmd, use_render_params, true);
+	/* Initialize propagation to higher levels. */
+	MultiresPropagateData data;
+	multires_reshape_propagate_prepare_from_mmd(
+        &data, depsgraph, object, mmd, use_render_params);
 	/* Run all the callbacks. */
 	BKE_subdiv_foreach_subdiv_geometry(
 	        subdiv,
@@ -494,6 +715,8 @@ static bool multires_reshape_from_vertcos(
 	        &mesh_settings,
 	        coarse_mesh);
 	BKE_subdiv_free(subdiv);
+	multires_reshape_propagate(&data);
+	multires_reshape_propagate_free(&data);
 	return true;
 }



More information about the Bf-blender-cvs mailing list