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:
authorBrecht Van Lommel <brecht@blender.org>2021-01-14 18:33:52 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-05-18 17:45:38 +0300
commit342e12d6d92198bba8355562600a2f97bb45fed5 (patch)
treea5f1e10205e7d66e5c6672fb416883a04475782c /source/blender/blenkernel
parentf517b3a29568fd43b722973c7c46d3c358ba0dda (diff)
Subdiv: support interpolating orco coordinates in subdivision surfaces
This makes changes to the opensubdiv module to support additional vertex data besides the vertex position, that is smootly interpolated the same way. This is different than varying data which is interpolated linearly. Fixes T96596: wrong generated texture coordinates with GPU subdivision. In that bug lazy subdivision would not interpolate orcos. Later on, this implementation can also be used to remove the modifier stack mechanism where modifiers are evaluated a second time for orcos, which is messy and inefficient. But that's a more risky change, this is just the part to fix the bug in 3.2. Differential Revision: https://developer.blender.org/D14973
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_subdiv_eval.h11
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc4
-rw-r--r--source/blender/blenkernel/intern/multires_reshape_smooth.c4
-rw-r--r--source/blender/blenkernel/intern/subdiv_eval.c54
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c39
5 files changed, 107 insertions, 5 deletions
diff --git a/source/blender/blenkernel/BKE_subdiv_eval.h b/source/blender/blenkernel/BKE_subdiv_eval.h
index a33140b721d..7673f18317a 100644
--- a/source/blender/blenkernel/BKE_subdiv_eval.h
+++ b/source/blender/blenkernel/BKE_subdiv_eval.h
@@ -15,6 +15,7 @@ extern "C" {
struct Mesh;
struct OpenSubdiv_EvaluatorCache;
+struct OpenSubdiv_EvaluatorSettings;
struct Subdiv;
typedef enum eSubdivEvaluatorType {
@@ -25,7 +26,8 @@ typedef enum eSubdivEvaluatorType {
/* Returns true if evaluator is ready for use. */
bool BKE_subdiv_eval_begin(struct Subdiv *subdiv,
eSubdivEvaluatorType evaluator_type,
- struct OpenSubdiv_EvaluatorCache *evaluator_cache);
+ struct OpenSubdiv_EvaluatorCache *evaluator_cache,
+ const struct OpenSubdiv_EvaluatorSettings *settings);
/* coarse_vertex_cos is an optional argument which allows to override coordinates of the coarse
* mesh. */
@@ -60,6 +62,13 @@ void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv,
void BKE_subdiv_eval_limit_point_and_normal(
struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3]);
+/* Evaluate smoothly interpolated vertex data (such as orco). */
+void BKE_subdiv_eval_vertex_data(struct Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ float r_vertex_data[]);
+
/* Evaluate face-varying layer (such as UV). */
void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv,
int face_varying_channel,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 7ca76e72839..6b43fe57e93 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -1180,6 +1180,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_id_free(nullptr, mesh_orco_cloth);
}
+ /* Remove temporary data layer only needed for modifier evaluation.
+ * Save some memory, and ensure GPU subdivision does not need to deal with this. */
+ CustomData_free_layers(&mesh_final->vdata, CD_CLOTH_ORCO, mesh_final->totvert);
+
/* Compute normals. */
if (is_own_mesh) {
mesh_calc_modifier_final_normals(mesh_input, &final_datamask, sculpt_dyntopo, mesh_final);
diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c
index b76e2b3aec6..8246de12ebf 100644
--- a/source/blender/blenkernel/intern/multires_reshape_smooth.c
+++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c
@@ -1073,7 +1073,9 @@ static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_c
converter_init(reshape_smooth_context, &converter);
Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter);
- BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, NULL);
+
+ OpenSubdiv_EvaluatorSettings evaluator_settings = {0};
+ BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, NULL, &evaluator_settings);
reshape_smooth_context->reshape_subdiv = reshape_subdiv;
diff --git a/source/blender/blenkernel/intern/subdiv_eval.c b/source/blender/blenkernel/intern/subdiv_eval.c
index 9edd9815400..d03c0f89948 100644
--- a/source/blender/blenkernel/intern/subdiv_eval.c
+++ b/source/blender/blenkernel/intern/subdiv_eval.c
@@ -44,7 +44,8 @@ static eOpenSubdivEvaluator opensubdiv_evalutor_from_subdiv_evaluator_type(
bool BKE_subdiv_eval_begin(Subdiv *subdiv,
eSubdivEvaluatorType evaluator_type,
- OpenSubdiv_EvaluatorCache *evaluator_cache)
+ OpenSubdiv_EvaluatorCache *evaluator_cache,
+ const OpenSubdiv_EvaluatorSettings *settings)
{
BKE_subdiv_stats_reset(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
if (subdiv->topology_refiner == NULL) {
@@ -57,7 +58,7 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv,
opensubdiv_evalutor_from_subdiv_evaluator_type(evaluator_type);
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
subdiv->evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(
- subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache);
+ subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache, settings);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
if (subdiv->evaluator == NULL) {
return false;
@@ -179,13 +180,52 @@ static void set_face_varying_data_from_uv(Subdiv *subdiv,
MEM_freeN(buffer);
}
+static void set_vertex_data_from_orco(Subdiv *subdiv, const Mesh *mesh)
+{
+ const float(*orco)[3] = CustomData_get_layer(&mesh->vdata, CD_ORCO);
+ const float(*cloth_orco)[3] = CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO);
+
+ if (orco || cloth_orco) {
+ OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
+ OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
+ const int num_verts = topology_refiner->getNumVertices(topology_refiner);
+
+ if (orco && cloth_orco) {
+ /* Set one by one if have both. */
+ for (int i = 0; i < num_verts; i++) {
+ float data[6];
+ copy_v3_v3(data, orco[i]);
+ copy_v3_v3(data + 3, cloth_orco[i]);
+ evaluator->setVertexData(evaluator, data, i, 1);
+ }
+ }
+ else {
+ /* Faster single call if we have either. */
+ if (orco) {
+ evaluator->setVertexData(evaluator, orco[0], 0, num_verts);
+ }
+ else if (cloth_orco) {
+ evaluator->setVertexData(evaluator, cloth_orco[0], 0, num_verts);
+ }
+ }
+ }
+}
+
+static void get_mesh_evaluator_settings(OpenSubdiv_EvaluatorSettings *settings, const Mesh *mesh)
+{
+ settings->num_vertex_data = (CustomData_has_layer(&mesh->vdata, CD_ORCO) ? 3 : 0) +
+ (CustomData_has_layer(&mesh->vdata, CD_CLOTH_ORCO) ? 3 : 0);
+}
+
bool BKE_subdiv_eval_begin_from_mesh(Subdiv *subdiv,
const Mesh *mesh,
const float (*coarse_vertex_cos)[3],
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
- if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache)) {
+ OpenSubdiv_EvaluatorSettings settings = {0};
+ get_mesh_evaluator_settings(&settings, mesh);
+ if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache, &settings)) {
return false;
}
return BKE_subdiv_eval_refine_from_mesh(subdiv, mesh, coarse_vertex_cos);
@@ -208,6 +248,8 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
set_face_varying_data_from_uv(subdiv, mesh, mloopuv, layer_index);
}
+ /* Set vertex data to orco. */
+ set_vertex_data_from_orco(subdiv, mesh);
/* Update evaluator to the new coarse geometry. */
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
subdiv->evaluator->refine(subdiv->evaluator);
@@ -281,6 +323,12 @@ void BKE_subdiv_eval_limit_point_and_normal(Subdiv *subdiv,
normalize_v3(r_N);
}
+void BKE_subdiv_eval_vertex_data(
+ Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_vertex_data[])
+{
+ subdiv->evaluator->evaluateVertexData(subdiv->evaluator, ptex_face_index, u, v, r_vertex_data);
+}
+
void BKE_subdiv_eval_face_varying(Subdiv *subdiv,
const int face_varying_channel,
const int ptex_face_index,
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 83427adcb43..e846dc2d807 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -44,6 +44,9 @@ typedef struct SubdivMeshContext {
/* UV layers interpolation. */
int num_uv_layers;
MLoopUV *uv_layers[MAX_MTFACE];
+ /* Orco interpolation. */
+ float (*orco)[3];
+ float (*cloth_orco)[3];
/* Per-subdivided vertex counter of averaged values. */
int *accumulated_counters;
bool have_displacement;
@@ -69,6 +72,9 @@ static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
ctx->poly_origindex = CustomData_get_layer(&subdiv_mesh->pdata, CD_ORIGINDEX);
/* UV layers interpolation. */
subdiv_mesh_ctx_cache_uv_layers(ctx);
+ /* Orco interpolation. */
+ ctx->orco = CustomData_get_layer(&subdiv_mesh->vdata, CD_ORCO);
+ ctx->cloth_orco = CustomData_get_layer(&subdiv_mesh->vdata, CD_CLOTH_ORCO);
}
static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
@@ -417,6 +423,34 @@ static void subdiv_mesh_tls_free(void *tls_v)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Evaluation helper functions
+ * \{ */
+
+static void subdiv_vertex_orco_evaluate(const SubdivMeshContext *ctx,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int subdiv_vertex_index)
+{
+ if (ctx->orco || ctx->cloth_orco) {
+ float vertex_data[6];
+ BKE_subdiv_eval_vertex_data(ctx->subdiv, ptex_face_index, u, v, vertex_data);
+
+ if (ctx->orco) {
+ copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data);
+ if (ctx->cloth_orco) {
+ copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data + 3);
+ }
+ }
+ else if (ctx->cloth_orco) {
+ copy_v3_v3(ctx->orco[subdiv_vertex_index], vertex_data);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Accumulation helpers
* \{ */
@@ -530,6 +564,8 @@ 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);
+ /* Evaluate undeformed texture coordinate. */
+ subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
/* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
BLI_BITMAP_DISABLE(ctx->subdiv_mesh->runtime.subsurf_face_dot_tags, subdiv_vertex_index);
}
@@ -556,6 +592,8 @@ 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);
+ /* Evaluate undeformed texture coordinate. */
+ subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
}
static void subdiv_mesh_vertex_displacement_every_corner_or_edge(
@@ -723,6 +761,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_vert->co);
subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vertex_index, u, v, subdiv_mesh);
+ subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
}
/** \} */