[Bf-blender-cvs] [08e6bccdf4a] blender2.8: Subsurf: Support subdivision of loose elements

Sergey Sharybin noreply at git.blender.org
Wed Aug 1 18:43:27 CEST 2018


Commit: 08e6bccdf4a2114847194fbe8adcb1fc83a1746f
Author: Sergey Sharybin
Date:   Tue Jul 31 15:09:29 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB08e6bccdf4a2114847194fbe8adcb1fc83a1746f

Subsurf: Support subdivision of loose elements

Applies to vertices and edges. Biggest annoyance here is that OpenSubdiv's
topology converter expects that there is no loose geometry, otherwise it
is getting confused.

For now solution is to create some sort of mapping from real Mesh vertex
and edge index to a non-loose-index. Now the annoying part is that this
is an extra step to calculate before we can compare topology, meaning FPS
will not be as great as if we knew for sure that topology didn't change.

Loose edges subdivision is different from what it used to be with old
subdivision code, but probably nice feature now is that endpoints of loose
edges are stay at the coarse vertex locations. This allows to have things
like plane with hair strands, without need to duplicate edge vertices at
endpoints.

All this required some re-work of topology refiner creation, which is now
only passing edges and vertices which are adjacent to face. This is how
topology refiner is supposed to be used, and this is how its validator
also works. Vertices which are adjacent to loose edges are marked as
infinite sharp. This seems to be good-enough approximation for now. In the
future we might tweaks things a bit and push such vertices in average
direction of loose edges, to match old subdivision code closer.

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

M	intern/opensubdiv/internal/opensubdiv_converter_factory.cc
M	intern/opensubdiv/internal/opensubdiv_internal.h
M	intern/opensubdiv/opensubdiv_converter_capi.h
M	source/blender/blenkernel/intern/subdiv_converter_mesh.c
M	source/blender/blenkernel/intern/subdiv_eval.c
M	source/blender/blenkernel/intern/subdiv_mesh.c

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

diff --git a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
index 48516cc80b7..06707cbf418 100644
--- a/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
+++ b/intern/opensubdiv/internal/opensubdiv_converter_factory.cc
@@ -346,16 +346,10 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
   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);
-    for (int i = 0; i < vertex_edges.size(); ++i) {
-      const int edge_index = vertex_edges[i];
-      ConstIndexArray edge_faces = getBaseEdgeFaces(refiner, edge_index);
-      if (edge_faces.size() == 0) {
-        setBaseVertexSharpness(refiner, vertex_index,
-                               Crease::SHARPNESS_INFINITE);
-        break;
-      }
-    }
-    if (vertex_edges.size() == 2) {
+    if (converter->isInfiniteSharpVertex(converter, vertex_index)) {
+      setBaseVertexSharpness(
+          refiner, vertex_index, Crease::SHARPNESS_INFINITE);
+    } else if (vertex_edges.size() == 2) {
       const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
       const float sharpness0 = converter->getEdgeSharpness(converter, edge0);
       const float sharpness1 = converter->getEdgeSharpness(converter, edge1);
diff --git a/intern/opensubdiv/internal/opensubdiv_internal.h b/intern/opensubdiv/internal/opensubdiv_internal.h
index b9d196bbe9e..16365896edf 100644
--- a/intern/opensubdiv/internal/opensubdiv_internal.h
+++ b/intern/opensubdiv/internal/opensubdiv_internal.h
@@ -24,9 +24,6 @@
 // Never do for release builds.
 #  undef OPENSUBDIV_VALIDATE_TOPOLOGY
 #else
-// TODO(sergey): Always disabled for now, the check doesn't handle multiple
-// non-manifolds from the OpenSubdiv side currently.
-// #  undef OPENSUBDIV_VALIDATE_TOPOLOGY
 #  define OPENSUBDIV_VALIDATE_TOPOLOGY
 #endif
 
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index a939f1117e0..58a231deb30 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -19,6 +19,8 @@
 #ifndef OPENSUBDIV_CONVERTER_CAPI_H_
 #define OPENSUBDIV_CONVERTER_CAPI_H_
 
+#include <stdint.h>  // for bool
+
 #include "opensubdiv_capi_type.h"
 
 #ifdef __cplusplus
@@ -34,6 +36,7 @@ typedef struct OpenSubdiv_Converter {
 
   //////////////////////////////////////////////////////////////////////////////
   // Global geometry counters.
+
   // Number of faces/edges/vertices in the base mesh.
   int (*getNumFaces)(const struct OpenSubdiv_Converter* converter);
   int (*getNumEdges)(const struct OpenSubdiv_Converter* converter);
@@ -92,6 +95,11 @@ typedef struct OpenSubdiv_Converter {
                          const int vertex_index,
                          int* vertex_faces);
 
+  // Check whether vertex is to be marked as an infinite sharp.
+  // This is a way to make sharp vertices which are adjacent to a loose edges.
+  bool (*isInfiniteSharpVertex)(const struct OpenSubdiv_Converter* converter,
+                                const int vertex_index);
+
   //////////////////////////////////////////////////////////////////////////////
   // Face-varying data.
 
diff --git a/source/blender/blenkernel/intern/subdiv_converter_mesh.c b/source/blender/blenkernel/intern/subdiv_converter_mesh.c
index 1a2c26b3564..50143dd46e1 100644
--- a/source/blender/blenkernel/intern/subdiv_converter_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_converter_mesh.c
@@ -31,6 +31,7 @@
 #include "DNA_meshdata_types.h"
 
 #include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
 #include "BLI_math_vector.h"
 
 #include "BKE_customdata.h"
@@ -68,6 +69,26 @@ typedef struct ConverterStorage {
 	 */
 	int *loop_uv_indices;
 	int num_uv_coordinates;
+
+	/* Indexed by coarse mesh elements, gives index of corresponding element
+	 * with ignoring all non-manifold entities.
+	 *
+	 * NOTE: This isn't strictly speaking manifold, this is more like non-loose
+	 * geometry index. As in, index of element as if there were no loose edges
+	 * or vertices in the mesh.
+	 */
+	int *manifold_vertex_index;
+	int *manifold_edge_index;
+	/* Indexed by vertex index from mesh, corresponds to whether this vertex has
+	 * infinite sharpness due to non-manifol topology.
+	 */
+	BLI_bitmap *infinite_sharp_vertices_map;
+	/* Reverse mapping to above. */
+	int *manifold_vertex_index_reverse;
+	int *manifold_edge_index_reverse;
+	/* Number of non-loose elements. */
+	int num_manifold_vertices;
+	int num_manifold_edges;
 } ConverterStorage;
 
 static OpenSubdiv_SchemeType get_scheme_type(
@@ -98,70 +119,81 @@ static int get_num_faces(const OpenSubdiv_Converter *converter)
 static int get_num_edges(const OpenSubdiv_Converter *converter)
 {
 	ConverterStorage *storage = converter->user_data;
-	return storage->mesh->totedge;
+	return storage->num_manifold_edges;
 }
 
-static int get_num_verts(const OpenSubdiv_Converter *converter)
+static int get_num_vertices(const OpenSubdiv_Converter *converter)
 {
 	ConverterStorage *storage = converter->user_data;
-	return storage->mesh->totvert;
+	return storage->num_manifold_vertices;
 }
 
-static int get_num_face_verts(const OpenSubdiv_Converter *converter, int face)
+static int get_num_face_vertices(const OpenSubdiv_Converter *converter,
+                                 int manifold_face_index)
 {
 	ConverterStorage *storage = converter->user_data;
-	return storage->mesh->mpoly[face].totloop;
+	return storage->mesh->mpoly[manifold_face_index].totloop;
 }
 
-static void get_face_verts(const OpenSubdiv_Converter *converter,
-                           int face,
-                           int *face_verts)
+static void get_face_vertices(const OpenSubdiv_Converter *converter,
+                              int manifold_face_index,
+                              int *manifold_face_vertices)
 {
 	ConverterStorage *storage = converter->user_data;
-	const MPoly *mp = &storage->mesh->mpoly[face];
+	const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
 	const MLoop *mloop = storage->mesh->mloop;
-	for (int loop = 0; loop < mp->totloop; loop++) {
-		face_verts[loop] = mloop[mp->loopstart + loop].v;
+	for (int corner = 0; corner < poly->totloop; corner++) {
+		manifold_face_vertices[corner] = storage->manifold_vertex_index[
+		        mloop[poly->loopstart + corner].v];
 	}
 }
 
 static void get_face_edges(const OpenSubdiv_Converter *converter,
-                           int face,
-                           int *face_edges)
+                           int manifold_face_index,
+                           int *manifold_face_edges)
 {
 	ConverterStorage *storage = converter->user_data;
-	const MPoly *mp = &storage->mesh->mpoly[face];
+	const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
 	const MLoop *mloop = storage->mesh->mloop;
-	for (int loop = 0; loop < mp->totloop; loop++) {
-		face_edges[loop] = mloop[mp->loopstart + loop].e;
+	for (int corner = 0; corner < poly->totloop; corner++) {
+		manifold_face_edges[corner] =
+		        storage->manifold_edge_index[mloop[poly->loopstart + corner].e];
 	}
 }
 
-static void get_edge_verts(const OpenSubdiv_Converter *converter,
-                           int edge,
-                           int *edge_verts)
+static void get_edge_vertices(const OpenSubdiv_Converter *converter,
+                              int manifold_edge_index,
+                              int *manifold_edge_vertices)
 {
 	ConverterStorage *storage = converter->user_data;
-	const MEdge *me = &storage->mesh->medge[edge];
-	edge_verts[0] = me->v1;
-	edge_verts[1] = me->v2;
+	const int edge_index =
+	        storage->manifold_edge_index_reverse[manifold_edge_index];
+	const MEdge *edge = &storage->mesh->medge[edge_index];
+	manifold_edge_vertices[0] = storage->manifold_vertex_index[edge->v1];
+	manifold_edge_vertices[1] = storage->manifold_vertex_index[edge->v2];
 }
 
-static int get_num_edge_faces(const OpenSubdiv_Converter *converter, int edge)
+static int get_num_edge_faces(const OpenSubdiv_Converter *converter,
+                              int manifold_edge_index)
 {
 	ConverterStorage *storage = converter->user_data;
+	const int edge_index =
+	        storage->manifold_edge_index_reverse[manifold_edge_index];
 #ifdef USE_MESH_ELEMENT_MAPPING
-	return storage->edge_poly_map[edge].count;
+	return storage->edge_poly_map[edge_index].count;
 #else
 	const Mesh *mesh = storage->mesh;
 	const MPoly *mpoly = mesh->mpoly;
 	const MLoop *mloop = mesh->mloop;
 	int num = 0;
-	for (int poly = 0; poly < mesh->totpoly; poly++) {
-		const MPoly *mp = &mpoly[poly];
-		for (int loop = 0; loop < mp->totloop; loop++) {
-			const MLoop *ml = &mloop[mp->loopstart + loop];
-			if (ml->e == edge) {
+	for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
+		const MPoly *poly = &mpoly[poly_index];
+		for (int corner = 0; corner < poly->totloop; corner++) {
+			const MLoop *loop = &mloop[poly->loopstart + corner];
+			if (storage->manifold_edge_index[loop->e] == -1) {
+				continue;
+			}
+			if (loop->e == edge_index) {
 				++num;
 				break;
 			}
@@ -172,25 +204,30 @@ static int get_num_edge_faces(const OpenSubdiv_Converter *converter, int edge)
 }
 
 static void get_edge_faces(const OpenSubdiv_Converter *converter,
-                           int edge,
-                           int *edge_faces)
+                           int manifold_edge_index,
+                           int *manifold_edge_faces)
 {
 	ConverterStorage *storage = converter->user_data;
+	const int edge_index =
+	        storage->manifold_edge_index_reverse[manifold_edge_index];
 #ifdef USE_MESH_ELEMENT_MAPPING
-	memcpy(edge_faces,
-	       storage->edge_poly_map[edge].indices,
-	       sizeof(int) * storage->edge_poly_map[edge].count);
+	memcpy(manifold_edge_faces,
+	       storage->edge_poly_map[edge_index].indices,
+	       sizeof(int) * storage->edge_poly_map[edge_index].count);
 #else
 	const Mesh *mesh = storage->mesh;
 	const MPoly *mpoly = mesh->mpoly;
 	const MLoop *mloop = mesh->mloop;
 	int 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list