Subdiv: Move most blenkernel subdiv code to C++ namespace

Move most code to `blender::bke::subdiv`. That helps organization
and makes using C++ in subdiv code easier, which will be useful for
removing the unnecessary opensubdiv C-API wrapper.
This commit is contained in:
Hans Goudey
2024-04-18 17:27:10 -04:00
parent ec09931d55
commit 11f0d88d13
42 changed files with 880 additions and 798 deletions

View File

@@ -20,8 +20,10 @@ struct MultiresModifierData;
struct Object;
struct Scene;
struct SubdivCCG;
struct SubdivSettings;
struct SubdivToMeshSettings;
namespace blender::bke::subdiv {
struct Settings;
struct ToMeshSettings;
} // namespace blender::bke::subdiv
/**
* Delete mesh mdisps and grid paint masks.
@@ -180,10 +182,11 @@ void multiresModifier_subdivide_to_level(Object *object,
/* Subdivision integration, defined in multires_subdiv.cc */
void BKE_multires_subdiv_settings_init(SubdivSettings *settings, const MultiresModifierData *mmd);
void BKE_multires_subdiv_settings_init(blender::bke::subdiv::Settings *settings,
const MultiresModifierData *mmd);
/* TODO(sergey): Replace this set of boolean flags with bitmask. */
void BKE_multires_subdiv_mesh_settings_init(SubdivToMeshSettings *mesh_settings,
void BKE_multires_subdiv_mesh_settings_init(blender::bke::subdiv::ToMeshSettings *mesh_settings,
const Scene *scene,
const Object *object,
const MultiresModifierData *mmd,

View File

@@ -16,9 +16,10 @@ struct MultiresModifierData;
struct OpenSubdiv_Converter;
struct OpenSubdiv_Evaluator;
struct OpenSubdiv_TopologyRefiner;
struct Subdiv;
enum eSubdivVtxBoundaryInterpolation {
namespace blender::bke::subdiv {
enum VtxBoundaryInterpolation {
/* Do not interpolate boundaries. */
SUBDIV_VTX_BOUNDARY_NONE,
/* Sharpen edges. */
@@ -27,7 +28,7 @@ enum eSubdivVtxBoundaryInterpolation {
SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER,
};
enum eSubdivFVarLinearInterpolation {
enum FVarLinearInterpolation {
SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE,
SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS,
@@ -36,7 +37,7 @@ enum eSubdivFVarLinearInterpolation {
SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL,
};
struct SubdivSettings {
struct Settings {
/* Simple subdivision corresponds to "Simple" option in the interface. When it's enabled, the
* subdivided mesh is not "smoothed": new vertices are added uniformly on the existing surface.
*
@@ -64,12 +65,12 @@ struct SubdivSettings {
bool use_creases;
eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation;
eSubdivFVarLinearInterpolation fvar_linear_interpolation;
VtxBoundaryInterpolation vtx_boundary_interpolation;
FVarLinearInterpolation fvar_linear_interpolation;
};
/* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
enum eSubdivStatsValue {
enum StatsValue {
SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME = 0,
SUBDIV_STATS_SUBDIV_TO_MESH,
SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY,
@@ -89,7 +90,7 @@ struct SubdivStats {
* spend on conversion from Blender data to OpenSubdiv data, and
* time spent on topology orientation on OpenSubdiv C-API side. */
double topology_refiner_creation_time;
/* Total time spent in BKE_subdiv_to_mesh(). */
/* Total time spent in blender::bke::subdiv::subdiv_to_mesh(). */
double subdiv_to_mesh_time;
/* Geometry (mesh vertices) creation time during SUBDIV_TYO_MESH. */
double subdiv_to_mesh_geometry_time;
@@ -107,19 +108,19 @@ struct SubdivStats {
double values_[NUM_SUBDIV_STATS_VALUES];
};
/* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
/* Per-value timestamp on when corresponding stats_begin() was
* called. */
double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
};
/* Functor which evaluates displacement at a given (u, v) of given ptex face. */
struct SubdivDisplacement {
struct Displacement {
/* Initialize displacement evaluator.
*
* Is called right before evaluation is actually needed. This allows to do
* some lazy initialization, like allocate evaluator from a main thread but
* then do actual evaluation from background job. */
void (*initialize)(SubdivDisplacement *displacement);
void (*initialize)(Displacement *displacement);
/* Return displacement which is to be added to the original coordinate.
*
@@ -131,7 +132,7 @@ struct SubdivDisplacement {
*
* Averaging of displacement for vertices created for over coarse vertices
* and edges is done by subdiv code. */
void (*eval_displacement)(SubdivDisplacement *displacement,
void (*eval_displacement)(Displacement *displacement,
int ptex_face_index,
float u,
float v,
@@ -140,7 +141,7 @@ struct SubdivDisplacement {
float r_D[3]);
/* Free the data, not the evaluator itself. */
void (*free)(SubdivDisplacement *displacement);
void (*free)(Displacement *displacement);
void *user_data;
};
@@ -154,7 +155,7 @@ struct Subdiv {
/* Settings this subdivision surface is created for.
*
* It is read-only after assignment in BKE_subdiv_new_from_FOO(). */
SubdivSettings settings;
Settings settings;
/* Topology refiner includes all the glue logic to feed Blender side
* topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
* drawer. */
@@ -162,7 +163,7 @@ struct Subdiv {
/* CPU side evaluator. */
OpenSubdiv_Evaluator *evaluator;
/* Optional displacement evaluator. */
SubdivDisplacement *displacement_evaluator;
Displacement *displacement_evaluator;
/* Statistics for debugging. */
SubdivStats stats;
@@ -188,37 +189,36 @@ struct Subdiv {
*/
/* (De)initialize the entire subdivision surface module. */
void BKE_subdiv_init();
void BKE_subdiv_exit();
void init();
void exit();
/* --------------------------------------------------------------------
* Conversion helpers.
*/
/* NOTE: uv_smooth is eSubsurfUVSmooth. */
eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth);
FVarLinearInterpolation fvar_interpolation_from_uv_smooth(int uv_smooth);
eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
int boundary_smooth);
VtxBoundaryInterpolation vtx_boundary_interpolation_from_subsurf(int boundary_smooth);
/* --------------------------------------------------------------------
* Statistics.
*/
void BKE_subdiv_stats_init(SubdivStats *stats);
void stats_init(SubdivStats *stats);
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value);
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value);
void stats_begin(SubdivStats *stats, StatsValue value);
void stats_end(SubdivStats *stats, StatsValue value);
void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value);
void stats_reset(SubdivStats *stats, StatsValue value);
void BKE_subdiv_stats_print(const SubdivStats *stats);
void stats_print(const SubdivStats *stats);
/* --------------------------------------------------------------------
* Settings.
*/
bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b);
bool settings_equal(const Settings *settings_a, const Settings *settings_b);
/* --------------------------------------------------------------------
* Construction.
@@ -226,9 +226,8 @@ bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSet
/* Construct new subdivision surface descriptor, from scratch, using given
* settings and topology. */
Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
OpenSubdiv_Converter *converter);
Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const Mesh *mesh);
Subdiv *new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter);
Subdiv *new_from_mesh(const Settings *settings, const Mesh *mesh);
/* Similar to above, but will not re-create descriptor if it was created for the
* same settings and topology.
@@ -238,24 +237,22 @@ Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const Mesh *mes
* NOTE: It is allowed to pass NULL as an existing subdivision surface
* descriptor. This will create a new descriptor without any extra checks.
*/
Subdiv *BKE_subdiv_update_from_converter(Subdiv *subdiv,
const SubdivSettings *settings,
OpenSubdiv_Converter *converter);
Subdiv *BKE_subdiv_update_from_mesh(Subdiv *subdiv,
const SubdivSettings *settings,
const Mesh *mesh);
Subdiv *update_from_converter(Subdiv *subdiv,
const Settings *settings,
OpenSubdiv_Converter *converter);
Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh);
void BKE_subdiv_free(Subdiv *subdiv);
void free(Subdiv *subdiv);
/* --------------------------------------------------------------------
* Displacement API.
*/
void BKE_subdiv_displacement_attach_from_multires(Subdiv *subdiv,
Mesh *mesh,
const MultiresModifierData *mmd);
void displacement_attach_from_multires(Subdiv *subdiv,
Mesh *mesh,
const MultiresModifierData *mmd);
void BKE_subdiv_displacement_detach(Subdiv *subdiv);
void displacement_detach(Subdiv *subdiv);
/* --------------------------------------------------------------------
* Topology helpers.
@@ -264,7 +261,7 @@ void BKE_subdiv_displacement_detach(Subdiv *subdiv);
/* For each element in the array, this stores the total number of ptex faces up to that element,
* with the total number of ptex faces being the last element in the array. The array is of length
* `base face count + 1`. */
int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
int *face_ptex_offset_get(Subdiv *subdiv);
/* --------------------------------------------------------------------
* PTex faces and grids.
@@ -272,37 +269,39 @@ int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
/* For a given (ptex_u, ptex_v) within a ptex face get corresponding
* (grid_u, grid_v) within a grid. */
BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(float ptex_u,
float ptex_v,
float *r_grid_u,
float *r_grid_v);
BLI_INLINE void ptex_face_uv_to_grid_uv(float ptex_u,
float ptex_v,
float *r_grid_u,
float *r_grid_v);
/* Inverse of above. */
BLI_INLINE void BKE_subdiv_grid_uv_to_ptex_face_uv(float grid_u,
float grid_v,
float *r_ptex_u,
float *r_ptex_v);
BLI_INLINE void grid_uv_to_ptex_face_uv(float grid_u,
float grid_v,
float *r_ptex_u,
float *r_ptex_v);
/* For a given subdivision level (which is NOT refinement level) get size of
* CCG grid (number of grid points on a side).
*/
BLI_INLINE int BKE_subdiv_grid_size_from_level(int level);
BLI_INLINE int grid_size_from_level(int level);
/* Simplified version of mdisp_rot_face_to_crn, only handles quad and
* works in normalized coordinates.
*
* NOTE: Output coordinates are in ptex coordinates. */
BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(float quad_u,
float quad_v,
float *r_corner_u,
float *r_corner_v);
BLI_INLINE int rotate_quad_to_corner(float quad_u,
float quad_v,
float *r_corner_u,
float *r_corner_v);
/* Converts (u, v) coordinate from within a grid to a quad coordinate in
* normalized ptex coordinates. */
BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(
BLI_INLINE void rotate_grid_to_quad(
int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v);
/* Convert Blender edge crease value to OpenSubdiv sharpness. */
BLI_INLINE float BKE_subdiv_crease_to_sharpness_f(float edge_crease);
BLI_INLINE float crease_to_sharpness(float edge_crease);
} // namespace blender::bke::subdiv
#include "intern/subdiv_inline.hh"

View File

@@ -21,7 +21,9 @@
struct CCGElem;
struct CCGKey;
struct Mesh;
namespace blender::bke::subdiv {
struct Subdiv;
}
/* --------------------------------------------------------------------
* Masks.
@@ -88,7 +90,7 @@ struct SubdivCCG {
*
* TODO(sergey): Make sure the whole descriptor is valid, including all the
* displacement attached to the surface. */
Subdiv *subdiv = nullptr;
blender::bke::subdiv::Subdiv *subdiv = nullptr;
/* A level at which geometry was subdivided. This is what defines grid
* resolution. It is NOT the topology refinement level. */
int level = -1;
@@ -183,7 +185,7 @@ struct SubdivCCG {
* TODO(sergey): Allow some user-counter or more explicit control over who owns
* the Subdiv. The goal should be to allow viewport GL Mesh and CCG to share
* same Subsurf without conflicts. */
std::unique_ptr<SubdivCCG> BKE_subdiv_to_ccg(Subdiv &subdiv,
std::unique_ptr<SubdivCCG> BKE_subdiv_to_ccg(blender::bke::subdiv::Subdiv &subdiv,
const SubdivToCCGSettings &settings,
const Mesh &coarse_mesh,
SubdivCCGMaskEvaluator *mask_evaluator);
@@ -191,7 +193,7 @@ std::unique_ptr<SubdivCCG> BKE_subdiv_to_ccg(Subdiv &subdiv,
/* Helper function, creates Mesh structure which is properly setup to use
* grids.
*/
Mesh *BKE_subdiv_to_ccg_mesh(Subdiv &subdiv,
Mesh *BKE_subdiv_to_ccg_mesh(blender::bke::subdiv::Subdiv &subdiv,
const SubdivToCCGSettings &settings,
const Mesh &coarse_mesh);

View File

@@ -11,6 +11,9 @@
#include "BLI_sys_types.h"
struct Mesh;
namespace blender::bke::subdiv {
struct Subdiv;
/* Special version of subdivision surface which calculates final positions for coarse vertices.
@@ -20,7 +23,9 @@ struct Subdiv;
* paint on a deformed mesh with sub-surf on it.
*
* vertex_cos are supposed to hold coordinates of the coarse mesh. */
void BKE_subdiv_deform_coarse_vertices(Subdiv *subdiv,
const Mesh *coarse_mesh,
float (*vertex_cos)[3],
int num_verts);
void deform_coarse_vertices(Subdiv *subdiv,
const Mesh *coarse_mesh,
float (*vertex_cos)[3],
int num_verts);
} // namespace blender::bke::subdiv

View File

@@ -13,6 +13,9 @@
struct Mesh;
struct OpenSubdiv_EvaluatorCache;
struct OpenSubdiv_EvaluatorSettings;
namespace blender::bke::subdiv {
struct Subdiv;
enum eSubdivEvaluatorType {
@@ -21,73 +24,71 @@ enum eSubdivEvaluatorType {
};
/* Returns true if evaluator is ready for use. */
bool BKE_subdiv_eval_begin(Subdiv *subdiv,
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache,
const OpenSubdiv_EvaluatorSettings *settings);
bool eval_begin(Subdiv *subdiv,
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache,
const OpenSubdiv_EvaluatorSettings *settings);
/* coarse_vertex_cos is an optional argument which allows to override coordinates of the coarse
* mesh. */
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);
bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
const Mesh *mesh,
const float (*coarse_vertex_cos)[3]);
bool eval_begin_from_mesh(Subdiv *subdiv,
const Mesh *mesh,
const float (*coarse_vertex_cos)[3],
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache);
bool eval_refine_from_mesh(Subdiv *subdiv, const Mesh *mesh, const float (*coarse_vertex_cos)[3]);
/* Makes sure displacement evaluator is initialized.
*
* NOTE: This function must be called once before evaluating displacement or
* final surface position. */
void BKE_subdiv_eval_init_displacement(Subdiv *subdiv);
void eval_init_displacement(Subdiv *subdiv);
/* Single point queries. */
/* Evaluate point at a limit surface, with optional derivatives and normal. */
void BKE_subdiv_eval_limit_point(
Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3]);
void BKE_subdiv_eval_limit_point_and_derivatives(Subdiv *subdiv,
int ptex_face_index,
float u,
float v,
float r_P[3],
float r_dPdu[3],
float r_dPdv[3]);
void BKE_subdiv_eval_limit_point_and_normal(
void eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3]);
void eval_limit_point_and_derivatives(Subdiv *subdiv,
int ptex_face_index,
float u,
float v,
float r_P[3],
float r_dPdu[3],
float r_dPdv[3]);
void eval_limit_point_and_normal(
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(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
float r_vertex_data[]);
void eval_vertex_data(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(Subdiv *subdiv,
int face_varying_channel,
int ptex_face_index,
float u,
float v,
float r_face_varying[2]);
void eval_face_varying(Subdiv *subdiv,
int face_varying_channel,
int ptex_face_index,
float u,
float v,
float r_face_varying[2]);
/* NOTE: Expects derivatives to be correct.
*
* TODO(sergey): This is currently used together with
* BKE_subdiv_eval_final_point() which can easily evaluate derivatives.
* eval_final_point() which can easily evaluate derivatives.
* Would be nice to have displacement evaluation function which does not require
* knowing derivatives ahead of a time. */
void BKE_subdiv_eval_displacement(Subdiv *subdiv,
int ptex_face_index,
float u,
float v,
const float dPdu[3],
const float dPdv[3],
float r_D[3]);
void eval_displacement(Subdiv *subdiv,
int ptex_face_index,
float u,
float v,
const float dPdu[3],
const float dPdv[3],
float r_D[3]);
/* Evaluate point on a limit surface with displacement applied to it. */
void BKE_subdiv_eval_final_point(
Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3]);
void eval_final_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3]);
} // namespace blender::bke::subdiv

View File

@@ -11,120 +11,123 @@
#include "BLI_sys_types.h"
struct Mesh;
namespace blender::bke::subdiv {
struct ToMeshSettings;
struct ForeachContext;
struct Subdiv;
struct SubdivForeachContext;
struct SubdivToMeshSettings;
using SubdivForeachTopologyInformationCb = bool (*)(const SubdivForeachContext *context,
int num_vertices,
int num_edges,
int num_loops,
int num_faces,
const int *subdiv_face_offset);
using ForeachTopologyInformationCb = bool (*)(const ForeachContext *context,
int num_vertices,
int num_edges,
int num_loops,
int num_faces,
const int *subdiv_face_offset);
using SubdivForeachVertexFromCornerCb = void (*)(const SubdivForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_vertex_index,
int coarse_face_index,
int coarse_corner,
int subdiv_vertex_index);
using ForeachVertexFromCornerCb = void (*)(const ForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_vertex_index,
int coarse_face_index,
int coarse_corner,
int subdiv_vertex_index);
using SubdivForeachVertexFromEdgeCb = void (*)(const SubdivForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_edge_index,
int coarse_face_index,
int coarse_corner,
int subdiv_vertex_index);
using ForeachVertexFromEdgeCb = void (*)(const ForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_edge_index,
int coarse_face_index,
int coarse_corner,
int subdiv_vertex_index);
using SubdivForeachVertexInnerCb = void (*)(const SubdivForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_face_index,
int coarse_corner,
int subdiv_vertex_index);
using SubdivForeachEdgeCb = void (*)(const SubdivForeachContext *context,
void *tls,
int coarse_edge_index,
int subdiv_edge_index,
bool is_loose,
int subdiv_v1,
int subdiv_v2);
using SubdivForeachLoopCb = void (*)(const SubdivForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_loop_index,
int coarse_face_index,
int coarse_corner,
int subdiv_loop_index,
int subdiv_vertex_index,
int subdiv_edge_index);
using SubdivForeachPolygonCb = void (*)(const SubdivForeachContext *context,
void *tls,
int coarse_face_index,
int subdiv_face_index,
int start_loop_index,
int num_loops);
using SubdivForeachLooseCb = void (*)(const SubdivForeachContext *context,
using ForeachVertexInnerCb = void (*)(const ForeachContext *context,
void *tls,
int coarse_vertex_index,
int ptex_face_index,
float u,
float v,
int coarse_face_index,
int coarse_corner,
int subdiv_vertex_index);
using SubdivForeachVertexOfLooseEdgeCb = void (*)(const SubdivForeachContext *context,
void *tls,
int coarse_edge_index,
float u,
int subdiv_vertex_index);
using ForeachEdgeCb = void (*)(const ForeachContext *context,
void *tls,
int coarse_edge_index,
int subdiv_edge_index,
bool is_loose,
int subdiv_v1,
int subdiv_v2);
struct SubdivForeachContext {
using ForeachLoopCb = void (*)(const ForeachContext *context,
void *tls,
int ptex_face_index,
float u,
float v,
int coarse_loop_index,
int coarse_face_index,
int coarse_corner,
int subdiv_loop_index,
int subdiv_vertex_index,
int subdiv_edge_index);
using ForeachPolygonCb = void (*)(const ForeachContext *context,
void *tls,
int coarse_face_index,
int subdiv_face_index,
int start_loop_index,
int num_loops);
using ForeachLooseCb = void (*)(const ForeachContext *context,
void *tls,
int coarse_vertex_index,
int subdiv_vertex_index);
using ForeachVertexOfLooseEdgeCb = void (*)(const ForeachContext *context,
void *tls,
int coarse_edge_index,
float u,
int subdiv_vertex_index);
struct ForeachContext {
/* Is called when topology information becomes available.
* Is only called once.
*
* NOTE: If this callback returns false, the foreach loop is aborted.
*/
SubdivForeachTopologyInformationCb topology_info;
ForeachTopologyInformationCb topology_info;
/* These callbacks are called from every ptex which shares "emitting"
* vertex or edge.
*/
SubdivForeachVertexFromCornerCb vertex_every_corner;
SubdivForeachVertexFromEdgeCb vertex_every_edge;
ForeachVertexFromCornerCb vertex_every_corner;
ForeachVertexFromEdgeCb vertex_every_edge;
/* 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.
*/
SubdivForeachVertexFromCornerCb vertex_corner;
SubdivForeachVertexFromEdgeCb vertex_edge;
ForeachVertexFromCornerCb vertex_corner;
ForeachVertexFromEdgeCb vertex_edge;
/* Called exactly once, always corresponds to a single ptex face. */
SubdivForeachVertexInnerCb vertex_inner;
ForeachVertexInnerCb vertex_inner;
/* Called once for each loose vertex. One loose coarse vertex corresponds
* to a single subdivision vertex.
*/
SubdivForeachLooseCb vertex_loose;
ForeachLooseCb vertex_loose;
/* Called once per vertex created for loose edge. */
SubdivForeachVertexOfLooseEdgeCb vertex_of_loose_edge;
ForeachVertexOfLooseEdgeCb vertex_of_loose_edge;
/* NOTE: If subdivided edge does not come from coarse edge, ORIGINDEX_NONE
* will be passed as coarse_edge_index.
*/
SubdivForeachEdgeCb edge;
ForeachEdgeCb edge;
/* NOTE: If subdivided loop does not come from coarse loop, ORIGINDEX_NONE
* will be passed as coarse_loop_index.
*/
SubdivForeachLoopCb loop;
SubdivForeachPolygonCb poly;
ForeachLoopCb loop;
ForeachPolygonCb poly;
/* User-defined pointer, to allow callbacks know something about context the
* traversal is happening for.
@@ -152,7 +155,9 @@ struct SubdivForeachContext {
* The main point here is to be able to get base level topology, which can be
* done with either of those. Having both of them is kind of redundant.
*/
bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
const SubdivForeachContext *context,
const SubdivToMeshSettings *mesh_settings,
const Mesh *coarse_mesh);
bool foreach_subdiv_geometry(Subdiv *subdiv,
const ForeachContext *context,
const ToMeshSettings *mesh_settings,
const Mesh *coarse_mesh);
} // namespace blender::bke::subdiv

View File

@@ -13,9 +13,12 @@
#include "BLI_sys_types.h"
struct Mesh;
namespace blender::bke::subdiv {
struct Subdiv;
struct SubdivToMeshSettings {
struct ToMeshSettings {
/**
* Resolution at which regular PTEX (created for quad face) are being
* evaluated. This defines how many vertices final mesh will have: every
@@ -29,19 +32,19 @@ struct SubdivToMeshSettings {
};
/** Create real hi-res mesh from subdivision, all geometry is "real". */
Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
const SubdivToMeshSettings *settings,
const Mesh *coarse_mesh);
Mesh *subdiv_to_mesh(Subdiv *subdiv, const ToMeshSettings *settings, const Mesh *coarse_mesh);
/**
* Interpolate a position along the `coarse_edge` at the relative `u` coordinate.
* If `is_simple` is false, this will perform a B-Spline interpolation using the edge neighbors,
* otherwise a linear interpolation will be done base on the edge vertices.
*/
void BKE_subdiv_mesh_interpolate_position_on_edge(const float (*coarse_positions)[3],
const blender::int2 *coarse_edges,
blender::GroupedSpan<int> vert_to_edge_map,
int coarse_edge_index,
bool is_simple,
float u,
float pos_r[3]);
void mesh_interpolate_position_on_edge(const float (*coarse_positions)[3],
const blender::int2 *coarse_edges,
blender::GroupedSpan<int> vert_to_edge_map,
int coarse_edge_index,
bool is_simple,
float u,
float pos_r[3]);
} // namespace blender::bke::subdiv

View File

@@ -19,18 +19,21 @@
struct Mesh;
struct Object;
struct Scene;
struct Subdiv;
struct SubdivSettings;
struct SubsurfModifierData;
namespace blender::bke::subdiv {
struct Subdiv;
struct Settings;
} // namespace blender::bke::subdiv
/* Runtime subsurf modifier data, cached in modifier on evaluated meshes. */
struct SubsurfRuntimeData {
/* Subdivision settings, exists before descriptor or mesh wrapper is created. */
SubdivSettings settings;
blender::bke::subdiv::Settings settings;
/* Cached subdivision surface descriptor, with topology and settings. */
Subdiv *subdiv_cpu;
Subdiv *subdiv_gpu;
blender::bke::subdiv::Subdiv *subdiv_cpu;
blender::bke::subdiv::Subdiv *subdiv_gpu;
/* Recent usage markers for UI diagnostics. To avoid UI flicker due to races
* between evaluation and UI redraw, they are set to 2 when an evaluator is used,
@@ -50,8 +53,8 @@ struct SubsurfRuntimeData {
int stats_totloop;
};
SubdivSettings BKE_subsurf_modifier_settings_init(const SubsurfModifierData *smd,
bool use_render_params);
blender::bke::subdiv::Settings BKE_subsurf_modifier_settings_init(const SubsurfModifierData *smd,
bool use_render_params);
bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, bool use_render_params);
@@ -78,15 +81,14 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh);
extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv);
extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(blender::bke::subdiv::Subdiv *subdiv);
/**
* Main goal of this function is to give usable subdivision surface descriptor
* which matches settings and topology.
*/
Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data,
const Mesh *mesh,
bool for_draw_code);
blender::bke::subdiv::Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(
SubsurfRuntimeData *runtime_data, const Mesh *mesh, bool for_draw_code);
/**
* Return the #ModifierMode required for the evaluation of the subsurf modifier,

View File

@@ -8,6 +8,10 @@
#pragma once
namespace blender::bke::subdiv {
struct Subdiv;
int BKE_subdiv_topology_num_fvar_layers_get(const Subdiv *subdiv);
int topology_num_fvar_layers_get(const Subdiv *subdiv);
} // namespace blender::bke::subdiv

View File

@@ -319,6 +319,7 @@ int BKE_mesh_wrapper_face_len(const Mesh *mesh)
static Mesh *mesh_wrapper_ensure_subdivision(Mesh *mesh)
{
using namespace blender::bke;
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)mesh->runtime->subsurf_runtime_data;
if (runtime_data == nullptr || runtime_data->settings.level == 0) {
return mesh;
@@ -327,7 +328,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *mesh)
/* Initialize the settings before ensuring the descriptor as this is checked to decide whether
* subdivision is needed at all, and checking the descriptor status might involve checking if the
* data is out-of-date, which is a very expensive operation. */
SubdivToMeshSettings mesh_settings;
subdiv::ToMeshSettings mesh_settings;
mesh_settings.resolution = runtime_data->resolution;
mesh_settings.use_optimal_display = runtime_data->use_optimal_display;
@@ -335,7 +336,8 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *mesh)
return mesh;
}
Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh, false);
subdiv::Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(
runtime_data, mesh, false);
if (subdiv == nullptr) {
/* Happens on bad topology, but also on empty input mesh. */
return mesh;
@@ -349,7 +351,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *mesh)
memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes());
}
Mesh *subdiv_mesh = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
Mesh *subdiv_mesh = subdiv::subdiv_to_mesh(subdiv, &mesh_settings, mesh);
if (use_clnors) {
BKE_mesh_set_custom_normals(subdiv_mesh,
@@ -359,7 +361,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *mesh)
}
if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) {
BKE_subdiv_free(subdiv);
subdiv::free(subdiv);
}
if (subdiv_mesh != mesh) {

View File

@@ -22,7 +22,9 @@ struct MDisps;
struct Mesh;
struct MultiresModifierData;
struct Object;
namespace blender::bke::subdiv {
struct Subdiv;
}
struct SubdivCCG;
struct MultiresReshapeContext {
@@ -45,7 +47,7 @@ struct MultiresReshapeContext {
*
* The coarse mesh of this subdivision surface is a base mesh with all deformation modifiers
* leading multires applied on it. */
Subdiv *subdiv;
blender::bke::subdiv::Subdiv *subdiv;
bool need_free_subdiv;
struct {
@@ -146,9 +148,9 @@ struct ReshapeConstGridElement {
* Create subdivision surface descriptor which is configured for surface evaluation at a given
* multi-res modifier.
*/
Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
Object *object,
const MultiresModifierData *mmd);
blender::bke::subdiv::Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
Object *object,
const MultiresModifierData *mmd);
/**
* \note Initialized base mesh to object's mesh, the Subdivision is created from the deformed
@@ -178,7 +180,7 @@ bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *resha
bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape_context,
Object *object,
MultiresModifierData *mmd,
Subdiv *subdiv,
blender::bke::subdiv::Subdiv *subdiv,
int top_level);
void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_context);

View File

@@ -135,7 +135,8 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)
{
BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, nullptr);
blender::bke::subdiv::eval_refine_from_mesh(
reshape_context->subdiv, reshape_context->base_mesh, nullptr);
}
void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context)
@@ -150,7 +151,8 @@ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *resh
blender::Array<blender::float3> deformed_verts =
BKE_multires_create_deformed_base_mesh_vert_coords(depsgraph, object, mmd);
BKE_subdiv_eval_refine_from_mesh(reshape_context->subdiv,
reshape_context->base_mesh,
reinterpret_cast<float(*)[3]>(deformed_verts.data()));
blender::bke::subdiv::eval_refine_from_mesh(
reshape_context->subdiv,
reshape_context->base_mesh,
reinterpret_cast<float(*)[3]>(deformed_verts.data()));
}

View File

@@ -138,7 +138,7 @@ struct MultiresReshapeSmoothContext {
blender::BitSpan loose_base_edges;
/* Subdivision surface created for geometry at a reshape level. */
Subdiv *reshape_subdiv;
blender::bke::subdiv::Subdiv *reshape_subdiv;
/* Limit surface of the base mesh with original sculpt level details on it, subdivided up to the
* top level.
@@ -176,7 +176,7 @@ static void linear_grids_init(LinearGrids *linear_grids)
static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int level)
{
const size_t grid_size = BKE_subdiv_grid_size_from_level(level);
const size_t grid_size = blender::bke::subdiv::grid_size_from_level(level);
const size_t grid_area = grid_size * grid_size;
const size_t num_grid_elements = num_grids * grid_area;
@@ -552,7 +552,7 @@ static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_con
if (reshape_smooth_context->reshape_subdiv == nullptr) {
return;
}
BKE_subdiv_free(reshape_smooth_context->reshape_subdiv);
blender::bke::subdiv::free(reshape_smooth_context->reshape_subdiv);
}
static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
@@ -562,7 +562,7 @@ static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
base_surface_grids_free(reshape_smooth_context);
}
static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
static bool foreach_topology_info(const blender::bke::subdiv::ForeachContext *foreach_context,
const int num_vertices,
const int num_edges,
const int num_loops,
@@ -595,7 +595,7 @@ static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
return true;
}
static void foreach_single_vertex(const SubdivForeachContext *foreach_context,
static void foreach_single_vertex(const blender::bke::subdiv::ForeachContext *foreach_context,
const GridCoord *grid_coord,
const int coarse_vertex_index,
const int subdiv_vertex_index)
@@ -627,11 +627,11 @@ static void foreach_single_vertex(const SubdivForeachContext *foreach_context,
}
crease = get_effective_crease_float(reshape_smooth_context, crease);
vertex->sharpness = BKE_subdiv_crease_to_sharpness_f(crease);
vertex->sharpness = blender::bke::subdiv::crease_to_sharpness(crease);
}
/* TODO(sergey): De-duplicate with similar function in multires_reshape_vertcos.cc */
static void foreach_vertex(const SubdivForeachContext *foreach_context,
static void foreach_vertex(const blender::bke::subdiv::ForeachContext *foreach_context,
const PTexCoord *ptex_coord,
const int coarse_vertex_index,
const int subdiv_vertex_index)
@@ -681,7 +681,7 @@ static void foreach_vertex(const SubdivForeachContext *foreach_context,
}
}
static void foreach_vertex_inner(const SubdivForeachContext *foreach_context,
static void foreach_vertex_inner(const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int ptex_face_index,
const float ptex_face_u,
@@ -697,15 +697,16 @@ static void foreach_vertex_inner(const SubdivForeachContext *foreach_context,
foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index);
}
static void foreach_vertex_every_corner(const SubdivForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float ptex_face_u,
const float ptex_face_v,
const int coarse_vertex_index,
const int /*coarse_face_index*/,
const int /*coarse_face_corner*/,
const int subdiv_vertex_index)
static void foreach_vertex_every_corner(
const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float ptex_face_u,
const float ptex_face_v,
const int coarse_vertex_index,
const int /*coarse_face_index*/,
const int /*coarse_face_corner*/,
const int subdiv_vertex_index)
{
PTexCoord ptex_coord{};
ptex_coord.ptex_face_index = ptex_face_index;
@@ -714,7 +715,7 @@ static void foreach_vertex_every_corner(const SubdivForeachContext *foreach_cont
foreach_vertex(foreach_context, &ptex_coord, coarse_vertex_index, subdiv_vertex_index);
}
static void foreach_vertex_every_edge(const SubdivForeachContext *foreach_context,
static void foreach_vertex_every_edge(const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float ptex_face_u,
@@ -731,7 +732,7 @@ static void foreach_vertex_every_edge(const SubdivForeachContext *foreach_contex
foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index);
}
static void foreach_loop(const SubdivForeachContext *foreach_context,
static void foreach_loop(const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int /*ptex_face_index*/,
const float /*ptex_face_u*/,
@@ -756,7 +757,7 @@ static void foreach_loop(const SubdivForeachContext *foreach_context,
corner->grid_index = first_grid_index + coarse_corner;
}
static void foreach_poly(const SubdivForeachContext *foreach_context,
static void foreach_poly(const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int /*coarse_face_index*/,
const int subdiv_face_index,
@@ -773,11 +774,12 @@ static void foreach_poly(const SubdivForeachContext *foreach_context,
face->num_corners = num_loops;
}
static void foreach_vertex_of_loose_edge(const SubdivForeachContext *foreach_context,
void * /*tls*/,
const int /*coarse_edge_index*/,
const float /*u*/,
const int vertex_index)
static void foreach_vertex_of_loose_edge(
const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int /*coarse_edge_index*/,
const float /*u*/,
const int vertex_index)
{
const MultiresReshapeSmoothContext *reshape_smooth_context =
static_cast<const MultiresReshapeSmoothContext *>(foreach_context->user_data);
@@ -801,10 +803,10 @@ static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context,
Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
edge->v1 = subdiv_v1;
edge->v2 = subdiv_v2;
edge->sharpness = BKE_subdiv_crease_to_sharpness_f(crease);
edge->sharpness = blender::bke::subdiv::crease_to_sharpness(crease);
}
static void foreach_edge(const SubdivForeachContext *foreach_context,
static void foreach_edge(const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int coarse_edge_index,
const int /*subdiv_edge_index*/,
@@ -870,7 +872,7 @@ static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context
{
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
SubdivForeachContext foreach_context{};
blender::bke::subdiv::ForeachContext foreach_context{};
foreach_context.topology_info = foreach_topology_info;
foreach_context.vertex_inner = foreach_vertex_inner;
foreach_context.vertex_every_corner = foreach_vertex_every_corner;
@@ -883,12 +885,12 @@ static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context
geometry_init_loose_information(reshape_smooth_context);
SubdivToMeshSettings mesh_settings;
blender::bke::subdiv::ToMeshSettings mesh_settings;
mesh_settings.resolution = get_reshape_level_resolution(reshape_context);
mesh_settings.use_optimal_display = false;
/* TODO(sergey): Tell the foreach() to ignore loose vertices. */
BKE_subdiv_foreach_subdiv_geometry(
blender::bke::subdiv::foreach_subdiv_geometry(
reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh);
}
@@ -909,10 +911,10 @@ static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(
const MultiresReshapeSmoothContext *reshape_smooth_context =
static_cast<const MultiresReshapeSmoothContext *>(converter->user_data);
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
const SubdivSettings *settings = &reshape_context->subdiv->settings;
const blender::bke::subdiv::Settings *settings = &reshape_context->subdiv->settings;
return OpenSubdiv_VtxBoundaryInterpolation(
BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(settings));
blender::bke::subdiv::converter_vtx_boundary_interpolation_from_settings(settings));
}
static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
@@ -921,10 +923,10 @@ static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
const MultiresReshapeSmoothContext *reshape_smooth_context =
static_cast<const MultiresReshapeSmoothContext *>(converter->user_data);
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
const SubdivSettings *settings = &reshape_context->subdiv->settings;
const blender::bke::subdiv::Settings *settings = &reshape_context->subdiv->settings;
return OpenSubdiv_FVarLinearInterpolation(
BKE_subdiv_converter_fvar_linear_from_settings(settings));
blender::bke::subdiv::converter_fvar_linear_from_settings(settings));
}
static bool specifies_full_topology(const OpenSubdiv_Converter * /*converter*/)
@@ -1069,19 +1071,23 @@ static void converter_init(const MultiresReshapeSmoothContext *reshape_smooth_co
static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context)
{
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
const SubdivSettings *settings = &reshape_context->subdiv->settings;
const blender::bke::subdiv::Settings *settings = &reshape_context->subdiv->settings;
OpenSubdiv_Converter converter;
converter_init(reshape_smooth_context, &converter);
Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter);
blender::bke::subdiv::Subdiv *reshape_subdiv = blender::bke::subdiv::new_from_converter(
settings, &converter);
OpenSubdiv_EvaluatorSettings evaluator_settings = {0};
BKE_subdiv_eval_begin(reshape_subdiv, SUBDIV_EVALUATOR_TYPE_CPU, nullptr, &evaluator_settings);
blender::bke::subdiv::eval_begin(reshape_subdiv,
blender::bke::subdiv::SUBDIV_EVALUATOR_TYPE_CPU,
nullptr,
&evaluator_settings);
reshape_smooth_context->reshape_subdiv = reshape_subdiv;
BKE_subdiv_converter_free(&converter);
blender::bke::subdiv::converter_free(&converter);
}
/* Callback to provide coarse position for subdivision surface topology at a reshape level. */
@@ -1094,7 +1100,7 @@ using ReshapeSubdivCoarsePositionCb =
static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_smooth_context,
ReshapeSubdivCoarsePositionCb coarse_position_cb)
{
Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
blender::bke::subdiv::Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
/* TODO(sergey): For non-trivial coarse_position_cb we should multi-thread this loop. */
@@ -1186,13 +1192,13 @@ static void reshape_subdiv_evaluate_limit_at_grid(
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
float dPdu[3], dPdv[3];
BKE_subdiv_eval_limit_point_and_derivatives(reshape_smooth_context->reshape_subdiv,
ptex_coord->ptex_face_index,
ptex_coord->u,
ptex_coord->v,
limit_P,
dPdu,
dPdv);
blender::bke::subdiv::eval_limit_point_and_derivatives(reshape_smooth_context->reshape_subdiv,
ptex_coord->ptex_face_index,
ptex_coord->u,
ptex_coord->v,
limit_P,
dPdu,
dPdv);
const int face_index = multires_reshape_grid_to_face_index(reshape_context,
grid_coord->grid_index);
@@ -1252,7 +1258,7 @@ static void linear_grid_element_delta_interpolate(
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
const int reshape_level = reshape_context->reshape.level;
const int reshape_level_grid_size = BKE_subdiv_grid_size_from_level(reshape_level);
const int reshape_level_grid_size = blender::bke::subdiv::grid_size_from_level(reshape_level);
const int reshape_level_grid_size_1 = reshape_level_grid_size - 1;
const float reshape_level_grid_size_1_inv = 1.0f / float(reshape_level_grid_size_1);
@@ -1452,14 +1458,14 @@ static void evaluate_higher_grid_positions_callback(
void * /*userdata_v*/)
{
const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
blender::bke::subdiv::Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context,
grid_coord);
/* Surface. */
float P[3];
BKE_subdiv_eval_limit_point(
blender::bke::subdiv::eval_limit_point(
reshape_subdiv, ptex_coord->ptex_face_index, ptex_coord->u, ptex_coord->v, P);
copy_v3_v3(grid_element.displacement, P);

View File

@@ -32,10 +32,11 @@
/** \name Construct/destruct reshape context
* \{ */
Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
/*const*/ Object *object,
const MultiresModifierData *mmd)
blender::bke::subdiv::Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
/*const*/ Object *object,
const MultiresModifierData *mmd)
{
using namespace blender::bke;
Mesh *base_mesh;
if (depsgraph != nullptr) {
@@ -47,13 +48,13 @@ Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgraph,
base_mesh = (Mesh *)object->data;
}
SubdivSettings subdiv_settings;
subdiv::Settings subdiv_settings;
BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, base_mesh);
if (!BKE_subdiv_eval_begin_from_mesh(
subdiv, base_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
subdiv::Subdiv *subdiv = subdiv::new_from_mesh(&subdiv_settings, base_mesh);
if (!subdiv::eval_begin_from_mesh(
subdiv, base_mesh, nullptr, subdiv::SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
{
BKE_subdiv_free(subdiv);
subdiv::free(subdiv);
return nullptr;
}
return subdiv;
@@ -115,7 +116,8 @@ static void context_init_commoon(MultiresReshapeContext *reshape_context)
BLI_assert(reshape_context->subdiv != nullptr);
BLI_assert(reshape_context->base_mesh != nullptr);
reshape_context->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(reshape_context->subdiv);
reshape_context->face_ptex_offset = blender::bke::subdiv::face_ptex_offset_get(
reshape_context->subdiv);
context_init_lookup(reshape_context);
context_init_grid_pointers(reshape_context);
@@ -166,11 +168,12 @@ bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *resh
reshape_context->reshape.level = multires_get_level(
scene_eval, object, mmd, use_render_params, true);
reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
reshape_context->reshape.grid_size = blender::bke::subdiv::grid_size_from_level(
reshape_context->reshape.level);
reshape_context->top.level = mmd->totlvl;
reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
reshape_context->top.grid_size = blender::bke::subdiv::grid_size_from_level(
reshape_context->top.level);
context_init_commoon(reshape_context);
@@ -206,11 +209,11 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape
reshape_context->reshape.level = multires_get_level(
scene_eval, object, mmd, use_render_params, true);
reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
reshape_context->reshape.grid_size = subdiv::grid_size_from_level(
reshape_context->reshape.level);
reshape_context->top.level = mmd->totlvl;
reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
reshape_context->top.grid_size = subdiv::grid_size_from_level(reshape_context->top.level);
const bke::AttributeAccessor attributes = base_mesh->attributes();
reshape_context->cd_vertex_crease = *attributes.lookup<float>("crease_vert", AttrDomain::Point);
@@ -239,11 +242,12 @@ bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_co
reshape_context->need_free_subdiv = false;
reshape_context->reshape.level = subdiv_ccg->level;
reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
reshape_context->reshape.grid_size = blender::bke::subdiv::grid_size_from_level(
reshape_context->reshape.level);
reshape_context->top.level = top_level;
reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
reshape_context->top.grid_size = blender::bke::subdiv::grid_size_from_level(
reshape_context->top.level);
context_init_commoon(reshape_context);
@@ -255,7 +259,7 @@ bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *resha
MultiresModifierData *mmd,
int top_level)
{
Subdiv *subdiv = multires_reshape_create_subdiv(nullptr, object, mmd);
blender::bke::subdiv::Subdiv *subdiv = multires_reshape_create_subdiv(nullptr, object, mmd);
const bool result = multires_reshape_context_create_from_subdiv(
reshape_context, object, mmd, subdiv, top_level);
@@ -268,7 +272,7 @@ bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *resha
bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape_context,
Object *object,
MultiresModifierData *mmd,
Subdiv *subdiv,
blender::bke::subdiv::Subdiv *subdiv,
int top_level)
{
using namespace blender;
@@ -292,11 +296,11 @@ bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape
reshape_context->need_free_subdiv = false;
reshape_context->reshape.level = mmd->totlvl;
reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level(
reshape_context->reshape.grid_size = subdiv::grid_size_from_level(
reshape_context->reshape.level);
reshape_context->top.level = top_level;
reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
reshape_context->top.grid_size = subdiv::grid_size_from_level(reshape_context->top.level);
context_init_commoon(reshape_context);
@@ -334,7 +338,7 @@ void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_contex
void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
{
if (reshape_context->need_free_subdiv) {
BKE_subdiv_free(reshape_context->subdiv);
blender::bke::subdiv::free(reshape_context->subdiv);
}
multires_reshape_free_original_grids(reshape_context);
@@ -397,15 +401,17 @@ PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *resh
grid_coord->grid_index);
float corner_u, corner_v;
BKE_subdiv_grid_uv_to_ptex_face_uv(grid_coord->u, grid_coord->v, &corner_u, &corner_v);
blender::bke::subdiv::grid_uv_to_ptex_face_uv(
grid_coord->u, grid_coord->v, &corner_u, &corner_v);
const int face_index = multires_reshape_grid_to_face_index(reshape_context,
grid_coord->grid_index);
const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
if (multires_reshape_is_quad_face(reshape_context, face_index)) {
float grid_u, grid_v;
BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &ptex_coord.u, &ptex_coord.v);
blender::bke::subdiv::ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
blender::bke::subdiv::rotate_grid_to_quad(
corner, grid_u, grid_v, &ptex_coord.u, &ptex_coord.v);
}
else {
ptex_coord.u = corner_u;
@@ -425,7 +431,7 @@ GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *resh
int corner_delta;
if (multires_reshape_is_quad_face(reshape_context, face_index)) {
corner_delta = BKE_subdiv_rotate_quad_to_corner(
corner_delta = blender::bke::subdiv::rotate_quad_to_corner(
ptex_coord->u, ptex_coord->v, &grid_coord.u, &grid_coord.v);
}
else {
@@ -435,7 +441,8 @@ GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *resh
}
grid_coord.grid_index = start_grid_index + corner_delta;
BKE_subdiv_ptex_face_uv_to_grid_uv(grid_coord.u, grid_coord.v, &grid_coord.u, &grid_coord.v);
blender::bke::subdiv::ptex_face_uv_to_grid_uv(
grid_coord.u, grid_coord.v, &grid_coord.u, &grid_coord.v);
return grid_coord;
}
@@ -493,7 +500,7 @@ ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
if (mdisps != nullptr) {
const MDisps *displacement_grid = &mdisps[grid_coord->grid_index];
if (displacement_grid->disps != nullptr) {
const int grid_size = BKE_subdiv_grid_size_from_level(displacement_grid->level);
const int grid_size = blender::bke::subdiv::grid_size_from_level(displacement_grid->level);
const int grid_x = lround(grid_coord->u * (grid_size - 1));
const int grid_y = lround(grid_coord->v * (grid_size - 1));
const int grid_element_index = grid_y * grid_size + grid_x;
@@ -505,7 +512,7 @@ ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
if (grid_paint_masks != nullptr) {
const GridPaintMask *paint_mask_grid = &grid_paint_masks[grid_coord->grid_index];
if (paint_mask_grid->data != nullptr) {
const int grid_size = BKE_subdiv_grid_size_from_level(paint_mask_grid->level);
const int grid_size = blender::bke::subdiv::grid_size_from_level(paint_mask_grid->level);
const int grid_x = lround(grid_coord->u * (grid_size - 1));
const int grid_y = lround(grid_coord->v * (grid_size - 1));
const int grid_element_index = grid_y * grid_size + grid_x;
@@ -529,8 +536,8 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha
{
float dPdu[3], dPdv[3];
const PTexCoord ptex_coord = multires_reshape_grid_coord_to_ptex(reshape_context, grid_coord);
Subdiv *subdiv = reshape_context->subdiv;
BKE_subdiv_eval_limit_point_and_derivatives(
blender::bke::subdiv::Subdiv *subdiv = reshape_context->subdiv;
blender::bke::subdiv::eval_limit_point_and_derivatives(
subdiv, ptex_coord.ptex_face_index, ptex_coord.u, ptex_coord.v, r_P, dPdu, dPdv);
const int face_index = multires_reshape_grid_to_face_index(reshape_context,
@@ -548,7 +555,7 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha
static void allocate_displacement_grid(MDisps *displacement_grid, const int level)
{
const int grid_size = BKE_subdiv_grid_size_from_level(level);
const int grid_size = blender::bke::subdiv::grid_size_from_level(level);
const int grid_area = grid_size * grid_size;
float(*disps)[3] = static_cast<float(*)[3]>(
MEM_calloc_arrayN(grid_area, sizeof(float[3]), "multires disps"));
@@ -587,7 +594,7 @@ static void ensure_mask_grids(Mesh *mesh, const int level)
return;
}
const int num_grids = mesh->corners_num;
const int grid_size = BKE_subdiv_grid_size_from_level(level);
const int grid_size = blender::bke::subdiv::grid_size_from_level(level);
const int grid_area = grid_size * grid_size;
for (int grid_index = 0; grid_index < num_grids; grid_index++) {
GridPaintMask *grid_paint_mask = &grid_paint_masks[grid_index];
@@ -703,7 +710,7 @@ static void foreach_grid_coordinate(const MultiresReshapeContext *reshape_contex
{
ForeachGridCoordinateTaskData data;
data.reshape_context = reshape_context;
data.grid_size = BKE_subdiv_grid_size_from_level(level);
data.grid_size = blender::bke::subdiv::grid_size_from_level(level);
data.grid_size_1_inv = 1.0f / (float(data.grid_size) - 1.0f);
data.callback = callback;
data.callback_userdata_v = userdata_v;

View File

@@ -25,7 +25,7 @@ struct MultiresReshapeAssignVertcosContext {
* This function will be called for every side of a boundary grid points for inner coordinates.
*/
static void multires_reshape_vertcos_foreach_single_vertex(
const SubdivForeachContext *foreach_context,
const blender::bke::subdiv::ForeachContext *foreach_context,
const GridCoord *grid_coord,
const int subdiv_vertex_index)
{
@@ -40,9 +40,10 @@ static void multires_reshape_vertcos_foreach_single_vertex(
}
/* TODO(sergey): De-duplicate with similar function in multires_reshape_smooth.cc */
static void multires_reshape_vertcos_foreach_vertex(const SubdivForeachContext *foreach_context,
const PTexCoord *ptex_coord,
const int subdiv_vertex_index)
static void multires_reshape_vertcos_foreach_vertex(
const blender::bke::subdiv::ForeachContext *foreach_context,
const PTexCoord *ptex_coord,
const int subdiv_vertex_index)
{
const MultiresReshapeAssignVertcosContext *reshape_vertcos_context =
static_cast<MultiresReshapeAssignVertcosContext *>(foreach_context->user_data);
@@ -90,9 +91,9 @@ static void multires_reshape_vertcos_foreach_vertex(const SubdivForeachContext *
}
}
/* SubdivForeachContext::topology_info() */
/* blender::bke::subdiv::ForeachContext::topology_info() */
static bool multires_reshape_vertcos_foreach_topology_info(
const SubdivForeachContext *foreach_context,
const blender::bke::subdiv::ForeachContext *foreach_context,
const int num_vertices,
const int /*num_edges*/,
const int /*num_loops*/,
@@ -107,9 +108,9 @@ static bool multires_reshape_vertcos_foreach_topology_info(
return true;
}
/* SubdivForeachContext::vertex_inner() */
/* blender::bke::subdiv::ForeachContext::vertex_inner() */
static void multires_reshape_vertcos_foreach_vertex_inner(
const SubdivForeachContext *foreach_context,
const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float ptex_face_u,
@@ -125,9 +126,9 @@ static void multires_reshape_vertcos_foreach_vertex_inner(
multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
}
/* SubdivForeachContext::vertex_every_corner() */
/* blender::bke::subdiv::ForeachContext::vertex_every_corner() */
static void multires_reshape_vertcos_foreach_vertex_every_corner(
const SubdivForeachContext *foreach_context,
const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float ptex_face_u,
@@ -144,9 +145,9 @@ static void multires_reshape_vertcos_foreach_vertex_every_corner(
multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
}
/* SubdivForeachContext::vertex_every_edge() */
/* blender::bke::subdiv::ForeachContext::vertex_every_edge() */
static void multires_reshape_vertcos_foreach_vertex_every_edge(
const SubdivForeachContext *foreach_context,
const blender::bke::subdiv::ForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float ptex_face_u,
@@ -173,17 +174,17 @@ bool multires_reshape_assign_final_coords_from_vertcos(
reshape_vertcos_context.vert_coords = vert_coords;
reshape_vertcos_context.num_vert_coords = num_vert_coords;
SubdivForeachContext foreach_context{};
blender::bke::subdiv::ForeachContext foreach_context{};
foreach_context.topology_info = multires_reshape_vertcos_foreach_topology_info;
foreach_context.vertex_inner = multires_reshape_vertcos_foreach_vertex_inner;
foreach_context.vertex_every_edge = multires_reshape_vertcos_foreach_vertex_every_edge;
foreach_context.vertex_every_corner = multires_reshape_vertcos_foreach_vertex_every_corner;
foreach_context.user_data = &reshape_vertcos_context;
SubdivToMeshSettings mesh_settings;
blender::bke::subdiv::ToMeshSettings mesh_settings;
mesh_settings.resolution = (1 << reshape_context->reshape.level) + 1;
mesh_settings.use_optimal_display = false;
return BKE_subdiv_foreach_subdiv_geometry(
return blender::bke::subdiv::foreach_subdiv_geometry(
reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh);
}

View File

@@ -15,19 +15,20 @@
#include "BKE_subdiv.hh"
#include "BKE_subdiv_mesh.hh"
void BKE_multires_subdiv_settings_init(SubdivSettings *settings, const MultiresModifierData *mmd)
void BKE_multires_subdiv_settings_init(blender::bke::subdiv::Settings *settings,
const MultiresModifierData *mmd)
{
settings->is_simple = false;
settings->is_adaptive = true;
settings->level = settings->is_simple ? 1 : mmd->quality;
settings->use_creases = (mmd->flags & eMultiresModifierFlag_UseCrease);
settings->vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
mmd->boundary_smooth);
settings->fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
settings->vtx_boundary_interpolation =
blender::bke::subdiv::vtx_boundary_interpolation_from_subsurf(mmd->boundary_smooth);
settings->fvar_linear_interpolation = blender::bke::subdiv::fvar_interpolation_from_uv_smooth(
mmd->uv_smooth);
}
void BKE_multires_subdiv_mesh_settings_init(SubdivToMeshSettings *mesh_settings,
void BKE_multires_subdiv_mesh_settings_init(blender::bke::subdiv::ToMeshSettings *mesh_settings,
const Scene *scene,
const Object *object,
const MultiresModifierData *mmd,

View File

@@ -31,25 +31,27 @@ static bool simple_to_catmull_clark_is_infinite_sharp_vertex(
return true;
}
static Subdiv *subdiv_for_simple_to_catmull_clark(Object *object, MultiresModifierData *mmd)
static blender::bke::subdiv::Subdiv *subdiv_for_simple_to_catmull_clark(Object *object,
MultiresModifierData *mmd)
{
SubdivSettings subdiv_settings;
using namespace blender::bke;
subdiv::Settings subdiv_settings;
BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
const Mesh *base_mesh = static_cast<const Mesh *>(object->data);
OpenSubdiv_Converter converter;
BKE_subdiv_converter_init_for_mesh(&converter, &subdiv_settings, base_mesh);
subdiv::converter_init_for_mesh(&converter, &subdiv_settings, base_mesh);
converter.getEdgeSharpness = simple_to_catmull_clark_get_edge_sharpness;
converter.isInfiniteSharpVertex = simple_to_catmull_clark_is_infinite_sharp_vertex;
Subdiv *subdiv = BKE_subdiv_new_from_converter(&subdiv_settings, &converter);
BKE_subdiv_converter_free(&converter);
subdiv::Subdiv *subdiv = subdiv::new_from_converter(&subdiv_settings, &converter);
subdiv::converter_free(&converter);
if (!BKE_subdiv_eval_begin_from_mesh(
subdiv, base_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
if (!subdiv::eval_begin_from_mesh(
subdiv, base_mesh, nullptr, subdiv::SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
{
BKE_subdiv_free(subdiv);
subdiv::free(subdiv);
return nullptr;
}
@@ -65,12 +67,12 @@ void multires_do_versions_simple_to_catmull_clark(Object *object, MultiresModifi
/* Store the grids displacement in object space against the simple limit surface. */
{
Subdiv *subdiv = subdiv_for_simple_to_catmull_clark(object, mmd);
blender::bke::subdiv::Subdiv *subdiv = subdiv_for_simple_to_catmull_clark(object, mmd);
MultiresReshapeContext reshape_context;
if (!multires_reshape_context_create_from_subdiv(
&reshape_context, object, mmd, subdiv, mmd->totlvl))
{
BKE_subdiv_free(subdiv);
blender::bke::subdiv::free(subdiv);
return;
}
@@ -78,7 +80,7 @@ void multires_do_versions_simple_to_catmull_clark(Object *object, MultiresModifi
multires_reshape_assign_final_coords_from_mdisps(&reshape_context);
multires_reshape_context_free(&reshape_context);
BKE_subdiv_free(subdiv);
blender::bke::subdiv::free(subdiv);
}
/* Calculate the new tangent displacement against the new Catmull-Clark limit surface. */

View File

@@ -24,16 +24,18 @@
#include "opensubdiv_evaluator_capi.hh"
#include "opensubdiv_topology_refiner_capi.hh"
namespace blender::bke::subdiv {
/* --------------------------------------------------------------------
* Module.
*/
void BKE_subdiv_init()
void init()
{
openSubdiv_init();
}
void BKE_subdiv_exit()
void exit()
{
openSubdiv_cleanup();
}
@@ -42,7 +44,7 @@ void BKE_subdiv_exit()
* Conversion helpers.
*/
eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth)
FVarLinearInterpolation fvar_interpolation_from_uv_smooth(int uv_smooth)
{
switch (uv_smooth) {
case SUBSURF_UV_SMOOTH_NONE:
@@ -62,8 +64,7 @@ eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int
return SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL;
}
eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
int boundary_smooth)
VtxBoundaryInterpolation vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
{
switch (boundary_smooth) {
case SUBSURF_BOUNDARY_SMOOTH_PRESERVE_CORNERS:
@@ -79,7 +80,7 @@ eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsu
* Settings.
*/
bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b)
bool settings_equal(const Settings *settings_a, const Settings *settings_b)
{
return (settings_a->is_simple == settings_b->is_simple &&
settings_a->is_adaptive == settings_b->is_adaptive &&
@@ -94,12 +95,11 @@ bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSet
/* Creation from scratch. */
Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
OpenSubdiv_Converter *converter)
Subdiv *new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter)
{
SubdivStats stats;
BKE_subdiv_stats_init(&stats);
BKE_subdiv_stats_begin(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
stats_init(&stats);
stats_begin(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
OpenSubdiv_TopologyRefinerSettings topology_refiner_settings;
topology_refiner_settings.level = settings->level;
topology_refiner_settings.is_adaptive = settings->is_adaptive;
@@ -118,40 +118,40 @@ Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
subdiv->topology_refiner = osd_topology_refiner;
subdiv->evaluator = nullptr;
subdiv->displacement_evaluator = nullptr;
BKE_subdiv_stats_end(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
stats_end(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
subdiv->stats = stats;
return subdiv;
}
Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const Mesh *mesh)
Subdiv *new_from_mesh(const Settings *settings, const Mesh *mesh)
{
if (mesh->verts_num == 0) {
return nullptr;
}
OpenSubdiv_Converter converter;
BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
Subdiv *subdiv = BKE_subdiv_new_from_converter(settings, &converter);
BKE_subdiv_converter_free(&converter);
converter_init_for_mesh(&converter, settings, mesh);
Subdiv *subdiv = new_from_converter(settings, &converter);
converter_free(&converter);
return subdiv;
}
/* Creation with cached-aware semantic. */
Subdiv *BKE_subdiv_update_from_converter(Subdiv *subdiv,
const SubdivSettings *settings,
OpenSubdiv_Converter *converter)
Subdiv *update_from_converter(Subdiv *subdiv,
const Settings *settings,
OpenSubdiv_Converter *converter)
{
/* Check if the existing descriptor can be re-used. */
bool can_reuse_subdiv = true;
if (subdiv != nullptr && subdiv->topology_refiner != nullptr) {
if (!BKE_subdiv_settings_equal(&subdiv->settings, settings)) {
if (!settings_equal(&subdiv->settings, settings)) {
can_reuse_subdiv = false;
}
else {
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE);
stats_begin(&subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE);
can_reuse_subdiv = openSubdiv_topologyRefinerCompareWithConverter(subdiv->topology_refiner,
converter);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE);
stats_end(&subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE);
}
}
else {
@@ -162,25 +162,23 @@ Subdiv *BKE_subdiv_update_from_converter(Subdiv *subdiv,
}
/* Create new subdiv. */
if (subdiv != nullptr) {
BKE_subdiv_free(subdiv);
free(subdiv);
}
return BKE_subdiv_new_from_converter(settings, converter);
return new_from_converter(settings, converter);
}
Subdiv *BKE_subdiv_update_from_mesh(Subdiv *subdiv,
const SubdivSettings *settings,
const Mesh *mesh)
Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
{
OpenSubdiv_Converter converter;
BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
subdiv = BKE_subdiv_update_from_converter(subdiv, settings, &converter);
BKE_subdiv_converter_free(&converter);
converter_init_for_mesh(&converter, settings, mesh);
subdiv = update_from_converter(subdiv, settings, &converter);
converter_free(&converter);
return subdiv;
}
/* Memory release. */
void BKE_subdiv_free(Subdiv *subdiv)
void free(Subdiv *subdiv)
{
if (subdiv->evaluator != nullptr) {
const eOpenSubdivEvaluator evaluator_type = subdiv->evaluator->type;
@@ -194,7 +192,7 @@ void BKE_subdiv_free(Subdiv *subdiv)
if (subdiv->topology_refiner != nullptr) {
openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner);
}
BKE_subdiv_displacement_detach(subdiv);
displacement_detach(subdiv);
if (subdiv->cache_.face_ptex_offset != nullptr) {
MEM_freeN(subdiv->cache_.face_ptex_offset);
}
@@ -205,7 +203,7 @@ void BKE_subdiv_free(Subdiv *subdiv)
* Topology helpers.
*/
int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv)
int *face_ptex_offset_get(Subdiv *subdiv)
{
if (subdiv->cache_.face_ptex_offset != nullptr) {
return subdiv->cache_.face_ptex_offset;
@@ -226,3 +224,5 @@ int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv)
subdiv->cache_.face_ptex_offset[num_coarse_faces] = ptex_offset;
return subdiv->cache_.face_ptex_offset;
}
} // namespace blender::bke::subdiv

View File

@@ -38,6 +38,7 @@ using blender::OffsetIndices;
using blender::Span;
using blender::Vector;
using blender::VectorSet;
using namespace blender::bke::subdiv;
/* -------------------------------------------------------------------- */
/** \name Various forward declarations
@@ -131,7 +132,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG &subdiv_ccg, Subdiv &subdiv)
const int64_t element_size = element_size_bytes_get(subdiv_ccg);
/* Allocate memory for surface grids. */
const int64_t num_grids = topology_refiner_count_face_corners(topology_refiner);
const int64_t grid_size = BKE_subdiv_grid_size_from_level(subdiv_ccg.level);
const int64_t grid_size = grid_size_from_level(subdiv_ccg.level);
const int64_t grid_area = grid_size * grid_size;
subdiv_ccg.grid_element_size = element_size;
subdiv_ccg.grids.reinitialize(num_grids);
@@ -158,18 +159,18 @@ static void subdiv_ccg_eval_grid_element_limit(Subdiv &subdiv,
uchar *element)
{
if (subdiv.displacement_evaluator != nullptr) {
BKE_subdiv_eval_final_point(&subdiv, ptex_face_index, u, v, (float *)element);
eval_final_point(&subdiv, ptex_face_index, u, v, (float *)element);
}
else if (subdiv_ccg.has_normal) {
BKE_subdiv_eval_limit_point_and_normal(&subdiv,
ptex_face_index,
u,
v,
(float *)element,
(float *)(element + subdiv_ccg.normal_offset));
eval_limit_point_and_normal(&subdiv,
ptex_face_index,
u,
v,
(float *)element,
(float *)(element + subdiv_ccg.normal_offset));
}
else {
BKE_subdiv_eval_limit_point(&subdiv, ptex_face_index, u, v, (float *)element);
eval_limit_point(&subdiv, ptex_face_index, u, v, (float *)element);
}
}
@@ -223,7 +224,7 @@ static void subdiv_ccg_eval_regular_grid(Subdiv &subdiv,
for (int x = 0; x < grid_size; x++) {
const float grid_u = x * grid_size_1_inv;
float u, v;
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
const size_t grid_element_index = size_t(y) * grid_size + x;
const size_t grid_element_offset = grid_element_index * element_size;
subdiv_ccg_eval_grid_element(
@@ -267,8 +268,7 @@ static bool subdiv_ccg_evaluate_grids(SubdivCCG &subdiv_ccg,
using namespace blender;
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv.topology_refiner;
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
const Span<int> face_ptex_offset(BKE_subdiv_face_ptex_offset_get(&subdiv),
subdiv_ccg.faces.size());
const Span<int> face_ptex_offset(face_ptex_offset_get(&subdiv), subdiv_ccg.faces.size());
threading::parallel_for(IndexRange(num_faces), 1024, [&](const IndexRange range) {
for (const int face_index : range) {
if (subdiv_ccg.faces[face_index].size() == 4) {
@@ -460,21 +460,21 @@ std::unique_ptr<SubdivCCG> BKE_subdiv_to_ccg(Subdiv &subdiv,
const Mesh &coarse_mesh,
SubdivCCGMaskEvaluator *mask_evaluator)
{
BKE_subdiv_stats_begin(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
stats_begin(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
std::unique_ptr<SubdivCCG> subdiv_ccg = std::make_unique<SubdivCCG>();
subdiv_ccg->subdiv = &subdiv;
subdiv_ccg->level = bitscan_forward_i(settings.resolution - 1);
subdiv_ccg->grid_size = BKE_subdiv_grid_size_from_level(subdiv_ccg->level);
subdiv_ccg->grid_size = grid_size_from_level(subdiv_ccg->level);
subdiv_ccg_init_layers(*subdiv_ccg, settings);
subdiv_ccg->faces = coarse_mesh.faces();
subdiv_ccg->grid_to_face_map = coarse_mesh.corner_to_face_map();
subdiv_ccg_alloc_elements(*subdiv_ccg, subdiv);
subdiv_ccg_init_faces_neighborhood(*subdiv_ccg);
if (!subdiv_ccg_evaluate_grids(*subdiv_ccg, subdiv, mask_evaluator)) {
BKE_subdiv_stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
return nullptr;
}
BKE_subdiv_stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
return subdiv_ccg;
}
@@ -483,15 +483,13 @@ Mesh *BKE_subdiv_to_ccg_mesh(Subdiv &subdiv,
const Mesh &coarse_mesh)
{
/* Make sure evaluator is ready. */
BKE_subdiv_stats_begin(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
if (!BKE_subdiv_eval_begin_from_mesh(
&subdiv, &coarse_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
{
stats_begin(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
if (!eval_begin_from_mesh(&subdiv, &coarse_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) {
if (coarse_mesh.faces_num) {
return nullptr;
}
}
BKE_subdiv_stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
stats_end(&subdiv.stats, SUBDIV_STATS_SUBDIV_TO_CCG);
SubdivCCGMaskEvaluator mask_evaluator;
bool has_mask = BKE_subdiv_ccg_mask_init_from_paint(&mask_evaluator, &coarse_mesh);
std::unique_ptr<SubdivCCG> subdiv_ccg = BKE_subdiv_to_ccg(
@@ -510,7 +508,7 @@ Mesh *BKE_subdiv_to_ccg_mesh(Subdiv &subdiv,
SubdivCCG::~SubdivCCG()
{
if (this->subdiv != nullptr) {
BKE_subdiv_free(this->subdiv);
free(this->subdiv);
}
for (const int i : this->adjacent_edges.index_range()) {
@@ -532,7 +530,7 @@ CCGKey BKE_subdiv_ccg_key(const SubdivCCG &subdiv_ccg, int level)
CCGKey key;
key.level = level;
key.elem_size = element_size_bytes_get(subdiv_ccg);
key.grid_size = BKE_subdiv_grid_size_from_level(level);
key.grid_size = grid_size_from_level(level);
key.grid_area = key.grid_size * key.grid_size;
key.grid_bytes = key.elem_size * key.grid_area;
@@ -1639,13 +1637,13 @@ static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG &subdiv_ccg,
const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord.grid_index);
const OffsetIndices<int> faces = subdiv_ccg.faces;
const IndexRange face = faces[face_index];
const int *face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
const int *face_ptex_offset = face_ptex_offset_get(subdiv);
*r_ptex_face_index = face_ptex_offset[face_index];
const float corner = coord.grid_index - face.start();
if (face.size() == 4) {
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_u, r_v);
rotate_grid_to_quad(corner, grid_u, grid_v, r_u, r_v);
}
else {
*r_ptex_face_index += corner;
@@ -1662,7 +1660,7 @@ void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg,
int ptex_face_index;
float u, v;
subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, &ptex_face_index, &u, &v);
BKE_subdiv_eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
}
/** \} */

View File

@@ -20,6 +20,8 @@
#include "MEM_guardedalloc.h"
using namespace blender::bke::subdiv;
struct PolyCornerIndex {
int face_index;
int corner;
@@ -53,13 +55,13 @@ static int mask_get_grid_and_coord(SubdivCCGMaskEvaluator *mask_evaluator,
int corner = 0;
if (face.size() == 4) {
float corner_u, corner_v;
corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v);
corner = rotate_quad_to_corner(u, v, &corner_u, &corner_v);
*r_mask_grid = &data->grid_paint_mask[start_grid_index + corner];
BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, grid_u, grid_v);
ptex_face_uv_to_grid_uv(corner_u, corner_v, grid_u, grid_v);
}
else {
*r_mask_grid = &data->grid_paint_mask[start_grid_index];
BKE_subdiv_ptex_face_uv_to_grid_uv(u, v, grid_u, grid_v);
ptex_face_uv_to_grid_uv(u, v, grid_u, grid_v);
}
return corner;
}
@@ -71,7 +73,7 @@ BLI_INLINE float read_mask_grid(const GridPaintMask *mask_grid,
if (mask_grid->data == nullptr) {
return 0;
}
const int grid_size = BKE_subdiv_grid_size_from_level(mask_grid->level);
const int grid_size = grid_size_from_level(mask_grid->level);
const int x = roundf(grid_u * (grid_size - 1));
const int y = roundf(grid_v * (grid_size - 1));
return mask_grid->data[y * grid_size + x];

View File

@@ -10,14 +10,16 @@
#include "opensubdiv_converter_capi.hh"
void BKE_subdiv_converter_free(OpenSubdiv_Converter *converter)
namespace blender::bke::subdiv {
void converter_free(OpenSubdiv_Converter *converter)
{
if (converter->freeUserData) {
converter->freeUserData(converter);
}
}
int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSettings *settings)
int converter_vtx_boundary_interpolation_from_settings(const Settings *settings)
{
switch (settings->vtx_boundary_interpolation) {
case SUBDIV_VTX_BOUNDARY_NONE:
@@ -31,8 +33,8 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe
return OSD_VTX_BOUNDARY_EDGE_ONLY;
}
/*OpenSubdiv_FVarLinearInterpolation*/ int BKE_subdiv_converter_fvar_linear_from_settings(
const SubdivSettings *settings)
/*OpenSubdiv_FVarLinearInterpolation*/ int converter_fvar_linear_from_settings(
const Settings *settings)
{
switch (settings->fvar_linear_interpolation) {
case SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE:
@@ -51,3 +53,5 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe
BLI_assert_msg(0, "Unknown fvar linear interpolation");
return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
}
} // namespace blender::bke::subdiv

View File

@@ -16,22 +16,27 @@
struct Mesh;
struct OpenSubdiv_Converter;
struct SubdivSettings;
void BKE_subdiv_converter_init_for_mesh(OpenSubdiv_Converter *converter,
const SubdivSettings *settings,
const Mesh *mesh);
namespace blender::bke::subdiv {
struct Settings;
void converter_init_for_mesh(OpenSubdiv_Converter *converter,
const Settings *settings,
const Mesh *mesh);
/* NOTE: Frees converter data, but not converter itself. This means, that if
* converter was allocated on heap, it is up to the user to free that memory. */
void BKE_subdiv_converter_free(OpenSubdiv_Converter *converter);
void converter_free(OpenSubdiv_Converter *converter);
/* ============================ INTERNAL HELPERS ============================ */
/* TODO(sergey): Find a way to make it OpenSubdiv_VtxBoundaryInterpolation,
* without breaking compilation without OpenSubdiv. */
int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSettings *settings);
int converter_vtx_boundary_interpolation_from_settings(const Settings *settings);
/* TODO(sergey): Find a way to make it OpenSubdiv_FVarLinearInterpolation,
* without breaking compilation without OpenSubdiv. */
int BKE_subdiv_converter_fvar_linear_from_settings(const SubdivSettings *settings);
int converter_fvar_linear_from_settings(const Settings *settings);
} // namespace blender::bke::subdiv

View File

@@ -22,23 +22,25 @@
#include "opensubdiv_converter_capi.hh"
namespace blender::bke::subdiv {
/* Enable work-around for non-working CPU evaluator when using bilinear scheme.
* This forces Catmark scheme with all edges marked as infinitely sharp. */
#define BUGGY_SIMPLE_SCHEME_WORKAROUND 1
struct ConverterStorage {
SubdivSettings settings;
Settings settings;
const Mesh *mesh;
blender::Span<blender::float3> vert_positions;
blender::Span<blender::int2> edges;
blender::OffsetIndices<int> faces;
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
Span<float3> vert_positions;
Span<int2> edges;
OffsetIndices<int> faces;
Span<int> corner_verts;
Span<int> corner_edges;
/* CustomData layer for vertex sharpnesses. */
blender::VArraySpan<float> cd_vertex_crease;
VArraySpan<float> cd_vertex_crease;
/* CustomData layer for edge sharpness. */
blender::VArraySpan<float> cd_edge_crease;
VArraySpan<float> cd_edge_crease;
/* Indexed by loop index, value denotes index of face-varying vertex
* which corresponds to the UV coordinate.
*/
@@ -55,7 +57,7 @@ struct ConverterStorage {
/* Indexed by vertex index from mesh, corresponds to whether this vertex has
* infinite sharpness due to non-manifold topology.
*/
blender::BitVector<> infinite_sharp_vertices_map;
BitVector<> infinite_sharp_vertices_map;
/* Reverse mapping to above. */
int *manifold_vertex_index_reverse;
int *manifold_edge_index_reverse;
@@ -85,7 +87,7 @@ static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
return OpenSubdiv_VtxBoundaryInterpolation(
BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(&storage->settings));
converter_vtx_boundary_interpolation_from_settings(&storage->settings));
}
static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
@@ -93,7 +95,7 @@ static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
return OpenSubdiv_FVarLinearInterpolation(
BKE_subdiv_converter_fvar_linear_from_settings(&storage->settings));
converter_fvar_linear_from_settings(&storage->settings));
}
static bool specifies_full_topology(const OpenSubdiv_Converter * /*converter*/)
@@ -130,7 +132,7 @@ static void get_face_vertices(const OpenSubdiv_Converter *converter,
int *manifold_face_vertices)
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
const blender::IndexRange face = storage->faces[manifold_face_index];
const IndexRange face = storage->faces[manifold_face_index];
for (int i = 0; i < face.size(); i++) {
const int vert = storage->corner_verts[face[i]];
manifold_face_vertices[i] = storage->manifold_vertex_index[vert];
@@ -143,7 +145,7 @@ static void get_edge_vertices(const OpenSubdiv_Converter *converter,
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index];
const blender::int2 &edge = storage->edges[edge_index];
const int2 &edge = storage->edges[edge_index];
manifold_edge_vertices[0] = storage->manifold_vertex_index[edge[0]];
manifold_edge_vertices[1] = storage->manifold_vertex_index[edge[1]];
}
@@ -160,7 +162,7 @@ static float get_edge_sharpness(const OpenSubdiv_Converter *converter, int manif
return 0.0f;
}
const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index];
return BKE_subdiv_crease_to_sharpness_f(storage->cd_edge_crease[edge_index]);
return crease_to_sharpness(storage->cd_edge_crease[edge_index]);
}
static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter,
@@ -186,7 +188,7 @@ static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, int man
return 0.0f;
}
const int vertex_index = storage->manifold_vertex_index_reverse[manifold_vertex_index];
return BKE_subdiv_crease_to_sharpness_f(storage->cd_vertex_crease[vertex_index]);
return crease_to_sharpness(storage->cd_vertex_crease[vertex_index]);
}
static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
@@ -226,7 +228,7 @@ static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int la
if (uv_vert->separate) {
storage->num_uv_coordinates++;
}
const blender::IndexRange face = storage->faces[uv_vert->face_index];
const IndexRange face = storage->faces[uv_vert->face_index];
const int global_loop_index = face.start() + uv_vert->loop_of_face_index;
storage->loop_uv_indices[global_loop_index] = storage->num_uv_coordinates;
uv_vert = uv_vert->next;
@@ -252,7 +254,7 @@ static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
const int corner)
{
ConverterStorage *storage = static_cast<ConverterStorage *>(converter->user_data);
const blender::IndexRange face = storage->faces[face_index];
const IndexRange face = storage->faces[face_index];
return storage->loop_uv_indices[face.start() + corner];
}
@@ -302,7 +304,7 @@ static void init_functions(OpenSubdiv_Converter *converter)
converter->freeUserData = free_user_data;
}
static void initialize_manifold_index_array(const blender::BitSpan not_used_map,
static void initialize_manifold_index_array(const BitSpan not_used_map,
const int num_elements,
int **r_indices,
int **r_indices_reverse,
@@ -345,7 +347,6 @@ static void initialize_manifold_index_array(const blender::BitSpan not_used_map,
static void initialize_manifold_indices(ConverterStorage *storage)
{
using namespace blender;
const Mesh *mesh = storage->mesh;
const bke::LooseVertCache &loose_verts = mesh->verts_no_face();
const bke::LooseEdgeCache &loose_edges = mesh->loose_edges();
@@ -374,11 +375,9 @@ static void initialize_manifold_indices(ConverterStorage *storage)
}
static void init_user_data(OpenSubdiv_Converter *converter,
const SubdivSettings *settings,
const Settings *settings,
const Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
ConverterStorage *user_data = MEM_new<ConverterStorage>(__func__);
user_data->settings = *settings;
user_data->mesh = mesh;
@@ -388,7 +387,7 @@ static void init_user_data(OpenSubdiv_Converter *converter,
user_data->corner_verts = mesh->corner_verts();
user_data->corner_edges = mesh->corner_edges();
if (settings->use_creases) {
const bke::AttributeAccessor attributes = mesh->attributes();
const AttributeAccessor attributes = mesh->attributes();
user_data->cd_vertex_crease = *attributes.lookup<float>("crease_vert", AttrDomain::Point);
user_data->cd_edge_crease = *attributes.lookup<float>("crease_edge", AttrDomain::Edge);
}
@@ -397,10 +396,12 @@ static void init_user_data(OpenSubdiv_Converter *converter,
converter->user_data = user_data;
}
void BKE_subdiv_converter_init_for_mesh(OpenSubdiv_Converter *converter,
const SubdivSettings *settings,
const Mesh *mesh)
void converter_init_for_mesh(OpenSubdiv_Converter *converter,
const Settings *settings,
const Mesh *mesh)
{
init_functions(converter);
init_user_data(converter, settings, mesh);
}
} // namespace blender::bke::subdiv

View File

@@ -23,6 +23,8 @@
#include "MEM_guardedalloc.h"
namespace blender::bke::subdiv {
/* -------------------------------------------------------------------- */
/** \name Subdivision context
* \{ */
@@ -75,10 +77,10 @@ static void subdiv_accumulate_vertex_displacement(SubdivDeformContext *ctx,
{
Subdiv *subdiv = ctx->subdiv;
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);
eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
/* Accumulate displacement if needed. */
if (ctx->have_displacement) {
BKE_subdiv_eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
/* NOTE: The storage for vertex coordinates is coming from an external world, not necessarily
* initialized to zeroes. */
if (ctx->accumulated_counters[vertex_index] == 0) {
@@ -97,7 +99,7 @@ static void subdiv_accumulate_vertex_displacement(SubdivDeformContext *ctx,
/** \name Subdivision callbacks
* \{ */
static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context,
static bool subdiv_mesh_topology_info(const ForeachContext *foreach_context,
const int /*num_vertices*/,
const int /*num_edges*/,
const int /*num_loops*/,
@@ -110,7 +112,7 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
return true;
}
static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_every_corner(const ForeachContext *foreach_context,
void * /*tls*/,
const int ptex_face_index,
const float u,
@@ -124,7 +126,7 @@ static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_
subdiv_accumulate_vertex_displacement(ctx, ptex_face_index, u, v, coarse_vertex_index);
}
static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_corner(const ForeachContext *foreach_context,
void * /*tls*/,
const int ptex_face_index,
const float u,
@@ -150,7 +152,7 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex
mul_v3_fl(D, inv_num_accumulated);
}
/* Copy custom data and evaluate position. */
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, vertex_co);
eval_limit_point(ctx->subdiv, ptex_face_index, u, v, vertex_co);
/* Apply displacement. */
add_v3_v3(vertex_co, D);
}
@@ -162,7 +164,7 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex
* \{ */
static void setup_foreach_callbacks(const SubdivDeformContext *subdiv_context,
SubdivForeachContext *foreach_context)
ForeachContext *foreach_context)
{
memset(foreach_context, 0, sizeof(*foreach_context));
/* General information. */
@@ -180,24 +182,22 @@ static void setup_foreach_callbacks(const SubdivDeformContext *subdiv_context,
/** \name Public entry point
* \{ */
void BKE_subdiv_deform_coarse_vertices(Subdiv *subdiv,
const Mesh *coarse_mesh,
float (*vertex_cos)[3],
int num_verts)
void deform_coarse_vertices(Subdiv *subdiv,
const Mesh *coarse_mesh,
float (*vertex_cos)[3],
int num_verts)
{
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
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 (!BKE_subdiv_eval_begin_from_mesh(
subdiv, coarse_mesh, vertex_cos, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
{
if (!eval_begin_from_mesh(subdiv, coarse_mesh, vertex_cos, SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) {
/* This could happen in two situations:
* - OpenSubdiv is disabled.
* - Something totally bad happened, and OpenSubdiv rejected our
* topology.
* In either way, we can't safely continue. */
if (coarse_mesh->faces_num) {
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
return;
}
}
@@ -210,25 +210,27 @@ void BKE_subdiv_deform_coarse_vertices(Subdiv *subdiv,
subdiv_context.num_verts = num_verts;
subdiv_context.have_displacement = (subdiv->displacement_evaluator != nullptr);
SubdivForeachContext foreach_context;
ForeachContext foreach_context;
setup_foreach_callbacks(&subdiv_context, &foreach_context);
foreach_context.user_data = &subdiv_context;
/* Dummy mesh rasterization settings. */
SubdivToMeshSettings mesh_settings;
ToMeshSettings mesh_settings;
mesh_settings.resolution = 1;
mesh_settings.use_optimal_display = false;
/* Multi-threaded traversal/evaluation. */
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
BKE_subdiv_foreach_subdiv_geometry(subdiv, &foreach_context, &mesh_settings, coarse_mesh);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
foreach_subdiv_geometry(subdiv, &foreach_context, &mesh_settings, coarse_mesh);
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);
stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
/* Free used memory. */
subdiv_mesh_context_free(&subdiv_context);
}
/** \} */
} // namespace blender::bke::subdiv

View File

@@ -10,7 +10,9 @@
#include "MEM_guardedalloc.h"
void BKE_subdiv_displacement_detach(Subdiv *subdiv)
namespace blender::bke::subdiv {
void displacement_detach(Subdiv *subdiv)
{
if (subdiv->displacement_evaluator == nullptr) {
return;
@@ -21,3 +23,5 @@ void BKE_subdiv_displacement_detach(Subdiv *subdiv)
MEM_freeN(subdiv->displacement_evaluator);
subdiv->displacement_evaluator = nullptr;
}
} // namespace blender::bke::subdiv

View File

@@ -25,6 +25,8 @@
#include "MEM_guardedalloc.h"
namespace blender::bke::subdiv {
struct PolyCornerIndex {
int face_index;
int corner;
@@ -36,7 +38,7 @@ struct MultiresDisplacementData {
/* Mesh is used to read external displacement. */
Mesh *mesh;
const MultiresModifierData *mmd;
blender::OffsetIndices<int> faces;
OffsetIndices<int> faces;
const MDisps *mdisps;
/* Indexed by PTEX face index, contains face/corner which corresponds
* to it.
@@ -61,7 +63,7 @@ enum eAverageWith {
AVERAGE_WITH_NEXT,
};
static int displacement_get_grid_and_coord(SubdivDisplacement *displacement,
static int displacement_get_grid_and_coord(Displacement *displacement,
const int ptex_face_index,
const float u,
const float v,
@@ -72,23 +74,23 @@ static int displacement_get_grid_and_coord(SubdivDisplacement *displacement,
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
displacement->user_data);
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
const blender::IndexRange face = data->faces[face_corner->face_index];
const IndexRange face = data->faces[face_corner->face_index];
const int start_grid_index = face.start() + face_corner->corner;
int corner = 0;
if (face.size() == 4) {
float corner_u, corner_v;
corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v);
corner = rotate_quad_to_corner(u, v, &corner_u, &corner_v);
*r_displacement_grid = &data->mdisps[start_grid_index + corner];
BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, grid_u, grid_v);
ptex_face_uv_to_grid_uv(corner_u, corner_v, grid_u, grid_v);
}
else {
*r_displacement_grid = &data->mdisps[start_grid_index];
BKE_subdiv_ptex_face_uv_to_grid_uv(u, v, grid_u, grid_v);
ptex_face_uv_to_grid_uv(u, v, grid_u, grid_v);
}
return corner;
}
static const MDisps *displacement_get_other_grid(SubdivDisplacement *displacement,
static const MDisps *displacement_get_other_grid(Displacement *displacement,
const int ptex_face_index,
const int corner,
const int corner_delta)
@@ -96,7 +98,7 @@ static const MDisps *displacement_get_other_grid(SubdivDisplacement *displacemen
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
displacement->user_data);
const PolyCornerIndex *face_corner = &data->ptex_face_corner[ptex_face_index];
const blender::IndexRange face = data->faces[face_corner->face_index];
const IndexRange face = data->faces[face_corner->face_index];
const int effective_corner = (face.size() == 4) ? corner : face_corner->corner;
const int next_corner = (effective_corner + corner_delta + face.size()) % face.size();
return &data->mdisps[face[next_corner]];
@@ -135,10 +137,10 @@ static void average_convert_grid_coord_to_ptex(const int num_corners,
float *r_ptex_face_v)
{
if (num_corners == 4) {
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
rotate_grid_to_quad(corner, grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
}
else {
BKE_subdiv_grid_uv_to_ptex_face_uv(grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
grid_uv_to_ptex_face_uv(grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
}
}
@@ -153,7 +155,7 @@ static void average_construct_tangent_matrix(Subdiv *subdiv,
const bool is_quad = num_corners == 4;
const int quad_corner = is_quad ? corner : 0;
float dummy_P[3], dPdu[3], dPdv[3];
BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, quad_corner);
}
@@ -210,7 +212,7 @@ static void average_get_other_ptex_and_corner(MultiresDisplacementData *data,
}
/* NOTE: Grid coordinates are relative to the other grid already. */
static void average_with_other(SubdivDisplacement *displacement,
static void average_with_other(Displacement *displacement,
const int ptex_face_index,
const int corner,
const float grid_u,
@@ -239,7 +241,7 @@ static void average_with_other(SubdivDisplacement *displacement,
mul_v3_fl(r_D, 0.5f);
}
static void average_with_all(SubdivDisplacement *displacement,
static void average_with_all(Displacement *displacement,
const int ptex_face_index,
const int corner,
const float /*grid_u*/,
@@ -255,7 +257,7 @@ static void average_with_all(SubdivDisplacement *displacement,
}
}
static void average_with_next(SubdivDisplacement *displacement,
static void average_with_next(Displacement *displacement,
const int ptex_face_index,
const int corner,
const float grid_u,
@@ -265,7 +267,7 @@ static void average_with_next(SubdivDisplacement *displacement,
average_with_other(displacement, ptex_face_index, corner, 0.0f, grid_u, 1, r_D);
}
static void average_with_prev(SubdivDisplacement *displacement,
static void average_with_prev(Displacement *displacement,
const int ptex_face_index,
const int corner,
const float /*grid_u*/,
@@ -275,7 +277,7 @@ static void average_with_prev(SubdivDisplacement *displacement,
average_with_other(displacement, ptex_face_index, corner, grid_v, 0.0f, -1, r_D);
}
static void average_displacement(SubdivDisplacement *displacement,
static void average_displacement(Displacement *displacement,
eAverageWith average_with,
const int ptex_face_index,
const int corner,
@@ -308,13 +310,13 @@ static int displacement_get_face_corner(MultiresDisplacementData *data,
const bool is_quad = (num_corners == 4);
if (is_quad) {
float dummy_corner_u, dummy_corner_v;
return BKE_subdiv_rotate_quad_to_corner(u, v, &dummy_corner_u, &dummy_corner_v);
return rotate_quad_to_corner(u, v, &dummy_corner_u, &dummy_corner_v);
}
return face_corner->corner;
}
static void initialize(SubdivDisplacement *displacement)
static void initialize(Displacement *displacement)
{
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
displacement->user_data);
@@ -322,7 +324,7 @@ static void initialize(SubdivDisplacement *displacement)
data->is_initialized = true;
}
static void eval_displacement(SubdivDisplacement *displacement,
static void eval_displacement(Displacement *displacement,
const int ptex_face_index,
const float u,
const float v,
@@ -353,7 +355,7 @@ static void eval_displacement(SubdivDisplacement *displacement,
average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
}
static void free_displacement(SubdivDisplacement *displacement)
static void free_displacement(Displacement *displacement)
{
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
displacement->user_data);
@@ -366,18 +368,18 @@ static void free_displacement(SubdivDisplacement *displacement)
static int count_num_ptex_faces(const Mesh *mesh)
{
int num_ptex_faces = 0;
const blender::OffsetIndices faces = mesh->faces();
const OffsetIndices faces = mesh->faces();
for (int face_index = 0; face_index < mesh->faces_num; face_index++) {
num_ptex_faces += (faces[face_index].size() == 4) ? 1 : faces[face_index].size();
}
return num_ptex_faces;
}
static void displacement_data_init_mapping(SubdivDisplacement *displacement, const Mesh *mesh)
static void displacement_data_init_mapping(Displacement *displacement, const Mesh *mesh)
{
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
displacement->user_data);
const blender::OffsetIndices faces = mesh->faces();
const OffsetIndices faces = mesh->faces();
const int num_ptex_faces = count_num_ptex_faces(mesh);
/* Allocate memory. */
data->ptex_face_corner = static_cast<PolyCornerIndex *>(
@@ -386,7 +388,7 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement, con
int ptex_face_index = 0;
PolyCornerIndex *ptex_face_corner = data->ptex_face_corner;
for (int face_index = 0; face_index < mesh->faces_num; face_index++) {
const blender::IndexRange face = faces[face_index];
const IndexRange face = faces[face_index];
if (face.size() == 4) {
ptex_face_corner[ptex_face_index].face_index = face_index;
ptex_face_corner[ptex_face_index].corner = 0;
@@ -402,7 +404,7 @@ static void displacement_data_init_mapping(SubdivDisplacement *displacement, con
}
}
static void displacement_init_data(SubdivDisplacement *displacement,
static void displacement_init_data(Displacement *displacement,
Subdiv *subdiv,
Mesh *mesh,
const MultiresModifierData *mmd)
@@ -410,36 +412,34 @@ static void displacement_init_data(SubdivDisplacement *displacement,
MultiresDisplacementData *data = static_cast<MultiresDisplacementData *>(
displacement->user_data);
data->subdiv = subdiv;
data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
data->grid_size = grid_size_from_level(mmd->totlvl);
data->mesh = mesh;
data->mmd = mmd;
data->faces = mesh->faces();
data->mdisps = static_cast<const MDisps *>(CustomData_get_layer(&mesh->corner_data, CD_MDISPS));
data->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
data->face_ptex_offset = face_ptex_offset_get(subdiv);
data->is_initialized = false;
displacement_data_init_mapping(displacement, mesh);
}
static void displacement_init_functions(SubdivDisplacement *displacement)
static void displacement_init_functions(Displacement *displacement)
{
displacement->initialize = initialize;
displacement->eval_displacement = eval_displacement;
displacement->free = free_displacement;
}
void BKE_subdiv_displacement_attach_from_multires(Subdiv *subdiv,
Mesh *mesh,
const MultiresModifierData *mmd)
void displacement_attach_from_multires(Subdiv *subdiv, Mesh *mesh, const MultiresModifierData *mmd)
{
/* Make sure we don't have previously assigned displacement. */
BKE_subdiv_displacement_detach(subdiv);
displacement_detach(subdiv);
/* It is possible to have mesh without CD_MDISPS layer. Happens when using
* dynamic topology. */
if (!CustomData_has_layer(&mesh->corner_data, CD_MDISPS)) {
return;
}
/* Allocate all required memory. */
SubdivDisplacement *displacement = MEM_cnew<SubdivDisplacement>("multires displacement");
Displacement *displacement = MEM_cnew<Displacement>("multires displacement");
displacement->user_data = MEM_callocN(sizeof(MultiresDisplacementData),
"multires displacement data");
displacement_init_data(displacement, subdiv, mesh, mmd);
@@ -447,3 +447,5 @@ void BKE_subdiv_displacement_attach_from_multires(Subdiv *subdiv,
/* Finish. */
subdiv->displacement_evaluator = displacement;
}
} // namespace blender::bke::subdiv

View File

@@ -25,6 +25,8 @@
* Helper functions.
*/
namespace blender::bke::subdiv {
static eOpenSubdivEvaluator opensubdiv_evalutor_from_subdiv_evaluator_type(
eSubdivEvaluatorType evaluator_type)
{
@@ -44,12 +46,12 @@ static eOpenSubdivEvaluator opensubdiv_evalutor_from_subdiv_evaluator_type(
* Main subdivision evaluation.
*/
bool BKE_subdiv_eval_begin(Subdiv *subdiv,
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache,
const OpenSubdiv_EvaluatorSettings *settings)
bool eval_begin(Subdiv *subdiv,
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache,
const OpenSubdiv_EvaluatorSettings *settings)
{
BKE_subdiv_stats_reset(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
stats_reset(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
if (subdiv->topology_refiner == nullptr) {
/* Happens on input mesh with just loose geometry,
* or when OpenSubdiv is disabled */
@@ -58,10 +60,10 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv,
if (subdiv->evaluator == nullptr) {
eOpenSubdivEvaluator opensubdiv_evaluator_type =
opensubdiv_evalutor_from_subdiv_evaluator_type(evaluator_type);
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
subdiv->evaluator = openSubdiv_createEvaluatorFromTopologyRefiner(
subdiv->topology_refiner, opensubdiv_evaluator_type, evaluator_cache);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_CREATE);
if (subdiv->evaluator == nullptr) {
return false;
}
@@ -70,15 +72,14 @@ bool BKE_subdiv_eval_begin(Subdiv *subdiv,
/* TODO(sergey): Check for topology change. */
}
subdiv->evaluator->setSettings(subdiv->evaluator, settings);
BKE_subdiv_eval_init_displacement(subdiv);
eval_init_displacement(subdiv);
return true;
}
static void set_coarse_positions(Subdiv *subdiv,
const blender::Span<blender::float3> positions,
const blender::bke::LooseVertCache &verts_no_face)
const Span<float3> positions,
const bke::LooseVertCache &verts_no_face)
{
using namespace blender;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
if (verts_no_face.count == 0) {
evaluator->setCoarsePositions(
@@ -105,7 +106,7 @@ static void set_coarse_positions(Subdiv *subdiv,
struct FaceVaryingDataFromUVContext {
OpenSubdiv_TopologyRefiner *topology_refiner;
const Mesh *mesh;
blender::OffsetIndices<int> faces;
OffsetIndices<int> faces;
const float (*mloopuv)[2];
float (*buffer)[2];
int layer_index;
@@ -205,25 +206,22 @@ static void get_mesh_evaluator_settings(OpenSubdiv_EvaluatorSettings *settings,
(CustomData_has_layer(&mesh->vert_data, 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)
bool eval_begin_from_mesh(Subdiv *subdiv,
const Mesh *mesh,
const float (*coarse_vertex_cos)[3],
eSubdivEvaluatorType evaluator_type,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
OpenSubdiv_EvaluatorSettings settings = {0};
get_mesh_evaluator_settings(&settings, mesh);
if (!BKE_subdiv_eval_begin(subdiv, evaluator_type, evaluator_cache, &settings)) {
if (!eval_begin(subdiv, evaluator_type, evaluator_cache, &settings)) {
return false;
}
return BKE_subdiv_eval_refine_from_mesh(subdiv, mesh, coarse_vertex_cos);
return eval_refine_from_mesh(subdiv, mesh, coarse_vertex_cos);
}
bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
const Mesh *mesh,
const float (*coarse_vertex_cos)[3])
bool eval_refine_from_mesh(Subdiv *subdiv, const Mesh *mesh, const float (*coarse_vertex_cos)[3])
{
using namespace blender;
if (subdiv->evaluator == nullptr) {
/* NOTE: This situation is supposed to be handled by begin(). */
BLI_assert_msg(0, "Is not supposed to happen");
@@ -247,13 +245,13 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
/* 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);
stats_begin(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
subdiv->evaluator->refine(subdiv->evaluator);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
stats_end(&subdiv->stats, SUBDIV_STATS_EVALUATOR_REFINE);
return true;
}
void BKE_subdiv_eval_init_displacement(Subdiv *subdiv)
void eval_init_displacement(Subdiv *subdiv)
{
if (subdiv->displacement_evaluator == nullptr) {
return;
@@ -268,20 +266,19 @@ void BKE_subdiv_eval_init_displacement(Subdiv *subdiv)
* Single point queries.
*/
void BKE_subdiv_eval_limit_point(
void eval_limit_point(
Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3])
{
BKE_subdiv_eval_limit_point_and_derivatives(
subdiv, ptex_face_index, u, v, r_P, nullptr, nullptr);
eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, r_P, nullptr, nullptr);
}
void BKE_subdiv_eval_limit_point_and_derivatives(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
float r_P[3],
float r_dPdu[3],
float r_dPdv[3])
void eval_limit_point_and_derivatives(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
float r_P[3],
float r_dPdu[3],
float r_dPdv[3])
{
subdiv->evaluator->evaluateLimit(subdiv->evaluator, ptex_face_index, u, v, r_P, r_dPdu, r_dPdv);
@@ -309,43 +306,43 @@ void BKE_subdiv_eval_limit_point_and_derivatives(Subdiv *subdiv,
}
}
void BKE_subdiv_eval_limit_point_and_normal(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
float r_P[3],
float r_N[3])
void eval_limit_point_and_normal(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
float r_P[3],
float r_N[3])
{
float dPdu[3], dPdv[3];
BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, r_P, dPdu, dPdv);
eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, r_P, dPdu, dPdv);
cross_v3_v3v3(r_N, dPdu, dPdv);
normalize_v3(r_N);
}
void BKE_subdiv_eval_vertex_data(
void 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,
const float u,
const float v,
float r_face_varying[2])
void eval_face_varying(Subdiv *subdiv,
const int face_varying_channel,
const int ptex_face_index,
const float u,
const float v,
float r_face_varying[2])
{
subdiv->evaluator->evaluateFaceVarying(
subdiv->evaluator, face_varying_channel, ptex_face_index, u, v, r_face_varying);
}
void BKE_subdiv_eval_displacement(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
const float dPdu[3],
const float dPdv[3],
float r_D[3])
void eval_displacement(Subdiv *subdiv,
const int ptex_face_index,
const float u,
const float v,
const float dPdu[3],
const float dPdv[3],
float r_D[3])
{
if (subdiv->displacement_evaluator == nullptr) {
zero_v3(r_D);
@@ -355,16 +352,18 @@ void BKE_subdiv_eval_displacement(Subdiv *subdiv,
subdiv->displacement_evaluator, ptex_face_index, u, v, dPdu, dPdv, r_D);
}
void BKE_subdiv_eval_final_point(
void eval_final_point(
Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3])
{
if (subdiv->displacement_evaluator) {
float dPdu[3], dPdv[3], D[3];
BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, r_P, dPdu, dPdv);
BKE_subdiv_eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, r_P, dPdu, dPdv);
eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
add_v3_v3(r_P, D);
}
else {
BKE_subdiv_eval_limit_point(subdiv, ptex_face_index, u, v, r_P);
eval_limit_point(subdiv, ptex_face_index, u, v, r_P);
}
}
} // namespace blender::bke::subdiv

View File

@@ -20,8 +20,7 @@
#include "MEM_guardedalloc.h"
using blender::IndexRange;
using blender::int2;
namespace blender::bke::subdiv {
/* -------------------------------------------------------------------- */
/** \name General helpers
@@ -66,13 +65,13 @@ BLI_INLINE int ptex_face_resolution_get(const IndexRange face, int resolution)
struct SubdivForeachTaskContext {
const Mesh *coarse_mesh;
blender::Span<int2> coarse_edges;
blender::OffsetIndices<int> coarse_faces;
blender::Span<int> coarse_corner_verts;
blender::Span<int> coarse_corner_edges;
const SubdivToMeshSettings *settings;
Span<int2> coarse_edges;
OffsetIndices<int> coarse_faces;
Span<int> coarse_corner_verts;
Span<int> coarse_corner_edges;
const ToMeshSettings *settings;
/* Callbacks. */
const SubdivForeachContext *foreach_context;
const ForeachContext *foreach_context;
/* Counters of geometry in subdivided mesh, initialized as a part of
* offsets calculation.
*/
@@ -119,7 +118,7 @@ struct SubdivForeachTaskContext {
static void *subdiv_foreach_tls_alloc(SubdivForeachTaskContext *ctx)
{
const SubdivForeachContext *foreach_context = ctx->foreach_context;
const ForeachContext *foreach_context = ctx->foreach_context;
void *tls = nullptr;
if (foreach_context->user_data_tls_size != 0) {
tls = MEM_mallocN(foreach_context->user_data_tls_size, "tls");
@@ -259,7 +258,7 @@ static void subdiv_foreach_ctx_init(Subdiv *subdiv, SubdivForeachTaskContext *ct
subdiv_foreach_ctx_init_offsets(ctx);
/* Calculate number of geometry in the result subdivision mesh. */
subdiv_foreach_ctx_count(ctx);
ctx->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
ctx->face_ptex_offset = face_ptex_offset_get(subdiv);
}
static void subdiv_foreach_ctx_free(SubdivForeachTaskContext *ctx)
@@ -279,12 +278,11 @@ static void subdiv_foreach_ctx_free(SubdivForeachTaskContext *ctx)
/* Traversal of corner vertices. They are coming from coarse vertices. */
static void subdiv_foreach_corner_vertices_regular_do(
SubdivForeachTaskContext *ctx,
void *tls,
const int coarse_face_index,
SubdivForeachVertexFromCornerCb vertex_corner,
bool check_usage)
static void subdiv_foreach_corner_vertices_regular_do(SubdivForeachTaskContext *ctx,
void *tls,
const int coarse_face_index,
ForeachVertexFromCornerCb vertex_corner,
bool check_usage)
{
const float weights[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
@@ -319,12 +317,11 @@ static void subdiv_foreach_corner_vertices_regular(SubdivForeachTaskContext *ctx
ctx, tls, coarse_face_index, ctx->foreach_context->vertex_corner, true);
}
static void subdiv_foreach_corner_vertices_special_do(
SubdivForeachTaskContext *ctx,
void *tls,
const int coarse_face_index,
SubdivForeachVertexFromCornerCb vertex_corner,
bool check_usage)
static void subdiv_foreach_corner_vertices_special_do(SubdivForeachTaskContext *ctx,
void *tls,
const int coarse_face_index,
ForeachVertexFromCornerCb vertex_corner,
bool check_usage)
{
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
int ptex_face_index = ctx->face_ptex_offset[coarse_face_index];
@@ -405,7 +402,7 @@ static void subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext *ctx,
static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ctx,
void *tls,
const int coarse_face_index,
SubdivForeachVertexFromEdgeCb vertex_edge,
ForeachVertexFromEdgeCb vertex_edge,
bool check_usage)
{
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
@@ -469,7 +466,7 @@ static void subdiv_foreach_edge_vertices_regular(SubdivForeachTaskContext *ctx,
static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ctx,
void *tls,
const int coarse_face_index,
SubdivForeachVertexFromEdgeCb vertex_edge,
ForeachVertexFromEdgeCb vertex_edge,
bool check_usage)
{
const IndexRange coarse_face = ctx->coarse_faces[coarse_face_index];
@@ -1752,7 +1749,7 @@ static void subdiv_foreach_single_thread_tasks(SubdivForeachTaskContext *ctx)
subdiv_foreach_single_geometry_vertices(ctx, tls);
subdiv_foreach_tls_free(ctx, tls);
const SubdivForeachContext *foreach_context = ctx->foreach_context;
const ForeachContext *foreach_context = ctx->foreach_context;
const bool is_loose_geometry_tagged = (foreach_context->vertex_every_edge != nullptr &&
foreach_context->vertex_every_corner != nullptr);
const bool is_loose_geometry_tags_needed = (foreach_context->vertex_loose != nullptr ||
@@ -1795,10 +1792,10 @@ static void subdiv_foreach_free(const void *__restrict userdata, void *__restric
ctx->foreach_context->user_data_tls_free(userdata_chunk);
}
bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
const SubdivForeachContext *context,
const SubdivToMeshSettings *mesh_settings,
const Mesh *coarse_mesh)
bool foreach_subdiv_geometry(Subdiv *subdiv,
const ForeachContext *context,
const ToMeshSettings *mesh_settings,
const Mesh *coarse_mesh)
{
SubdivForeachTaskContext ctx = {nullptr};
ctx.coarse_mesh = coarse_mesh;
@@ -1867,3 +1864,5 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
}
/** \} */
} // namespace blender::bke::subdiv

View File

@@ -13,33 +13,35 @@
#include "BKE_subdiv.hh"
BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(const float ptex_u,
const float ptex_v,
float *r_grid_u,
float *r_grid_v)
namespace blender::bke::subdiv {
BLI_INLINE void ptex_face_uv_to_grid_uv(const float ptex_u,
const float ptex_v,
float *r_grid_u,
float *r_grid_v)
{
*r_grid_u = 1.0f - ptex_v;
*r_grid_v = 1.0f - ptex_u;
}
BLI_INLINE void BKE_subdiv_grid_uv_to_ptex_face_uv(const float grid_u,
const float grid_v,
float *r_ptex_u,
float *r_ptex_v)
BLI_INLINE void grid_uv_to_ptex_face_uv(const float grid_u,
const float grid_v,
float *r_ptex_u,
float *r_ptex_v)
{
*r_ptex_u = 1.0f - grid_v;
*r_ptex_v = 1.0f - grid_u;
}
BLI_INLINE int BKE_subdiv_grid_size_from_level(const int level)
BLI_INLINE int grid_size_from_level(const int level)
{
return (1 << (level - 1)) + 1;
}
BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(const float quad_u,
const float quad_v,
float *r_corner_u,
float *r_corner_v)
BLI_INLINE int rotate_quad_to_corner(const float quad_u,
const float quad_v,
float *r_corner_u,
float *r_corner_v)
{
int corner;
if (quad_u <= 0.5f && quad_v <= 0.5f) {
@@ -66,7 +68,7 @@ BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(const float quad_u,
return corner;
}
BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(
BLI_INLINE void rotate_grid_to_quad(
const int corner, const float grid_u, const float grid_v, float *r_quad_u, float *r_quad_v)
{
if (corner == 0) {
@@ -88,7 +90,9 @@ BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(
}
}
BLI_INLINE float BKE_subdiv_crease_to_sharpness_f(float edge_crease)
BLI_INLINE float crease_to_sharpness(float edge_crease)
{
return edge_crease * edge_crease * 10.0f;
}
} // namespace blender::bke::subdiv

View File

@@ -27,32 +27,27 @@
#include "MEM_guardedalloc.h"
using blender::float2;
using blender::float3;
using blender::IndexRange;
using blender::int2;
using blender::MutableSpan;
using blender::Span;
namespace blender::bke::subdiv {
/* -------------------------------------------------------------------- */
/** \name Subdivision Context
* \{ */
struct SubdivMeshContext {
const SubdivToMeshSettings *settings;
const ToMeshSettings *settings;
const Mesh *coarse_mesh;
blender::Span<float3> coarse_positions;
blender::Span<int2> coarse_edges;
blender::OffsetIndices<int> coarse_faces;
blender::Span<int> coarse_corner_verts;
Span<float3> coarse_positions;
Span<int2> coarse_edges;
OffsetIndices<int> coarse_faces;
Span<int> coarse_corner_verts;
Subdiv *subdiv;
Mesh *subdiv_mesh;
blender::MutableSpan<float3> subdiv_positions;
blender::MutableSpan<int2> subdiv_edges;
blender::MutableSpan<int> subdiv_face_offsets;
blender::MutableSpan<int> subdiv_corner_verts;
blender::MutableSpan<int> subdiv_corner_edges;
MutableSpan<float3> subdiv_positions;
MutableSpan<int2> subdiv_edges;
MutableSpan<int> subdiv_face_offsets;
MutableSpan<int> subdiv_corner_verts;
MutableSpan<int> subdiv_corner_edges;
/* Cached custom data arrays for faster access. */
int *vert_origindex;
@@ -72,12 +67,12 @@ struct SubdivMeshContext {
/* Write optimal display edge tags into a boolean array rather than the final bit vector
* to avoid race conditions when setting bits. */
blender::Array<bool> subdiv_display_edges;
Array<bool> subdiv_display_edges;
/* Lazily initialize a map from vertices to connected edges. */
blender::Array<int> vert_to_edge_offsets;
blender::Array<int> vert_to_edge_indices;
blender::GroupedSpan<int> vert_to_edge_map;
Array<int> vert_to_edge_offsets;
Array<int> vert_to_edge_indices;
GroupedSpan<int> vert_to_edge_map;
};
static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
@@ -231,8 +226,8 @@ static void vertex_interpolation_init(const SubdivMeshContext *ctx,
/* Interpolate center of face right away, it stays unchanged for all
* ptex faces. */
const float weight = 1.0f / float(coarse_face.size());
blender::Array<float, 32> weights(coarse_face.size());
blender::Array<int, 32> indices(coarse_face.size());
Array<float, 32> weights(coarse_face.size());
Array<int, 32> indices(coarse_face.size());
for (int i = 0; i < coarse_face.size(); i++) {
weights[i] = weight;
indices[i] = ctx->coarse_corner_verts[coarse_face.start() + i];
@@ -361,8 +356,8 @@ static void loop_interpolation_init(const SubdivMeshContext *ctx,
/* Interpolate center of face right away, it stays unchanged for all
* ptex faces. */
const float weight = 1.0f / float(coarse_face.size());
blender::Array<float, 32> weights(coarse_face.size());
blender::Array<int, 32> indices(coarse_face.size());
Array<float, 32> weights(coarse_face.size());
Array<int, 32> indices(coarse_face.size());
for (int i = 0; i < coarse_face.size(); i++) {
weights[i] = weight;
indices[i] = coarse_face.start() + i;
@@ -472,7 +467,7 @@ static void subdiv_vertex_orco_evaluate(const SubdivMeshContext *ctx,
{
if (ctx->orco || ctx->cloth_orco) {
float vertex_data[6];
BKE_subdiv_eval_vertex_data(ctx->subdiv, ptex_face_index, u, v, vertex_data);
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);
@@ -501,11 +496,11 @@ static void subdiv_accumulate_vertex_displacement(SubdivMeshContext *ctx,
/* Accumulate displacement. */
Subdiv *subdiv = ctx->subdiv;
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);
eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
/* NOTE: The subdivided mesh is allocated in this module, and its vertices are kept at zero
* locations as a default calloc(). */
BKE_subdiv_eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
ctx->subdiv_positions[subdiv_vertex_index] += D;
if (ctx->accumulated_counters) {
@@ -519,7 +514,7 @@ static void subdiv_accumulate_vertex_displacement(SubdivMeshContext *ctx,
/** \name Callbacks
* \{ */
static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context,
static bool subdiv_mesh_topology_info(const ForeachContext *foreach_context,
const int num_vertices,
const int num_edges,
const int num_loops,
@@ -539,7 +534,7 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.clear();
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.resize(num_vertices);
if (subdiv_context->settings->use_optimal_display) {
subdiv_context->subdiv_display_edges = blender::Array<bool>(num_edges, false);
subdiv_context->subdiv_display_edges = Array<bool>(num_edges, false);
}
return true;
}
@@ -599,7 +594,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);
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_position);
eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_position);
/* Apply displacement. */
subdiv_position += D;
/* Evaluate undeformed texture coordinate. */
@@ -627,7 +622,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);
BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_position);
eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_position);
/* Apply displacement. */
add_v3_v3(subdiv_position, D);
/* Evaluate undeformed texture coordinate. */
@@ -635,7 +630,7 @@ static void evaluate_vertex_and_apply_displacement_interpolate(
}
static void subdiv_mesh_vertex_displacement_every_corner_or_edge(
const SubdivForeachContext *foreach_context,
const ForeachContext *foreach_context,
void * /*tls*/,
const int ptex_face_index,
const float u,
@@ -646,22 +641,21 @@ static void subdiv_mesh_vertex_displacement_every_corner_or_edge(
subdiv_accumulate_vertex_displacement(ctx, ptex_face_index, u, v, subdiv_vertex_index);
}
static void subdiv_mesh_vertex_displacement_every_corner(
const SubdivForeachContext *foreach_context,
void *tls,
const int ptex_face_index,
const float u,
const float v,
const int /*coarse_vertex_index*/,
const int /*coarse_face_index*/,
const int /*coarse_corner*/,
const int subdiv_vertex_index)
static void subdiv_mesh_vertex_displacement_every_corner(const ForeachContext *foreach_context,
void *tls,
const int ptex_face_index,
const float u,
const float v,
const int /*coarse_vertex_index*/,
const int /*coarse_face_index*/,
const int /*coarse_corner*/,
const int subdiv_vertex_index)
{
subdiv_mesh_vertex_displacement_every_corner_or_edge(
foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
}
static void subdiv_mesh_vertex_displacement_every_edge(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_displacement_every_edge(const ForeachContext *foreach_context,
void *tls,
const int ptex_face_index,
const float u,
@@ -675,7 +669,7 @@ static void subdiv_mesh_vertex_displacement_every_edge(const SubdivForeachContex
foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
}
static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_corner(const ForeachContext *foreach_context,
void * /*tls*/,
const int ptex_face_index,
const float u,
@@ -722,7 +716,7 @@ static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx,
tls->vertex_interpolation_coarse_corner = coarse_corner;
}
static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_edge(const ForeachContext *foreach_context,
void *tls_v,
const int ptex_face_index,
const float u,
@@ -767,7 +761,7 @@ static void subdiv_mesh_tag_center_vertex(const IndexRange coarse_face,
}
}
static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_inner(const ForeachContext *foreach_context,
void *tls_v,
const int ptex_face_index,
const float u,
@@ -784,7 +778,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
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);
BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, subdiv_position);
eval_final_point(subdiv, ptex_face_index, u, v, subdiv_position);
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);
}
@@ -815,7 +809,7 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
}
}
static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_edge(const ForeachContext *foreach_context,
void * /*tls*/,
const int coarse_edge_index,
const int subdiv_edge_index,
@@ -863,7 +857,7 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
}
Subdiv *subdiv = ctx->subdiv;
for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
BKE_subdiv_eval_face_varying(
eval_face_varying(
subdiv, layer_index, ptex_face_index, u, v, ctx->uv_layers[layer_index][corner_index]);
}
}
@@ -899,7 +893,7 @@ static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx,
tls->loop_interpolation_coarse_corner = coarse_corner;
}
static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_loop(const ForeachContext *foreach_context,
void *tls_v,
const int ptex_face_index,
const float u,
@@ -926,7 +920,7 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
/** \name Polygons subdivision process
* \{ */
static void subdiv_mesh_face(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_face(const ForeachContext *foreach_context,
void * /*tls*/,
const int coarse_face_index,
const int subdiv_face_index,
@@ -949,7 +943,7 @@ static void subdiv_mesh_face(const SubdivForeachContext *foreach_context,
/** \name Loose elements subdivision process
* \{ */
static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_loose(const ForeachContext *foreach_context,
void * /*tls*/,
const int coarse_vertex_index,
const int subdiv_vertex_index)
@@ -962,7 +956,7 @@ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context
* - neighbors[0] is an edge adjacent to edge->v1.
* - neighbors[1] is an edge adjacent to edge->v2. */
static void find_edge_neighbors(const int2 *coarse_edges,
const blender::GroupedSpan<int> vert_to_edge_map,
const GroupedSpan<int> vert_to_edge_map,
const int edge_index,
const int2 *neighbors[2])
{
@@ -1035,13 +1029,13 @@ static void points_for_loose_edges_interpolation_get(const float (*coarse_positi
}
}
void BKE_subdiv_mesh_interpolate_position_on_edge(const float (*coarse_positions)[3],
const blender::int2 *coarse_edges,
const blender::GroupedSpan<int> vert_to_edge_map,
const int coarse_edge_index,
const bool is_simple,
const float u,
float pos_r[3])
void mesh_interpolate_position_on_edge(const float (*coarse_positions)[3],
const int2 *coarse_edges,
const GroupedSpan<int> vert_to_edge_map,
const int coarse_edge_index,
const bool is_simple,
const float u,
float pos_r[3])
{
const int2 &coarse_edge = coarse_edges[coarse_edge_index];
if (is_simple) {
@@ -1083,7 +1077,7 @@ static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx,
}
}
static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach_context,
static void subdiv_mesh_vertex_of_loose_edge(const ForeachContext *foreach_context,
void * /*tls*/,
const int coarse_edge_index,
const float u,
@@ -1099,7 +1093,7 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach
subdiv_mesh_vertex_of_loose_edge_interpolate(ctx, coarse_edge, u, subdiv_vertex_index);
}
/* Interpolate coordinate. */
BKE_subdiv_mesh_interpolate_position_on_edge(
mesh_interpolate_position_on_edge(
reinterpret_cast<const float(*)[3]>(ctx->coarse_positions.data()),
ctx->coarse_edges.data(),
ctx->vert_to_edge_map,
@@ -1116,7 +1110,7 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach
* \{ */
static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
SubdivForeachContext *foreach_context)
ForeachContext *foreach_context)
{
memset(foreach_context, 0, sizeof(*foreach_context));
/* General information. */
@@ -1143,24 +1137,20 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
/** \name Public entry point
* \{ */
Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
const SubdivToMeshSettings *settings,
const Mesh *coarse_mesh)
Mesh *subdiv_to_mesh(Subdiv *subdiv, const ToMeshSettings *settings, const Mesh *coarse_mesh)
{
using namespace blender;
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_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 (!BKE_subdiv_eval_begin_from_mesh(
subdiv, coarse_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr))
{
if (!eval_begin_from_mesh(subdiv, coarse_mesh, nullptr, SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) {
/* This could happen in two situations:
* - OpenSubdiv is disabled.
* - Something totally bad happened, and OpenSubdiv rejected our
* topology.
* In either way, we can't safely continue. */
if (coarse_mesh->faces_num) {
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
return nullptr;
}
}
@@ -1174,7 +1164,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
subdiv_context.coarse_faces = coarse_mesh->faces();
subdiv_context.coarse_corner_verts = coarse_mesh->corner_verts();
if (coarse_mesh->loose_edges().count > 0) {
subdiv_context.vert_to_edge_map = bke::mesh::build_vert_to_edge_map(
subdiv_context.vert_to_edge_map = mesh::build_vert_to_edge_map(
subdiv_context.coarse_edges,
coarse_mesh->verts_num,
subdiv_context.vert_to_edge_offsets,
@@ -1184,15 +1174,15 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
subdiv_context.subdiv = subdiv;
subdiv_context.have_displacement = (subdiv->displacement_evaluator != nullptr);
/* Multi-threaded traversal/evaluation. */
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
SubdivForeachContext foreach_context;
stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
ForeachContext foreach_context;
setup_foreach_callbacks(&subdiv_context, &foreach_context);
SubdivMeshTLS tls{};
foreach_context.user_data = &subdiv_context;
foreach_context.user_data_tls_size = sizeof(SubdivMeshTLS);
foreach_context.user_data_tls = &tls;
BKE_subdiv_foreach_subdiv_geometry(subdiv, &foreach_context, settings, coarse_mesh);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
foreach_subdiv_geometry(subdiv, &foreach_context, settings, coarse_mesh);
stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
Mesh *result = subdiv_context.subdiv_mesh;
/* NOTE: Using normals from the limit surface gives different results than Blender's vertex
@@ -1228,9 +1218,11 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
}
// BKE_mesh_validate(result, true, true);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
subdiv_mesh_context_free(&subdiv_context);
return result;
}
/** \} */
} // namespace blender::bke::subdiv

View File

@@ -19,28 +19,29 @@
#include "GPU_capabilities.hh"
#include "GPU_context.hh"
SubdivSettings BKE_subsurf_modifier_settings_init(const SubsurfModifierData *smd,
const bool use_render_params)
using namespace blender::bke;
subdiv::Settings BKE_subsurf_modifier_settings_init(const SubsurfModifierData *smd,
const bool use_render_params)
{
const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels;
SubdivSettings settings{};
subdiv::Settings settings{};
settings.is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
settings.is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision);
settings.level = settings.is_simple ? 1 :
(settings.is_adaptive ? smd->quality : requested_levels);
settings.use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease);
settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
settings.vtx_boundary_interpolation = subdiv::vtx_boundary_interpolation_from_subsurf(
smd->boundary_smooth);
settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
smd->uv_smooth);
settings.fvar_linear_interpolation = subdiv::fvar_interpolation_from_uv_smooth(smd->uv_smooth);
return settings;
}
bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params)
{
SubdivSettings settings = BKE_subsurf_modifier_settings_init(smd, use_render_params);
subdiv::Settings settings = BKE_subsurf_modifier_settings_init(smd, use_render_params);
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
if (settings.level == 0) {
@@ -90,7 +91,7 @@ bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd
bool BKE_subsurf_modifier_has_split_normals(const SubsurfModifierData *smd, const Mesh *mesh)
{
return BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh) ||
mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner;
mesh->normals_domain() == MeshNormalDomain::Corner;
}
static bool is_subdivision_evaluation_possible_on_gpu()
@@ -157,20 +158,20 @@ bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
return runtime_data && runtime_data->has_gpu_subdiv;
}
void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv) = nullptr;
void (*BKE_subsurf_modifier_free_gpu_cache_cb)(subdiv::Subdiv *subdiv) = nullptr;
Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data,
const Mesh *mesh,
const bool for_draw_code)
subdiv::Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data,
const Mesh *mesh,
const bool for_draw_code)
{
if (for_draw_code) {
runtime_data->used_gpu = 2; /* countdown in frames */
return runtime_data->subdiv_gpu = BKE_subdiv_update_from_mesh(
return runtime_data->subdiv_gpu = subdiv::update_from_mesh(
runtime_data->subdiv_gpu, &runtime_data->settings, mesh);
}
runtime_data->used_cpu = 2;
return runtime_data->subdiv_cpu = BKE_subdiv_update_from_mesh(
return runtime_data->subdiv_cpu = subdiv::update_from_mesh(
runtime_data->subdiv_cpu, &runtime_data->settings, mesh);
}

View File

@@ -12,7 +12,9 @@
#include "BLI_time.h"
void BKE_subdiv_stats_init(SubdivStats *stats)
namespace blender::bke::subdiv {
void stats_init(SubdivStats *stats)
{
stats->topology_refiner_creation_time = 0.0;
stats->subdiv_to_mesh_time = 0.0;
@@ -24,22 +26,22 @@ void BKE_subdiv_stats_init(SubdivStats *stats)
stats->topology_compare_time = 0.0;
}
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
void stats_begin(SubdivStats *stats, StatsValue value)
{
stats->begin_timestamp_[value] = BLI_time_now_seconds();
}
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
void stats_end(SubdivStats *stats, StatsValue value)
{
stats->values_[value] = BLI_time_now_seconds() - stats->begin_timestamp_[value];
}
void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value)
void stats_reset(SubdivStats *stats, StatsValue value)
{
stats->values_[value] = 0.0;
}
void BKE_subdiv_stats_print(const SubdivStats *stats)
void stats_print(const SubdivStats *stats)
{
#define STATS_PRINT_TIME(stats, value, description) \
do { \
@@ -61,3 +63,5 @@ void BKE_subdiv_stats_print(const SubdivStats *stats)
#undef STATS_PRINT_TIME
}
} // namespace blender::bke::subdiv

View File

@@ -12,8 +12,12 @@
#include "opensubdiv_topology_refiner_capi.hh"
int BKE_subdiv_topology_num_fvar_layers_get(const Subdiv *subdiv)
namespace blender::bke::subdiv {
int topology_num_fvar_layers_get(const Subdiv *subdiv)
{
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
return topology_refiner->getNumFVarChannels(topology_refiner);
}
} // namespace blender::bke::subdiv

View File

@@ -585,7 +585,7 @@ gpu::VertBuf *draw_subdiv_build_origindex_buffer(int *vert_origindex, uint num_l
/** \name Utilities for DRWPatchMap.
* \{ */
static void draw_patch_map_build(DRWPatchMap *gpu_patch_map, Subdiv *subdiv)
static void draw_patch_map_build(DRWPatchMap *gpu_patch_map, bke::subdiv::Subdiv *subdiv)
{
gpu::VertBuf *patch_map_handles = GPU_vertbuf_calloc();
GPU_vertbuf_init_with_format_ex(patch_map_handles, get_patch_handle_format(), GPU_USAGE_STATIC);
@@ -839,7 +839,8 @@ static DRWSubdivCache &mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache &mbc)
return *subdiv_cache;
}
static void draw_subdiv_invalidate_evaluator_for_orco(Subdiv *subdiv, const Mesh *mesh)
static void draw_subdiv_invalidate_evaluator_for_orco(bke::subdiv::Subdiv *subdiv,
const Mesh *mesh)
{
if (!(subdiv && subdiv->evaluator)) {
return;
@@ -875,8 +876,8 @@ static void draw_subdiv_invalidate_evaluator_for_orco(Subdiv *subdiv, const Mesh
struct DRWCacheBuildingContext {
const Mesh *coarse_mesh;
const Subdiv *subdiv;
const SubdivToMeshSettings *settings;
const bke::subdiv::Subdiv *subdiv;
const bke::subdiv::ToMeshSettings *settings;
DRWSubdivCache *cache;
@@ -901,7 +902,7 @@ struct DRWCacheBuildingContext {
const int *e_origindex;
};
static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_context,
static bool draw_subdiv_topology_info_cb(const bke::subdiv::ForeachContext *foreach_context,
const int num_verts,
const int num_edges,
const int num_loops,
@@ -1001,7 +1002,7 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
return true;
}
static void draw_subdiv_vertex_corner_cb(const SubdivForeachContext *foreach_context,
static void draw_subdiv_vertex_corner_cb(const bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int /*ptex_face_index*/,
const float /*u*/,
@@ -1016,7 +1017,7 @@ static void draw_subdiv_vertex_corner_cb(const SubdivForeachContext *foreach_con
ctx->vert_origindex_map[subdiv_vertex_index] = coarse_vertex_index;
}
static void draw_subdiv_vertex_edge_cb(const SubdivForeachContext * /*foreach_context*/,
static void draw_subdiv_vertex_edge_cb(const bke::subdiv::ForeachContext * /*foreach_context*/,
void * /*tls_v*/,
const int /*ptex_face_index*/,
const float /*u*/,
@@ -1026,10 +1027,10 @@ static void draw_subdiv_vertex_edge_cb(const SubdivForeachContext * /*foreach_co
const int /*coarse_corner*/,
const int /*subdiv_vertex_index*/)
{
/* Required if SubdivForeachContext.vertex_corner is also set. */
/* Required if bke::subdiv::ForeachContext.vertex_corner is also set. */
}
static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context,
static void draw_subdiv_edge_cb(const bke::subdiv::ForeachContext *foreach_context,
void * /*tls*/,
const int coarse_edge_index,
const int subdiv_edge_index,
@@ -1066,7 +1067,7 @@ static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context,
}
}
static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context,
static void draw_subdiv_loop_cb(const bke::subdiv::ForeachContext *foreach_context,
void * /*tls_v*/,
const int ptex_face_index,
const float u,
@@ -1089,7 +1090,7 @@ static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context,
ctx->subdiv_loop_vert_index[subdiv_loop_index] = coarse_vertex_index;
}
static void draw_subdiv_foreach_callbacks(SubdivForeachContext *foreach_context)
static void draw_subdiv_foreach_callbacks(bke::subdiv::ForeachContext *foreach_context)
{
memset(foreach_context, 0, sizeof(*foreach_context));
foreach_context->topology_info = draw_subdiv_topology_info_cb;
@@ -1099,16 +1100,17 @@ static void draw_subdiv_foreach_callbacks(SubdivForeachContext *foreach_context)
foreach_context->vertex_edge = draw_subdiv_vertex_edge_cb;
}
static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context, Subdiv *subdiv)
static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context,
bke::subdiv::Subdiv *subdiv)
{
SubdivForeachContext foreach_context;
bke::subdiv::ForeachContext foreach_context;
draw_subdiv_foreach_callbacks(&foreach_context);
foreach_context.user_data = cache_building_context;
BKE_subdiv_foreach_subdiv_geometry(subdiv,
&foreach_context,
cache_building_context->settings,
cache_building_context->coarse_mesh);
bke::subdiv::foreach_subdiv_geometry(subdiv,
&foreach_context,
cache_building_context->settings,
cache_building_context->coarse_mesh);
/* Now that traversal is done, we can set up the right original indices for the
* subdiv-loop-to-coarse-edge map.
@@ -1166,11 +1168,11 @@ static void build_vertex_face_adjacency_maps(DRWSubdivCache &cache)
}
static bool draw_subdiv_build_cache(DRWSubdivCache &cache,
Subdiv *subdiv,
bke::subdiv::Subdiv *subdiv,
const Mesh *mesh_eval,
const SubsurfRuntimeData *runtime_data)
{
SubdivToMeshSettings to_mesh_settings;
bke::subdiv::ToMeshSettings to_mesh_settings;
to_mesh_settings.resolution = runtime_data->resolution;
to_mesh_settings.use_optimal_display = false;
@@ -1209,7 +1211,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache &cache,
/* Build buffers for the PatchMap. */
draw_patch_map_build(&cache.gpu_patch_map, subdiv);
cache.face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
cache.face_ptex_offset = bke::subdiv::face_ptex_offset_get(subdiv);
/* Build patch coordinates for all the face dots. */
cache.fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(),
@@ -1437,7 +1439,7 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache &cache,
return;
}
Subdiv *subdiv = cache.subdiv;
bke::subdiv::Subdiv *subdiv = cache.subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
OpenSubdiv_Buffer src_buffer_interface;
@@ -1519,7 +1521,7 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache &cache,
return;
}
Subdiv *subdiv = cache.subdiv;
bke::subdiv::Subdiv *subdiv = cache.subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
OpenSubdiv_Buffer src_buffer_interface;
@@ -1769,7 +1771,7 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache &cache,
return;
}
Subdiv *subdiv = cache.subdiv;
bke::subdiv::Subdiv *subdiv = cache.subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
OpenSubdiv_Buffer src_buffer_interface;
@@ -2117,13 +2119,14 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
draw_subdiv_invalidate_evaluator_for_orco(runtime_data->subdiv_gpu, mesh_eval);
Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh_eval, true);
bke::subdiv::Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(
runtime_data, mesh_eval, true);
if (!subdiv) {
return false;
}
if (!BKE_subdiv_eval_begin_from_mesh(
subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GPU, evaluator_cache))
if (!bke::subdiv::eval_begin_from_mesh(
subdiv, mesh_eval, nullptr, bke::subdiv::SUBDIV_EVALUATOR_TYPE_GPU, evaluator_cache))
{
/* This could happen in two situations:
* - OpenSubdiv is disabled.
@@ -2253,7 +2256,7 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac
DRWSubdivLooseVertex &subd_v1 = loose_subd_verts[subd_vert_offset];
subd_v1.coarse_vertex_index = (i == 0) ? coarse_edge[0] : -1u;
const float u1 = i * inv_resolution_1;
BKE_subdiv_mesh_interpolate_position_on_edge(
bke::subdiv::mesh_interpolate_position_on_edge(
reinterpret_cast<const float(*)[3]>(coarse_positions.data()),
coarse_edges.data(),
vert_to_edge_map,
@@ -2268,7 +2271,7 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac
DRWSubdivLooseVertex &subd_v2 = loose_subd_verts[subd_vert_offset];
subd_v2.coarse_vertex_index = ((i + 1) == resolution - 1) ? coarse_edge[1] : -1u;
const float u2 = (i + 1) * inv_resolution_1;
BKE_subdiv_mesh_interpolate_position_on_edge(
bke::subdiv::mesh_interpolate_position_on_edge(
reinterpret_cast<const float(*)[3]>(coarse_positions.data()),
coarse_edges.data(),
vert_to_edge_map,
@@ -2376,7 +2379,7 @@ void DRW_subdiv_free()
static LinkNode *gpu_subdiv_free_queue = nullptr;
static ThreadMutex gpu_subdiv_queue_mutex = BLI_MUTEX_INITIALIZER;
void DRW_subdiv_cache_free(Subdiv *subdiv)
void DRW_subdiv_cache_free(bke::subdiv::Subdiv *subdiv)
{
BLI_mutex_lock(&gpu_subdiv_queue_mutex);
BLI_linklist_prepend(&gpu_subdiv_free_queue, subdiv);
@@ -2392,10 +2395,11 @@ void DRW_cache_free_old_subdiv()
BLI_mutex_lock(&gpu_subdiv_queue_mutex);
while (gpu_subdiv_free_queue != nullptr) {
Subdiv *subdiv = static_cast<Subdiv *>(BLI_linklist_pop(&gpu_subdiv_free_queue));
bke::subdiv::Subdiv *subdiv = static_cast<bke::subdiv::Subdiv *>(
BLI_linklist_pop(&gpu_subdiv_free_queue));
/* Set the type to CPU so that we do actually free the cache. */
subdiv->evaluator->type = OPENSUBDIV_EVALUATOR_CPU;
BKE_subdiv_free(subdiv);
bke::subdiv::free(subdiv);
}
BLI_mutex_unlock(&gpu_subdiv_queue_mutex);

View File

@@ -17,7 +17,9 @@ class VertBuf;
struct GPUVertFormat;
struct Mesh;
struct Object;
namespace blender::bke::subdiv {
struct Subdiv;
}
struct ToolSettings;
namespace blender::draw {
@@ -103,7 +105,7 @@ struct DRWSubdivLooseGeom {
struct DRWSubdivCache {
const Mesh *mesh;
BMesh *bm;
Subdiv *subdiv;
bke::subdiv::Subdiv *subdiv;
bool optimal_display;
bool hide_unmapped_edges;
bool use_custom_loop_normals;
@@ -211,7 +213,7 @@ void DRW_create_subdivision(Object *ob,
void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cache);
void DRW_subdiv_cache_free(Subdiv *subdiv);
void DRW_subdiv_cache_free(bke::subdiv::Subdiv *subdiv);
void draw_subdiv_init_origindex_buffer(gpu::VertBuf *buffer,
int32_t *vert_origindex,

View File

@@ -863,14 +863,17 @@ static int bmesh_restore(bContext *C, Node &unode, Object *ob, SculptSession *ss
*
* Note that the dependency graph is ensured to be evaluated prior to the undo step is decoded,
* so if the object's modifier stack references other object it is all fine. */
static void refine_subdiv(Depsgraph *depsgraph, SculptSession *ss, Object *object, Subdiv *subdiv)
static void refine_subdiv(Depsgraph *depsgraph,
SculptSession *ss,
Object *object,
bke::subdiv::Subdiv *subdiv)
{
Array<float3> deformed_verts = BKE_multires_create_deformed_base_mesh_vert_coords(
depsgraph, object, ss->multires.modifier);
BKE_subdiv_eval_refine_from_mesh(subdiv,
static_cast<const Mesh *>(object->data),
reinterpret_cast<float(*)[3]>(deformed_verts.data()));
bke::subdiv::eval_refine_from_mesh(subdiv,
static_cast<const Mesh *>(object->data),
reinterpret_cast<float(*)[3]>(deformed_verts.data()));
}
static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt)

View File

@@ -564,23 +564,24 @@ static Mesh *subdivide_edit_mesh(const Object *object,
const BMEditMesh *em,
const SubsurfModifierData *smd)
{
using namespace blender;
Mesh *me_from_em = BKE_mesh_from_bmesh_for_eval_nomain(
em->bm, nullptr, static_cast<const Mesh *>(object->data));
BKE_mesh_ensure_default_orig_index_customdata(me_from_em);
SubdivSettings settings = BKE_subsurf_modifier_settings_init(smd, false);
bke::subdiv::Settings settings = BKE_subsurf_modifier_settings_init(smd, false);
if (settings.level == 1) {
return me_from_em;
}
SubdivToMeshSettings mesh_settings;
bke::subdiv::ToMeshSettings mesh_settings;
mesh_settings.resolution = (1 << smd->levels) + 1;
mesh_settings.use_optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges);
Subdiv *subdiv = BKE_subdiv_new_from_mesh(&settings, me_from_em);
Mesh *result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, me_from_em);
bke::subdiv::Subdiv *subdiv = bke::subdiv::new_from_mesh(&settings, me_from_em);
Mesh *result = bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, me_from_em);
BKE_id_free(nullptr, me_from_em);
BKE_subdiv_free(subdiv);
bke::subdiv::free(subdiv);
return result;
}

View File

@@ -45,7 +45,7 @@
struct MultiresRuntimeData {
/* Cached subdivision surface descriptor, with topology and settings. */
Subdiv *subdiv;
blender::bke::subdiv::Subdiv *subdiv;
};
static void init_data(ModifierData *md)
@@ -80,7 +80,7 @@ static void free_runtime_data(void *runtime_data_v)
}
MultiresRuntimeData *runtime_data = (MultiresRuntimeData *)runtime_data_v;
if (runtime_data->subdiv != nullptr) {
BKE_subdiv_free(runtime_data->subdiv);
blender::bke::subdiv::free(runtime_data->subdiv);
}
MEM_freeN(runtime_data);
}
@@ -104,12 +104,14 @@ static MultiresRuntimeData *multires_ensure_runtime(MultiresModifierData *mmd)
/* Main goal of this function is to give usable subdivision surface descriptor
* which matches settings and topology. */
static Subdiv *subdiv_descriptor_ensure(MultiresModifierData *mmd,
const SubdivSettings *subdiv_settings,
const Mesh *mesh)
static blender::bke::subdiv::Subdiv *subdiv_descriptor_ensure(
MultiresModifierData *mmd,
const blender::bke::subdiv::Settings *subdiv_settings,
const Mesh *mesh)
{
MultiresRuntimeData *runtime_data = (MultiresRuntimeData *)mmd->modifier.runtime;
Subdiv *subdiv = BKE_subdiv_update_from_mesh(runtime_data->subdiv, subdiv_settings, mesh);
blender::bke::subdiv::Subdiv *subdiv = blender::bke::subdiv::update_from_mesh(
runtime_data->subdiv, subdiv_settings, mesh);
runtime_data->subdiv = subdiv;
return subdiv;
}
@@ -119,7 +121,7 @@ static Subdiv *subdiv_descriptor_ensure(MultiresModifierData *mmd,
static Mesh *multires_as_mesh(MultiresModifierData *mmd,
const ModifierEvalContext *ctx,
Mesh *mesh,
Subdiv *subdiv)
blender::bke::subdiv::Subdiv *subdiv)
{
Mesh *result = mesh;
const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
@@ -127,7 +129,7 @@ static Mesh *multires_as_mesh(MultiresModifierData *mmd,
const bool ignore_control_edges = (ctx->flag & MOD_APPLY_TO_BASE_MESH);
const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
Object *object = ctx->object;
SubdivToMeshSettings mesh_settings;
blender::bke::subdiv::ToMeshSettings mesh_settings;
BKE_multires_subdiv_mesh_settings_init(&mesh_settings,
scene,
object,
@@ -138,8 +140,8 @@ static Mesh *multires_as_mesh(MultiresModifierData *mmd,
if (mesh_settings.resolution < 3) {
return result;
}
BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
blender::bke::subdiv::displacement_attach_from_multires(subdiv, mesh, mmd);
result = blender::bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, mesh);
return result;
}
@@ -164,7 +166,7 @@ static void multires_ccg_settings_init(SubdivToCCGSettings *settings,
static Mesh *multires_as_ccg(MultiresModifierData *mmd,
const ModifierEvalContext *ctx,
Mesh *mesh,
Subdiv *subdiv)
blender::bke::subdiv::Subdiv *subdiv)
{
Mesh *result = mesh;
SubdivToCCGSettings ccg_settings;
@@ -172,7 +174,7 @@ static Mesh *multires_as_ccg(MultiresModifierData *mmd,
if (ccg_settings.resolution < 3) {
return result;
}
BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
blender::bke::subdiv::displacement_attach_from_multires(subdiv, mesh, mmd);
result = BKE_subdiv_to_ccg_mesh(*subdiv, ccg_settings, *mesh);
/* NOTE: CCG becomes an owner of Subdiv descriptor, so can not share
@@ -192,13 +194,13 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
return result;
#endif
MultiresModifierData *mmd = (MultiresModifierData *)md;
SubdivSettings subdiv_settings;
blender::bke::subdiv::Settings subdiv_settings;
BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
if (subdiv_settings.level == 0) {
return result;
}
MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd);
Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
blender::bke::subdiv::Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
if (subdiv == nullptr) {
/* Happens on bad topology, also on empty input mesh. */
return result;
@@ -235,7 +237,7 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
sculpt_session->faces = {};
sculpt_session->corner_verts = {};
}
// BKE_subdiv_stats_print(&subdiv->stats);
// blender::bke::subdiv::stats_print(&subdiv->stats);
}
else {
if (use_clnors) {
@@ -252,9 +254,9 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
BKE_mesh_set_custom_normals(result, corner_normals);
CustomData_free_layers(&result->corner_data, CD_NORMAL, result->corners_num);
}
// BKE_subdiv_stats_print(&subdiv->stats);
// blender::bke::subdiv::stats_print(&subdiv->stats);
if (subdiv != runtime_data->subdiv) {
BKE_subdiv_free(subdiv);
blender::bke::subdiv::free(subdiv);
}
}
return result;
@@ -274,7 +276,7 @@ static void deform_matrices(ModifierData *md,
MultiresModifierData *mmd = (MultiresModifierData *)md;
SubdivSettings subdiv_settings;
blender::bke::subdiv::Settings subdiv_settings;
BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
if (subdiv_settings.level == 0) {
return;
@@ -287,16 +289,16 @@ static void deform_matrices(ModifierData *md,
}
MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd);
Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
blender::bke::subdiv::Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
if (subdiv == nullptr) {
/* Happens on bad topology, also on empty input mesh. */
return;
}
BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
BKE_subdiv_deform_coarse_vertices(
blender::bke::subdiv::displacement_attach_from_multires(subdiv, mesh, mmd);
blender::bke::subdiv::deform_coarse_vertices(
subdiv, mesh, reinterpret_cast<float(*)[3]>(positions.data()), positions.size());
if (subdiv != runtime_data->subdiv) {
BKE_subdiv_free(subdiv);
blender::bke::subdiv::free(subdiv);
}
}

View File

@@ -86,10 +86,10 @@ static void free_runtime_data(void *runtime_data_v)
}
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)runtime_data_v;
if (runtime_data->subdiv_cpu != nullptr) {
BKE_subdiv_free(runtime_data->subdiv_cpu);
blender::bke::subdiv::free(runtime_data->subdiv_cpu);
}
if (runtime_data->subdiv_gpu != nullptr) {
BKE_subdiv_free(runtime_data->subdiv_gpu);
blender::bke::subdiv::free(runtime_data->subdiv_gpu);
}
MEM_freeN(runtime_data);
}
@@ -128,7 +128,7 @@ static int subdiv_levels_for_modifier_get(const SubsurfModifierData *smd,
/* Subdivide into fully qualified mesh. */
static void subdiv_mesh_settings_init(SubdivToMeshSettings *settings,
static void subdiv_mesh_settings_init(blender::bke::subdiv::ToMeshSettings *settings,
const SubsurfModifierData *smd,
const ModifierEvalContext *ctx)
{
@@ -141,15 +141,15 @@ static void subdiv_mesh_settings_init(SubdivToMeshSettings *settings,
static Mesh *subdiv_as_mesh(SubsurfModifierData *smd,
const ModifierEvalContext *ctx,
Mesh *mesh,
Subdiv *subdiv)
blender::bke::subdiv::Subdiv *subdiv)
{
Mesh *result = mesh;
SubdivToMeshSettings mesh_settings;
blender::bke::subdiv::ToMeshSettings mesh_settings;
subdiv_mesh_settings_init(&mesh_settings, smd, ctx);
if (mesh_settings.resolution < 3) {
return result;
}
result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
result = blender::bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, mesh);
return result;
}
@@ -168,7 +168,7 @@ static void subdiv_ccg_settings_init(SubdivToCCGSettings *settings,
static Mesh *subdiv_as_ccg(SubsurfModifierData *smd,
const ModifierEvalContext *ctx,
Mesh *mesh,
Subdiv *subdiv)
blender::bke::subdiv::Subdiv *subdiv)
{
Mesh *result = mesh;
SubdivToCCGSettings ccg_settings;
@@ -187,7 +187,7 @@ static void subdiv_cache_mesh_wrapper_settings(const ModifierEvalContext *ctx,
SubsurfModifierData *smd,
SubsurfRuntimeData *runtime_data)
{
SubdivToMeshSettings mesh_settings;
blender::bke::subdiv::ToMeshSettings mesh_settings;
subdiv_mesh_settings_init(&mesh_settings, smd, ctx);
runtime_data->has_gpu_subdiv = true;
@@ -239,7 +239,8 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
}
}
Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh, false);
blender::bke::subdiv::Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(
runtime_data, mesh, false);
if (subdiv == nullptr) {
/* Happens on bad topology, but also on empty input mesh. */
return result;
@@ -265,9 +266,9 @@ static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh
&result->corner_data, CD_NORMAL, result->corners_num)));
CustomData_free_layers(&result->corner_data, CD_NORMAL, result->corners_num);
}
// BKE_subdiv_stats_print(&subdiv->stats);
// blender::bke::subdiv::stats_print(&subdiv->stats);
if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) {
BKE_subdiv_free(subdiv);
blender::bke::subdiv::free(subdiv);
}
return result;
}
@@ -290,15 +291,16 @@ static void deform_matrices(ModifierData *md,
return;
}
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh, false);
blender::bke::subdiv::Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(
runtime_data, mesh, false);
if (subdiv == nullptr) {
/* Happens on bad topology, but also on empty input mesh. */
return;
}
BKE_subdiv_deform_coarse_vertices(
blender::bke::subdiv::deform_coarse_vertices(
subdiv, mesh, reinterpret_cast<float(*)[3]>(positions.data()), positions.size());
if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) {
BKE_subdiv_free(subdiv);
blender::bke::subdiv::free(subdiv);
}
}

View File

@@ -24,29 +24,29 @@ static void node_declare(NodeDeclarationBuilder &b)
static Mesh *simple_subdivide_mesh(const Mesh &mesh, const int level)
{
/* Initialize mesh settings. */
SubdivToMeshSettings mesh_settings;
bke::subdiv::ToMeshSettings mesh_settings;
mesh_settings.resolution = (1 << level) + 1;
mesh_settings.use_optimal_display = false;
/* Initialize subdivision settings. */
SubdivSettings subdiv_settings;
bke::subdiv::Settings subdiv_settings;
subdiv_settings.is_simple = true;
subdiv_settings.is_adaptive = false;
subdiv_settings.use_creases = false;
subdiv_settings.level = 1;
subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
0);
subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(0);
subdiv_settings.vtx_boundary_interpolation =
bke::subdiv::vtx_boundary_interpolation_from_subsurf(0);
subdiv_settings.fvar_linear_interpolation = bke::subdiv::fvar_interpolation_from_uv_smooth(0);
/* Apply subdivision from mesh. */
Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, &mesh);
bke::subdiv::Subdiv *subdiv = bke::subdiv::new_from_mesh(&subdiv_settings, &mesh);
if (!subdiv) {
return nullptr;
}
Mesh *result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, &mesh);
Mesh *result = bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, &mesh);
BKE_subdiv_free(subdiv);
bke::subdiv::free(subdiv);
geometry::debug_randomize_mesh_order(result);
return result;

View File

@@ -126,27 +126,27 @@ static Mesh *mesh_subsurf_calc(const Mesh *mesh,
mesh = mesh_copy;
}
SubdivToMeshSettings mesh_settings;
bke::subdiv::ToMeshSettings mesh_settings;
mesh_settings.resolution = (1 << level) + 1;
mesh_settings.use_optimal_display = false;
SubdivSettings subdiv_settings;
bke::subdiv::Settings subdiv_settings;
subdiv_settings.is_simple = false;
subdiv_settings.is_adaptive = false;
subdiv_settings.use_creases = use_creases;
subdiv_settings.level = level;
subdiv_settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
boundary_smooth);
subdiv_settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
subdiv_settings.vtx_boundary_interpolation =
bke::subdiv::vtx_boundary_interpolation_from_subsurf(boundary_smooth);
subdiv_settings.fvar_linear_interpolation = bke::subdiv::fvar_interpolation_from_uv_smooth(
uv_smooth);
Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, mesh);
bke::subdiv::Subdiv *subdiv = bke::subdiv::new_from_mesh(&subdiv_settings, mesh);
if (!subdiv) {
return nullptr;
}
Mesh *result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
BKE_subdiv_free(subdiv);
Mesh *result = bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, mesh);
bke::subdiv::free(subdiv);
if (use_creases) {
/* Remove the layer in case it was created by the node from the field input. The fact

View File

@@ -308,7 +308,7 @@ void WM_init(bContext *C, int argc, const char **argv)
GPU_render_end();
}
BKE_subdiv_init();
blender::bke::subdiv::init();
ED_spacemacros_init();
@@ -588,7 +588,7 @@ void WM_exit_ex(bContext *C, const bool do_python_exit, const bool do_user_exit_
COM_deinitialize();
#endif
BKE_subdiv_exit();
bke::subdiv::exit();
if (gpu_is_init) {
BKE_image_free_unused_gpu_textures();