[Bf-blender-cvs] [8e8952b7e36] blender2.8: Multires: Initial work to get sculpting to work with OpenSubdiv

Sergey Sharybin noreply at git.blender.org
Fri Sep 14 14:44:54 CEST 2018


Commit: 8e8952b7e363b878cfc97440c1d2254dffbaf840
Author: Sergey Sharybin
Date:   Fri Sep 14 10:56:54 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB8e8952b7e363b878cfc97440c1d2254dffbaf840

Multires: Initial work to get sculpting to work with OpenSubdiv

Allows to go to sculpt mode, do brush strokes, get out of sculpt mode
and have deformation preserved.

The issues currently is that the current implementation of CCG
storage is created from the limit surface, without displacement
taken into account. It is trivial to get displaced coordinates,
but it is more tricky to get displaced normals. This is something
to be solved next.

Another limitation is that this only works for sculpting at a maximal
multires level. There is code to be done to support propagation
of displacement onto a higher levels.

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

M	source/blender/blenkernel/BKE_multires.h
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/BKE_subdiv_ccg.h
M	source/blender/blenkernel/intern/multires.c
M	source/blender/blenkernel/intern/multires_reshape.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/modifiers/intern/MOD_multires.c

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

diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 92755477d5e..26173643cbf 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -33,6 +33,7 @@
  */
 
 enum MultiresModifiedFlags;
+
 struct Depsgraph;
 struct DerivedMesh;
 struct MDisps;
@@ -42,6 +43,7 @@ struct Multires;
 struct MultiresModifierData;
 struct Object;
 struct Scene;
+struct SubdivCCG;
 
 struct MLoop;
 struct MVert;
@@ -126,6 +128,9 @@ bool multiresModifier_reshapeFromDeformModifier(
         struct MultiresModifierData *mmd,
         struct Object *ob,
         struct ModifierData *md);
+bool multiresModifier_reshapeFromCCG(
+        struct Object *dst,
+        struct SubdivCCG *subdiv_ccg);
 
 /* Subdivision integration, defined in multires_subdiv.c */
 
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index ade23a2a9ca..d2d09609221 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -56,6 +56,7 @@ struct Scene;
 struct ViewLayer;
 struct Sculpt;
 struct StrokeCache;
+struct SubdivCCG;
 struct Tex;
 struct ImagePool;
 struct UnifiedPaintSettings;
@@ -198,6 +199,9 @@ typedef struct SculptSession {
 	/* Undo/redo log for dynamic topology sculpting */
 	struct BMLog *bm_log;
 
+	/* Limit surface/grids. */
+	struct SubdivCCG *subdiv_ccg;
+
 	/* PBVH acceleration structure */
 	struct PBVH *pbvh;
 	bool show_diffuse_color;
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 3838474381c..47fedb565fc 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -155,6 +155,8 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
 /* multires level, only valid for type == PBVH_GRIDS */
 void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
 
+struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh, int *num_grids);
+
 /* Only valid for type == PBVH_BMESH */
 struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
 void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h
index 59a31e158cc..c760fb04fd3 100644
--- a/source/blender/blenkernel/BKE_subdiv_ccg.h
+++ b/source/blender/blenkernel/BKE_subdiv_ccg.h
@@ -114,6 +114,17 @@ typedef struct SubdivCCG {
 	/* TODO(sergey): Consider adding CD layers here, so we can draw final mesh
 	 * from grids, and have UVs and such work.
 	 */
+
+	/* Integration with sculpting. */
+	/* TODO(sergey): Is this really best way to go? Kind of annoying to have
+	 * such use-related flags in a more or less generic structure.
+	 */
+	struct {
+		/* Corresponds to MULTIRES_COORDS_MODIFIED. */
+		bool coords;
+		/* Corresponds to MULTIRES_HIDDEN_MODIFIED. */
+		bool hidden;
+	} dirty;
 } SubdivCCG;
 
 /* Create real hi-res CCG from subdivision.
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 22a335c7fd4..4dd64e3d8b2 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -57,6 +57,7 @@
 #include "BKE_multires.h"
 #include "BKE_paint.h"
 #include "BKE_scene.h"
+#include "BKE_subdiv_ccg.h"
 #include "BKE_subsurf.h"
 #include "BKE_editmesh.h"
 
@@ -389,21 +390,46 @@ static void multires_dm_mark_as_modified(DerivedMesh *dm, MultiresModifiedFlags
 	ccgdm->multires.modified_flags |= flags;
 }
 
+static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg,
+                                          MultiresModifiedFlags flags)
+{
+	if (flags & MULTIRES_COORDS_MODIFIED) {
+		subdiv_ccg->dirty.coords = true;
+	}
+	if (flags & MULTIRES_HIDDEN_MODIFIED) {
+		subdiv_ccg->dirty.hidden = true;
+	}
+}
+
 void multires_mark_as_modified(Object *ob, MultiresModifiedFlags flags)
 {
-	if (ob && ob->derivedFinal)
-		multires_dm_mark_as_modified(ob->derivedFinal, flags);
+	if (ob == NULL) {
+		return;
+	}
+	Mesh *mesh = ob->data;
+	SubdivCCG *subdiv_ccg = mesh->runtime.subsurf_ccg;
+	if (subdiv_ccg == NULL) {
+		return;
+	}
+	multires_ccg_mark_as_modified(subdiv_ccg, flags);
 }
 
 void multires_force_update(Object *ob)
 {
-	if (ob) {
-		BKE_object_free_derived_caches(ob);
-
-		if (ob->sculpt && ob->sculpt->pbvh) {
-			BKE_pbvh_free(ob->sculpt->pbvh);
-			ob->sculpt->pbvh = NULL;
+	if (ob == NULL) {
+		return;
+	}
+	if (ob->sculpt && ob->sculpt->pbvh) {
+		PBVH *pbvh = ob->sculpt->pbvh;
+		if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
+			multiresModifier_reshapeFromCCG(ob, ob->sculpt->subdiv_ccg);
+		}
+		else {
+			/* NOTE: Disabled for until OpenSubdiv is enabled by default. */
+			// BLI_assert(!"multires_force_update is used on non-grids PBVH");
 		}
+		BKE_pbvh_free(pbvh);
+		ob->sculpt->pbvh = NULL;
 	}
 }
 
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index bdd871b5d37..782c7638b58 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -35,13 +35,16 @@
 
 #include "BLI_utildefines.h"
 #include "BLI_math_vector.h"
+#include "BLI_task.h"
 
+#include "BKE_ccg.h"
 #include "BKE_library.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
 #include "BKE_modifier.h"
 #include "BKE_multires.h"
 #include "BKE_subdiv.h"
+#include "BKE_subdiv_ccg.h"
 #include "BKE_subdiv_eval.h"
 #include "BKE_subdiv_foreach.h"
 #include "BKE_subdiv_mesh.h"
@@ -126,8 +129,23 @@ BLI_INLINE void construct_tangent_matrix(float tangent_matrix[3][3],
 	normalize_v3(tangent_matrix[2]);
 }
 
+static void multires_reshape_init_mmd(
+        MultiresModifierData *reshape_mmd,
+        const MultiresModifierData *mmd)
+{
+	*reshape_mmd = *mmd;
+}
+
+static void multires_reshape_init_mmd_top_level(
+        MultiresModifierData *reshape_mmd,
+        const MultiresModifierData *mmd)
+{
+	*reshape_mmd = *mmd;
+	reshape_mmd->lvl = reshape_mmd->totlvl;
+}
+
 /* =============================================================================
- * Reshape internal functionality.
+ * General reshape implementaiton, reused by all particular cases.
  */
 
 typedef struct MultiresReshapeContext {
@@ -135,25 +153,10 @@ typedef struct MultiresReshapeContext {
 	Object *object;
 	const Mesh *coarse_mesh;
 	MDisps *mdisps;
-	const float (*deformed_verts)[3];
-	int num_deformed_verts;
+	/* NOTE: This is a grid size on th top level. */
 	int grid_size;
 } MultiresReshapeContext;
 
-static bool multires_reshape_topology_info(
-        const SubdivForeachContext *foreach_context,
-        const int num_vertices,
-        const int UNUSED(num_edges),
-        const int UNUSED(num_loops),
-        const int UNUSED(num_polygons))
-{
-	MultiresReshapeContext *ctx = foreach_context->user_data;
-	if (num_vertices != ctx->num_deformed_verts) {
-		return false;
-	}
-	return true;
-}
-
 static void multires_reshape_vertex_copy_to_next(
         MultiresReshapeContext *ctx,
         const MPoly *coarse_poly,
@@ -238,13 +241,13 @@ static void copy_boundary_displacement(
 	}
 }
 
-static void multires_reshape_vertex(
+static void multires_reshape_vertex_from_final_coord(
         MultiresReshapeContext *ctx,
         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)
+        const float final_P[3])
 {
 	Subdiv *subdiv = ctx->subdiv;
 	const int grid_size = ctx->grid_size;
@@ -273,7 +276,6 @@ static void multires_reshape_vertex(
 		ptex_uv_to_grid_uv(u, v, &grid_u, &grid_v);
 	}
 	/* Convert object coordinate to a tangent space of displacement grid. */
-	const float *final_P = ctx->deformed_verts[subdiv_vertex_index];
 	float D[3];
 	sub_v3_v3v3(D, final_P, P);
 	float tangent_matrix[3][3];
@@ -292,6 +294,47 @@ static void multires_reshape_vertex(
 	        ctx, coarse_poly, face_corner, grid_x, grid_y, displacement_grid);
 }
 
+/* =============================================================================
+ * Reshape from deformed veretx coordinates.
+ */
+
+typedef struct MultiresReshapeFromDeformedVertsContext {
+	MultiresReshapeContext reshape_ctx;
+	const float (*deformed_verts)[3];
+	int num_deformed_verts;
+} MultiresReshapeFromDeformedVertsContext;
+
+static bool multires_reshape_topology_info(
+        const SubdivForeachContext *foreach_context,
+        const int num_vertices,
+        const int UNUSED(num_edges),
+        const int UNUSED(num_loops),
+        const int UNUSED(num_polygons))
+{
+	MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
+	if (num_vertices != ctx->num_deformed_verts) {
+		return false;
+	}
+	return true;
+}
+
+static void multires_reshape_vertex(
+        MultiresReshapeFromDeformedVertsContext *ctx,
+        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)
+{
+	const float *final_P = ctx->deformed_verts[subdiv_vertex_index];
+	multires_reshape_vertex_from_final_coord(
+	        &ctx->reshape_ctx,
+	        ptex_face_index, u, v,
+	        coarse_poly_index,
+	        coarse_corner,
+            final_P);
+}
+
 static void multires_reshape_vertex_inner(
         const SubdivForeachContext *foreach_context,
         void *UNUSED(tls_v),
@@ -301,7 +344,7 @@ static void multires_reshape_vertex_inner(
         const int coarse_corner,
         const int subdiv_vertex_index)
 {
-	MultiresReshapeContext *ctx = foreach_context->user_data;
+	MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
 	multires_reshape_vertex(
 	        ctx,
 	        ptex_face_index, u, v,
@@ -320,7 +363,7 @@ static void multires_reshape_vertex_every_corner(
         const int coarse_corner,
         const int subdiv_vertex_index)
 {
-	MultiresReshapeContext *ctx = foreach_context->user_data;
+	MultiresReshapeFromDeformedVertsContext *ctx = foreach_context->user_data;
 	multires_reshape_vertex(
 	        ctx,
 	        ptex_face_index, u, v,
@@ -339,7 +382,7 @@ static void multires_reshape_vertex_every_edge(

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list