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>2019-01-17 14:06:26 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-01-18 14:29:53 +0300
commit02f86482b4e528f4cee106983c0c6ef81b0ca3e3 (patch)
tree934b735c8dd9c27fe0344a992ee776bb80092a07 /source/blender/blenkernel
parent076019c5f2b9d7f115187b55970a22439eec1397 (diff)
Multires: Simplify reshaping code
The idea is to run reshaping for every boundary vertex of a grid rather than trying to copy boundary grid elements. While this is somewhat slower, this avoids all this tangent flipping magic, which tempts to be rather tricky and fragile.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_multires.h6
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c311
2 files changed, 100 insertions, 217 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 7cefda3330d..f246522fffe 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -155,8 +155,10 @@ void BKE_multires_subdiv_mesh_settings_init(
/* For a given partial derivatives of a ptex face get tangent matrix for
* displacement.
- * Corner needs to be known to properly "rotate" partial derivatives.
- */
+ *
+ * Corner needs to be known to properly "rotate" partial derivatives when the
+ * matrix is being constructed for quad. For non-quad the corner is to be set
+ * to 0. */
BLI_INLINE void BKE_multires_construct_tangent_matrix(
float tangent_matrix[3][3],
const float dPdu[3],
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index 96f5e9b6b01..6fd9176dbcb 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -143,119 +143,63 @@ static void multires_reshape_ensure_grids(Mesh *mesh, const int grid_level)
multires_reshape_ensure_mask_grids(mesh, grid_level);
}
-static void multires_reshape_vertex_copy_to_next(
- MultiresReshapeContext *ctx,
+/* Convert normalized coordinate within a grid to a normalized coordinate within
+ * a ptex face. */
+static void multires_reshape_grid_coord_to_ptex(
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 corner, const float corner_u, const float corner_v,
+ float *r_ptex_face_u, float *r_ptex_face_v)
{
- const int grid_size = ctx->top_grid_size;
- const int next_current_corner = (current_corner + 1) % coarse_poly->totloop;
- 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];
+ if (coarse_poly->totloop == 4) {
+ float grid_u, grid_v;
+ BKE_subdiv_ptex_face_uv_to_grid_uv(
+ corner_u, corner_v, &grid_u, &grid_v);
+ BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v,
+ r_ptex_face_u, r_ptex_face_v);
+ }
+ else {
+ *r_ptex_face_u = corner_u;
+ *r_ptex_face_v = corner_v;
}
}
-static void multires_reshape_vertex_copy_to_prev(
- MultiresReshapeContext *ctx,
+/* NOTE: The tangent vectors are measured in ptex face normalized coordinates,
+ * which is different from grid tangent. */
+static void multires_reshape_sample_surface(
+ Subdiv *subdiv,
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 corner, const float corner_u, const float corner_v,
+ const int ptex_face_index,
+ float r_P[3], float r_dPdu[3], float r_dPdv[3])
{
- const int grid_size = ctx->top_grid_size;
- const int prev_current_corner =
- (current_corner - 1 + coarse_poly->totloop) % coarse_poly->totloop;
- 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];
- }
+ float ptex_face_u, ptex_face_v;
+ multires_reshape_grid_coord_to_ptex(coarse_poly, corner, corner_u, corner_v,
+ &ptex_face_u, &ptex_face_v);
+ BKE_subdiv_eval_limit_point_and_derivatives(
+ subdiv,
+ ptex_face_index, ptex_face_u, ptex_face_v,
+ r_P, r_dPdu, r_dPdv);
}
-static void copy_boundary_displacement(
- MultiresReshapeContext *ctx,
+static void multires_reshape_tangent_matrix_for_corner(
const MPoly *coarse_poly,
- const int corner,
- const int grid_x, const int grid_y,
- const MDisps *displacement_grid,
- const GridPaintMask *mask_grid)
+ const int coarse_corner,
+ const float dPdu[3], const float dPdv[3],
+ float r_tangent_matrix[3][3])
{
- 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;
- 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);
- }
- }
- else if (grid_x == 0) {
- multires_reshape_vertex_copy_to_prev(
- ctx,
- coarse_poly,
- corner,
- displacement_grid,
- mask_grid,
- grid_x, grid_y);
- }
- else if (grid_y == 0) {
- multires_reshape_vertex_copy_to_next(
- ctx,
- coarse_poly,
- corner,
- displacement_grid,
- mask_grid,
- grid_x, grid_y);
- }
+ /* For a quad faces we would need to flip the tangent, since they will use
+ * use different coordinates within displacement grid comparent to ptex
+ * face. */
+ const bool is_quad = (coarse_poly->totloop == 4);
+ const int tangent_corner = is_quad ? coarse_corner : 0;
+ BKE_multires_construct_tangent_matrix(
+ r_tangent_matrix, dPdu, dPdv, tangent_corner);
}
static void multires_reshape_vertex_from_final_data(
MultiresReshapeContext *ctx,
const int ptex_face_index,
- const float u, const float v,
+ const float corner_u, const float corner_v,
const int coarse_poly_index,
const int coarse_corner,
const float final_P[3], const float final_mask)
@@ -268,62 +212,39 @@ static void multires_reshape_vertex_from_final_data(
const int loop_index = coarse_poly->loopstart + coarse_corner;
/* Evaluate limit surface. */
float P[3], dPdu[3], dPdv[3];
- BKE_subdiv_eval_limit_point_and_derivatives(
- subdiv, ptex_face_index, u, v, P, dPdu, dPdv);
- /* Get coordinate and corner configuration. */
- float grid_u, grid_v;
- MDisps *displacement_grid;
- GridPaintMask *grid_paint_mask = NULL;
- int face_corner = coarse_corner;
- int grid_corner = 0;
- int grid_index;
- if (coarse_poly->totloop == 4) {
- float corner_u, corner_v;
- face_corner = BKE_subdiv_rotate_quad_to_corner(
- u, v, &corner_u, &corner_v);
- grid_corner = face_corner;
- grid_index = loop_index + face_corner;
- BKE_subdiv_ptex_face_uv_to_grid_uv(
- corner_u, corner_v, &grid_u, &grid_v);
- }
- else {
- grid_index = loop_index;
- BKE_subdiv_ptex_face_uv_to_grid_uv(u, v, &grid_u, &grid_v);
- }
- displacement_grid = &ctx->mdisps[grid_index];
- if (ctx->grid_paint_mask != NULL) {
- grid_paint_mask = &ctx->grid_paint_mask[grid_index];
- BLI_assert(grid_paint_mask->level == displacement_grid->level);
- }
+ multires_reshape_sample_surface(
+ subdiv,
+ coarse_poly,
+ coarse_corner, corner_u, corner_v,
+ ptex_face_index,
+ P, dPdu, dPdv);
+ /* Construct tangent matrix which matches orientation of the current
+ * displacement grid. */
+ float tangent_matrix[3][3], inv_tangent_matrix[3][3];
+ multires_reshape_tangent_matrix_for_corner(coarse_poly, coarse_corner,
+ dPdu, dPdv,
+ tangent_matrix);
+ invert_m3_m3(inv_tangent_matrix, tangent_matrix);
/* Convert object coordinate to a tangent space of displacement grid. */
float D[3];
sub_v3_v3v3(D, final_P, P);
- float tangent_matrix[3][3];
- BKE_multires_construct_tangent_matrix(
- tangent_matrix, dPdu, dPdv, grid_corner);
- float inv_tangent_matrix[3][3];
- invert_m3_m3(inv_tangent_matrix, tangent_matrix);
float tangent_D[3];
mul_v3_m3v3(tangent_D, inv_tangent_matrix, D);
- /* Write tangent displacement. */
+ /* Calculate index of element within the grid. */
+ float grid_u, grid_v;
+ BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
const int grid_x = (grid_u * (grid_size - 1) + 0.5f);
const int grid_y = (grid_v * (grid_size - 1) + 0.5f);
const int index = grid_y * grid_size + grid_x;
+ /* Write tangent displacement. */
+ MDisps *displacement_grid = &ctx->mdisps[loop_index];
copy_v3_v3(displacement_grid->disps[index], tangent_D);
/* Write mask grid. */
- if (grid_paint_mask != NULL) {
+ if (ctx->grid_paint_mask != NULL) {
+ GridPaintMask *grid_paint_mask = &ctx->grid_paint_mask[loop_index];
+ BLI_assert(grid_paint_mask->level == displacement_grid->level);
grid_paint_mask->data[index] = final_mask;
}
- /* Copy boundary to the next/previous grids.
- *
- * NOTE: Only do this for quads faces, since other ones will call reshape
- * for every boundary vertex, ensuring proper continuity across boundaries.
- */
- if (coarse_poly->totloop == 4) {
- copy_boundary_displacement(
- ctx, coarse_poly, face_corner, grid_x, grid_y,
- displacement_grid, grid_paint_mask);
- }
}
/* =============================================================================
@@ -779,11 +700,25 @@ static void multires_reshape_vertex(
const int subdiv_vertex_index)
{
const float *final_P = ctx->deformed_verts[subdiv_vertex_index];
+ const Mesh *coarse_mesh = ctx->reshape_ctx.coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
+ float corner_u, corner_v;
+ int actual_coarse_corner;
+ if (coarse_poly->totloop == 4) {
+ actual_coarse_corner = BKE_subdiv_rotate_quad_to_corner(
+ u, v, &corner_u, &corner_v);
+ }
+ else {
+ actual_coarse_corner = coarse_corner;
+ corner_u = u;
+ corner_v = v;
+ }
multires_reshape_vertex_from_final_data(
&ctx->reshape_ctx,
- ptex_face_index, u, v,
+ ptex_face_index, corner_u, corner_v,
coarse_poly_index,
- coarse_corner,
+ actual_coarse_corner,
final_P, 0.0f);
}
@@ -1037,72 +972,35 @@ typedef struct ReshapeFromCCGTaskData {
/*const*/ CCGElem **grids;
} ReshapeFromCCGTaskData;
-static void reshape_from_ccg_regular_face(ReshapeFromCCGTaskData *data,
- const MPoly *coarse_poly)
-{
- const CCGKey *key = data->key;
- /*const*/ CCGElem **grids = data->grids;
- const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const int key_grid_size = key->grid_size;
- const int key_grid_size_1 = key_grid_size - 1;
- const int resolution = 2 * key_grid_size - 1;
- const float resolution_1_inv = 1.0f / (float)(resolution - 1);
- const int coarse_poly_index = coarse_poly - coarse_mpoly;
- const int ptex_face_index = data->face_ptex_offset[coarse_poly_index];
- for (int y = 0; y < resolution; y++) {
- const float v = y * resolution_1_inv;
- for (int x = 0; x < resolution; x++) {
- const float u = x * resolution_1_inv;
- float corner_u, corner_v;
- float grid_u, grid_v;
- const int face_corner = BKE_subdiv_rotate_quad_to_corner(
- u, v, &corner_u, &corner_v);
- BKE_subdiv_ptex_face_uv_to_grid_uv(
- corner_u, corner_v, &grid_u, &grid_v);
- /*const*/ CCGElem *grid =
- grids[coarse_poly->loopstart + face_corner];
- /*const*/ CCGElem *grid_element = CCG_grid_elem(
- key,
- grid,
- key_grid_size_1 * grid_u,
- key_grid_size_1 * grid_v);
- const float *final_P = CCG_elem_co(key, grid_element);
- float final_mask = 0.0f;
- if (key->has_mask) {
- final_mask = *CCG_elem_mask(key, grid_element);
- }
- multires_reshape_vertex_from_final_data(
- &data->reshape_ctx,
- ptex_face_index,
- u, v,
- coarse_poly_index,
- 0,
- final_P, final_mask);
- }
- }
-}
-
-static void reshape_from_ccg_special_face(ReshapeFromCCGTaskData *data,
- const MPoly *coarse_poly)
+static void reshape_from_ccg_task(
+ void *__restrict userdata,
+ const int coarse_poly_index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
+ ReshapeFromCCGTaskData *data = userdata;
const CCGKey *key = data->key;
/*const*/ CCGElem **grids = data->grids;
const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
const int key_grid_size = key->grid_size;
const int key_grid_size_1 = key_grid_size - 1;
const int resolution = key_grid_size;
const float resolution_1_inv = 1.0f / (float)(resolution - 1);
- const int coarse_poly_index = coarse_poly - coarse_mpoly;
- const int ptex_face_index = data->face_ptex_offset[coarse_poly_index];
+ const int start_ptex_face_index = data->face_ptex_offset[coarse_poly_index];
+ const bool is_quad = (coarse_poly->totloop == 4);
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
for (int y = 0; y < resolution; y++) {
- const float v = y * resolution_1_inv;
+ const float corner_v = y * resolution_1_inv;
for (int x = 0; x < resolution; x++) {
- const float u = x * resolution_1_inv;
+ const float corner_u = x * resolution_1_inv;
+ /* Quad faces consists of a single ptex face. */
+ const int ptex_face_index =
+ is_quad ? start_ptex_face_index
+ : start_ptex_face_index + corner;
float grid_u, grid_v;
- BKE_subdiv_ptex_face_uv_to_grid_uv(u, v, &grid_u, &grid_v);
+ BKE_subdiv_ptex_face_uv_to_grid_uv(
+ corner_u, corner_v, &grid_u, &grid_v);
/*const*/ CCGElem *grid =
grids[coarse_poly->loopstart + corner];
/*const*/ CCGElem *grid_element = CCG_grid_elem(
@@ -1117,8 +1015,8 @@ static void reshape_from_ccg_special_face(ReshapeFromCCGTaskData *data,
}
multires_reshape_vertex_from_final_data(
&data->reshape_ctx,
- ptex_face_index + corner,
- u, v,
+ ptex_face_index,
+ corner_u, corner_v,
coarse_poly_index,
corner,
final_P, final_mask);
@@ -1127,23 +1025,6 @@ static void reshape_from_ccg_special_face(ReshapeFromCCGTaskData *data,
}
}
-static void reshape_from_ccg_task(
- void *__restrict userdata,
- const int coarse_poly_index,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- ReshapeFromCCGTaskData *data = userdata;
- const Mesh *coarse_mesh = data->reshape_ctx.coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- if (coarse_poly->totloop == 4) {
- reshape_from_ccg_regular_face(data, coarse_poly);
- }
- else {
- reshape_from_ccg_special_face(data, coarse_poly);
- }
-}
-
bool multiresModifier_reshapeFromCCG(
const int tot_level,
Mesh *coarse_mesh,