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:
Diffstat (limited to 'source/blender/blenkernel/intern/subdiv_mesh.c')
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c102
1 files changed, 16 insertions, 86 deletions
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 5bf519e5f70..c334d9a2c33 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -21,6 +21,7 @@
* \ingroup bke
*/
+#include "BKE_mesh.h"
#include "BKE_subdiv_mesh.h"
#include "atomic_ops.h"
@@ -58,23 +59,8 @@ typedef struct SubdivMeshContext {
/* UV layers interpolation. */
int num_uv_layers;
MLoopUV *uv_layers[MAX_MTFACE];
- /* Accumulated values.
- *
- * Averaging is happening for vertices along the coarse edges and corners.
- * This is needed for both displacement and normals.
- *
- * Displacement is being accumulated to a vertices coordinates, since those
- * are not needed during traversal of edge/corner vertices.
- *
- * For normals we are using dedicated array, since we can not use same
- * vertices (normals are `short`, which will cause a lot of precision
- * issues). */
- float (*accumulated_normals)[3];
/* Per-subdivided vertex counter of averaged values. */
int *accumulated_counters;
- /* Denotes whether normals can be evaluated from a limit surface. One case
- * when it's not possible is when displacement is used. */
- bool can_evaluate_normals;
bool have_displacement;
} SubdivMeshContext;
@@ -102,20 +88,12 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
{
- if (!ctx->can_evaluate_normals && !ctx->have_displacement) {
- return;
- }
- /* TODO(sergey): Technically, this is overallocating, we don't need memory
- * for an inner subdivision vertices. */
- ctx->accumulated_normals = MEM_calloc_arrayN(
- num_vertices, sizeof(*ctx->accumulated_normals), "subdiv accumulated normals");
ctx->accumulated_counters = MEM_calloc_arrayN(
num_vertices, sizeof(*ctx->accumulated_counters), "subdiv accumulated counters");
}
static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
{
- MEM_SAFE_FREE(ctx->accumulated_normals);
MEM_SAFE_FREE(ctx->accumulated_counters);
}
@@ -450,48 +428,23 @@ static void subdiv_mesh_tls_free(void *tls_v)
/** \} */
-/* -------------------------------------------------------------------- */
-/** \name Evaluation helper 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);
- }
-}
-
/** \} */
/* -------------------------------------------------------------------- */
/** \name Accumulation helpers
* \{ */
-static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext *ctx,
- const int ptex_face_index,
- const float u,
- const float v,
- MVert *subdiv_vert)
+static void subdiv_accumulate_vertex_displacement(SubdivMeshContext *ctx,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ MVert *subdiv_vert)
{
Subdiv *subdiv = ctx->subdiv;
const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
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);
- /* Accumulate normal. */
- if (ctx->can_evaluate_normals) {
- float N[3];
- cross_v3_v3v3(N, dPdu, dPdv);
- normalize_v3(N);
- add_v3_v3(ctx->accumulated_normals[subdiv_vertex_index], N);
- }
+
/* Accumulate displacement if needed. */
if (ctx->have_displacement) {
/* NOTE: The subdivided mesh is allocated in this module, and its vertices are kept at zero
@@ -589,13 +542,6 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
/* Apply displacement. */
add_v3_v3(subdiv_vert->co, D);
- /* Copy normal from accumulated storage. */
- if (ctx->can_evaluate_normals) {
- float N[3];
- copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
- normalize_v3(N);
- normal_float_to_short_v3(subdiv_vert->no, N);
- }
/* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
subdiv_vert->flag &= ~ME_VERT_FACEDOT;
}
@@ -622,15 +568,6 @@ static void evaluate_vertex_and_apply_displacement_interpolate(
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
/* Apply displacement. */
add_v3_v3(subdiv_vert->co, D);
- /* Copy normal from accumulated storage. */
- if (ctx->can_evaluate_normals) {
- const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
- float N[3];
- copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
- mul_v3_fl(N, inv_num_accumulated);
- normalize_v3(N);
- normal_float_to_short_v3(subdiv_vert->no, N);
- }
}
static void subdiv_mesh_vertex_every_corner_or_edge(const SubdivForeachContext *foreach_context,
@@ -644,7 +581,7 @@ static void subdiv_mesh_vertex_every_corner_or_edge(const SubdivForeachContext *
Mesh *subdiv_mesh = ctx->subdiv_mesh;
MVert *subdiv_mvert = subdiv_mesh->mvert;
MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
- subdiv_accumulate_vertex_normal_and_displacement(ctx, ptex_face_index, u, v, subdiv_vert);
+ subdiv_accumulate_vertex_displacement(ctx, ptex_face_index, u, v, subdiv_vert);
}
static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_context,
@@ -793,8 +730,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly, coarse_corner);
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
- eval_final_point_and_vertex_normal(
- subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
+ BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_vert->co);
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v);
}
@@ -1141,12 +1077,6 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *
/* TODO(sergey): This matches old behavior, but we can as well interpolate
* it. Maybe even using vertex varying attributes. */
subdiv_vertex->bweight = 0.0f;
- /* Reset normal, initialize it in a similar way as edit mode does for a
- * vertices adjacent to a loose edges.
- * See `mesh_evaluate#mesh_calc_normals_vert_fallback` */
- float no[3];
- normalize_v3_v3(no, subdiv_vertex->co);
- normal_float_to_short_v3(subdiv_vertex->no, no);
}
/** \} */
@@ -1161,8 +1091,8 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
memset(foreach_context, 0, sizeof(*foreach_context));
/* General information. */
foreach_context->topology_info = subdiv_mesh_topology_info;
- /* Every boundary geometry. Used for displacement and normals averaging. */
- if (subdiv_context->can_evaluate_normals || subdiv_context->have_displacement) {
+ /* Every boundary geometry. Used for displacement averaging. */
+ if (subdiv_context->have_displacement) {
foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
}
@@ -1212,8 +1142,6 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
subdiv_context.coarse_mesh = coarse_mesh;
subdiv_context.subdiv = subdiv;
subdiv_context.have_displacement = (subdiv->displacement_evaluator != NULL);
- subdiv_context.can_evaluate_normals = !subdiv_context.have_displacement &&
- subdiv_context.subdiv->settings.is_adaptive;
/* Multi-threaded traversal/evaluation. */
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
SubdivForeachContext foreach_context;
@@ -1227,9 +1155,11 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
Mesh *result = subdiv_context.subdiv_mesh;
// BKE_mesh_validate(result, true, true);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
- if (!subdiv_context.can_evaluate_normals) {
- BKE_mesh_normals_tag_dirty(result);
- }
+ /* Using normals from the limit surface gives different results than Blender's vertex normal
+ * calculation. Since vertex normals are supposed to be a consistent cache, don't bother
+ * calculating them here. The work may have been pointless anyway if the mesh is deformed or
+ * changed afterwards. */
+ BKE_mesh_normals_tag_dirty(result);
/* Free used memory. */
subdiv_mesh_context_free(&subdiv_context);
return result;