From 5ee0200d439f5b5697541bb8e7d6ec945c86298e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 21 Sep 2018 15:30:55 +0200 Subject: Multires: Support masks propagation to higher levels --- .../blender/blenkernel/intern/multires_reshape.c | 207 +++++++++++++++------ source/blender/blenkernel/intern/subdiv_ccg.c | 12 +- 2 files changed, 158 insertions(+), 61 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index f0757a492c9..c051ea3ea22 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -228,21 +228,30 @@ static void multires_reshape_vertex_copy_to_next( const MPoly *coarse_poly, const int current_corner, const MDisps *current_displacement_grid, + const GridPaintMask *current_mask_grid, const int current_grid_x, const int current_grid_y) { const int grid_size = ctx->grid_size; const int next_current_corner = (current_corner + 1) % coarse_poly->totloop; - MDisps *next_displacement_grid = &ctx->mdisps[ - coarse_poly->loopstart + next_current_corner]; const int next_grid_x = 0; const int next_grid_y = current_grid_x; const int current_index = current_grid_y * grid_size + current_grid_x; const int next_index = next_grid_y * grid_size + next_grid_x; + /* Copy displacement. */ + MDisps *next_displacement_grid = &ctx->mdisps[ + coarse_poly->loopstart + next_current_corner]; float *next_displacement = next_displacement_grid->disps[next_index]; copy_v3_v3(next_displacement, current_displacement_grid->disps[current_index]); SWAP(float, next_displacement[0], next_displacement[1]); next_displacement[0] = -next_displacement[0]; + /* Copy mask, if exists. */ + if (current_mask_grid != NULL) { + GridPaintMask *next_mask_grid = &ctx->grid_paint_mask[ + coarse_poly->loopstart + next_current_corner]; + next_mask_grid->data[next_index] = + current_mask_grid->data[current_index]; + } } static void multires_reshape_vertex_copy_to_prev( @@ -250,22 +259,31 @@ static void multires_reshape_vertex_copy_to_prev( const MPoly *coarse_poly, const int current_corner, const MDisps *current_displacement_grid, + const GridPaintMask *current_mask_grid, const int current_grid_x, const int current_grid_y) { const int grid_size = ctx->grid_size; const int prev_current_corner = (current_corner - 1 + coarse_poly->totloop) % coarse_poly->totloop; - MDisps *prev_displacement_grid = &ctx->mdisps[ - coarse_poly->loopstart + prev_current_corner]; const int prev_grid_x = current_grid_y; const int prev_grid_y = 0; const int current_index = current_grid_y * grid_size + current_grid_x; const int prev_index = prev_grid_y * grid_size + prev_grid_x; + /* Copy displacement. */ + MDisps *prev_displacement_grid = &ctx->mdisps[ + coarse_poly->loopstart + prev_current_corner]; float *prev_displacement = prev_displacement_grid->disps[prev_index]; copy_v3_v3(prev_displacement, current_displacement_grid->disps[current_index]); SWAP(float, prev_displacement[0], prev_displacement[1]); prev_displacement[1] = -prev_displacement[1]; + /* Copy mask, if exists. */ + if (current_mask_grid != NULL) { + GridPaintMask *prev_mask_grid = &ctx->grid_paint_mask[ + coarse_poly->loopstart + prev_current_corner]; + prev_mask_grid->data[prev_index] = + current_mask_grid->data[current_index]; + } } static void copy_boundary_displacement( @@ -273,19 +291,24 @@ static void copy_boundary_displacement( const MPoly *coarse_poly, const int corner, const int grid_x, const int grid_y, - const MDisps *displacement_grid) + const MDisps *displacement_grid, + const GridPaintMask *mask_grid) { if (grid_x == 0 && grid_y == 0) { for (int i = 0; i < coarse_poly->totloop; i++) { const int current_face_corner = (corner + i) % coarse_poly->totloop; - MDisps *current_displacement_grid = &ctx->mdisps[ - coarse_poly->loopstart + current_face_corner]; + const int grid_index = coarse_poly->loopstart + current_face_corner; + MDisps *current_displacement_grid = &ctx->mdisps[grid_index]; + GridPaintMask *current_mask_grid = + mask_grid != NULL ? &ctx->grid_paint_mask[grid_index] + : NULL; multires_reshape_vertex_copy_to_next( ctx, coarse_poly, current_face_corner, current_displacement_grid, + current_mask_grid, 0, 0); } } @@ -295,6 +318,7 @@ static void copy_boundary_displacement( coarse_poly, corner, displacement_grid, + mask_grid, grid_x, grid_y); } else if (grid_y == 0) { @@ -303,6 +327,7 @@ static void copy_boundary_displacement( coarse_poly, corner, displacement_grid, + mask_grid, grid_x, grid_y); } } @@ -368,7 +393,8 @@ static void multires_reshape_vertex_from_final_data( } /* Copy boundary to the next/previous grids */ copy_boundary_displacement( - ctx, coarse_poly, face_corner, grid_x, grid_y, displacement_grid); + ctx, coarse_poly, face_corner, grid_x, grid_y, + displacement_grid, grid_paint_mask); } /* ============================================================================= @@ -383,8 +409,16 @@ typedef struct MultiresPropagateData { int top_grid_size; MDisps *old_displacement_grids; MDisps *new_displacement_grids; + GridPaintMask *grid_paint_mask; } MultiresPropagateData; +typedef struct MultiresPropagateCornerData { + float old_coord[3]; + float new_coord[3]; + float coord_delta[3]; + float mask; +} MultiresPropagateCornerData; + static void multires_reshape_propagate_prepare( MultiresPropagateData *data, Object *object, @@ -423,6 +457,8 @@ static void multires_reshape_propagate_prepare( data->top_grid_size = (1 << (top_level - 1)) + 1; data->old_displacement_grids = old_mdisps; data->new_displacement_grids = mdisps; + data->grid_paint_mask = + CustomData_get_layer(&coarse_mesh->ldata, CD_GRID_PAINT_MASK); } static void multires_reshape_propagate_prepare_from_mmd( @@ -438,40 +474,97 @@ static void multires_reshape_propagate_prepare_from_mmd( multires_reshape_propagate_prepare(data, object, level, mmd->totlvl); } -static void multires_reshape_propagate_calc_simple_delta( - float r_delta[3], +static void multires_reshape_propagate_corner_data( + MultiresPropagateCornerData* corner, const MDisps *old_displacement_grid, const MDisps *new_displacement_grid, + const GridPaintMask *grid_paint_mask, const int grid_size, - const int x, const int y) + const int grid_skip, + const int reshape_x, const int reshape_y) { - copy_v3_v3(r_delta, new_displacement_grid->disps[y * grid_size + x]); + const int x = reshape_x * grid_skip; + const int y = reshape_y * grid_skip; + const int grid_index = y * grid_size + x; if (old_displacement_grid->disps != NULL) { - sub_v3_v3(r_delta, old_displacement_grid->disps[y * grid_size + x]); + copy_v3_v3(corner->old_coord, old_displacement_grid->disps[grid_index]); + } + else { + zero_v3(corner->old_coord); + } + copy_v3_v3(corner->new_coord, new_displacement_grid->disps[grid_index]); + sub_v3_v3v3(corner->coord_delta, corner->new_coord, corner->old_coord); + if (grid_paint_mask != NULL) { + corner->mask = grid_paint_mask->data[grid_index]; + } + else { + corner->mask = 0.0f; } } -static void multires_reshape_propagate_calc_reshape_delta( - float r_delta[3], +static void multires_reshape_propagate_all_corners_data( + MultiresPropagateCornerData corners[4], const MDisps *old_displacement_grid, const MDisps *new_displacement_grid, + const GridPaintMask *grid_paint_mask, 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); + int corner_index = 0; + for (int dy = 0; dy <= 1; dy++) { + for (int dx = 0; dx <= 1; dx++) { + multires_reshape_propagate_corner_data( + &corners[corner_index], + old_displacement_grid, + new_displacement_grid, + grid_paint_mask, + grid_size, + grid_skip, + reshape_x + dx, reshape_y + dy); + corner_index++; + } + } +} + +static void multires_reshape_propagate_interpolate_coord( + MDisps *new_displacement_grid, + const MultiresPropagateCornerData corners[4], + const float weights[4], + const int x, const int y, + const int grid_size) +{ + float delta[3]; + interp_v3_v3v3v3v3( + delta, + corners[0].coord_delta, corners[1].coord_delta, + corners[2].coord_delta, corners[3].coord_delta, + weights); + const int index = y * grid_size + x; + float *new_displacement = new_displacement_grid->disps[index]; + add_v3_v3(new_displacement, delta); +} + +static void multires_reshape_propagate_interpolate_mask( + GridPaintMask *grid_paint_mask, + const MultiresPropagateCornerData corners[4], + const float weights[4], + const int x, const int y, + const int grid_size) +{ + const int index = y * grid_size + x; + grid_paint_mask->data[index] = + corners[0].mask * weights[0] + + corners[1].mask * weights[1] + + corners[2].mask * weights[2] + + corners[3].mask * weights[3]; } static void multires_reshape_propagate_grid( MultiresPropagateData *data, const MDisps *old_displacement_grid, - MDisps *new_displacement_grid) + MDisps *new_displacement_grid, + GridPaintMask *grid_paint_mask) { const int reshape_grid_size = data->reshape_grid_size; const int top_grid_size = data->top_grid_size; @@ -485,32 +578,14 @@ static void multires_reshape_propagate_grid( 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], + MultiresPropagateCornerData corners[4]; + multires_reshape_propagate_all_corners_data( + corners, old_displacement_grid, new_displacement_grid, + grid_paint_mask, 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; @@ -536,20 +611,26 @@ static void multires_reshape_propagate_grid( 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); + const int final_x = reshape_x * grid_skip + x; + const int final_y = reshape_y * grid_skip + y; + const float linear_weights[4] = {(1.0f - u) * (1.0f - v), + u * (1.0f - v), + (1.0f - u) * v, + u * v}; + multires_reshape_propagate_interpolate_coord( + new_displacement_grid, + corners, + linear_weights, + final_x, final_y, + top_grid_size); + if (grid_paint_mask != NULL) { + multires_reshape_propagate_interpolate_mask( + grid_paint_mask, + corners, + linear_weights, + final_x, final_y, + top_grid_size); + } } } } @@ -569,8 +650,14 @@ static void multires_reshape_propagate(MultiresPropagateData *data) { if (old_displacement_grid->level != new_displacement_grid->level) { continue; } + GridPaintMask *grid_paint_mask = + data->grid_paint_mask != NULL + ? &data->grid_paint_mask[grid_index] + : NULL; multires_reshape_propagate_grid( - data, old_displacement_grid, new_displacement_grid); + data, old_displacement_grid, + new_displacement_grid, + grid_paint_mask); } } diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 5ec675494f5..c05bf8ad76d 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -215,7 +215,7 @@ static void subdiv_ccg_eval_grid_element( data->mask_evaluator, ptex_face_index, u, v); } else { - *mask_value_ptr = 0; + *mask_value_ptr = 0.0f; } } } @@ -933,6 +933,13 @@ static void average_grid_element(SubdivCCG *subdiv_ccg, average_grid_element_value_v3(CCG_elem_no(key, grid_element_a), CCG_elem_no(key, grid_element_b)); } + if (subdiv_ccg->has_mask) { + float mask = + (*CCG_elem_mask(key, grid_element_a) + + *CCG_elem_mask(key, grid_element_b)) * 0.5f; + *CCG_elem_mask(key, grid_element_a) = mask; + *CCG_elem_mask(key, grid_element_b) = mask; + } } static void copy_grid_element(SubdivCCG *subdiv_ccg, @@ -944,6 +951,9 @@ static void copy_grid_element(SubdivCCG *subdiv_ccg, if (subdiv_ccg->has_normal) { copy_v3_v3(CCG_elem_no(key, destination), CCG_elem_no(key, source)); } + if (subdiv_ccg->has_mask) { + *CCG_elem_mask(key, destination) = *CCG_elem_mask(key, source); + } } static void subdiv_ccg_average_inner_face_grids( -- cgit v1.2.3