diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_subdiv_eval.h | 11 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.cc | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/multires_reshape_smooth.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subdiv_eval.c | 54 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subdiv_mesh.c | 39 |
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); } /** \} */ |