Subdiv: Remove topology refiner C-API wrapper
Remove the indirection previously used for the topology refiner to separate C and C++ code. Instead retrieve the base level in calling code and call opensubdiv API functions directly. This avoids copying arrays of mesh indices and should reduce function call overhead since index retrieval can now be inlined. It also lets us remove a lot of boilerplate shim code. The downside is increased need for WITH_OPENSUBDIV defines in various parts of blenkernel, but I think that is required to avoid the previous indirection and have the kernel deal with OpenSubdiv more directly. Pull Request: https://projects.blender.org/blender/blender/pulls/120825
This commit is contained in:
@@ -64,7 +64,6 @@ if(WITH_OPENSUBDIV)
|
||||
internal/topology/mesh_topology.cc
|
||||
internal/topology/mesh_topology_compare.cc
|
||||
internal/topology/mesh_topology.h
|
||||
internal/topology/topology_refiner_capi.cc
|
||||
internal/topology/topology_refiner_factory.cc
|
||||
internal/topology/topology_refiner_impl.cc
|
||||
internal/topology/topology_refiner_impl_compare.cc
|
||||
@@ -95,7 +94,6 @@ else()
|
||||
list(APPEND SRC
|
||||
stub/opensubdiv_stub.cc
|
||||
stub/opensubdiv_evaluator_stub.cc
|
||||
stub/opensubdiv_topology_refiner_stub.cc
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ static void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
|
||||
}
|
||||
|
||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
blender::opensubdiv::TopologyRefinerImpl *topology_refiner,
|
||||
eOpenSubdivEvaluator evaluator_type,
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache)
|
||||
{
|
||||
|
||||
@@ -420,11 +420,11 @@ OpenSubdiv_EvaluatorImpl::~OpenSubdiv_EvaluatorImpl()
|
||||
}
|
||||
|
||||
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
blender::opensubdiv::TopologyRefinerImpl *topology_refiner,
|
||||
eOpenSubdivEvaluator evaluator_type,
|
||||
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr)
|
||||
{
|
||||
TopologyRefiner *refiner = topology_refiner->impl->topology_refiner;
|
||||
TopologyRefiner *refiner = topology_refiner->topology_refiner;
|
||||
if (refiner == NULL) {
|
||||
// Happens on bad topology.
|
||||
return NULL;
|
||||
@@ -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();
|
||||
const bool is_adaptive = topology_refiner->getIsAdaptive();
|
||||
const int level = topology_refiner->settings.level;
|
||||
const bool is_adaptive = topology_refiner->settings.is_adaptive;
|
||||
// Common settings for stencils and patches.
|
||||
const bool stencil_generate_intermediate_levels = is_adaptive;
|
||||
const bool stencil_generate_offsets = true;
|
||||
|
||||
@@ -22,10 +22,10 @@ struct OpenSubdiv_Buffer;
|
||||
struct OpenSubdiv_EvaluatorCacheImpl;
|
||||
struct OpenSubdiv_EvaluatorSettings;
|
||||
struct OpenSubdiv_PatchCoord;
|
||||
class OpenSubdiv_TopologyRefiner;
|
||||
|
||||
namespace blender::opensubdiv {
|
||||
|
||||
class TopologyRefinerImpl;
|
||||
class PatchMap;
|
||||
|
||||
// Wrapper around implementation, which defines API which we are capable to
|
||||
@@ -197,7 +197,7 @@ struct OpenSubdiv_EvaluatorImpl {
|
||||
};
|
||||
|
||||
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
blender::opensubdiv::TopologyRefinerImpl *topology_refiner,
|
||||
eOpenSubdivEvaluator evaluator_type,
|
||||
OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr);
|
||||
|
||||
|
||||
@@ -106,8 +106,12 @@ class MeshTopology {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Comparison.
|
||||
|
||||
// Check whether this topology refiner defines same topology as the given
|
||||
// converter.
|
||||
// Compare given topology with converter. Returns truth if topology
|
||||
// matches given converter, false otherwise.
|
||||
//
|
||||
// This allows users to construct converter (which is supposed to be cheap)
|
||||
// and compare with existing topology before going into more computationally
|
||||
// complicated parts of subdivision process.
|
||||
bool isEqualToConverter(const OpenSubdiv_Converter *converter) const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2018 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "internal/base/type_convert.h"
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
|
||||
static const OpenSubdiv::Far::TopologyRefiner *getOSDTopologyRefiner(
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner)
|
||||
{
|
||||
return topology_refiner->impl->topology_refiner;
|
||||
}
|
||||
|
||||
static const OpenSubdiv::Far::TopologyLevel &getOSDTopologyBaseLevel(
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner)
|
||||
{
|
||||
return getOSDTopologyRefiner(topology_refiner)->GetLevel(0);
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getSubdivisionLevel() const
|
||||
{
|
||||
return this->impl->settings.level;
|
||||
}
|
||||
|
||||
bool OpenSubdiv_TopologyRefiner::getIsAdaptive() const
|
||||
{
|
||||
return this->impl->settings.is_adaptive;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Query basic topology information from base level.
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumVertices() const
|
||||
{
|
||||
return getOSDTopologyBaseLevel(this).GetNumVertices();
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumEdges() const
|
||||
{
|
||||
return getOSDTopologyBaseLevel(this).GetNumEdges();
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumFaces() const
|
||||
{
|
||||
return getOSDTopologyBaseLevel(this).GetNumFaces();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PTex face geometry queries.
|
||||
|
||||
static void convertArrayToRaw(const OpenSubdiv::Far::ConstIndexArray &array, int *raw_array)
|
||||
{
|
||||
for (int i = 0; i < array.size(); ++i) {
|
||||
raw_array[i] = array[i];
|
||||
}
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumFaceVertices(const int face_index) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
return base_level.GetFaceVertices(face_index).size();
|
||||
}
|
||||
|
||||
void OpenSubdiv_TopologyRefiner::getFaceVertices(const int face_index,
|
||||
int *face_vertices_indices) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
OpenSubdiv::Far::ConstIndexArray array = base_level.GetFaceVertices(face_index);
|
||||
convertArrayToRaw(array, face_vertices_indices);
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumFaceEdges(const int face_index) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
return base_level.GetFaceEdges(face_index).size();
|
||||
}
|
||||
|
||||
void OpenSubdiv_TopologyRefiner::getFaceEdges(const int face_index, int *face_edges_indices) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
OpenSubdiv::Far::ConstIndexArray array = base_level.GetFaceEdges(face_index);
|
||||
convertArrayToRaw(array, face_edges_indices);
|
||||
}
|
||||
|
||||
void OpenSubdiv_TopologyRefiner::getEdgeVertices(const int edge_index,
|
||||
int edge_vertices_indices[2]) const
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumVertexEdges(const int vertex_index) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
return base_level.GetVertexEdges(vertex_index).size();
|
||||
}
|
||||
|
||||
void OpenSubdiv_TopologyRefiner::getVertexEdges(const int vertex_index,
|
||||
int *vertex_edges_indices) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
OpenSubdiv::Far::ConstIndexArray array = base_level.GetVertexEdges(vertex_index);
|
||||
convertArrayToRaw(array, vertex_edges_indices);
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumFacePtexFaces(const int face_index) const
|
||||
{
|
||||
const int num_face_vertices = this->getNumFaceVertices(face_index);
|
||||
if (num_face_vertices == 4) {
|
||||
return 1;
|
||||
}
|
||||
return num_face_vertices;
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumPtexFaces() const
|
||||
{
|
||||
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 += this->getNumFacePtexFaces(face_index);
|
||||
}
|
||||
return num_ptex_faces;
|
||||
}
|
||||
|
||||
void OpenSubdiv_TopologyRefiner::fillFacePtexIndexOffset(int *face_ptex_index_offset) const
|
||||
{
|
||||
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 += this->getNumFacePtexFaces(face_index);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Face-varying data.
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumFVarChannels() const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
return base_level.GetNumFVarChannels();
|
||||
}
|
||||
|
||||
OpenSubdiv_FVarLinearInterpolation OpenSubdiv_TopologyRefiner::getFVarLinearInterpolation() const
|
||||
{
|
||||
return blender::opensubdiv::getCAPIFVarLinearInterpolationFromOSD(
|
||||
getOSDTopologyRefiner(this)->GetFVarLinearInterpolation());
|
||||
}
|
||||
|
||||
int OpenSubdiv_TopologyRefiner::getNumFVarValues(const int channel) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
return base_level.GetNumFVarValues(channel);
|
||||
}
|
||||
|
||||
const int *OpenSubdiv_TopologyRefiner::getFaceFVarValueIndices(const int face_index,
|
||||
const int channel) const
|
||||
{
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level = getOSDTopologyBaseLevel(this);
|
||||
return &base_level.GetFaceFVarValues(face_index, channel)[0];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Internal helpers.
|
||||
|
||||
OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
|
||||
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings)
|
||||
{
|
||||
using blender::opensubdiv::TopologyRefinerImpl;
|
||||
|
||||
TopologyRefinerImpl *topology_refiner_impl = TopologyRefinerImpl::createFromConverter(converter,
|
||||
*settings);
|
||||
if (topology_refiner_impl == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner = MEM_new<OpenSubdiv_TopologyRefiner>(__func__);
|
||||
topology_refiner->impl = static_cast<OpenSubdiv_TopologyRefinerImpl *>(topology_refiner_impl);
|
||||
|
||||
return topology_refiner;
|
||||
}
|
||||
|
||||
void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refiner)
|
||||
{
|
||||
delete topology_refiner->impl;
|
||||
MEM_delete(topology_refiner);
|
||||
}
|
||||
|
||||
bool openSubdiv_topologyRefinerCompareWithConverter(
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner, const OpenSubdiv_Converter *converter)
|
||||
{
|
||||
return topology_refiner->impl->isEqualToConverter(converter);
|
||||
}
|
||||
@@ -17,6 +17,16 @@
|
||||
#include "internal/topology/mesh_topology.h"
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
// Those settings don't really belong to OpenSubdiv's topology refiner, but
|
||||
// we are keeping track of them on our side of topology refiner. This is to
|
||||
// make it possible to ensure we are not trying to abuse same OpenSubdiv's
|
||||
// topology refiner with different subdivision levels or with different
|
||||
// adaptive settings.
|
||||
struct OpenSubdiv_TopologyRefinerSettings {
|
||||
bool is_adaptive;
|
||||
int level;
|
||||
};
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
|
||||
namespace blender::opensubdiv {
|
||||
@@ -31,6 +41,11 @@ class TopologyRefinerImpl {
|
||||
TopologyRefinerImpl();
|
||||
~TopologyRefinerImpl();
|
||||
|
||||
const OpenSubdiv::Far::TopologyLevel &base_level() const
|
||||
{
|
||||
return topology_refiner->GetLevel(0);
|
||||
}
|
||||
|
||||
// Check whether this topology refiner defines same topology as the given
|
||||
// converter.
|
||||
// Covers options, geometry, and geometry tags.
|
||||
@@ -62,6 +77,4 @@ class TopologyRefinerImpl {
|
||||
|
||||
} // namespace blender::opensubdiv
|
||||
|
||||
struct OpenSubdiv_TopologyRefinerImpl : public blender::opensubdiv::TopologyRefinerImpl {};
|
||||
|
||||
#endif // OPENSUBDIV_TOPOLOGY_REFINER_IMPL_H_
|
||||
|
||||
@@ -12,7 +12,9 @@ struct OpenSubdiv_EvaluatorCacheImpl;
|
||||
struct OpenSubdiv_EvaluatorImpl;
|
||||
struct OpenSubdiv_EvaluatorInternal;
|
||||
struct OpenSubdiv_PatchCoord;
|
||||
class OpenSubdiv_TopologyRefiner;
|
||||
namespace blender::opensubdiv {
|
||||
class TopologyRefinerImpl;
|
||||
}
|
||||
|
||||
struct OpenSubdiv_EvaluatorSettings {
|
||||
// Number of smoothly interpolated vertex data channels.
|
||||
@@ -225,7 +227,7 @@ struct OpenSubdiv_EvaluatorCache {
|
||||
};
|
||||
|
||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
blender::opensubdiv::TopologyRefinerImpl *topology_refiner,
|
||||
eOpenSubdivEvaluator evaluator_type,
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache);
|
||||
|
||||
|
||||
@@ -4,112 +4,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint> // for bool
|
||||
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
struct OpenSubdiv_TopologyRefinerImpl;
|
||||
|
||||
// Those settings don't really belong to OpenSubdiv's topology refiner, but
|
||||
// we are keeping track of them on our side of topology refiner. This is to
|
||||
// make it possible to ensure we are not trying to abuse same OpenSubdiv's
|
||||
// topology refiner with different subdivision levels or with different
|
||||
// adaptive settings.
|
||||
struct OpenSubdiv_TopologyRefinerSettings {
|
||||
bool is_adaptive;
|
||||
int level;
|
||||
};
|
||||
|
||||
// C-style wrapper around actual topology refiner.
|
||||
//
|
||||
// The only purpose is to allow C-only code to access C++ implementation of the
|
||||
// topology refiner.
|
||||
class OpenSubdiv_TopologyRefiner {
|
||||
public:
|
||||
// Query subdivision level the refiner is created for.
|
||||
int getSubdivisionLevel() const;
|
||||
bool getIsAdaptive() const;
|
||||
|
||||
// NOTE: All queries are querying base level.
|
||||
//
|
||||
// TODO(sergey): Consider making it more obvious in function naming,
|
||||
// but since it's unlikely (or at least, will be uncommon use) for API
|
||||
// which queries final geometry, we should be fine with this name for
|
||||
// now.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Query basic topology information from base level.
|
||||
|
||||
int getNumVertices() const;
|
||||
int getNumEdges() const;
|
||||
int getNumFaces() const;
|
||||
|
||||
int getNumFaceVertices(int face_index) const;
|
||||
void getFaceVertices(int face_index, int *face_vertices_indices) const;
|
||||
|
||||
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(int vertex_index) const;
|
||||
void getVertexEdges(int vertex_index, int *vertex_edges_indices) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// PTex face geometry queries.
|
||||
|
||||
// Ptex face corresponds to OpenSubdiv's internal "patch" and to Blender's
|
||||
// subdivision grid. The rule commes as:
|
||||
// - Triangle face consist of 3 ptex faces, ordered in the order of
|
||||
// face-vertices.
|
||||
// - 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(int face_index) const;
|
||||
int getNumPtexFaces() const;
|
||||
|
||||
// Initialize a per-base-face offset measured in ptex face indices.
|
||||
//
|
||||
// Basically, face_ptex_offset[base_face_index] is a total number of ptex
|
||||
// faces created for bases faces [0 .. base_face_index - 1].
|
||||
//
|
||||
// The array must contain at least total number of ptex faces elements.
|
||||
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;
|
||||
// Get face-varying interpolation type.
|
||||
OpenSubdiv_FVarLinearInterpolation getFVarLinearInterpolation() const;
|
||||
// Get total number of face-varying values in a particular 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(int face_index, int channel) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Internal use.
|
||||
|
||||
// Implementation of the topology refiner.
|
||||
OpenSubdiv_TopologyRefinerImpl *impl;
|
||||
};
|
||||
|
||||
// NOTE: Will return NULL in cases of bad topology.
|
||||
// NOTE: Mesh without faces is considered a bad topology.
|
||||
OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
|
||||
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings);
|
||||
|
||||
void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
|
||||
// Compare given topology refiner with converter. Returns truth if topology
|
||||
// refiner matches given converter, false otherwise.
|
||||
//
|
||||
// This allows users to construct converter (which is supposed to be cheap)
|
||||
// and compare with existing refiner before going into more computationally
|
||||
// complicated parts of subdivision process.
|
||||
bool openSubdiv_topologyRefinerCompareWithConverter(
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner, const OpenSubdiv_Converter *converter);
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||
OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
|
||||
blender::opensubdiv::TopologyRefinerImpl * /*topology_refiner*/,
|
||||
eOpenSubdivEvaluator /*evaluator_type*/,
|
||||
OpenSubdiv_EvaluatorCache * /*evaluator_cache*/)
|
||||
{
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2018 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
|
||||
OpenSubdiv_Converter * /*converter*/, const OpenSubdiv_TopologyRefinerSettings * /*settings*/)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner * /*topology_refiner*/) {}
|
||||
|
||||
bool openSubdiv_topologyRefinerCompareWithConverter(
|
||||
const OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
|
||||
const OpenSubdiv_Converter * /*converter*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user