Refactor: Simplify subdiv utilities
- Return evaluated points as function return value. Used in cases when only limit or final point is requested, without partial derivatives. - Re-order function argument list and use default argument values to simplify usage in the simple/typical cases. No functional changes expected.
This commit is contained in:
@@ -278,9 +278,8 @@ inline int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, const
|
||||
return subdiv_ccg.grid_to_face_map[grid_index];
|
||||
}
|
||||
|
||||
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg,
|
||||
const SubdivCCGCoord &coord,
|
||||
blender::float3 &r_point);
|
||||
blender::float3 BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg,
|
||||
const SubdivCCGCoord &coord);
|
||||
void BKE_subdiv_ccg_eval_limit_positions(const SubdivCCG &subdiv_ccg,
|
||||
const CCGKey &key,
|
||||
int grid_index,
|
||||
|
||||
@@ -35,9 +35,9 @@ bool eval_begin(Subdiv *subdiv,
|
||||
*/
|
||||
bool eval_begin_from_mesh(Subdiv *subdiv,
|
||||
const Mesh *mesh,
|
||||
Span<float3> coarse_vert_positions,
|
||||
eSubdivEvaluatorType evaluator_type,
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache);
|
||||
Span<float3> coarse_vert_positions = {},
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache = nullptr);
|
||||
bool eval_refine_from_mesh(Subdiv *subdiv, const Mesh *mesh, Span<float3> coarse_vert_positions);
|
||||
|
||||
/* Makes sure displacement evaluator is initialized.
|
||||
@@ -50,7 +50,7 @@ void eval_init_displacement(Subdiv *subdiv);
|
||||
|
||||
/* Evaluate point at a limit surface, with optional derivatives and normal. */
|
||||
|
||||
void eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float3 &r_P);
|
||||
float3 eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v);
|
||||
void eval_limit_point_and_derivatives(Subdiv *subdiv,
|
||||
int ptex_face_index,
|
||||
float u,
|
||||
@@ -88,6 +88,6 @@ void eval_displacement(Subdiv *subdiv,
|
||||
float3 &r_D);
|
||||
|
||||
/* Evaluate point on a limit surface with displacement applied to it. */
|
||||
void eval_final_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float3 &r_P);
|
||||
float3 eval_final_point(Subdiv *subdiv, int ptex_face_index, float u, float v);
|
||||
|
||||
} // namespace blender::bke::subdiv
|
||||
|
||||
@@ -98,48 +98,48 @@ struct ForeachContext {
|
||||
*
|
||||
* NOTE: If this callback returns false, the foreach loop is aborted.
|
||||
*/
|
||||
ForeachTopologyInformationCb topology_info;
|
||||
ForeachTopologyInformationCb topology_info = nullptr;
|
||||
/* These callbacks are called from every ptex which shares "emitting"
|
||||
* vertex or edge.
|
||||
*/
|
||||
ForeachVertexFromCornerCb vertex_every_corner;
|
||||
ForeachVertexFromEdgeCb vertex_every_edge;
|
||||
ForeachVertexFromCornerCb vertex_every_corner = nullptr;
|
||||
ForeachVertexFromEdgeCb vertex_every_edge = nullptr;
|
||||
/* Those callbacks are run once per subdivision vertex, ptex is undefined
|
||||
* as in it will be whatever first ptex face happened to be traversed in
|
||||
* the multi-threaded environment and which shares "emitting" vertex or
|
||||
* edge.
|
||||
*/
|
||||
ForeachVertexFromCornerCb vertex_corner;
|
||||
ForeachVertexFromEdgeCb vertex_edge;
|
||||
ForeachVertexFromCornerCb vertex_corner = nullptr;
|
||||
ForeachVertexFromEdgeCb vertex_edge = nullptr;
|
||||
/* Called exactly once, always corresponds to a single ptex face. */
|
||||
ForeachVertexInnerCb vertex_inner;
|
||||
ForeachVertexInnerCb vertex_inner = nullptr;
|
||||
/* Called once for each loose vertex. One loose coarse vertex corresponds
|
||||
* to a single subdivision vertex.
|
||||
*/
|
||||
ForeachLooseCb vertex_loose;
|
||||
ForeachLooseCb vertex_loose = nullptr;
|
||||
/* Called once per vertex created for loose edge. */
|
||||
ForeachVertexOfLooseEdgeCb vertex_of_loose_edge;
|
||||
ForeachVertexOfLooseEdgeCb vertex_of_loose_edge = nullptr;
|
||||
/* NOTE: If subdivided edge does not come from coarse edge, ORIGINDEX_NONE
|
||||
* will be passed as coarse_edge_index.
|
||||
*/
|
||||
ForeachEdgeCb edge;
|
||||
ForeachEdgeCb edge = nullptr;
|
||||
/* NOTE: If subdivided loop does not come from coarse loop, ORIGINDEX_NONE
|
||||
* will be passed as coarse_loop_index.
|
||||
*/
|
||||
ForeachLoopCb loop;
|
||||
ForeachPolygonCb poly;
|
||||
ForeachLoopCb loop = nullptr;
|
||||
ForeachPolygonCb poly = nullptr;
|
||||
|
||||
/* User-defined pointer, to allow callbacks know something about context the
|
||||
* traversal is happening for.
|
||||
*/
|
||||
void *user_data;
|
||||
void *user_data = nullptr;
|
||||
|
||||
/* Initial value of TLS data. */
|
||||
void *user_data_tls;
|
||||
void *user_data_tls = nullptr;
|
||||
/* Size of TLS data. */
|
||||
size_t user_data_tls_size;
|
||||
size_t user_data_tls_size = 0;
|
||||
/* Function to free TLS storage. */
|
||||
void (*user_data_tls_free)(void *tls);
|
||||
void (*user_data_tls_free)(void *tls) = nullptr;
|
||||
};
|
||||
|
||||
/* Invokes callbacks in the order and with values which corresponds to creation
|
||||
|
||||
@@ -25,9 +25,9 @@ struct ToMeshSettings {
|
||||
* created for a corner of non-quad face) will have resolution of
|
||||
* `resolution - 1`.
|
||||
*/
|
||||
int resolution;
|
||||
int resolution = -1;
|
||||
/** When true, only edges emitted from coarse ones will be displayed. */
|
||||
bool use_optimal_display;
|
||||
bool use_optimal_display = false;
|
||||
};
|
||||
|
||||
/** Create real hi-res mesh from subdivision, all geometry is "real". */
|
||||
|
||||
@@ -1319,9 +1319,8 @@ static void evaluate_higher_grid_positions(MultiresReshapeSmoothContext *reshape
|
||||
reshape_context, grid_coord);
|
||||
|
||||
/* Surface. */
|
||||
blender::float3 P;
|
||||
blender::bke::subdiv::eval_limit_point(
|
||||
reshape_subdiv, ptex_coord->ptex_face_index, ptex_coord->u, ptex_coord->v, P);
|
||||
const blender::float3 P = blender::bke::subdiv::eval_limit_point(
|
||||
reshape_subdiv, ptex_coord->ptex_face_index, ptex_coord->u, ptex_coord->v);
|
||||
|
||||
*grid_element.displacement = P;
|
||||
|
||||
|
||||
@@ -56,9 +56,7 @@ blender::bke::subdiv::Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgrap
|
||||
if (!subdiv) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!subdiv::eval_begin_from_mesh(
|
||||
subdiv, base_mesh, {}, subdiv::SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
|
||||
{
|
||||
if (!subdiv::eval_begin_from_mesh(subdiv, base_mesh, subdiv::SUBDIV_EVALUATOR_TYPE_CPU)) {
|
||||
subdiv::free(subdiv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -48,9 +48,7 @@ static blender::bke::subdiv::Subdiv *subdiv_for_simple_to_catmull_clark(Object *
|
||||
subdiv::Subdiv *subdiv = subdiv::new_from_converter(&subdiv_settings, &converter);
|
||||
subdiv::converter_free(&converter);
|
||||
|
||||
if (!subdiv::eval_begin_from_mesh(
|
||||
subdiv, base_mesh, {}, subdiv::SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
|
||||
{
|
||||
if (!subdiv::eval_begin_from_mesh(subdiv, base_mesh, subdiv::SUBDIV_EVALUATOR_TYPE_CPU)) {
|
||||
subdiv::free(subdiv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ static void subdiv_ccg_eval_grid_element_limit(Subdiv &subdiv,
|
||||
const int element)
|
||||
{
|
||||
if (subdiv.displacement_evaluator != nullptr) {
|
||||
eval_final_point(&subdiv, ptex_face_index, u, v, subdiv_ccg.positions[element]);
|
||||
subdiv_ccg.positions[element] = eval_final_point(&subdiv, ptex_face_index, u, v);
|
||||
}
|
||||
else if (!subdiv_ccg.normals.is_empty()) {
|
||||
eval_limit_point_and_normal(&subdiv,
|
||||
@@ -120,7 +120,7 @@ static void subdiv_ccg_eval_grid_element_limit(Subdiv &subdiv,
|
||||
subdiv_ccg.normals[element]);
|
||||
}
|
||||
else {
|
||||
eval_limit_point(&subdiv, ptex_face_index, u, v, subdiv_ccg.positions[element]);
|
||||
subdiv_ccg.positions[element] = eval_limit_point(&subdiv, ptex_face_index, u, v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ Mesh *BKE_subdiv_to_ccg_mesh(Subdiv &subdiv,
|
||||
{
|
||||
/* Make sure evaluator is ready. */
|
||||
stats_begin(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
|
||||
if (!eval_begin_from_mesh(&subdiv, &coarse_mesh, {}, SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) {
|
||||
if (!eval_begin_from_mesh(&subdiv, &coarse_mesh, SUBDIV_EVALUATOR_TYPE_CPU)) {
|
||||
if (coarse_mesh.faces_num) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1600,15 +1600,13 @@ static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG &subdiv_ccg,
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg,
|
||||
const SubdivCCGCoord &coord,
|
||||
float3 &r_point)
|
||||
float3 BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
|
||||
{
|
||||
Subdiv *subdiv = subdiv_ccg.subdiv;
|
||||
int ptex_face_index;
|
||||
float u, v;
|
||||
subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, ptex_face_index, u, v);
|
||||
eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
|
||||
return eval_limit_point(subdiv, ptex_face_index, u, v);
|
||||
}
|
||||
|
||||
void BKE_subdiv_ccg_eval_limit_positions(const SubdivCCG &subdiv_ccg,
|
||||
@@ -1623,7 +1621,7 @@ void BKE_subdiv_ccg_eval_limit_positions(const SubdivCCG &subdiv_ccg,
|
||||
const int i = CCG_grid_xy_to_index(key.grid_size, x, y);
|
||||
coord.x = x;
|
||||
coord.y = y;
|
||||
BKE_subdiv_ccg_eval_limit_point(subdiv_ccg, coord, r_limit_positions[i]);
|
||||
r_limit_positions[i] = BKE_subdiv_ccg_eval_limit_point(subdiv_ccg, coord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ static void subdiv_mesh_vertex_corner(const ForeachContext *foreach_context,
|
||||
mul_v3_fl(D, inv_num_accumulated);
|
||||
}
|
||||
/* Copy custom data and evaluate position. */
|
||||
eval_limit_point(ctx->subdiv, ptex_face_index, u, v, vertex_co);
|
||||
vertex_co = eval_limit_point(ctx->subdiv, ptex_face_index, u, v);
|
||||
/* Apply displacement. */
|
||||
add_v3_v3(vertex_co, D);
|
||||
}
|
||||
@@ -186,9 +186,7 @@ void deform_coarse_vertices(Subdiv *subdiv,
|
||||
stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
/* Make sure evaluator is up to date with possible new topology, and that
|
||||
* is refined for the new positions of coarse vertices. */
|
||||
if (!eval_begin_from_mesh(
|
||||
subdiv, coarse_mesh, vert_positions, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
|
||||
{
|
||||
if (!eval_begin_from_mesh(subdiv, coarse_mesh, SUBDIV_EVALUATOR_TYPE_CPU, vert_positions)) {
|
||||
/* This could happen in two situations:
|
||||
* - OpenSubdiv is disabled.
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our
|
||||
|
||||
@@ -220,8 +220,8 @@ static void get_mesh_evaluator_settings(OpenSubdiv_EvaluatorSettings *settings,
|
||||
|
||||
bool eval_begin_from_mesh(Subdiv *subdiv,
|
||||
const Mesh *mesh,
|
||||
const Span<float3> coarse_vert_positions,
|
||||
eSubdivEvaluatorType evaluator_type,
|
||||
const Span<float3> coarse_vert_positions,
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
||||
{
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
@@ -288,13 +288,15 @@ void eval_init_displacement(Subdiv *subdiv)
|
||||
* Single point queries.
|
||||
*/
|
||||
|
||||
void eval_limit_point(
|
||||
Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float3 &r_P)
|
||||
float3 eval_limit_point(Subdiv *subdiv, const int ptex_face_index, const float u, const float v)
|
||||
{
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
float3 r_P;
|
||||
subdiv->evaluator->eval_output->evaluateLimit(ptex_face_index, u, v, r_P, nullptr, nullptr);
|
||||
return r_P;
|
||||
#else
|
||||
UNUSED_VARS(subdiv, ptex_face_index, u, v, r_P);
|
||||
return {0.0f, 0.0f, 0.0f};
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -383,9 +385,9 @@ void eval_displacement(Subdiv *subdiv,
|
||||
subdiv->displacement_evaluator, ptex_face_index, u, v, dPdu, dPdv, r_D);
|
||||
}
|
||||
|
||||
void eval_final_point(
|
||||
Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float3 &r_P)
|
||||
float3 eval_final_point(Subdiv *subdiv, const int ptex_face_index, const float u, const float v)
|
||||
{
|
||||
float3 r_P;
|
||||
if (subdiv->displacement_evaluator) {
|
||||
float3 dPdu;
|
||||
float3 dPdv;
|
||||
@@ -395,8 +397,9 @@ void eval_final_point(
|
||||
r_P += D;
|
||||
}
|
||||
else {
|
||||
eval_limit_point(subdiv, ptex_face_index, u, v, r_P);
|
||||
r_P = eval_limit_point(subdiv, ptex_face_index, u, v);
|
||||
}
|
||||
return r_P;
|
||||
}
|
||||
|
||||
} // namespace blender::bke::subdiv
|
||||
|
||||
@@ -644,7 +644,7 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
|
||||
}
|
||||
/* Copy custom data and evaluate position. */
|
||||
subdiv_vertex_data_copy(ctx, coarse_vertex_index, subdiv_vertex_index);
|
||||
eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_position);
|
||||
subdiv_position = eval_limit_point(ctx->subdiv, ptex_face_index, u, v);
|
||||
/* Apply displacement. */
|
||||
subdiv_position += D;
|
||||
/* Evaluate undeformed texture coordinate. */
|
||||
@@ -672,7 +672,7 @@ static void evaluate_vertex_and_apply_displacement_interpolate(
|
||||
}
|
||||
/* Interpolate custom data and evaluate position. */
|
||||
subdiv_vertex_data_interpolate(ctx, subdiv_vertex_index, vertex_interpolation, u, v);
|
||||
eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_position);
|
||||
subdiv_position = eval_limit_point(ctx->subdiv, ptex_face_index, u, v);
|
||||
/* Apply displacement. */
|
||||
add_v3_v3(subdiv_position, D);
|
||||
/* Evaluate undeformed texture coordinate. */
|
||||
@@ -825,10 +825,9 @@ static void subdiv_mesh_vertex_inner(const ForeachContext *foreach_context,
|
||||
Subdiv *subdiv = ctx->subdiv;
|
||||
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
|
||||
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
||||
float3 &subdiv_position = ctx->subdiv_positions[subdiv_vertex_index];
|
||||
subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_face_index, coarse_corner);
|
||||
subdiv_vertex_data_interpolate(ctx, subdiv_vertex_index, &tls->vertex_interpolation, u, v);
|
||||
eval_final_point(subdiv, ptex_face_index, u, v, subdiv_position);
|
||||
ctx->subdiv_positions[subdiv_vertex_index] = eval_final_point(subdiv, ptex_face_index, u, v);
|
||||
subdiv_mesh_tag_center_vertex(coarse_face, subdiv_vertex_index, u, v, subdiv_mesh);
|
||||
subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
|
||||
}
|
||||
@@ -1158,11 +1157,10 @@ Mesh *subdiv_to_mesh(Subdiv *subdiv, const ToMeshSettings *settings, const Mesh
|
||||
stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
/* Make sure evaluator is up to date with possible new topology, and that
|
||||
* it is refined for the new positions of coarse vertices. */
|
||||
if (!eval_begin_from_mesh(subdiv, coarse_mesh, {}, SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) {
|
||||
if (!eval_begin_from_mesh(subdiv, coarse_mesh, SUBDIV_EVALUATOR_TYPE_CPU)) {
|
||||
/* This could happen in two situations:
|
||||
* - OpenSubdiv is disabled.
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our
|
||||
* topology.
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our topology.
|
||||
* In either way, we can't safely continue. */
|
||||
if (coarse_mesh->faces_num) {
|
||||
stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
||||
|
||||
@@ -1628,12 +1628,11 @@ static bool draw_subdiv_create_requested_buffers(Object &ob,
|
||||
};
|
||||
|
||||
if (!bke::subdiv::eval_begin_from_mesh(
|
||||
subdiv, mesh_eval, {}, bke::subdiv::SUBDIV_EVALUATOR_TYPE_GPU, g_subdiv_evaluator_cache))
|
||||
subdiv, mesh_eval, bke::subdiv::SUBDIV_EVALUATOR_TYPE_GPU))
|
||||
{
|
||||
/* This could happen in two situations:
|
||||
* - OpenSubdiv is disabled.
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our
|
||||
* topology.
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our topology.
|
||||
* In either way, we can't safely continue. However, we still have to handle potential loose
|
||||
* geometry, which is done separately. */
|
||||
if (mesh_eval->faces_num) {
|
||||
|
||||
Reference in New Issue
Block a user