Subdiv: Make OpenSubdiv_TopologyRefiner into a C++ class

Replace the C-class pattern function pointers with actual class methods.
Other than the obvious benefit of not requiring the "this" pointer to be
explicitly passed into every function call, this will make it much simpler
to remove the entire C-API class and replace it with its "impl" next.

For that next step we need to expose code to the implementation
of the topology refiner, so instead of defining stubs locally in the
opensubdiv intern class, we spread some WITH_OPENSUBDIV checks
in the blenkernel. As far as I know this is the only way to remove the
intermediate C-API and call opensubdiv functions directly from there.
This commit is contained in:
Hans Goudey
2024-04-18 22:27:35 -04:00
parent 52c0f4078a
commit 7f5dd29abd
11 changed files with 179 additions and 168 deletions

View File

@@ -433,8 +433,8 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
const bool has_varying_data = false;
const int num_face_varying_channels = refiner->GetNumFVarChannels();
const bool has_face_varying_data = (num_face_varying_channels != 0);
const int level = topology_refiner->getSubdivisionLevel(topology_refiner);
const bool is_adaptive = topology_refiner->getIsAdaptive(topology_refiner);
const int level = topology_refiner->getSubdivisionLevel();
const bool is_adaptive = topology_refiner->getIsAdaptive();
// Common settings for stencils and patches.
const bool stencil_generate_intermediate_levels = is_adaptive;
const bool stencil_generate_offsets = true;

View File

@@ -22,7 +22,7 @@ struct OpenSubdiv_Buffer;
struct OpenSubdiv_EvaluatorCacheImpl;
struct OpenSubdiv_EvaluatorSettings;
struct OpenSubdiv_PatchCoord;
struct OpenSubdiv_TopologyRefiner;
class OpenSubdiv_TopologyRefiner;
namespace blender::opensubdiv {
@@ -197,7 +197,7 @@ struct OpenSubdiv_EvaluatorImpl {
};
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
struct OpenSubdiv_TopologyRefiner *topology_refiner,
OpenSubdiv_TopologyRefiner *topology_refiner,
eOpenSubdivEvaluator evaluator_type,
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr);

View File

@@ -22,32 +22,32 @@ static const OpenSubdiv::Far::TopologyLevel &getOSDTopologyBaseLevel(
return getOSDTopologyRefiner(topology_refiner)->GetLevel(0);
}
static int getSubdivisionLevel(const OpenSubdiv_TopologyRefiner *topology_refiner)
int OpenSubdiv_TopologyRefiner::getSubdivisionLevel() const
{
return topology_refiner->impl->settings.level;
return this->impl->settings.level;
}
static bool getIsAdaptive(const OpenSubdiv_TopologyRefiner *topology_refiner)
bool OpenSubdiv_TopologyRefiner::getIsAdaptive() const
{
return topology_refiner->impl->settings.is_adaptive;
return this->impl->settings.is_adaptive;
}
////////////////////////////////////////////////////////////////////////////////
// Query basic topology information from base level.
static int getNumVertices(const OpenSubdiv_TopologyRefiner *topology_refiner)
int OpenSubdiv_TopologyRefiner::getNumVertices() const
{
return getOSDTopologyBaseLevel(topology_refiner).GetNumVertices();
return getOSDTopologyBaseLevel(this).GetNumVertices();
}
static int getNumEdges(const OpenSubdiv_TopologyRefiner *topology_refiner)
int OpenSubdiv_TopologyRefiner::getNumEdges() const
{
return getOSDTopologyBaseLevel(topology_refiner).GetNumEdges();
return getOSDTopologyBaseLevel(this).GetNumEdges();
}
static int getNumFaces(const OpenSubdiv_TopologyRefiner *topology_refiner)
int OpenSubdiv_TopologyRefiner::getNumFaces() const
{
return getOSDTopologyBaseLevel(topology_refiner).GetNumFaces();
return getOSDTopologyBaseLevel(this).GetNumFaces();
}
////////////////////////////////////////////////////////////////////////////////
@@ -60,164 +60,117 @@ static void convertArrayToRaw(const OpenSubdiv::Far::ConstIndexArray &array, int
}
}
static int getNumFaceVertices(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index)
int OpenSubdiv_TopologyRefiner::getNumFaceVertices(const int face_index) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
return base_level.GetFaceVertices(face_index).size();
}
static void getFaceVertices(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_vertices_indices)
void OpenSubdiv_TopologyRefiner::getFaceVertices(const int face_index,
int *face_vertices_indices) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetFaceVertices(face_index);
convertArrayToRaw(array, face_vertices_indices);
}
static int getNumFaceEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index)
int OpenSubdiv_TopologyRefiner::getNumFaceEdges(const int face_index) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
return base_level.GetFaceEdges(face_index).size();
}
static void getFaceEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_edges_indices)
void OpenSubdiv_TopologyRefiner::getFaceEdges(const int face_index, int *face_edges_indices) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetFaceEdges(face_index);
convertArrayToRaw(array, face_edges_indices);
}
static void getEdgeVertices(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int edge_index,
int edge_vertices_indices[2])
void OpenSubdiv_TopologyRefiner::getEdgeVertices(const int edge_index,
int edge_vertices_indices[2]) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetEdgeVertices(edge_index);
assert(array.size() == 2);
edge_vertices_indices[0] = array[0];
edge_vertices_indices[1] = array[1];
}
static int getNumVertexEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int vertex_index)
int OpenSubdiv_TopologyRefiner::getNumVertexEdges(const int vertex_index) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
return base_level.GetVertexEdges(vertex_index).size();
}
static void getVertexEdges(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int vertex_index,
int *vertex_edges_indices)
void OpenSubdiv_TopologyRefiner::getVertexEdges(const int vertex_index,
int *vertex_edges_indices) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
OpenSubdiv::Far::ConstIndexArray array = base_level.GetVertexEdges(vertex_index);
convertArrayToRaw(array, vertex_edges_indices);
}
static int getNumFacePtexFaces(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index)
int OpenSubdiv_TopologyRefiner::getNumFacePtexFaces(const int face_index) const
{
const int num_face_vertices = topology_refiner->getNumFaceVertices(topology_refiner, face_index);
const int num_face_vertices = this->getNumFaceVertices(face_index);
if (num_face_vertices == 4) {
return 1;
}
return num_face_vertices;
}
static int getNumPtexFaces(const OpenSubdiv_TopologyRefiner *topology_refiner)
int OpenSubdiv_TopologyRefiner::getNumPtexFaces() const
{
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
const int num_faces = this->getNumFaces();
int num_ptex_faces = 0;
for (int face_index = 0; face_index < num_faces; ++face_index) {
num_ptex_faces += topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
num_ptex_faces += this->getNumFacePtexFaces(face_index);
}
return num_ptex_faces;
}
static void fillFacePtexIndexOffset(const OpenSubdiv_TopologyRefiner *topology_refiner,
int *face_ptex_index_offset)
void OpenSubdiv_TopologyRefiner::fillFacePtexIndexOffset(int *face_ptex_index_offset) const
{
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
const int num_faces = this->getNumFaces();
int num_ptex_faces = 0;
for (int face_index = 0; face_index < num_faces; ++face_index) {
face_ptex_index_offset[face_index] = num_ptex_faces;
num_ptex_faces += topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
num_ptex_faces += this->getNumFacePtexFaces(face_index);
}
}
////////////////////////////////////////////////////////////////////////////////
// Face-varying data.
static int getNumFVarChannels(const struct OpenSubdiv_TopologyRefiner *topology_refiner)
int OpenSubdiv_TopologyRefiner::getNumFVarChannels() const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
return base_level.GetNumFVarChannels();
}
static OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation(
const struct OpenSubdiv_TopologyRefiner *topology_refiner)
OpenSubdiv_FVarLinearInterpolation OpenSubdiv_TopologyRefiner::getFVarLinearInterpolation() const
{
return blender::opensubdiv::getCAPIFVarLinearInterpolationFromOSD(
getOSDTopologyRefiner(topology_refiner)->GetFVarLinearInterpolation());
getOSDTopologyRefiner(this)->GetFVarLinearInterpolation());
}
static int getNumFVarValues(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
const int channel)
int OpenSubdiv_TopologyRefiner::getNumFVarValues(const int channel) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
return base_level.GetNumFVarValues(channel);
}
static const int *getFaceFVarValueIndices(
const struct OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
const int channel)
const int *OpenSubdiv_TopologyRefiner::getFaceFVarValueIndices(const int face_index,
const int channel) const
{
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(topology_refiner);
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
return &base_level.GetFaceFVarValues(face_index, channel)[0];
}
////////////////////////////////////////////////////////////////////////////////
// Internal helpers.
static void assignFunctionPointers(OpenSubdiv_TopologyRefiner *topology_refiner)
{
topology_refiner->getSubdivisionLevel = getSubdivisionLevel;
topology_refiner->getIsAdaptive = getIsAdaptive;
// Basic topology information.
topology_refiner->getNumVertices = getNumVertices;
topology_refiner->getNumEdges = getNumEdges;
topology_refiner->getNumFaces = getNumFaces;
topology_refiner->getNumFaceVertices = getNumFaceVertices;
topology_refiner->getFaceVertices = getFaceVertices;
topology_refiner->getNumFaceEdges = getNumFaceEdges;
topology_refiner->getFaceEdges = getFaceEdges;
topology_refiner->getEdgeVertices = getEdgeVertices;
topology_refiner->getNumVertexEdges = getNumVertexEdges;
topology_refiner->getVertexEdges = getVertexEdges;
// PTex face geometry.
topology_refiner->getNumFacePtexFaces = getNumFacePtexFaces;
topology_refiner->getNumPtexFaces = getNumPtexFaces;
topology_refiner->fillFacePtexIndexOffset = fillFacePtexIndexOffset;
// Face-varying data.
topology_refiner->getNumFVarChannels = getNumFVarChannels;
topology_refiner->getFVarLinearInterpolation = getFVarLinearInterpolation;
topology_refiner->getNumFVarValues = getNumFVarValues;
topology_refiner->getFaceFVarValueIndices = getFaceFVarValueIndices;
}
static OpenSubdiv_TopologyRefiner *allocateTopologyRefiner()
{
OpenSubdiv_TopologyRefiner *topology_refiner = MEM_new<OpenSubdiv_TopologyRefiner>(__func__);
assignFunctionPointers(topology_refiner);
return topology_refiner;
}
OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings)
{
@@ -229,7 +182,7 @@ OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
return nullptr;
}
OpenSubdiv_TopologyRefiner *topology_refiner = allocateTopologyRefiner();
OpenSubdiv_TopologyRefiner *topology_refiner = MEM_new<OpenSubdiv_TopologyRefiner>(__func__);
topology_refiner->impl = static_cast<OpenSubdiv_TopologyRefinerImpl *>(topology_refiner_impl);
return topology_refiner;

View File

@@ -12,7 +12,7 @@ struct OpenSubdiv_EvaluatorCacheImpl;
struct OpenSubdiv_EvaluatorImpl;
struct OpenSubdiv_EvaluatorInternal;
struct OpenSubdiv_PatchCoord;
struct OpenSubdiv_TopologyRefiner;
class OpenSubdiv_TopologyRefiner;
struct OpenSubdiv_EvaluatorSettings {
// Number of smoothly interpolated vertex data channels.

View File

@@ -25,10 +25,11 @@ struct OpenSubdiv_TopologyRefinerSettings {
//
// The only purpose is to allow C-only code to access C++ implementation of the
// topology refiner.
struct OpenSubdiv_TopologyRefiner {
class OpenSubdiv_TopologyRefiner {
public:
// Query subdivision level the refiner is created for.
int (*getSubdivisionLevel)(const OpenSubdiv_TopologyRefiner *topology_refiner);
bool (*getIsAdaptive)(const OpenSubdiv_TopologyRefiner *topology_refiner);
int getSubdivisionLevel() const;
bool getIsAdaptive() const;
// NOTE: All queries are querying base level.
//
@@ -40,29 +41,19 @@ struct OpenSubdiv_TopologyRefiner {
//////////////////////////////////////////////////////////////////////////////
// Query basic topology information from base level.
int (*getNumVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner);
int (*getNumEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner);
int (*getNumFaces)(const OpenSubdiv_TopologyRefiner *topology_refiner);
int getNumVertices() const;
int getNumEdges() const;
int getNumFaces() const;
int (*getNumFaceVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index);
void (*getFaceVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_vertices_indices);
int getNumFaceVertices(int face_index) const;
void getFaceVertices(int face_index, int *face_vertices_indices) const;
int (*getNumFaceEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index);
void (*getFaceEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
int *face_edges_indices);
void (*getEdgeVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int edge_index,
int edge_vertices_indices[2]);
int getNumFaceEdges(int face_index) const;
void getFaceEdges(int face_index, int *face_edges_indices) const;
void getEdgeVertices(int edge_index, int edge_vertices_indices[2]) const;
int (*getNumVertexEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int vertex_index);
void (*getVertexEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int vertex_index,
int *vertex_edges_indices);
int getNumVertexEdges(int vertex_index) const;
void getVertexEdges(int vertex_index, int *vertex_edges_indices) const;
//////////////////////////////////////////////////////////////////////////////
// PTex face geometry queries.
@@ -74,9 +65,8 @@ struct OpenSubdiv_TopologyRefiner {
// - Quad face consists of a single ptex face.
// - N-gons (similar to triangle) consists of N ptex faces, ordered same
// way as for triangle.
int (*getNumFacePtexFaces)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index);
int (*getNumPtexFaces)(const OpenSubdiv_TopologyRefiner *topology_refiner);
int getNumFacePtexFaces(int face_index) const;
int getNumPtexFaces() const;
// Initialize a per-base-face offset measured in ptex face indices.
//
@@ -84,26 +74,22 @@ struct OpenSubdiv_TopologyRefiner {
// faces created for bases faces [0 .. base_face_index - 1].
//
// The array must contain at least total number of ptex faces elements.
void (*fillFacePtexIndexOffset)(const OpenSubdiv_TopologyRefiner *topology_refiner,
int *face_ptex_index_offset);
void fillFacePtexIndexOffset(int *face_ptex_index_offset) const;
//////////////////////////////////////////////////////////////////////////////
// Face-varying data.
// Number of face-varying channels (or how they are called in Blender layers).
int (*getNumFVarChannels)(const OpenSubdiv_TopologyRefiner *topology_refiner);
int getNumFVarChannels() const;
// Get face-varying interpolation type.
OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
const OpenSubdiv_TopologyRefiner *topology_refiner);
OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation() const;
// Get total number of face-varying values in a particular channel.
int (*getNumFVarValues)(const OpenSubdiv_TopologyRefiner *topology_refiner, const int channel);
int getNumFVarValues(int channel) const;
// Get face-varying value indices associated with a particular face.
//
// This is an array of indices inside of face-varying array, array elements
// are aligned with face corners (or loops in Blender terminology).
const int *(*getFaceFVarValueIndices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
const int face_index,
const int channel);
const int *getFaceFVarValueIndices(int face_index, int channel) const;
//////////////////////////////////////////////////////////////////////////////
// Internal use.

View File

@@ -9,7 +9,7 @@
#include <cstddef>
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
struct OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
eOpenSubdivEvaluator /*evaluator_type*/,
OpenSubdiv_EvaluatorCache * /*evaluator_cache*/)
{