Commit: f6eccd367cf7ef504ebeef332b62a86d928f5542
Author: Sergey Sharybin
Date:   Mon Jul 23 18:40:04 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBf6eccd367cf7ef504ebeef332b62a86d928f5542

Subsurf: Subdivide polygons to the same resolution

Previously it was ptex faces which were subdividing to the same
resolution. This was looking like more details for non-quad faces,
but was also causing discontinuity in the edge where quad touches
non-quad polygon.

Now ptex faces which are coming from non-quad faces are subdivided
at a half of resolution, matching old behavior and solving
discontinuity problem.

===================================================================

M       source/blender/blenkernel/BKE_subdiv.h
M       source/blender/blenkernel/intern/subdiv.c
M       source/blender/blenkernel/intern/subdiv_mesh.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_subdiv.h 
b/source/blender/blenkernel/BKE_subdiv.h
index a1792866255..003dc7a37d3 100644
--- a/source/blender/blenkernel/BKE_subdiv.h
+++ b/source/blender/blenkernel/BKE_subdiv.h
@@ -94,26 +94,6 @@ typedef struct Subdiv {
         */
        SubdivSettings settings;
 
-       /* Total number of ptex faces on subdivision level 0.
-        *
-        * Ptex face is what is internally used by OpenSubdiv for evaluator. It 
is
-        * a quad face, which corresponds to Blender's legacy Catmull Clark 
grids.
-        *
-        * Basically, here is a correspondence between polygons and ptex faces:
-        * - Triangle consists of 3 PTex faces.
-        * - Quad is a single PTex face.
-        * - N-gon is N PTex faces.
-        *
-        * This value is initialized in BKE_subdiv_new_from_FOO() and is 
read-only
-        * after this.
-        */
-       int num_ptex_faces;
-
-       /* Indexed by base face index, element indicates total number of ptex 
faces
-        * created for preceding base faces.
-        */
-       int *face_ptex_offset;
-
        /* 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.
diff --git a/source/blender/blenkernel/intern/subdiv.c 
b/source/blender/blenkernel/intern/subdiv.c
index 794da2d3477..0bf969b7de2 100644
--- a/source/blender/blenkernel/intern/subdiv.c
+++ b/source/blender/blenkernel/intern/subdiv.c
@@ -42,23 +42,6 @@
 #  include "opensubdiv_topology_refiner_capi.h"
 #endif
 
-#ifdef WITH_OPENSUBDIV
-static void update_subdiv_after_topology_change(Subdiv *subdiv)
-{
-       /* Count ptex faces. */
-       subdiv->num_ptex_faces = subdiv->topology_refiner->getNumPtexFaces(
-               subdiv->topology_refiner);
-       /* Initialize offset of base faces in ptex indices. */
-       MEM_SAFE_FREE(subdiv->face_ptex_offset);
-       subdiv->face_ptex_offset = MEM_malloc_arrayN(subdiv->num_ptex_faces,
-                                                    sizeof(int),
-                                                    "subdiv ptex offset");
-       subdiv->topology_refiner->fillFacePtexIndexOffset(
-               subdiv->topology_refiner,
-               subdiv->face_ptex_offset);
-}
-#endif
-
 Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
                                       struct OpenSubdiv_Converter *converter)
 {
@@ -79,7 +62,6 @@ Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings 
*settings,
        subdiv->settings = *settings;
        subdiv->topology_refiner = osd_topology_refiner;
        subdiv->evaluator = NULL;
-       update_subdiv_after_topology_change(subdiv);
        BKE_subdiv_stats_end(&stats, 
SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME);
        subdiv->stats = stats;
        return subdiv;
@@ -113,7 +95,6 @@ void BKE_subdiv_free(Subdiv *subdiv)
        if (subdiv->topology_refiner != NULL) {
                openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner);
        }
-       MEM_SAFE_FREE(subdiv->face_ptex_offset);
        MEM_freeN(subdiv);
 #endif
 }
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c 
b/source/blender/blenkernel/intern/subdiv_mesh.c
index 83f2069ea0f..eb47d9158d3 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -38,27 +38,40 @@
 
 #include "BKE_mesh.h"
 
-/* TODO(sergey): Somehow move this to subdiv code? */
-static int mpoly_ptex_faces_count_get(const MPoly *mp)
+#include "MEM_guardedalloc.h"
+
+/* 
=============================================================================
+ * General helpers.
+ */
+
+/* Number of ptex faces for a given polygon. */
+BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly)
 {
-       if (mp->totloop == 4) {
-               return 1;
-       }
-       else {
-               return mp->totloop;
-       }
+       return (poly->totloop == 4) ? 1 : poly->totloop;
 }
 
-static int num_edges_per_ptex_get(const int resolution)
+BLI_INLINE int num_edges_per_ptex_face_get(const int resolution)
 {
        return 2 * (resolution - 1) * resolution;
 }
 
-static int num_polys_per_ptex_get(const int resolution)
+/* Number of subdivision polygons per ptex face. */
+BLI_INLINE int num_polys_per_ptex_get(const int resolution)
 {
        return (resolution - 1) * (resolution - 1);
 }
 
+/* Subdivision resolution per given polygon's ptex faces. */
+BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution)
+{
+       return (poly->totloop == 4) ? (resolution)
+                                   : ((resolution >> 1) + 1);
+}
+
+/* 
=============================================================================
+ * Mesh subdivision context.
+ */
+
 typedef struct SubdivMeshContext {
        const Mesh *coarse_mesh;
        Subdiv *subdiv;
@@ -72,8 +85,127 @@ typedef struct SubdivMeshContext {
        /* UV layers interpolation. */
        int num_uv_layers;
        MLoopUV *uv_layers[MAX_MTFACE];
+
+       /* Indexed by coarse polygon index, indicates offset in subdivided mesh
+        * vertices, edges and polygons arrays, where first element of the poly
+        * begins.
+        */
+       int *subdiv_vertex_offset;
+       int *subdiv_edge_offset;
+       int *subdiv_polygon_offset;
+       /* Indexed by base face index, element indicates total number of ptex 
faces
+        * created for preceding base faces.
+        */
+       int *face_ptex_offset;
+
+       /* Counters of geometry in subdivided mesh, initialized as a part of
+        * offsets calculation.
+        */
+       int num_subdiv_vertices;
+       int num_subdiv_edges;
+       int num_subdiv_loops;
+       int num_subdiv_polygons;
 } SubdivMeshContext;
 
+static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
+{
+       Mesh *subdiv_mesh = ctx->subdiv_mesh;
+       ctx->num_uv_layers =
+               CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
+       for (int layer_index = 0; layer_index < ctx->num_uv_layers; 
++layer_index) {
+               ctx->uv_layers[layer_index] = CustomData_get_layer_n(
+                       &subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
+       }
+}
+
+static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
+{
+       Mesh *subdiv_mesh = ctx->subdiv_mesh;
+       /* Pointers to original indices layers. */
+       ctx->vert_origindex = CustomData_get_layer(
+               &subdiv_mesh->vdata, CD_ORIGINDEX);
+       ctx->edge_origindex = CustomData_get_layer(
+               &subdiv_mesh->edata, CD_ORIGINDEX);
+       ctx->loop_origindex = CustomData_get_layer(
+               &subdiv_mesh->ldata, CD_ORIGINDEX);
+       ctx->poly_origindex = CustomData_get_layer(
+               &subdiv_mesh->pdata, CD_ORIGINDEX);
+       /* UV layers interpolation. */
+       subdiv_mesh_ctx_cache_uv_layers(ctx);
+}
+
+static void subdiv_mesh_ctx_init_offsets(SubdivMeshContext *ctx)
+{
+       const Mesh *coarse_mesh = ctx->coarse_mesh;
+       const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+       /* Allocate memory. */
+       ctx->subdiv_vertex_offset = MEM_malloc_arrayN(
+               coarse_mesh->totpoly,
+               sizeof(*ctx->subdiv_vertex_offset),
+               "vertex_offset");
+       ctx->subdiv_edge_offset = MEM_malloc_arrayN(
+               coarse_mesh->totpoly,
+               sizeof(*ctx->subdiv_edge_offset),
+               "subdiv_edge_offset");
+       ctx->subdiv_polygon_offset = MEM_malloc_arrayN(
+               coarse_mesh->totpoly,
+               sizeof(*ctx->subdiv_polygon_offset),
+               "subdiv_polygon_offset");
+       ctx->face_ptex_offset = MEM_malloc_arrayN(coarse_mesh->totpoly,
+                                                 
sizeof(*ctx->face_ptex_offset),
+                                                 "face_ptex_offset");
+       /* Fill in offsets. */
+       int vertex_offset = 0;
+       int edge_offset = 0;
+       int polygon_offset = 0;
+       int face_ptex_offset = 0;
+       for (int poly_index = 0; poly_index < coarse_mesh->totpoly; 
poly_index++) {
+               const MPoly *coarse_poly = &coarse_mpoly[poly_index];
+               const int ptex_face_resolution = ptex_face_resolution_get(
+                       coarse_poly, ctx->settings->resolution);
+               const int ptex_face_resolution2 =
+                       ptex_face_resolution * ptex_face_resolution;
+               const int num_ptex_faces_per_poly =
+                       num_ptex_faces_per_poly_get(coarse_poly);
+               ctx->subdiv_vertex_offset[poly_index] = vertex_offset;
+               ctx->subdiv_edge_offset[poly_index] = edge_offset;
+               ctx->subdiv_polygon_offset[poly_index] = polygon_offset;
+               ctx->face_ptex_offset[poly_index] = face_ptex_offset;
+               vertex_offset += num_ptex_faces_per_poly * 
ptex_face_resolution2;
+               edge_offset += num_ptex_faces_per_poly *
+                       num_edges_per_ptex_face_get(ptex_face_resolution);
+               polygon_offset +=
+                       num_ptex_faces_per_poly *
+                       num_polys_per_ptex_get(ptex_face_resolution);
+               face_ptex_offset += num_ptex_faces_per_poly;
+       }
+       ctx->num_subdiv_vertices = vertex_offset;
+       ctx->num_subdiv_edges = edge_offset;
+       ctx->num_subdiv_polygons = polygon_offset;
+       ctx->num_subdiv_loops = 4 * ctx->num_subdiv_polygons;
+}
+
+static void subdiv_mesh_ctx_init(SubdivMeshContext *ctx)
+{
+       subdiv_mesh_ctx_init_offsets(ctx);
+}
+
+static void subdiv_mesh_ctx_init_result(SubdivMeshContext *ctx)
+{
+       subdiv_mesh_ctx_cache_custom_data_layers(ctx);
+}
+
+static void subdiv_mesh_ctx_free(SubdivMeshContext *ctx)
+{
+       MEM_freeN(ctx->subdiv_vertex_offset);
+       MEM_freeN(ctx->subdiv_edge_offset);
+       MEM_freeN(ctx->face_ptex_offset);
+}
+
+/* 
=============================================================================
+ * Loop custom data copy helpers.
+ */
+
 typedef struct LoopsOfPtex {
        /* First loop of the ptex, starts at ptex (0, 0) and goes in u 
direction. */
        const MLoop *first_loop;
@@ -112,6 +244,10 @@ static void loops_of_ptex_get(
        }
 }
 
+/* 
=============================================================================
+ * Edge custom data copy helpers.
+ */
+
 typedef struct EdgesOfPtex {
        /* First edge of the ptex, starts at ptex (0, 0) and goes in u 
direction. */
        const MEdge *first_edge;
@@ -145,6 +281,10 @@ static void edges_of_ptex_get(
        }
 }
 
+/* 
=============================================================================
+ * Vertex custom data interpolation helpers.
+ */
+
 /* TODO(sergey): Somehow de-duplicate with loops storage, without too much
  * exception cases all over the code.
  */
@@ -285,6 +425,10 @@ static void vertex_interpolation_end(
        }
 }
 
+/* 
=============================================================================
+ * Loop custom data interpolation helpers.
+ */
+
 typedef struct LoopsForInterpolation {
  /* This field points to a loop data which is to be used for interpolation.
         * The idea is to avoid unnecessary allocations for regular faces, where
@@ -413,6 +557,10 @@ static

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to