[Bf-blender-cvs] [f6eccd367cf] blender2.8: Subsurf: Subdivide polygons to the same resolution

Sergey Sharybin noreply at git.blender.org
Mon Jul 23 19:17:14 CEST 2018


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. @@



More information about the Bf-blender-cvs mailing list