[Bf-blender-cvs] [6b6c27694e1] blender2.8: Subsurf: Implement foreach traversal for subdivsion topology

Sergey Sharybin noreply at git.blender.org
Wed Aug 22 12:22:10 CEST 2018


Commit: 6b6c27694e16ee1f21fe562408afc8a1fa4690f6
Author: Sergey Sharybin
Date:   Mon Aug 20 12:46:44 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB6b6c27694e16ee1f21fe562408afc8a1fa4690f6

Subsurf: Implement foreach traversal for subdivsion topology

This makes it more generic process to perform actions which
depend on ptex face + (u, v) and on subdivided vertex index.

Currently it is still just a subdivision calculation process,
but same foreach callbacks can easily be used to propagate
displacement from known vertex locations back to displacement
grids.

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

M	source/blender/blenkernel/BKE_subdiv.h
M	source/blender/blenkernel/CMakeLists.txt
A	source/blender/blenkernel/intern/subdiv_foreach.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 9f8a0f261e6..76539383f16 100644
--- a/source/blender/blenkernel/BKE_subdiv.h
+++ b/source/blender/blenkernel/BKE_subdiv.h
@@ -35,6 +35,7 @@ struct OpenSubdiv_Converter;
 struct OpenSubdiv_Evaluator;
 struct OpenSubdiv_TopologyRefiner;
 struct Subdiv;
+struct SubdivToMeshSettings;
 
 /** \file BKE_subdiv.h
  *  \ingroup bke
@@ -252,6 +253,149 @@ void BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal(
         void *point_buffer, const int point_offset, const int point_stride,
         void *normal_buffer, const int normal_offset, const int normal_stride);
 
+/* ========================== FOREACH/TRAVERSE API ========================== */
+
+struct SubdivForeachContext;
+
+typedef bool (*SubdivForeachTopologyInformationCb)(
+        const struct SubdivForeachContext *context,
+        const int num_vertices,
+        const int num_edges,
+        const int num_loops,
+        const int num_polygons);
+
+typedef void (*SubdivForeachVertexFromCornerCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int ptex_face_index,
+        const float u, const float v,
+        const int coarse_vertex_index,
+        const int coarse_poly_index,
+        const int coarse_corner,
+        const int subdiv_vertex_index);
+
+typedef void (*SubdivForeachVertexFromEdgeCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int ptex_face_index,
+        const float u, const float v,
+        const int coarse_edge_index,
+        const int coarse_poly_index,
+        const int coarse_corner,
+        const int subdiv_vertex_index);
+
+typedef void (*SubdivForeachVertexInnerCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int ptex_face_index,
+        const float u, const float v,
+        const int coarse_poly_index,
+        const int coarse_corner,
+        const int subdiv_vertex_index);
+
+typedef void (*SubdivForeachEdgeCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int coarse_edge_index,
+        const int subdiv_edge_index,
+        const int subdiv_v1, const int subdiv_v2);
+
+typedef void (*SubdivForeachLoopCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int ptex_face_index,
+        const float u, const float v,
+        const int coarse_loop_index,
+        const int coarse_poly_index,
+        const int coarse_corner,
+        const int subdiv_loop_index,
+        const int subdiv_vertex_index, const int subdiv_edge_index);
+
+typedef void (*SubdivForeachPolygonCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int coarse_poly_index,
+        const int subdiv_poly_index,
+        const int start_loop_index, const int num_loops);
+
+typedef void (*SubdivForeachLooseCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int coarse_vertex_index,
+        const int subdiv_vertex_index);
+
+typedef void (*SubdivForeachVertexOfLooseEdgeCb)(
+        const struct SubdivForeachContext *context,
+        void *tls,
+        const int coarse_edge_index,
+        const float u,
+        const int subdiv_vertex_index);
+
+typedef struct SubdivForeachContext {
+	/* Is called when topology information becomes available.
+	 * Is only called once.
+	 *
+	 * NOTE: If this callback returns false, the foreach loop is aborted.
+	 */
+	SubdivForeachTopologyInformationCb topology_info;
+	/* These callbacks are called from every ptex which shares "emitting"
+	 * vertex or edge.
+	 */
+	SubdivForeachVertexFromCornerCb vertex_every_corner;
+	SubdivForeachVertexFromEdgeCb vertex_every_edge;
+	/* Those callbacks are run once per subdivision vertex, ptex is undefined
+	 * as in it will be whatever first ptex face happened to be tarversed in
+	 * the multi-threaded environment ahd which shares "emitting" vertex or
+	 * edge.
+	 */
+	SubdivForeachVertexFromCornerCb vertex_corner;
+	SubdivForeachVertexFromEdgeCb vertex_edge;
+	/* Called exactly once, always corresponds to a single ptex face. */
+	SubdivForeachVertexInnerCb vertex_inner;
+	/* Called once for each loose vertex. One loose coarse vertexcorresponds
+	 * to a single subdivision vertex.
+	 */
+	SubdivForeachLooseCb vertex_loose;
+	/* Called once per vertex created for loose edge. */
+	SubdivForeachVertexOfLooseEdgeCb vertex_of_loose_edge;
+	/* NOTE: If subdivided edge does not come from coarse edge, ORIGINDEX_NONE
+	 * will be passed as coarse_edge_index.
+	 */
+	SubdivForeachEdgeCb edge;
+	/* NOTE: If subdivided loop does not come from coarse loop, ORIGINDEX_NONE
+	 * will be passed as coarse_loop_index.
+	 */
+	SubdivForeachLoopCb loop;
+	SubdivForeachPolygonCb poly;
+
+	/* User-defined pointer, to allow callbacks know something about context the
+	 * traversal is happening for,
+	 */
+	void *user_data;
+
+	/* Initial value of TLS data. */
+	void *user_data_tls;
+	/* Size of TLS data. */
+	size_t user_data_tls_size;
+	/* Function to free TLS storage. */
+	void (*user_data_tls_free)(void *tls);
+} SubdivForeachContext;
+
+/* Invokes callbacks in the order and with values which corresponds to creation
+ * of final subdivided mesh.
+ *
+ * Returns truth if the whole topology was traversed, without any early exits.
+ *
+ * TODO(sergey): Need to either get rid of subdiv or of coarse_mesh.
+ * The main point here is th be abel to get base level topology, which can be
+ * done with either of those. Having both of them is kind of redundant.
+ */
+bool BKE_subdiv_foreach_subdiv_geometry(
+        struct Subdiv *subdiv,
+        const struct SubdivForeachContext *context,
+        const struct SubdivToMeshSettings *mesh_settings,
+        const struct Mesh *coarse_mesh);
+
 /* =========================== SUBDIV TO MESH API =========================== */
 
 typedef struct SubdivToMeshSettings {
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index aeb4830127d..01900d5b6cf 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -197,6 +197,7 @@ set(SRC
 	intern/subdiv_displacement.c
 	intern/subdiv_displacement_multires.c
 	intern/subdiv_eval.c
+	intern/subdiv_foreach.c
 	intern/subdiv_mesh.c
 	intern/subdiv_stats.c
 	intern/subsurf_ccg.c
diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c
new file mode 100644
index 00000000000..b68b65475ac
--- /dev/null
+++ b/source/blender/blenkernel/intern/subdiv_foreach.c
@@ -0,0 +1,2041 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2018 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/subdiv_foreach.c
+ *  \ingroup bke
+ */
+
+#include "BKE_subdiv.h"
+
+#include "atomic_ops.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_key_types.h"
+
+#include "BLI_alloca.h"
+#include "BLI_bitmap.h"
+#include "BLI_math_vector.h"
+#include "BLI_task.h"
+
+#include "BKE_mesh.h"
+#include "BKE_key.h"
+
+#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)
+{
+	return (poly->totloop == 4) ? 1 : poly->totloop;
+}
+
+BLI_INLINE int num_edges_per_ptex_face_get(const int resolution)
+{
+	return 2 * (resolution - 1) * resolution;
+}
+
+BLI_INLINE int num_inner_edges_per_ptex_face_get(const int resolution)
+{
+	if (resolution < 2) {
+		return 0;
+	}
+	return (resolution - 2) * resolution +
+	       (resolution - 1) * (resolution - 1);
+}
+
+/* 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);
+}
+
+/* =============================================================================
+ * Context which is passed to all threaded tasks.
+ */
+
+typedef struct SubdivForeachTaskContext {
+	const Mesh *coarse_mesh;
+	const SubdivToMeshSettings *settings;
+	/* Callbacks. */
+	const SubdivForeachContext *foreach_context;
+	/* 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;
+	/* Offsets of various geometry in the subdivision mesh arrays. */
+	int vertices_corner_offset;
+	int vertices_edge_offset;
+	int vertices_inner_offset;
+	int edge_boundary_offset;
+	int edge_inner_offset;
+	/* 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_of

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list