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:
authorSergey Sharybin <sergey.vfx@gmail.com>2018-09-21 12:18:37 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2018-09-21 12:24:33 +0300
commit619c55027f718c1018051da41bcd89943445e663 (patch)
treed61a2b9e7a2fade50248f06c1218e0915c9e9eae /source/blender/blenkernel/intern/multires_reshape.c
parent495c7463fc39b8bec1f678af28e94a207e0d1217 (diff)
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.
Diffstat (limited to 'source/blender/blenkernel/intern/multires_reshape.c')
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c225
1 files changed, 224 insertions, 1 deletions
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;
}