From 5e46e3d28a6948feff3a4937a84f42f9627e317d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 27 Sep 2024 19:01:12 +0200 Subject: [PATCH] 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 --- intern/opensubdiv/CMakeLists.txt | 2 - .../internal/evaluator/evaluator_capi.cc | 2 +- .../internal/evaluator/evaluator_impl.cc | 8 +- .../internal/evaluator/evaluator_impl.h | 4 +- .../internal/topology/mesh_topology.h | 8 +- .../topology/topology_refiner_capi.cc | 201 ------------------ .../internal/topology/topology_refiner_impl.h | 17 +- .../opensubdiv/opensubdiv_evaluator_capi.hh | 6 +- .../opensubdiv_topology_refiner_capi.hh | 110 +--------- .../stub/opensubdiv_evaluator_stub.cc | 2 +- .../stub/opensubdiv_topology_refiner_stub.cc | 24 --- source/blender/blenkernel/BKE_subdiv.hh | 6 +- .../intern/multires_reshape_smooth.cc | 16 +- .../intern/multires_reshape_util.cc | 9 + .../blenkernel/intern/multires_versioning.cc | 8 + source/blender/blenkernel/intern/subdiv.cc | 38 ++-- .../blender/blenkernel/intern/subdiv_ccg.cc | 104 ++++----- .../blender/blenkernel/intern/subdiv_eval.cc | 24 ++- .../blenkernel/intern/subdiv_topology.cc | 8 +- .../intern/draw_cache_impl_subdivision.cc | 12 +- .../editors/uvedit/uvedit_unwrap_ops.cc | 3 + 21 files changed, 170 insertions(+), 442 deletions(-) delete mode 100644 intern/opensubdiv/internal/topology/topology_refiner_capi.cc delete mode 100644 intern/opensubdiv/stub/opensubdiv_topology_refiner_stub.cc diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt index 7f26fbefa67..261da1d5399 100644 --- a/intern/opensubdiv/CMakeLists.txt +++ b/intern/opensubdiv/CMakeLists.txt @@ -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() diff --git a/intern/opensubdiv/internal/evaluator/evaluator_capi.cc b/intern/opensubdiv/internal/evaluator/evaluator_capi.cc index 25265455965..dd4c3fa7ae5 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_capi.cc +++ b/intern/opensubdiv/internal/evaluator/evaluator_capi.cc @@ -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) { diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc index 96e9f2008f9..4ac70f542df 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc +++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc @@ -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; diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.h b/intern/opensubdiv/internal/evaluator/evaluator_impl.h index 2f06a8c85d3..e8d1525c6d9 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_impl.h +++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.h @@ -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); diff --git a/intern/opensubdiv/internal/topology/mesh_topology.h b/intern/opensubdiv/internal/topology/mesh_topology.h index 395dcfd3815..8d3780fbef3 100644 --- a/intern/opensubdiv/internal/topology/mesh_topology.h +++ b/intern/opensubdiv/internal/topology/mesh_topology.h @@ -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: diff --git a/intern/opensubdiv/internal/topology/topology_refiner_capi.cc b/intern/opensubdiv/internal/topology/topology_refiner_capi.cc deleted file mode 100644 index e7d2e34f13b..00000000000 --- a/intern/opensubdiv/internal/topology/topology_refiner_capi.cc +++ /dev/null @@ -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(__func__); - topology_refiner->impl = static_cast(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); -} diff --git a/intern/opensubdiv/internal/topology/topology_refiner_impl.h b/intern/opensubdiv/internal/topology/topology_refiner_impl.h index b982334d5c4..19a85577fec 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_impl.h +++ b/intern/opensubdiv/internal/topology/topology_refiner_impl.h @@ -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_ diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.hh b/intern/opensubdiv/opensubdiv_evaluator_capi.hh index d25f6126e03..6afd6b3220f 100644 --- a/intern/opensubdiv/opensubdiv_evaluator_capi.hh +++ b/intern/opensubdiv/opensubdiv_evaluator_capi.hh @@ -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); diff --git a/intern/opensubdiv/opensubdiv_topology_refiner_capi.hh b/intern/opensubdiv/opensubdiv_topology_refiner_capi.hh index f2214698a7b..fcb923be3d0 100644 --- a/intern/opensubdiv/opensubdiv_topology_refiner_capi.hh +++ b/intern/opensubdiv/opensubdiv_topology_refiner_capi.hh @@ -4,112 +4,4 @@ #pragma once -#include // 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" diff --git a/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc b/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc index 01867c1f548..a11ce24b99e 100644 --- a/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc +++ b/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc @@ -9,7 +9,7 @@ #include OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner( - OpenSubdiv_TopologyRefiner * /*topology_refiner*/, + blender::opensubdiv::TopologyRefinerImpl * /*topology_refiner*/, eOpenSubdivEvaluator /*evaluator_type*/, OpenSubdiv_EvaluatorCache * /*evaluator_cache*/) { diff --git a/intern/opensubdiv/stub/opensubdiv_topology_refiner_stub.cc b/intern/opensubdiv/stub/opensubdiv_topology_refiner_stub.cc deleted file mode 100644 index b6538f293db..00000000000 --- a/intern/opensubdiv/stub/opensubdiv_topology_refiner_stub.cc +++ /dev/null @@ -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 - -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; -} diff --git a/source/blender/blenkernel/BKE_subdiv.hh b/source/blender/blenkernel/BKE_subdiv.hh index 0ee0fdd1229..774f2a42bba 100644 --- a/source/blender/blenkernel/BKE_subdiv.hh +++ b/source/blender/blenkernel/BKE_subdiv.hh @@ -15,7 +15,9 @@ struct Mesh; struct MultiresModifierData; struct OpenSubdiv_Converter; struct OpenSubdiv_Evaluator; -class OpenSubdiv_TopologyRefiner; +namespace blender::opensubdiv { +class TopologyRefinerImpl; +} namespace blender::bke::subdiv { @@ -159,7 +161,7 @@ struct Subdiv { /* 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. */ - OpenSubdiv_TopologyRefiner *topology_refiner; + blender::opensubdiv::TopologyRefinerImpl *topology_refiner; /* CPU side evaluator. */ OpenSubdiv_Evaluator *evaluator; /* Optional displacement evaluator. */ diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.cc b/source/blender/blenkernel/intern/multires_reshape_smooth.cc index 528811829c6..aad4c99e7d6 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.cc +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.cc @@ -32,6 +32,8 @@ #include "atomic_ops.h" #include "subdiv_converter.hh" +#ifdef WITH_OPENSUBDIV + /* -------------------------------------------------------------------- */ /** \name Local Structs * \{ */ @@ -317,13 +319,13 @@ static int get_face_grid_index(const MultiresReshapeSmoothContext *reshape_smoot const Corner *first_corner = &reshape_smooth_context->geometry.corners[face->start_corner_index]; const int grid_index = first_corner->grid_index; -#ifndef NDEBUG +# ifndef NDEBUG for (int face_corner = 0; face_corner < face->num_corners; ++face_corner) { const int corner_index = face->start_corner_index + face_corner; const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index]; BLI_assert(corner->grid_index == grid_index); } -#endif +# endif return grid_index; } @@ -1422,6 +1424,8 @@ static void evaluate_higher_grid_positions( }); } +#endif + /** \} */ /* -------------------------------------------------------------------- */ @@ -1431,6 +1435,7 @@ static void evaluate_higher_grid_positions( void multires_reshape_smooth_object_grids_with_details( const MultiresReshapeContext *reshape_context) { +#ifdef WITH_OPENSUBDIV const int level_difference = (reshape_context->top.level - reshape_context->reshape.level); if (level_difference == 0) { /* Early output. */ @@ -1458,11 +1463,15 @@ void multires_reshape_smooth_object_grids_with_details( evaluate_higher_grid_positions_with_details(&reshape_smooth_context); context_free(&reshape_smooth_context); +#else + UNUSED_VARS(reshape_context); +#endif } void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, const eMultiresSubdivideModeType mode) { +#ifdef WITH_OPENSUBDIV const int level_difference = (reshape_context->top.level - reshape_context->reshape.level); if (level_difference == 0) { /* Early output. */ @@ -1481,6 +1490,9 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_ evaluate_higher_grid_positions(&reshape_smooth_context); context_free(&reshape_smooth_context); +#else + UNUSED_VARS(reshape_context, mode); +#endif } /** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape_util.cc b/source/blender/blenkernel/intern/multires_reshape_util.cc index 5d23c83fb19..82aaeb3ff0e 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.cc +++ b/source/blender/blenkernel/intern/multires_reshape_util.cc @@ -51,6 +51,9 @@ blender::bke::subdiv::Subdiv *multires_reshape_create_subdiv(Depsgraph *depsgrap subdiv::Settings subdiv_settings; BKE_multires_subdiv_settings_init(&subdiv_settings, mmd); subdiv::Subdiv *subdiv = subdiv::new_from_mesh(&subdiv_settings, base_mesh); + if (!subdiv) { + return nullptr; + } if (!subdiv::eval_begin_from_mesh( subdiv, base_mesh, {}, subdiv::SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) { @@ -164,6 +167,9 @@ bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *resh reshape_context->base_corner_edges = base_mesh->corner_edges(); reshape_context->subdiv = multires_reshape_create_subdiv(nullptr, object, mmd); + if (!reshape_context->subdiv) { + return false; + } reshape_context->need_free_subdiv = true; reshape_context->reshape.level = multires_get_level( @@ -205,6 +211,9 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape reshape_context->base_corner_edges = base_mesh->corner_edges(); reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd); + if (!reshape_context->subdiv) { + return false; + } reshape_context->need_free_subdiv = true; reshape_context->reshape.level = multires_get_level( diff --git a/source/blender/blenkernel/intern/multires_versioning.cc b/source/blender/blenkernel/intern/multires_versioning.cc index 82032a04d68..54426895df2 100644 --- a/source/blender/blenkernel/intern/multires_versioning.cc +++ b/source/blender/blenkernel/intern/multires_versioning.cc @@ -19,6 +19,8 @@ #include "opensubdiv_converter_capi.hh" #include "subdiv_converter.hh" +#ifdef WITH_OPENSUBDIV + static float simple_to_catmull_clark_get_edge_sharpness(const OpenSubdiv_Converter * /*converter*/, int /*manifold_edge_index*/) { @@ -58,8 +60,11 @@ static blender::bke::subdiv::Subdiv *subdiv_for_simple_to_catmull_clark(Object * return subdiv; } +#endif + void multires_do_versions_simple_to_catmull_clark(Object *object, MultiresModifierData *mmd) { +#ifdef WITH_OPENSUBDIV const Mesh *base_mesh = static_cast(object->data); if (base_mesh->corners_num == 0) { return; @@ -93,4 +98,7 @@ void multires_do_versions_simple_to_catmull_clark(Object *object, MultiresModifi multires_reshape_object_grids_to_tangent_displacement(&reshape_context); multires_reshape_context_free(&reshape_context); } +#else + UNUSED_VARS(object, mmd); +#endif } diff --git a/source/blender/blenkernel/intern/subdiv.cc b/source/blender/blenkernel/intern/subdiv.cc index a8fd4d51ef4..41e8b63a079 100644 --- a/source/blender/blenkernel/intern/subdiv.cc +++ b/source/blender/blenkernel/intern/subdiv.cc @@ -22,7 +22,9 @@ #include "opensubdiv_capi.hh" #include "opensubdiv_converter_capi.hh" #include "opensubdiv_evaluator_capi.hh" -#include "opensubdiv_topology_refiner_capi.hh" +#ifdef WITH_OPENVDB +# include "opensubdiv_topology_refiner_capi.hh" +#endif namespace blender::bke::subdiv { @@ -97,16 +99,17 @@ bool settings_equal(const Settings *settings_a, const Settings *settings_b) Subdiv *new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter) { +#ifdef WITH_OPENSUBDIV SubdivStats stats; 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; - OpenSubdiv_TopologyRefiner *osd_topology_refiner = nullptr; + blender::opensubdiv::TopologyRefinerImpl *osd_topology_refiner = nullptr; if (converter->getNumVertices(converter) != 0) { - osd_topology_refiner = openSubdiv_createTopologyRefinerFromConverter( - converter, &topology_refiner_settings); + osd_topology_refiner = blender::opensubdiv::TopologyRefinerImpl::createFromConverter( + converter, topology_refiner_settings); } else { /* TODO(sergey): Check whether original geometry had any vertices. @@ -121,6 +124,10 @@ Subdiv *new_from_converter(const Settings *settings, OpenSubdiv_Converter *conve stats_end(&stats, SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME); subdiv->stats = stats; return subdiv; +#else + UNUSED_VARS(settings, converter); + return nullptr; +#endif } Subdiv *new_from_mesh(const Settings *settings, const Mesh *mesh) @@ -141,6 +148,7 @@ Subdiv *update_from_converter(Subdiv *subdiv, const Settings *settings, OpenSubdiv_Converter *converter) { +#ifdef WITH_OPENSUBDIV /* Check if the existing descriptor can be re-used. */ bool can_reuse_subdiv = true; if (subdiv != nullptr && subdiv->topology_refiner != nullptr) { @@ -149,8 +157,7 @@ Subdiv *update_from_converter(Subdiv *subdiv, } else { stats_begin(&subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE); - can_reuse_subdiv = openSubdiv_topologyRefinerCompareWithConverter(subdiv->topology_refiner, - converter); + can_reuse_subdiv = subdiv->topology_refiner->isEqualToConverter(converter); stats_end(&subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE); } } @@ -165,6 +172,10 @@ Subdiv *update_from_converter(Subdiv *subdiv, free(subdiv); } return new_from_converter(settings, converter); +#else + UNUSED_VARS(subdiv, settings, converter); + return nullptr; +#endif } Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh) @@ -180,6 +191,7 @@ Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *m void free(Subdiv *subdiv) { +#ifdef WITH_OPENSUBDIV if (subdiv->evaluator != nullptr) { const eOpenSubdivEvaluator evaluator_type = subdiv->evaluator->type; if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU) { @@ -189,14 +201,15 @@ void free(Subdiv *subdiv) } openSubdiv_deleteEvaluator(subdiv->evaluator); } - if (subdiv->topology_refiner != nullptr) { - openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner); - } + delete subdiv->topology_refiner; displacement_detach(subdiv); if (subdiv->cache_.face_ptex_offset != nullptr) { MEM_freeN(subdiv->cache_.face_ptex_offset); } MEM_freeN(subdiv); +#else + UNUSED_VARS(subdiv); +#endif } /* -------------------------------------------------------------------- @@ -209,16 +222,17 @@ int *face_ptex_offset_get(Subdiv *subdiv) if (subdiv->cache_.face_ptex_offset != nullptr) { return subdiv->cache_.face_ptex_offset; } - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; if (topology_refiner == nullptr) { return nullptr; } - const int num_coarse_faces = topology_refiner->getNumFaces(); + const int num_coarse_faces = topology_refiner->base_level().GetNumFaces(); subdiv->cache_.face_ptex_offset = static_cast( MEM_malloc_arrayN(num_coarse_faces + 1, sizeof(int), __func__)); int ptex_offset = 0; for (int face_index = 0; face_index < num_coarse_faces; face_index++) { - const int num_ptex_faces = topology_refiner->getNumFacePtexFaces(face_index); + const int face_size = topology_refiner->base_level().GetFaceVertices(face_index).size(); + const int num_ptex_faces = face_size == 4 ? 1 : face_size; subdiv->cache_.face_ptex_offset[face_index] = ptex_offset; ptex_offset += num_ptex_faces; } diff --git a/source/blender/blenkernel/intern/subdiv_ccg.cc b/source/blender/blenkernel/intern/subdiv_ccg.cc index aa461065f66..9dc25fd722d 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg.cc @@ -24,7 +24,9 @@ #include "BKE_subdiv.hh" #include "BKE_subdiv_eval.hh" -#include "opensubdiv_topology_refiner_capi.hh" +#ifdef WITH_OPENSUBDIV +# include "opensubdiv_topology_refiner_capi.hh" +#endif using blender::Array; using blender::float3; @@ -61,12 +63,13 @@ void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG &subdiv_ccg, * \{ */ /* TODO(sergey): Make it more accessible function. */ -static int topology_refiner_count_face_corners(const OpenSubdiv_TopologyRefiner *topology_refiner) +static int topology_refiner_count_face_corners( + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner) { - const int num_faces = topology_refiner->getNumFaces(); + const int num_faces = topology_refiner->base_level().GetNumFaces(); int num_corners = 0; for (int face_index = 0; face_index < num_faces; face_index++) { - num_corners += topology_refiner->getNumFaceVertices(face_index); + num_corners += topology_refiner->base_level().GetFaceVertices(face_index).size(); } return num_corners; } @@ -77,7 +80,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG &subdiv_ccg, Subdiv &subdiv, const SubdivToCCGSettings &settings) { - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv.topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv.topology_refiner; /* Allocate memory for surface grids. */ const int64_t num_grids = topology_refiner_count_face_corners(topology_refiner); const int64_t grid_size = grid_size_from_level(subdiv_ccg.level); @@ -210,8 +213,8 @@ static bool subdiv_ccg_evaluate_grids(SubdivCCG &subdiv_ccg, SubdivCCGMaskEvaluator *mask_evaluator) { using namespace blender; - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv.topology_refiner; - const int num_faces = topology_refiner->getNumFaces(); + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv.topology_refiner; + const int num_faces = topology_refiner->base_level().GetNumFaces(); const Span 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) { @@ -267,8 +270,8 @@ static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG &subdiv_ccg) { Subdiv *subdiv = subdiv_ccg.subdiv; const OffsetIndices faces = subdiv_ccg.faces; - OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; - const int num_edges = topology_refiner->getNumEdges(); + const OpenSubdiv::Far::TopologyLevel &base_level = subdiv->topology_refiner->base_level(); + const int num_edges = base_level.GetNumEdges(); const int grid_size = subdiv_ccg.grid_size; if (num_edges == 0) { /* Early output, nothing to do in this case. */ @@ -276,24 +279,20 @@ static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG &subdiv_ccg) } subdiv_ccg_allocate_adjacent_edges(subdiv_ccg, num_edges); - Vector face_vertices; - Vector face_edges; /* Store adjacency for all faces. */ for (const int face_index : faces.index_range()) { const IndexRange face = faces[face_index]; const int num_face_grids = face.size(); - face_vertices.reinitialize(num_face_grids); - topology_refiner->getFaceVertices(face_index, face_vertices.data()); + const OpenSubdiv::Far::ConstIndexArray face_vertices = base_level.GetFaceVertices(face_index); /* Note that order of edges is same as order of MLoops, which also * means it's the same as order of grids. */ - face_edges.reinitialize(num_face_grids); - topology_refiner->getFaceEdges(face_index, face_edges.data()); + const OpenSubdiv::Far::ConstIndexArray face_edges = base_level.GetFaceEdges(face_index); /* Store grids adjacency for this edge. */ for (int corner = 0; corner < num_face_grids; corner++) { const int vertex_index = face_vertices[corner]; const int edge_index = face_edges[corner]; - int edge_vertices[2]; - topology_refiner->getEdgeVertices(edge_index, edge_vertices); + const OpenSubdiv::Far::ConstIndexArray edge_vertices = base_level.GetEdgeVertices( + edge_index); const bool is_edge_flipped = (edge_vertices[0] != vertex_index); /* Grid which is adjacent to the current corner. */ const int current_grid_index = face.start() + corner; @@ -353,21 +352,20 @@ static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG &subdiv_ccg) { Subdiv *subdiv = subdiv_ccg.subdiv; const OffsetIndices faces = subdiv_ccg.faces; - OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; - const int num_vertices = topology_refiner->getNumVertices(); + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; + const int num_vertices = topology_refiner->base_level().GetNumVertices(); const int grid_size = subdiv_ccg.grid_size; if (num_vertices == 0) { /* Early output, nothing to do in this case. */ return; } subdiv_ccg_allocate_adjacent_vertices(subdiv_ccg, num_vertices); - Vector face_vertices; /* Store adjacency for all faces. */ for (const int face_index : faces.index_range()) { const IndexRange face = faces[face_index]; const int num_face_grids = face.size(); - face_vertices.reinitialize(num_face_grids); - topology_refiner->getFaceVertices(face_index, face_vertices.data()); + const OpenSubdiv::Far::ConstIndexArray face_vertices = + topology_refiner->base_level().GetFaceVertices(face_index); for (int corner = 0; corner < num_face_grids; corner++) { const int vertex_index = face_vertices[corner]; /* Grid which is adjacent to the current corner. */ @@ -858,20 +856,16 @@ static void subdiv_ccg_affected_face_adjacency(SubdivCCG &subdiv_ccg, blender::Set &adjacent_edges) { Subdiv *subdiv = subdiv_ccg.subdiv; - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; - - Vector face_vertices; - Vector face_edges; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; face_mask.foreach_index([&](const int face_index) { - const int num_face_grids = subdiv_ccg.faces[face_index].size(); - face_vertices.reinitialize(num_face_grids); - topology_refiner->getFaceVertices(face_index, face_vertices.data()); - adjacent_verts.add_multiple(face_vertices); + const OpenSubdiv::Far::ConstIndexArray face_vertices = + topology_refiner->base_level().GetFaceVertices(face_index); + adjacent_verts.add_multiple({face_vertices.begin(), face_vertices.size()}); - face_edges.reinitialize(num_face_grids); - topology_refiner->getFaceEdges(face_index, face_edges.data()); - adjacent_edges.add_multiple(face_edges); + const OpenSubdiv::Far::ConstIndexArray face_edges = + topology_refiner->base_level().GetFaceEdges(face_index); + adjacent_edges.add_multiple({face_edges.begin(), face_edges.size()}); }); } @@ -1115,15 +1109,14 @@ static int adjacent_vertex_index_from_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord) { Subdiv *subdiv = subdiv_ccg.subdiv; - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; const int face_index = subdiv_ccg.grid_to_face_map[coord.grid_index]; const IndexRange face = subdiv_ccg.faces[face_index]; const int face_grid_index = coord.grid_index - face.start(); - const int num_face_grids = face.size(); - Array face_vertices(num_face_grids); - topology_refiner->getFaceVertices(face_index, face_vertices.data()); + const OpenSubdiv::Far::ConstIndexArray face_vertices = + topology_refiner->base_level().GetFaceVertices(face_index); const int adjacent_vertex_index = face_vertices[face_grid_index]; return adjacent_vertex_index; @@ -1136,29 +1129,27 @@ static void neighbor_coords_corner_vertex_get(const SubdivCCG &subdiv_ccg, SubdivCCGNeighbors &r_neighbors) { Subdiv *subdiv = subdiv_ccg.subdiv; - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord); - const int num_vertex_edges = topology_refiner->getNumVertexEdges(adjacent_vertex_index); + const OpenSubdiv::Far::ConstIndexArray vertex_edges = + topology_refiner->base_level().GetVertexEdges(adjacent_vertex_index); const SubdivCCGAdjacentVertex &adjacent_vert = subdiv_ccg.adjacent_verts[adjacent_vertex_index]; const int num_adjacent_faces = adjacent_vert.num_adjacent_faces; subdiv_ccg_neighbors_init( - r_neighbors, num_vertex_edges, (include_duplicates) ? num_adjacent_faces - 1 : 0); + r_neighbors, vertex_edges.size(), (include_duplicates) ? num_adjacent_faces - 1 : 0); - Array vertex_edges(num_vertex_edges); - topology_refiner->getVertexEdges(adjacent_vertex_index, vertex_edges.data()); - - for (int i = 0; i < num_vertex_edges; ++i) { + for (int i = 0; i < vertex_edges.size(); ++i) { const int edge_index = vertex_edges[i]; /* Use very first grid of every edge. */ const int edge_face_index = 0; /* Depending edge orientation we use first (zero-based) or previous-to-last point. */ - int edge_vertices_indices[2]; - topology_refiner->getEdgeVertices(edge_index, edge_vertices_indices); + const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices = + topology_refiner->base_level().GetEdgeVertices(edge_index); int edge_point_index, duplicate_edge_point_index; if (edge_vertices_indices[0] == adjacent_vertex_index) { duplicate_edge_point_index = 0; @@ -1178,7 +1169,7 @@ static void neighbor_coords_corner_vertex_get(const SubdivCCG &subdiv_ccg, if (include_duplicates) { /* Add duplicates of the current grid vertex in adjacent faces if requested. */ - for (int i = 0, duplicate_i = num_vertex_edges; i < num_adjacent_faces; i++) { + for (int i = 0, duplicate_i = vertex_edges.size(); i < num_adjacent_faces; i++) { SubdivCCGCoord neighbor_coord = adjacent_vert.corner_coords[i]; if (neighbor_coord.grid_index != coord.grid_index) { r_neighbors.coords[duplicate_i++] = neighbor_coord; @@ -1190,15 +1181,14 @@ static void neighbor_coords_corner_vertex_get(const SubdivCCG &subdiv_ccg, static int adjacent_edge_index_from_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord) { Subdiv *subdiv = subdiv_ccg.subdiv; - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; const int face_index = subdiv_ccg.grid_to_face_map[coord.grid_index]; const IndexRange face = subdiv_ccg.faces[face_index]; const int face_grid_index = coord.grid_index - face.start(); - const int num_face_edges = topology_refiner->getNumFaceEdges(face_index); - Array face_edges(num_face_edges); - topology_refiner->getFaceEdges(face_index, face_edges.data()); + const OpenSubdiv::Far::ConstIndexArray face_edges = topology_refiner->base_level().GetFaceEdges( + face_index); const int grid_size_1 = subdiv_ccg.grid_size - 1; int adjacent_edge_index = -1; @@ -1218,11 +1208,11 @@ static int adjacent_edge_point_index_from_coord(const SubdivCCG &subdiv_ccg, const int adjacent_edge_index) { Subdiv *subdiv = subdiv_ccg.subdiv; - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord); - int edge_vertices_indices[2]; - topology_refiner->getEdgeVertices(adjacent_edge_index, edge_vertices_indices); + const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices = + topology_refiner->base_level().GetEdgeVertices(adjacent_edge_index); /* Vertex index of an edge which is used to see whether edge points in the right direction. * Tricky part here is that depending whether input coordinate is are maximum X or Y coordinate @@ -1490,18 +1480,18 @@ const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG &subdiv_ccg) #ifdef WITH_OPENSUBDIV if (subdiv_ccg.cache_.start_face_grid_index.is_empty()) { const Subdiv *subdiv = subdiv_ccg.subdiv; - OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; if (topology_refiner == nullptr) { return nullptr; } - const int num_coarse_faces = topology_refiner->getNumFaces(); + const int num_coarse_faces = topology_refiner->base_level().GetNumFaces(); subdiv_ccg.cache_.start_face_grid_index.reinitialize(num_coarse_faces); int start_grid_index = 0; for (int face_index = 0; face_index < num_coarse_faces; face_index++) { - const int num_face_grids = topology_refiner->getNumFaceVertices(face_index); + const int num_face_grids = topology_refiner->base_level().GetFaceVertices(face_index).size(); subdiv_ccg.cache_.start_face_grid_index[face_index] = start_grid_index; start_grid_index += num_face_grids; } diff --git a/source/blender/blenkernel/intern/subdiv_eval.cc b/source/blender/blenkernel/intern/subdiv_eval.cc index a34004d5c9b..fd27ad48206 100644 --- a/source/blender/blenkernel/intern/subdiv_eval.cc +++ b/source/blender/blenkernel/intern/subdiv_eval.cc @@ -19,7 +19,9 @@ #include "MEM_guardedalloc.h" #include "opensubdiv_evaluator_capi.hh" -#include "opensubdiv_topology_refiner_capi.hh" +#ifdef WITH_OPENSUBDIV +# include "opensubdiv_topology_refiner_capi.hh" +#endif /* -------------------------------------------------------------------- * Helper functions. @@ -106,7 +108,7 @@ static void set_coarse_positions(Subdiv *subdiv, /* Context which is used to fill face varying data in parallel. */ struct FaceVaryingDataFromUVContext { - OpenSubdiv_TopologyRefiner *topology_refiner; + opensubdiv::TopologyRefinerImpl *topology_refiner; const Mesh *mesh; OffsetIndices faces; const float (*mloopuv)[2]; @@ -119,16 +121,16 @@ static void set_face_varying_data_from_uv_task(void *__restrict userdata, const TaskParallelTLS *__restrict /*tls*/) { FaceVaryingDataFromUVContext *ctx = static_cast(userdata); - OpenSubdiv_TopologyRefiner *topology_refiner = ctx->topology_refiner; + opensubdiv::TopologyRefinerImpl *topology_refiner = ctx->topology_refiner; const int layer_index = ctx->layer_index; const float(*mluv)[2] = &ctx->mloopuv[ctx->faces[face_index].start()]; /* TODO(sergey): OpenSubdiv's C-API converter can change winding of * loops of a face, need to watch for that, to prevent wrong UVs assigned. */ - const int num_face_vertices = topology_refiner->getNumFaceVertices(face_index); - const int *uv_indices = topology_refiner->getFaceFVarValueIndices(face_index, layer_index); - for (int vertex_index = 0; vertex_index < num_face_vertices; vertex_index++, mluv++) { + const OpenSubdiv::Vtr::ConstIndexArray uv_indices = + topology_refiner->base_level().GetFaceFVarValues(face_index, layer_index); + for (int vertex_index = 0; vertex_index < uv_indices.size(); vertex_index++, mluv++) { copy_v2_v2(ctx->buffer[uv_indices[vertex_index]], *mluv); } } @@ -138,12 +140,12 @@ static void set_face_varying_data_from_uv(Subdiv *subdiv, const float (*mloopuv)[2], const int layer_index) { - OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; - const int num_faces = topology_refiner->getNumFaces(); + const int num_faces = topology_refiner->base_level().GetNumFaces(); const float(*mluv)[2] = mloopuv; - const int num_fvar_values = topology_refiner->getNumFVarValues(layer_index); + const int num_fvar_values = topology_refiner->base_level().GetNumFVarValues(layer_index); /* Use a temporary buffer so we do not upload UVs one at a time to the GPU. */ float(*buffer)[2] = static_cast( MEM_mallocN(sizeof(float[2]) * num_fvar_values, __func__)); @@ -176,9 +178,9 @@ static void set_vertex_data_from_orco(Subdiv *subdiv, const Mesh *mesh) CustomData_get_layer(&mesh->vert_data, CD_CLOTH_ORCO)); if (orco || cloth_orco) { - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; + blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; - const int num_verts = topology_refiner->getNumVertices(); + const int num_verts = topology_refiner->base_level().GetNumVertices(); if (orco && cloth_orco) { /* Set one by one if have both. */ diff --git a/source/blender/blenkernel/intern/subdiv_topology.cc b/source/blender/blenkernel/intern/subdiv_topology.cc index 563a7d912bb..46e2ed7c5b4 100644 --- a/source/blender/blenkernel/intern/subdiv_topology.cc +++ b/source/blender/blenkernel/intern/subdiv_topology.cc @@ -12,15 +12,17 @@ #include "BKE_subdiv.hh" -#include "opensubdiv_topology_refiner_capi.hh" +#ifdef WITH_OPENSUBDIV +# include "opensubdiv_topology_refiner_capi.hh" +#endif namespace blender::bke::subdiv { int topology_num_fvar_layers_get(const Subdiv *subdiv) { #ifdef WITH_OPENSUBDIV - const OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; - return topology_refiner->getNumFVarChannels(); + const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner; + return topology_refiner->base_level().GetNumFVarChannels(); #else UNUSED_VARS(subdiv); return 0; diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index b59d21c1270..71e34c0a052 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -40,7 +40,9 @@ #include "opensubdiv_capi_type.hh" #include "opensubdiv_converter_capi.hh" #include "opensubdiv_evaluator_capi.hh" -#include "opensubdiv_topology_refiner_capi.hh" +#ifdef WITH_OPENSUBDIV +# include "opensubdiv_topology_refiner_capi.hh" +#endif #include "draw_cache_extract.hh" #include "draw_cache_impl.hh" @@ -848,10 +850,10 @@ static void draw_subdiv_invalidate_evaluator_for_orco(bke::subdiv::Subdiv *subdi openSubdiv_deleteEvaluator(subdiv->evaluator); subdiv->evaluator = nullptr; - if (subdiv->topology_refiner != nullptr) { - openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner); - subdiv->topology_refiner = nullptr; - } +#ifdef WITH_OPENSUBDIV + delete subdiv->topology_refiner; + subdiv->topology_refiner = nullptr; +#endif } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc index 64af972af71..b7bf66422e2 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc @@ -811,6 +811,9 @@ static Mesh *subdivide_edit_mesh(const Object *object, mesh_settings.use_optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges); bke::subdiv::Subdiv *subdiv = bke::subdiv::new_from_mesh(&settings, me_from_em); + if (!subdiv) { + return nullptr; + } Mesh *result = bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, me_from_em); BKE_id_free(nullptr, me_from_em); bke::subdiv::free(subdiv);