OpenSubdiv: API, expose vertex boundary interpolation option
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 31 Oct 2018 16:46:22 +0000 (17:46 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 31 Oct 2018 16:47:40 +0000 (17:47 +0100)
Only affects internal API, bout could be exposed as an option for
the compatibility reasons with other software.

Is a part of some ongoing development of multires, but might or
might not be used.

intern/opensubdiv/internal/opensubdiv_converter_factory.cc
intern/opensubdiv/opensubdiv_capi_type.h
intern/opensubdiv/opensubdiv_converter_capi.h
source/blender/blenkernel/BKE_subdiv.h
source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
source/blender/blenkernel/intern/multires_subdiv.c
source/blender/blenkernel/intern/subdiv_converter.c
source/blender/blenkernel/intern/subdiv_converter.h
source/blender/blenkernel/intern/subdiv_converter_mesh.c
source/blender/modifiers/intern/MOD_subsurf.c

index 901a421314a964dbac8e297f48a171a59abdab95..4f3fb1462f311a3e82659cc2dd0131dd40b9ea94 100644 (file)
@@ -441,6 +441,26 @@ inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
 
 namespace opensubdiv_capi {
 
+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::Sdc::Options;
@@ -451,7 +471,9 @@ OpenSubdiv::Far::TopologyRefiner* createOSDTopologyRefinerFromConverter(
       getFVarLinearInterpolationFromCAPI(
           converter->getFVarLinearInterpolation(converter));
   Options options;
-  options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
+  options.SetVtxBoundaryInterpolation(
+      getVtxBoundaryInterpolationFromCAPI(
+          converter->getVtxBoundaryInterpolation(converter)));
   options.SetCreasingMethod(Options::CREASE_UNIFORM);
   options.SetFVarLinearInterpolation(linear_interpolation);
 
index b326e53e168cc8378448c5e361af61b950740016..57f62fd988833a3b9222d86b6ed1a95b6065e2f5 100644 (file)
@@ -40,6 +40,15 @@ typedef enum OpenSubdiv_SchemeType {
   OSD_SCHEME_LOOP,
 } OpenSubdiv_SchemeType;
 
+typedef enum OpenSubdiv_VtxBoundaryInterpolation {
+  // Do not interpolate boundaries
+  OSD_VTX_BOUNDARY_NONE,
+  // Sharpen edges.
+  OSD_VTX_BOUNDARY_EDGE_ONLY,
+  // sharpen edges and corners,
+  OSD_VTX_BOUNDARY_EDGE_AND_CORNER,
+} OpenSubdiv_VtxBoundaryInterpolation;
+
 typedef enum OpenSubdiv_FVarLinearInterpolation {
   OSD_FVAR_LINEAR_INTERPOLATION_NONE,
   OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
index 9f559ee208b67c8eaff144b52950b131cd8673e7..389e16e0f3fab919a2e3c4a744c37dffa0275be2 100644 (file)
@@ -31,6 +31,8 @@ typedef struct OpenSubdiv_Converter {
   OpenSubdiv_SchemeType (*getSchemeType)(
       const struct OpenSubdiv_Converter* converter);
 
+  OpenSubdiv_VtxBoundaryInterpolation (*getVtxBoundaryInterpolation)(
+      const struct OpenSubdiv_Converter* converter);
   OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
       const struct OpenSubdiv_Converter* converter);
 
index 09fcce369d49d8201a5daf7221102c848852bb98..06d57062b599b36730685487947a49c3bf85f437 100644 (file)
@@ -43,7 +43,16 @@ struct OpenSubdiv_TopologyRefiner;
 struct Subdiv;
 struct SubdivToMeshSettings;
 
-typedef enum {
+typedef enum eSubdivVtxBoundaryInterpolation {
+  /* Do not interpolate boundaries. */
+  SUBDIV_VTX_BOUNDARY_NONE,
+  /* Sharpen edges. */
+  SUBDIV_VTX_BOUNDARY_EDGE_ONLY,
+  /* sharpen edges and corners, */
+  SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER,
+} eSubdivVtxBoundaryInterpolation;
+
+typedef enum eSubdivFVarLinearInterpolation {
        SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE,
        SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
        SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS,
@@ -56,6 +65,7 @@ typedef struct SubdivSettings {
        bool is_simple;
        bool is_adaptive;
        int level;
+       eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation;
        eSubdivFVarLinearInterpolation fvar_linear_interpolation;
 } SubdivSettings;
 
index f81a1d9eec920af26eb3630138893a5319d8893c..0301582b303adc8631c0b88f4e2399af4ea07556 100644 (file)
@@ -84,6 +84,13 @@ static OpenSubdiv_SchemeType conv_dm_get_type(
                return OSD_SCHEME_CATMARK;
 }
 
+static OpenSubdiv_VtxBoundaryInterpolation
+conv_dm_get_vtx_boundary_interpolation(
+        const OpenSubdiv_Converter *UNUSED(converter))
+{
+       return OSD_VTX_BOUNDARY_EDGE_ONLY;
+}
+
 static OpenSubdiv_FVarLinearInterpolation conv_dm_get_fvar_linear_interpolation(
         const OpenSubdiv_Converter *converter)
 {
@@ -448,6 +455,8 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
 
        converter->getSchemeType = conv_dm_get_type;
 
+       converter->getVtxBoundaryInterpolation =
+               conv_dm_get_vtx_boundary_interpolation;
        converter->getFVarLinearInterpolation =
                conv_dm_get_fvar_linear_interpolation;
        converter->specifiesFullTopology = conv_dm_specifies_full_topology;
@@ -546,6 +555,13 @@ static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(
        }
 }
 
+static OpenSubdiv_VtxBoundaryInterpolation
+conv_ccg_get_vtx_boundary_interpolation(
+        const OpenSubdiv_Converter *UNUSED(converter))
+{
+       return OSD_VTX_BOUNDARY_EDGE_ONLY;
+}
+
 static OpenSubdiv_FVarLinearInterpolation
 conv_ccg_get_fvar_linear_interpolation(const OpenSubdiv_Converter *converter)
 {
@@ -750,6 +766,8 @@ void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
 {
        converter->getSchemeType = conv_ccg_get_bilinear_type;
 
+       converter->getVtxBoundaryInterpolation =
+               conv_ccg_get_vtx_boundary_interpolation;
        converter->getFVarLinearInterpolation =
                conv_ccg_get_fvar_linear_interpolation;
        converter->specifiesFullTopology = conv_ccg_specifies_full_topology;
index f745418295dc76b661ccde45ad2afd90e44468cf..e0b316d49de0137afd68dd44c730b41002ad99f2 100644 (file)
@@ -48,6 +48,7 @@ void BKE_multires_subdiv_settings_init(
        settings->is_simple = (mmd->simple != 0);
        settings->is_adaptive = !settings->is_simple;
        settings->level = mmd->quality;
+       settings->vtx_boundary_interpolation = SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
        settings->fvar_linear_interpolation =
                BKE_subdiv_fvar_interpolation_from_uv_smooth(mmd->uv_smooth);
 }
index 47e87bfdd78d5584660b789a6eb2fd842becc1b0..b3eab1565d7f87e9205273669641f26fb8f7e200 100644 (file)
@@ -40,6 +40,21 @@ void BKE_subdiv_converter_free(struct OpenSubdiv_Converter *converter)
        }
 }
 
+int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(
+        const SubdivSettings *settings)
+{
+       switch (settings->vtx_boundary_interpolation) {
+               case SUBDIV_VTX_BOUNDARY_NONE:
+                       return OSD_VTX_BOUNDARY_NONE;
+               case SUBDIV_VTX_BOUNDARY_EDGE_ONLY:
+                       return OSD_VTX_BOUNDARY_EDGE_ONLY;
+               case SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER:
+                       return OSD_VTX_BOUNDARY_EDGE_AND_CORNER;
+       }
+       BLI_assert(!"Unknown vtx boundary interpolation");
+       return OSD_VTX_BOUNDARY_EDGE_ONLY;
+}
+
 /*OpenSubdiv_FVarLinearInterpolation*/ int
 BKE_subdiv_converter_fvar_linear_from_settings(const SubdivSettings *settings)
 {
index 0326c9e504c071285a0d3b16131789f884b86fa6..17172bc29f78b86c36239d19584522fcb86f0524 100644 (file)
@@ -52,6 +52,12 @@ void BKE_subdiv_converter_free(struct OpenSubdiv_Converter *converter);
 
 /* ============================ INTERNAL HELPERS ============================ */
 
+/* TODO(sergey): Find a way to make it OpenSubdiv_VtxBoundaryInterpolation,
+ * without breaking compilation without OpenSubdiv.
+ */
+int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(
+        const SubdivSettings *settings);
+
 /* TODO(sergey): Find a way to make it OpenSubdiv_FVarLinearInterpolation,
  * without breaking compilation without OpenSubdiv.
  */
index d17ee49ca0c78f8200ef55cddc6dbf8986a0ee54..34675da063e18b86152542247e66ce88b176232e 100644 (file)
@@ -87,6 +87,13 @@ static OpenSubdiv_SchemeType get_scheme_type(
        }
 }
 
+static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(
+        const struct OpenSubdiv_Converter* converter) {
+       ConverterStorage *storage = converter->user_data;
+       return BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(
+               &storage->settings);
+}
+
 static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
         const OpenSubdiv_Converter *converter)
 {
@@ -264,6 +271,7 @@ static void free_user_data(const OpenSubdiv_Converter *converter)
 static void init_functions(OpenSubdiv_Converter *converter)
 {
        converter->getSchemeType = get_scheme_type;
+       converter->getVtxBoundaryInterpolation = get_vtx_boundary_interpolation;
        converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
        converter->specifiesFullTopology = specifies_full_topology;
 
index 4aee0ba589e4241683f2e8fecef8eecc53229d6c..dee9089d7d3cad5bfb624978d4e0606ff1a7e20f 100644 (file)
@@ -158,6 +158,7 @@ static void subdiv_settings_init(SubdivSettings *settings,
        settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
        settings->is_adaptive = !settings->is_simple;
        settings->level = smd->quality;
+       settings->vtx_boundary_interpolation = SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
        settings->fvar_linear_interpolation =
                BKE_subdiv_fvar_interpolation_from_uv_smooth(smd->uv_smooth);
 }