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-08-14 18:05:54 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2018-08-15 16:40:08 +0300
commit913b8396d971f258df70827274bcdf86dd894185 (patch)
tree56b0a0f53752ed26da0ea1580a26bfe41490310d /source/blender/blenkernel/intern/subdiv_mesh.c
parent5a89dfe06baa2ab96947bb6b5f6c63c4b864fab2 (diff)
Multires: Initial groundwork to hook up displacement to new Subdiv object
Adds a displacement support for OpenSubdiov based subsurf object implemented as a callback which gives vector displacement in object space. Currently is implemented to calculate displacement based on myltires displacement grids, but we can support things in the future if needed. Submitting to review to see if there is something obviously wrong in the direction (old multires code was sharing same displacement code to both calculate final displaced mesh and reshape an existing one, which is rather confusing and probably can be done more cleanly?). Reviewers: brecht Reviewed By: brecht Differential Revision: https://developer.blender.org/D3604
Diffstat (limited to 'source/blender/blenkernel/intern/subdiv_mesh.c')
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c291
1 files changed, 287 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 3d948dc9508..c8f67c2a893 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -668,6 +668,50 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
}
/* =============================================================================
+ * Helper evaluation functions.
+ */
+
+static void eval_final_point_and_vertex_normal(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ float r_P[3], short r_N[3])
+{
+ if (subdiv->displacement_evaluator == NULL) {
+ BKE_subdiv_eval_limit_point_and_short_normal(
+ subdiv, ptex_face_index, u, v, r_P, r_N);
+ }
+ else {
+ BKE_subdiv_eval_final_point(
+ subdiv, ptex_face_index, u, v, r_P);
+ }
+}
+
+/* =============================================================================
+ * Displacement helpers
+ */
+
+static void subdiv_accumulate_vertex_displacement(
+ Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u, const float v,
+ MVert *subdiv_vert)
+{
+ float dummy_P[3], dPdu[3], dPdv[3], D[3];
+ BKE_subdiv_eval_limit_point_and_derivatives(
+ subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
+ BKE_subdiv_eval_displacement(subdiv,
+ ptex_face_index, u, v,
+ dPdu, dPdv,
+ D);
+ add_v3_v3(subdiv_vert->co, D);
+ if (subdiv_vert->flag & ME_VERT_TMP_TAG) {
+ mul_v3_fl(subdiv_vert->co, 0.5f);
+ }
+ subdiv_vert->flag |= ME_VERT_TMP_TAG;
+}
+
+/* =============================================================================
* Vertex subdivision process.
*/
@@ -682,6 +726,7 @@ static void subdiv_vertex_data_copy(
Mesh *subdiv_mesh = ctx->subdiv_mesh;
const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
+ subdiv_vertex->flag &= ~ME_VERT_TMP_TAG;
CustomData_copy_data(&coarse_mesh->vdata,
&ctx->subdiv_mesh->vdata,
coarse_vertex_index,
@@ -700,6 +745,7 @@ static void subdiv_vertex_data_interpolate(
u * (1.0f - v),
u * v,
(1.0f - u) * v};
+ subdiv_vertex->flag &= ~ME_VERT_TMP_TAG;
CustomData_interp(vertex_interpolation->vertex_data,
&ctx->subdiv_mesh->vdata,
vertex_interpolation->vertex_indices,
@@ -711,6 +757,7 @@ static void subdiv_vertex_data_interpolate(
}
}
+
/* Evaluation of corner vertices. They are coming from coarse vertices. */
static void subdiv_evaluate_corner_vertices_regular(
@@ -740,12 +787,19 @@ static void subdiv_evaluate_corner_vertices_regular(
const MVert *coarse_vert = &coarse_mvert[coarse_loop->v];
MVert *subdiv_vert = &subdiv_mvert[
ctx->vertices_corner_offset + coarse_loop->v];
+ /* Displacement is accumulated in subdiv vertex position.
+ * need to back it up before copying data fro original vertex.
+ */
+ float D[3];
+ copy_v3_v3(D, subdiv_vert->co);
subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
BKE_subdiv_eval_limit_point_and_short_normal(
subdiv,
ptex_face_index,
weights[corner][0], weights[corner][1],
subdiv_vert->co, subdiv_vert->no);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
}
}
@@ -775,12 +829,19 @@ static void subdiv_evaluate_corner_vertices_special(
const MVert *coarse_vert = &coarse_mvert[coarse_loop->v];
MVert *subdiv_vert = &subdiv_mvert[
ctx->vertices_corner_offset + coarse_loop->v];
+ /* Displacement is accumulated in subdiv vertex position.
+ * need to back it up before copying data fro original vertex.
+ */
+ float D[3];
+ copy_v3_v3(D, subdiv_vert->co);
subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
BKE_subdiv_eval_limit_point_and_short_normal(
subdiv,
ptex_face_index,
0.0f, 0.0f,
subdiv_vert->co, subdiv_vert->no);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
}
}
@@ -795,6 +856,76 @@ static void subdiv_evaluate_corner_vertices(SubdivMeshContext *ctx,
}
}
+static void subdiv_displace_corner_vertices_regular(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const float weights[4][2] = {{0.0f, 0.0f},
+ {1.0f, 0.0f},
+ {1.0f, 1.0f},
+ {0.0f, 1.0f}};
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_corner_offset + coarse_loop->v];
+ const float u = weights[corner][0];
+ const float v = weights[corner][1];
+ subdiv_accumulate_vertex_displacement(
+ subdiv, ptex_face_index, u, v, subdiv_vert);
+ }
+}
+
+static void subdiv_displace_corner_vertices_special(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++, ptex_face_index++)
+ {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_corner_offset + coarse_loop->v];
+ subdiv_accumulate_vertex_displacement(
+ subdiv, ptex_face_index, 0.0f, 0.0f, subdiv_vert);
+ }
+}
+
+static void subdiv_displace_corner_vertices(SubdivMeshContext *ctx)
+{
+ Subdiv *subdiv = ctx->subdiv;
+ if (subdiv->displacement_evaluator == NULL) {
+ return;
+ }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ if (coarse_poly->totloop == 4) {
+ subdiv_displace_corner_vertices_regular(ctx, coarse_poly);
+ }
+ else {
+ subdiv_displace_corner_vertices_special(ctx, coarse_poly);
+ }
+ }
+}
+
/* Evaluation of edge vertices. They are coming from coarse edges. */
static void subdiv_evaluate_edge_vertices_regular(
@@ -851,6 +982,11 @@ static void subdiv_evaluate_edge_vertices_regular(
u = (corner == 1) ? 1.0f : 0.0f;
v = fac;
}
+ /* Displacement is accumulated in subdiv vertex position.
+ * need to back it up before copying data fro original vertex.
+ */
+ float D[3];
+ copy_v3_v3(D, subdiv_vert->co);
subdiv_vertex_data_interpolate(ctx,
subdiv_vert,
vertex_interpolation,
@@ -860,6 +996,8 @@ static void subdiv_evaluate_edge_vertices_regular(
ptex_face_index,
u, v,
subdiv_vert->co, subdiv_vert->no);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
}
}
}
@@ -913,6 +1051,11 @@ static void subdiv_evaluate_edge_vertices_special(
vertex_index++, subdiv_vert += veretx_delta)
{
float u = vertex_index * inv_ptex_resolution_1;
+ /* Displacement is accumulated in subdiv vertex position.
+ * need to back it up before copying data fro original vertex.
+ */
+ float D[3];
+ copy_v3_v3(D, subdiv_vert->co);
subdiv_vertex_data_interpolate(ctx,
subdiv_vert,
vertex_interpolation,
@@ -922,6 +1065,8 @@ static void subdiv_evaluate_edge_vertices_special(
ptex_face_index,
u, 0.0f,
subdiv_vert->co, subdiv_vert->no);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
}
const int next_ptex_face_index =
ptex_face_start_index + (corner + 1) % coarse_poly->totloop;
@@ -930,6 +1075,11 @@ static void subdiv_evaluate_edge_vertices_special(
vertex_index++, subdiv_vert += veretx_delta)
{
float v = 1.0f - vertex_index * inv_ptex_resolution_1;
+ /* Displacement is accumulated in subdiv vertex position.
+ * need to back it up before copying data fro original vertex.
+ */
+ float D[3];
+ copy_v3_v3(D, subdiv_vert->co);
subdiv_vertex_data_interpolate(ctx,
subdiv_vert,
vertex_interpolation,
@@ -939,6 +1089,8 @@ static void subdiv_evaluate_edge_vertices_special(
next_ptex_face_index,
0.0f, v,
subdiv_vert->co, subdiv_vert->no);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
}
}
}
@@ -958,6 +1110,129 @@ static void subdiv_evaluate_edge_vertices(
}
}
+static void subdiv_displace_edge_vertices_regular(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const int resolution = ctx->settings->resolution;
+ const int resolution_1 = resolution - 1;
+ const float inv_resolution_1 = 1.0f / (float)resolution_1;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_index = ctx->face_ptex_offset[poly_index];
+ for (int corner = 0; corner < coarse_poly->totloop; corner++) {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
+ for (int vertex_index = 0;
+ vertex_index < num_subdiv_vertices_per_coarse_edge;
+ vertex_index++, subdiv_vert++)
+ {
+ float fac = (vertex_index + 1) * inv_resolution_1;
+ if (flip) {
+ fac = 1.0f - fac;
+ }
+ if (corner >= 2) {
+ fac = 1.0f - fac;
+ }
+ float u, v;
+ if ((corner & 1) == 0) {
+ u = fac;
+ v = (corner == 2) ? 1.0f : 0.0f;
+ }
+ else {
+ u = (corner == 1) ? 1.0f : 0.0f;
+ v = fac;
+ }
+ subdiv_accumulate_vertex_displacement(
+ subdiv, ptex_face_index, u, v, subdiv_vert);
+ }
+ }
+}
+
+static void subdiv_displace_edge_vertices_special(
+ SubdivMeshContext *ctx,
+ const MPoly *coarse_poly)
+{
+ const int resolution = ctx->settings->resolution;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+ const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1);
+ const float inv_ptex_resolution_1 =
+ 1.0f / (float)(num_vertices_per_ptex_edge - 1);
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const int poly_index = coarse_poly - coarse_mesh->mpoly;
+ const int ptex_face_start_index = ctx->face_ptex_offset[poly_index];
+ int ptex_face_index = ptex_face_start_index;
+ for (int corner = 0;
+ corner < coarse_poly->totloop;
+ corner++, ptex_face_index++)
+ {
+ const MLoop *coarse_loop =
+ &coarse_mloop[coarse_poly->loopstart + corner];
+ const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
+ const bool flip = (coarse_edge->v2 == coarse_loop->v);
+ MVert *subdiv_vert = &subdiv_mvert[
+ ctx->vertices_edge_offset +
+ coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
+ int veretx_delta = 1;
+ if (flip) {
+ subdiv_vert += num_subdiv_vertices_per_coarse_edge - 1;
+ veretx_delta = -1;
+ }
+ for (int vertex_index = 1;
+ vertex_index < num_vertices_per_ptex_edge;
+ vertex_index++, subdiv_vert += veretx_delta)
+ {
+ float u = vertex_index * inv_ptex_resolution_1;
+ subdiv_accumulate_vertex_displacement(
+ subdiv, ptex_face_index, u, 0.0f, subdiv_vert);
+ }
+ const int next_ptex_face_index =
+ ptex_face_start_index + (corner + 1) % coarse_poly->totloop;
+ for (int vertex_index = 1;
+ vertex_index < num_vertices_per_ptex_edge - 1;
+ vertex_index++, subdiv_vert += veretx_delta)
+ {
+ float v = 1.0f - vertex_index * inv_ptex_resolution_1;
+ subdiv_accumulate_vertex_displacement(
+ subdiv, next_ptex_face_index, 0.0f, v, subdiv_vert);
+ }
+ }
+}
+static void subdiv_displace_edge_vertices(SubdivMeshContext *ctx)
+{
+ Subdiv *subdiv = ctx->subdiv;
+ if (subdiv->displacement_evaluator == NULL) {
+ return;
+ }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
+ const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+ if (coarse_poly->totloop == 4) {
+ subdiv_displace_edge_vertices_regular(ctx, coarse_poly);
+ }
+ else {
+ subdiv_displace_edge_vertices_special(ctx, coarse_poly);
+ }
+ }
+}
+
/* Evaluation of inner vertices, they are coming from ptex patches. */
static void subdiv_evaluate_inner_vertices_regular(
@@ -988,7 +1263,7 @@ static void subdiv_evaluate_inner_vertices_regular(
subdiv_vert,
vertex_interpolation,
u, v);
- BKE_subdiv_eval_limit_point_and_short_normal(
+ eval_final_point_and_vertex_normal(
subdiv,
ptex_face_index,
u, v,
@@ -1024,7 +1299,7 @@ static void subdiv_evaluate_inner_vertices_special(
subdiv_vert,
vertex_interpolation,
1.0f, 1.0f);
- BKE_subdiv_eval_limit_point_and_short_normal(
+ eval_final_point_and_vertex_normal(
subdiv,
ptex_face_index,
1.0f, 1.0f,
@@ -1048,7 +1323,7 @@ static void subdiv_evaluate_inner_vertices_special(
subdiv_vert,
vertex_interpolation,
u, v);
- BKE_subdiv_eval_limit_point_and_short_normal(
+ eval_final_point_and_vertex_normal(
subdiv,
ptex_face_index,
u, v,
@@ -2415,9 +2690,14 @@ Mesh *BKE_subdiv_to_mesh(
ctx.subdiv_mesh = result;
subdiv_mesh_ctx_init_result(&ctx);
/* Multi-threaded evaluation. */
- ParallelRangeSettings parallel_range_settings;
BKE_subdiv_stats_begin(&subdiv->stats,
SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
+ /* Single threaded passes to average displacement on the corner vertices
+ * and boundary edges.
+ */
+ subdiv_displace_corner_vertices(&ctx);
+ subdiv_displace_edge_vertices(&ctx);
+ ParallelRangeSettings parallel_range_settings;
BLI_parallel_range_settings_defaults(&parallel_range_settings);
BLI_task_parallel_range(0, coarse_mesh->totpoly,
&ctx,
@@ -2439,5 +2719,8 @@ Mesh *BKE_subdiv_to_mesh(
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
// BKE_mesh_validate(result, true, true);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
+ if (subdiv->displacement_evaluator != NULL) {
+ result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+ }
return result;
}