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);