From c81a5f58f8bee9e592963d5e65a62d2a9eba7825 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 19 May 2020 09:26:22 +0200 Subject: OpenSubdiv: Refactor, move topology refiner factory to topology folder --- .../internal/opensubdiv_converter_factory.cc | 296 --------------------- .../internal/opensubdiv_converter_factory.h | 39 --- .../internal/topology/topology_refiner_capi.cc | 2 +- .../internal/topology/topology_refiner_factory.cc | 296 +++++++++++++++++++++ .../internal/topology/topology_refiner_factory.h | 39 +++ 5 files changed, 336 insertions(+), 336 deletions(-) delete mode 100644 intern/opensubdiv/internal/opensubdiv_converter_factory.cc delete mode 100644 intern/opensubdiv/internal/opensubdiv_converter_factory.h create mode 100644 intern/opensubdiv/internal/topology/topology_refiner_factory.cc create mode 100644 intern/opensubdiv/internal/topology/topology_refiner_factory.h (limited to 'intern/opensubdiv/internal') diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc deleted file mode 100644 index dba2a969062..00000000000 --- a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2015 Blender Foundation. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// Author: Sergey Sharybin - -#ifdef _MSC_VER -# include -#endif - -#include "internal/opensubdiv_converter_factory.h" - -#include -#include - -#include - -#include "internal/opensubdiv_converter_internal.h" -#include "internal/opensubdiv_internal.h" -#include "internal/opensubdiv_util.h" -#include "opensubdiv_converter_capi.h" - -using blender::opensubdiv::min; -using blender::opensubdiv::stack; -using blender::opensubdiv::vector; - -struct TopologyRefinerData { - const OpenSubdiv_Converter *converter; -}; - -namespace OpenSubdiv { -namespace OPENSUBDIV_VERSION { -namespace Far { - -template<> -inline bool TopologyRefinerFactory::resizeComponentTopology( - TopologyRefiner &refiner, const TopologyRefinerData &cb_data) -{ - const OpenSubdiv_Converter *converter = cb_data.converter; - // Faces and face-vertices. - const int num_faces = converter->getNumFaces(converter); - setNumBaseFaces(refiner, num_faces); - for (int face_index = 0; face_index < num_faces; ++face_index) { - const int num_face_vertices = converter->getNumFaceVertices(converter, face_index); - setNumBaseFaceVertices(refiner, face_index, num_face_vertices); - } - // Vertices. - const int num_vertices = converter->getNumVertices(converter); - setNumBaseVertices(refiner, num_vertices); - // If converter does not provide full topology, we are done. - if (!converter->specifiesFullTopology(converter)) { - return true; - } - // Edges and edge-faces. - const int num_edges = converter->getNumEdges(converter); - setNumBaseEdges(refiner, num_edges); - for (int edge_index = 0; edge_index < num_edges; ++edge_index) { - const int num_edge_faces = converter->getNumEdgeFaces(converter, edge_index); - setNumBaseEdgeFaces(refiner, edge_index, num_edge_faces); - } - // Vertex-faces and vertex-edges. - for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { - const int num_vert_edges = converter->getNumVertexEdges(converter, vertex_index); - const int num_vert_faces = converter->getNumVertexFaces(converter, vertex_index); - setNumBaseVertexEdges(refiner, vertex_index, num_vert_edges); - setNumBaseVertexFaces(refiner, vertex_index, num_vert_faces); - } - return true; -} - -template<> -inline bool TopologyRefinerFactory::assignComponentTopology( - TopologyRefiner &refiner, const TopologyRefinerData &cb_data) -{ - using Far::IndexArray; - const OpenSubdiv_Converter *converter = cb_data.converter; - const bool full_topology_specified = converter->specifiesFullTopology(converter); - // Face relations. - const int num_faces = converter->getNumFaces(converter); - for (int face_index = 0; face_index < num_faces; ++face_index) { - IndexArray dst_face_verts = getBaseFaceVertices(refiner, face_index); - converter->getFaceVertices(converter, face_index, &dst_face_verts[0]); - if (full_topology_specified) { - IndexArray dst_face_edges = getBaseFaceEdges(refiner, face_index); - converter->getFaceEdges(converter, face_index, &dst_face_edges[0]); - } - } - // If converter does not provide full topology, we are done. - if (!full_topology_specified) { - return true; - } - // Edge relations. - const int num_edges = converter->getNumEdges(converter); - for (int edge_index = 0; edge_index < num_edges; ++edge_index) { - // Edge-vertices. - IndexArray dst_edge_vertices = getBaseEdgeVertices(refiner, edge_index); - converter->getEdgeVertices(converter, edge_index, &dst_edge_vertices[0]); - // Edge-faces. - IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge_index); - converter->getEdgeFaces(converter, edge_index, &dst_edge_faces[0]); - } - // Vertex relations. - const int num_vertices = converter->getNumVertices(converter); - vector vertex_faces, vertex_edges; - for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { - // Vertex-faces. - IndexArray dst_vertex_faces = getBaseVertexFaces(refiner, vertex_index); - const int num_vertex_faces = converter->getNumVertexFaces(converter, vertex_index); - vertex_faces.resize(num_vertex_faces); - converter->getVertexFaces(converter, vertex_index, &vertex_faces[0]); - // Vertex-edges. - IndexArray dst_vertex_edges = getBaseVertexEdges(refiner, vertex_index); - const int num_vertex_edges = converter->getNumVertexEdges(converter, vertex_index); - vertex_edges.resize(num_vertex_edges); - converter->getVertexEdges(converter, vertex_index, &vertex_edges[0]); - memcpy(&dst_vertex_edges[0], &vertex_edges[0], sizeof(int) * num_vertex_edges); - memcpy(&dst_vertex_faces[0], &vertex_faces[0], sizeof(int) * num_vertex_faces); - } - populateBaseLocalIndices(refiner); - return true; -} - -template<> -inline bool TopologyRefinerFactory::assignComponentTags( - TopologyRefiner &refiner, const TopologyRefinerData &cb_data) -{ - using OpenSubdiv::Sdc::Crease; - const OpenSubdiv_Converter *converter = cb_data.converter; - const bool full_topology_specified = converter->specifiesFullTopology(converter); - if (full_topology_specified || converter->getEdgeVertices != NULL) { - const int num_edges = converter->getNumEdges(converter); - for (int edge_index = 0; edge_index < num_edges; ++edge_index) { - const float sharpness = converter->getEdgeSharpness(converter, edge_index); - if (sharpness < 1e-6f) { - continue; - } - if (full_topology_specified) { - setBaseEdgeSharpness(refiner, edge_index, sharpness); - } - else { - int edge_vertices[2]; - converter->getEdgeVertices(converter, edge_index, edge_vertices); - const int base_edge_index = findBaseEdge(refiner, edge_vertices[0], edge_vertices[1]); - if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) { - printf("OpenSubdiv Error: failed to find reconstructed edge\n"); - return false; - } - setBaseEdgeSharpness(refiner, base_edge_index, sharpness); - } - } - } - // OpenSubdiv expects non-manifold vertices to be sharp but at the time it - // handles correct cases when vertex is a corner of plane. Currently mark - // vertices which are adjacent to a loose edge as sharp, but this decision - // needs some more investigation. - const int num_vertices = converter->getNumVertices(converter); - for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { - ConstIndexArray vertex_edges = getBaseVertexEdges(refiner, vertex_index); - if (converter->isInfiniteSharpVertex(converter, vertex_index)) { - setBaseVertexSharpness(refiner, vertex_index, Crease::SHARPNESS_INFINITE); - continue; - } - - // Get sharpness provided by the converter. - float sharpness = 0.0f; - if (converter->getVertexSharpness != NULL) { - sharpness = converter->getVertexSharpness(converter, vertex_index); - } - - // If it's vertex where 2 non-manifold edges meet adjust vertex sharpness to - // the edges. - // This way having a plane with all 4 edges set to be sharp produces sharp - // corners in the subdivided result. - if (vertex_edges.size() == 2) { - const int edge0 = vertex_edges[0], edge1 = vertex_edges[1]; - const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0); - const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1); - // TODO(sergey): Find a better mixing between edge and vertex sharpness. - sharpness += min(sharpness0, sharpness1); - sharpness = min(sharpness, 10.0f); - } - - setBaseVertexSharpness(refiner, vertex_index, sharpness); - } - return true; -} - -template<> -inline bool TopologyRefinerFactory::assignFaceVaryingTopology( - TopologyRefiner &refiner, const TopologyRefinerData &cb_data) -{ - const OpenSubdiv_Converter *converter = cb_data.converter; - if (converter->getNumUVLayers == NULL) { - assert(converter->precalcUVLayer == NULL); - assert(converter->getNumUVCoordinates == NULL); - assert(converter->getFaceCornerUVIndex == NULL); - assert(converter->finishUVLayer == NULL); - return true; - } - const int num_layers = converter->getNumUVLayers(converter); - if (num_layers <= 0) { - // No UV maps, we can skip any face-varying data. - return true; - } - const int num_faces = getNumBaseFaces(refiner); - for (int layer_index = 0; layer_index < num_layers; ++layer_index) { - converter->precalcUVLayer(converter, layer_index); - const int num_uvs = converter->getNumUVCoordinates(converter); - // Fill in per-corner index of the UV. - const int channel = createBaseFVarChannel(refiner, num_uvs); - // TODO(sergey): Need to check whether converter changed the winding of - // face to match OpenSubdiv's expectations. - for (int face_index = 0; face_index < num_faces; ++face_index) { - Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner, face_index, channel); - for (int corner = 0; corner < dst_face_uvs.size(); ++corner) { - const int uv_index = converter->getFaceCornerUVIndex(converter, face_index, corner); - dst_face_uvs[corner] = uv_index; - } - } - converter->finishUVLayer(converter); - } - return true; -} - -template<> -inline void TopologyRefinerFactory::reportInvalidTopology( - TopologyError /*errCode*/, const char *msg, const TopologyRefinerData & /*mesh*/) -{ - printf("OpenSubdiv Error: %s\n", msg); -} - -} /* namespace Far */ -} /* namespace OPENSUBDIV_VERSION */ -} /* namespace OpenSubdiv */ - -namespace blender { -namespace opensubdiv { - -namespace { - -OpenSubdiv::Sdc::Options::VtxBoundaryInterpolation getVtxBoundaryInterpolationFromCAPI( - OpenSubdiv_VtxBoundaryInterpolation boundary_interpolation) -{ - using OpenSubdiv::Sdc::Options; - switch (boundary_interpolation) { - case OSD_VTX_BOUNDARY_NONE: - return Options::VTX_BOUNDARY_NONE; - case OSD_VTX_BOUNDARY_EDGE_ONLY: - return Options::VTX_BOUNDARY_EDGE_ONLY; - case OSD_VTX_BOUNDARY_EDGE_AND_CORNER: - return Options::VTX_BOUNDARY_EDGE_AND_CORNER; - } - assert(!"Unknown veretx boundary interpolation."); - return Options::VTX_BOUNDARY_EDGE_ONLY; -} - -} // namespace - -OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter( - OpenSubdiv_Converter *converter) -{ - using OpenSubdiv::Far::TopologyRefinerFactory; - using OpenSubdiv::Sdc::Options; - const OpenSubdiv::Sdc::SchemeType scheme_type = getSchemeTypeFromCAPI( - converter->getSchemeType(converter)); - const Options::FVarLinearInterpolation linear_interpolation = getFVarLinearInterpolationFromCAPI( - converter->getFVarLinearInterpolation(converter)); - Options options; - options.SetVtxBoundaryInterpolation( - getVtxBoundaryInterpolationFromCAPI(converter->getVtxBoundaryInterpolation(converter))); - options.SetCreasingMethod(Options::CREASE_UNIFORM); - options.SetFVarLinearInterpolation(linear_interpolation); - - TopologyRefinerFactory::Options topology_options(scheme_type, options); -#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY - topology_options.validateFullTopology = true; -#endif - TopologyRefinerData cb_data; - cb_data.converter = converter; - return TopologyRefinerFactory::Create(cb_data, topology_options); -} - -} // namespace opensubdiv -} // namespace blender diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.h b/intern/opensubdiv/internal/opensubdiv_converter_factory.h deleted file mode 100644 index 3519d3059b2..00000000000 --- a/intern/opensubdiv/internal/opensubdiv_converter_factory.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 Blender Foundation. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -// -// Author: Sergey Sharybin - -#ifndef OPENSUBDIV_CONVERTER_FACTORY_H_ -#define OPENSUBDIV_CONVERTER_FACTORY_H_ - -#ifdef _MSC_VER -# include -#endif - -#include - -struct OpenSubdiv_Converter; - -namespace blender { -namespace opensubdiv { - -OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter( - struct OpenSubdiv_Converter *converter); - -} // namespace opensubdiv -} // namespace blender - -#endif // OPENSUBDIV_CONVERTER_FACTORY_H_ diff --git a/intern/opensubdiv/internal/topology/topology_refiner_capi.cc b/intern/opensubdiv/internal/topology/topology_refiner_capi.cc index ff58ac68866..9bfba259671 100644 --- a/intern/opensubdiv/internal/topology/topology_refiner_capi.cc +++ b/intern/opensubdiv/internal/topology/topology_refiner_capi.cc @@ -19,11 +19,11 @@ #include "opensubdiv_topology_refiner_capi.h" #include "MEM_guardedalloc.h" -#include "internal/opensubdiv_converter_factory.h" #include "internal/opensubdiv_converter_internal.h" #include "internal/opensubdiv_edge_map.h" #include "internal/opensubdiv_internal.h" #include "internal/opensubdiv_util.h" +#include "internal/topology/topology_refiner_factory.h" #include "internal/topology/topology_refiner_impl.h" using blender::opensubdiv::vector; diff --git a/intern/opensubdiv/internal/topology/topology_refiner_factory.cc b/intern/opensubdiv/internal/topology/topology_refiner_factory.cc new file mode 100644 index 00000000000..1f69025782d --- /dev/null +++ b/intern/opensubdiv/internal/topology/topology_refiner_factory.cc @@ -0,0 +1,296 @@ +// Copyright 2015 Blender Foundation. All rights reserved. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// Author: Sergey Sharybin + +#ifdef _MSC_VER +# include +#endif + +#include "internal/topology/topology_refiner_factory.h" + +#include +#include + +#include + +#include "internal/opensubdiv_converter_internal.h" +#include "internal/opensubdiv_internal.h" +#include "internal/opensubdiv_util.h" +#include "opensubdiv_converter_capi.h" + +using blender::opensubdiv::min; +using blender::opensubdiv::stack; +using blender::opensubdiv::vector; + +struct TopologyRefinerData { + const OpenSubdiv_Converter *converter; +}; + +namespace OpenSubdiv { +namespace OPENSUBDIV_VERSION { +namespace Far { + +template<> +inline bool TopologyRefinerFactory::resizeComponentTopology( + TopologyRefiner &refiner, const TopologyRefinerData &cb_data) +{ + const OpenSubdiv_Converter *converter = cb_data.converter; + // Faces and face-vertices. + const int num_faces = converter->getNumFaces(converter); + setNumBaseFaces(refiner, num_faces); + for (int face_index = 0; face_index < num_faces; ++face_index) { + const int num_face_vertices = converter->getNumFaceVertices(converter, face_index); + setNumBaseFaceVertices(refiner, face_index, num_face_vertices); + } + // Vertices. + const int num_vertices = converter->getNumVertices(converter); + setNumBaseVertices(refiner, num_vertices); + // If converter does not provide full topology, we are done. + if (!converter->specifiesFullTopology(converter)) { + return true; + } + // Edges and edge-faces. + const int num_edges = converter->getNumEdges(converter); + setNumBaseEdges(refiner, num_edges); + for (int edge_index = 0; edge_index < num_edges; ++edge_index) { + const int num_edge_faces = converter->getNumEdgeFaces(converter, edge_index); + setNumBaseEdgeFaces(refiner, edge_index, num_edge_faces); + } + // Vertex-faces and vertex-edges. + for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { + const int num_vert_edges = converter->getNumVertexEdges(converter, vertex_index); + const int num_vert_faces = converter->getNumVertexFaces(converter, vertex_index); + setNumBaseVertexEdges(refiner, vertex_index, num_vert_edges); + setNumBaseVertexFaces(refiner, vertex_index, num_vert_faces); + } + return true; +} + +template<> +inline bool TopologyRefinerFactory::assignComponentTopology( + TopologyRefiner &refiner, const TopologyRefinerData &cb_data) +{ + using Far::IndexArray; + const OpenSubdiv_Converter *converter = cb_data.converter; + const bool full_topology_specified = converter->specifiesFullTopology(converter); + // Face relations. + const int num_faces = converter->getNumFaces(converter); + for (int face_index = 0; face_index < num_faces; ++face_index) { + IndexArray dst_face_verts = getBaseFaceVertices(refiner, face_index); + converter->getFaceVertices(converter, face_index, &dst_face_verts[0]); + if (full_topology_specified) { + IndexArray dst_face_edges = getBaseFaceEdges(refiner, face_index); + converter->getFaceEdges(converter, face_index, &dst_face_edges[0]); + } + } + // If converter does not provide full topology, we are done. + if (!full_topology_specified) { + return true; + } + // Edge relations. + const int num_edges = converter->getNumEdges(converter); + for (int edge_index = 0; edge_index < num_edges; ++edge_index) { + // Edge-vertices. + IndexArray dst_edge_vertices = getBaseEdgeVertices(refiner, edge_index); + converter->getEdgeVertices(converter, edge_index, &dst_edge_vertices[0]); + // Edge-faces. + IndexArray dst_edge_faces = getBaseEdgeFaces(refiner, edge_index); + converter->getEdgeFaces(converter, edge_index, &dst_edge_faces[0]); + } + // Vertex relations. + const int num_vertices = converter->getNumVertices(converter); + vector vertex_faces, vertex_edges; + for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { + // Vertex-faces. + IndexArray dst_vertex_faces = getBaseVertexFaces(refiner, vertex_index); + const int num_vertex_faces = converter->getNumVertexFaces(converter, vertex_index); + vertex_faces.resize(num_vertex_faces); + converter->getVertexFaces(converter, vertex_index, &vertex_faces[0]); + // Vertex-edges. + IndexArray dst_vertex_edges = getBaseVertexEdges(refiner, vertex_index); + const int num_vertex_edges = converter->getNumVertexEdges(converter, vertex_index); + vertex_edges.resize(num_vertex_edges); + converter->getVertexEdges(converter, vertex_index, &vertex_edges[0]); + memcpy(&dst_vertex_edges[0], &vertex_edges[0], sizeof(int) * num_vertex_edges); + memcpy(&dst_vertex_faces[0], &vertex_faces[0], sizeof(int) * num_vertex_faces); + } + populateBaseLocalIndices(refiner); + return true; +} + +template<> +inline bool TopologyRefinerFactory::assignComponentTags( + TopologyRefiner &refiner, const TopologyRefinerData &cb_data) +{ + using OpenSubdiv::Sdc::Crease; + const OpenSubdiv_Converter *converter = cb_data.converter; + const bool full_topology_specified = converter->specifiesFullTopology(converter); + if (full_topology_specified || converter->getEdgeVertices != NULL) { + const int num_edges = converter->getNumEdges(converter); + for (int edge_index = 0; edge_index < num_edges; ++edge_index) { + const float sharpness = converter->getEdgeSharpness(converter, edge_index); + if (sharpness < 1e-6f) { + continue; + } + if (full_topology_specified) { + setBaseEdgeSharpness(refiner, edge_index, sharpness); + } + else { + int edge_vertices[2]; + converter->getEdgeVertices(converter, edge_index, edge_vertices); + const int base_edge_index = findBaseEdge(refiner, edge_vertices[0], edge_vertices[1]); + if (base_edge_index == OpenSubdiv::Far::INDEX_INVALID) { + printf("OpenSubdiv Error: failed to find reconstructed edge\n"); + return false; + } + setBaseEdgeSharpness(refiner, base_edge_index, sharpness); + } + } + } + // OpenSubdiv expects non-manifold vertices to be sharp but at the time it + // handles correct cases when vertex is a corner of plane. Currently mark + // vertices which are adjacent to a loose edge as sharp, but this decision + // needs some more investigation. + const int num_vertices = converter->getNumVertices(converter); + for (int vertex_index = 0; vertex_index < num_vertices; ++vertex_index) { + ConstIndexArray vertex_edges = getBaseVertexEdges(refiner, vertex_index); + if (converter->isInfiniteSharpVertex(converter, vertex_index)) { + setBaseVertexSharpness(refiner, vertex_index, Crease::SHARPNESS_INFINITE); + continue; + } + + // Get sharpness provided by the converter. + float sharpness = 0.0f; + if (converter->getVertexSharpness != NULL) { + sharpness = converter->getVertexSharpness(converter, vertex_index); + } + + // If it's vertex where 2 non-manifold edges meet adjust vertex sharpness to + // the edges. + // This way having a plane with all 4 edges set to be sharp produces sharp + // corners in the subdivided result. + if (vertex_edges.size() == 2) { + const int edge0 = vertex_edges[0], edge1 = vertex_edges[1]; + const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0); + const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1); + // TODO(sergey): Find a better mixing between edge and vertex sharpness. + sharpness += min(sharpness0, sharpness1); + sharpness = min(sharpness, 10.0f); + } + + setBaseVertexSharpness(refiner, vertex_index, sharpness); + } + return true; +} + +template<> +inline bool TopologyRefinerFactory::assignFaceVaryingTopology( + TopologyRefiner &refiner, const TopologyRefinerData &cb_data) +{ + const OpenSubdiv_Converter *converter = cb_data.converter; + if (converter->getNumUVLayers == NULL) { + assert(converter->precalcUVLayer == NULL); + assert(converter->getNumUVCoordinates == NULL); + assert(converter->getFaceCornerUVIndex == NULL); + assert(converter->finishUVLayer == NULL); + return true; + } + const int num_layers = converter->getNumUVLayers(converter); + if (num_layers <= 0) { + // No UV maps, we can skip any face-varying data. + return true; + } + const int num_faces = getNumBaseFaces(refiner); + for (int layer_index = 0; layer_index < num_layers; ++layer_index) { + converter->precalcUVLayer(converter, layer_index); + const int num_uvs = converter->getNumUVCoordinates(converter); + // Fill in per-corner index of the UV. + const int channel = createBaseFVarChannel(refiner, num_uvs); + // TODO(sergey): Need to check whether converter changed the winding of + // face to match OpenSubdiv's expectations. + for (int face_index = 0; face_index < num_faces; ++face_index) { + Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner, face_index, channel); + for (int corner = 0; corner < dst_face_uvs.size(); ++corner) { + const int uv_index = converter->getFaceCornerUVIndex(converter, face_index, corner); + dst_face_uvs[corner] = uv_index; + } + } + converter->finishUVLayer(converter); + } + return true; +} + +template<> +inline void TopologyRefinerFactory::reportInvalidTopology( + TopologyError /*errCode*/, const char *msg, const TopologyRefinerData & /*mesh*/) +{ + printf("OpenSubdiv Error: %s\n", msg); +} + +} /* namespace Far */ +} /* namespace OPENSUBDIV_VERSION */ +} /* namespace OpenSubdiv */ + +namespace blender { +namespace opensubdiv { + +namespace { + +OpenSubdiv::Sdc::Options::VtxBoundaryInterpolation getVtxBoundaryInterpolationFromCAPI( + OpenSubdiv_VtxBoundaryInterpolation boundary_interpolation) +{ + using OpenSubdiv::Sdc::Options; + switch (boundary_interpolation) { + case OSD_VTX_BOUNDARY_NONE: + return Options::VTX_BOUNDARY_NONE; + case OSD_VTX_BOUNDARY_EDGE_ONLY: + return Options::VTX_BOUNDARY_EDGE_ONLY; + case OSD_VTX_BOUNDARY_EDGE_AND_CORNER: + return Options::VTX_BOUNDARY_EDGE_AND_CORNER; + } + assert(!"Unknown veretx boundary interpolation."); + return Options::VTX_BOUNDARY_EDGE_ONLY; +} + +} // namespace + +OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter( + OpenSubdiv_Converter *converter) +{ + using OpenSubdiv::Far::TopologyRefinerFactory; + using OpenSubdiv::Sdc::Options; + const OpenSubdiv::Sdc::SchemeType scheme_type = getSchemeTypeFromCAPI( + converter->getSchemeType(converter)); + const Options::FVarLinearInterpolation linear_interpolation = getFVarLinearInterpolationFromCAPI( + converter->getFVarLinearInterpolation(converter)); + Options options; + options.SetVtxBoundaryInterpolation( + getVtxBoundaryInterpolationFromCAPI(converter->getVtxBoundaryInterpolation(converter))); + options.SetCreasingMethod(Options::CREASE_UNIFORM); + options.SetFVarLinearInterpolation(linear_interpolation); + + TopologyRefinerFactory::Options topology_options(scheme_type, options); +#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY + topology_options.validateFullTopology = true; +#endif + TopologyRefinerData cb_data; + cb_data.converter = converter; + return TopologyRefinerFactory::Create(cb_data, topology_options); +} + +} // namespace opensubdiv +} // namespace blender diff --git a/intern/opensubdiv/internal/topology/topology_refiner_factory.h b/intern/opensubdiv/internal/topology/topology_refiner_factory.h new file mode 100644 index 00000000000..4333292f3d1 --- /dev/null +++ b/intern/opensubdiv/internal/topology/topology_refiner_factory.h @@ -0,0 +1,39 @@ +// Copyright 2015 Blender Foundation. All rights reserved. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// Author: Sergey Sharybin + +#ifndef OPENSUBDIV_TOPOLOGY_REFINER_FACTORY_H_ +#define OPENSUBDIV_TOPOLOGY_REFINER_FACTORY_H_ + +#ifdef _MSC_VER +# include +#endif + +#include + +struct OpenSubdiv_Converter; + +namespace blender { +namespace opensubdiv { + +OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter( + struct OpenSubdiv_Converter *converter); + +} // namespace opensubdiv +} // namespace blender + +#endif // OPENSUBDIV_TOPOLOGY_REFINER_FACTORY_H_ -- cgit v1.2.3