[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29164] trunk/blender/source/blender: Sculpt & modifiers: patch by Sergey Sharybin, with modifications by me.

Brecht Van Lommel brecht at blender.org
Wed Jun 2 20:04:31 CEST 2010


Revision: 29164
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29164
Author:   blendix
Date:     2010-06-02 20:04:31 +0200 (Wed, 02 Jun 2010)

Log Message:
-----------
Sculpt & modifiers: patch by Sergey Sharybin, with modifications by me.

Fixes various crashes and redraw problems, most noticeable new feature
is that you can now sculpt on a multires mesh with deforming modifiers
preceding it.

I've left out support for sculpting on multires with enabled modifiers
following it, in this case only the base mesh can be sculpted now. The
code changes needed to do this are just too ugly in my opinion, would
need a more torough redesign which I don't think we should try now. In
my opinion this is also not really an important case, since it's going
to be incredibly slow anyway to run a modifier on a high res mesh while
sculpting.


So, to summarize current state:

* Fastest sculpting: base mesh with no modifiers or multires with only
  modifiers preceding it.
* Slower sculpting: base mesh with modifiers, depends on the speed of
  the modifiers.
* Not supported: multires mesh with modifiers following it.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_subsurf.h
    trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c
    trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c
    trunk/blender/source/blender/blenkernel/intern/multires.c
    trunk/blender/source/blender/blenkernel/intern/subsurf_ccg.c
    trunk/blender/source/blender/blenlib/BLI_pbvh.h
    trunk/blender/source/blender/blenlib/intern/pbvh.c
    trunk/blender/source/blender/editors/sculpt_paint/sculpt.c
    trunk/blender/source/blender/editors/sculpt_paint/sculpt_intern.h
    trunk/blender/source/blender/modifiers/intern/MOD_multires.c

Modified: trunk/blender/source/blender/blenkernel/BKE_subsurf.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_subsurf.h	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenkernel/BKE_subsurf.h	2010-06-02 18:04:31 UTC (rev 29164)
@@ -72,6 +72,7 @@
 	char *faceFlags;
 
 	struct PBVH *pbvh;
+	int pbvh_draw;
 	struct ListBase *fmap;
 	struct IndexNode *fmap_mem;
 

Modified: trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenkernel/intern/DerivedMesh.c	2010-06-02 18:04:31 UTC (rev 29164)
@@ -1870,10 +1870,6 @@
 		/* grab modifiers until index i */
 		if((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
 			break;
-
-		/*don't allow other modifiers past multires if in sculpt mode*/
-		if (!useRenderParams && ((ob->mode & OB_MODE_SCULPT) && ob->sculpt))
-			break;
 	}
 
 	for(md=firstmd; md; md=md->next)

Modified: trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenkernel/intern/cdderivedmesh.c	2010-06-02 18:04:31 UTC (rev 29164)
@@ -74,6 +74,7 @@
 
 	/* Cached */
 	struct PBVH *pbvh;
+	int pbvh_draw;
 	/* Mesh connectivity */
 	struct ListBase *fmap;
 	struct IndexNode *fmap_mem;
@@ -188,6 +189,7 @@
 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 {
 	CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+	Mesh *me= (ob)? ob->data: NULL;
 
 	if(!ob) {
 		cddm->pbvh= NULL;
@@ -196,13 +198,17 @@
 
 	if(!ob->sculpt)
 		return NULL;
-	if(ob->sculpt->pbvh)
+	if(ob->sculpt->pbvh) {
 		cddm->pbvh= ob->sculpt->pbvh;
+		cddm->pbvh_draw = (cddm->mvert == me->mvert);
+	}
 
+	/* always build pbvh from original mesh, and only use it for drawing if
+	   this derivedmesh is just original mesh. it's the multires subsurf dm
+	   that this is actually for, to support a pbvh on a modified mesh */
 	if(!cddm->pbvh && ob->type == OB_MESH) {
-		Mesh *me= ob->data;
-
 		cddm->pbvh = BLI_pbvh_new();
+		cddm->pbvh_draw = (cddm->mvert == me->mvert);
 		BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
 				   me->totface, me->totvert);
 	}
@@ -417,7 +423,7 @@
 	glVertex3fv(mvert[index].co);	\
 }
 
-	if(cddm->pbvh) {
+	if(cddm->pbvh && cddm->pbvh_draw) {
 		if(dm->numFaceData) {
 			float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 

Modified: trunk/blender/source/blender/blenkernel/intern/multires.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/multires.c	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenkernel/intern/multires.c	2010-06-02 18:04:31 UTC (rev 29164)
@@ -654,7 +654,9 @@
 			int i, j, numGrids, highGridSize, lowGridSize;
 
 			/* create subsurf DM from original mesh at high level */
-			cddm = CDDM_from_mesh(me, NULL);
+			if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform);
+			else cddm = CDDM_from_mesh(me, NULL);
+
 			highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0);
 
 			/* create multires DM from original mesh and displacements */
@@ -705,7 +707,9 @@
 		else {
 			DerivedMesh *cddm, *subdm;
 
-			cddm = CDDM_from_mesh(me, NULL);
+			if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform);
+			else cddm = CDDM_from_mesh(me, NULL);
+
 			subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0);
 			cddm->release(cddm);
 

Modified: trunk/blender/source/blender/blenkernel/intern/subsurf_ccg.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/subsurf_ccg.c	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenkernel/intern/subsurf_ccg.c	2010-06-02 18:04:31 UTC (rev 29164)
@@ -44,6 +44,7 @@
 #include "BKE_cdderivedmesh.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
+#include "BKE_modifier.h"
 #include "BKE_paint.h"
 #include "BKE_scene.h"
 #include "BKE_subsurf.h"
@@ -2229,10 +2230,28 @@
 	return ccgdm->fmap;
 }
 
+static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm)
+{
+	ModifierData *md;
+	MultiresModifierData *mmd= ccgdm->multires.mmd;
+
+	/* in sync with sculpt mode, only use multires grid pbvh if we are
+	   the last enabled modifier in the stack, otherwise we use the base
+	   mesh */
+	if(!mmd)
+		return 0;
+	
+	for(md=mmd->modifier.next; md; md= md->next)
+		if(modifier_isEnabled(mmd->modifier.scene, md, eModifierMode_Realtime))
+			return 0;
+	
+	return 1;
+}
+
 static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
 {
 	CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
-	int gridSize, numGrids;
+	int gridSize, numGrids, grid_pbvh;
 
 	if(!ob) {
 		ccgdm->pbvh= NULL;
@@ -2241,13 +2260,30 @@
 
 	if(!ob->sculpt)
 		return NULL;
-	if(ob->sculpt->pbvh)
-		ccgdm->pbvh= ob->sculpt->pbvh;
 
+	grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
+
+	if(ob->sculpt->pbvh) {
+		if(grid_pbvh) {
+			/* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
+			   but this can be freed on ccgdm release, this updates the pointers
+			   when the ccgdm gets remade, the assumption is that the topology
+			   does not change. */
+			ccgdm_create_grids(dm);
+			BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces);
+		}
+
+		ccgdm->pbvh = ob->sculpt->pbvh;
+		ccgdm->pbvh_draw = grid_pbvh;
+	}
+
 	if(ccgdm->pbvh)
 		return ccgdm->pbvh;
 
-	if(ccgdm->multires.mmd) {
+	/* no pbvh exists yet, we need to create one. only in case of multires
+	   we build a pbvh over the modified mesh, in other cases the base mesh
+	   is being sculpted, so we build a pbvh from that. */
+	if(grid_pbvh) {
 		ccgdm_create_grids(dm);
 
 		gridSize = ccgDM_getGridSize(dm);
@@ -2256,6 +2292,7 @@
 		ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
 		BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
 			numGrids, gridSize, (void**)ccgdm->gridFaces);
+		ccgdm->pbvh_draw = 1;
 	}
 	else if(ob->type == OB_MESH) {
 		Mesh *me= ob->data;
@@ -2263,6 +2300,7 @@
 		ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
 		BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
 				   me->totface, me->totvert);
+		ccgdm->pbvh_draw = 0;
 	}
 
 	return ccgdm->pbvh;

Modified: trunk/blender/source/blender/blenlib/BLI_pbvh.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_pbvh.h	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenlib/BLI_pbvh.h	2010-06-02 18:04:31 UTC (rev 29164)
@@ -111,6 +111,8 @@
 void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
 void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
 void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface);
+void BLI_pbvh_grids_update(PBVH *bvh, struct DMGridData **grids,
+	struct DMGridAdjacency *gridadj, void **gridfaces);
 
 /* Vertex Iterator */
 

Modified: trunk/blender/source/blender/blenlib/intern/pbvh.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/pbvh.c	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/blenlib/intern/pbvh.c	2010-06-02 18:04:31 UTC (rev 29164)
@@ -1323,3 +1323,10 @@
 	}
 }
 
+void BLI_pbvh_grids_update(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj, void **gridfaces)
+{
+	bvh->grids= grids;
+	bvh->gridadj= gridadj;
+	bvh->gridfaces= gridfaces;
+}
+

Modified: trunk/blender/source/blender/editors/sculpt_paint/sculpt.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/sculpt.c	2010-06-02 17:58:28 UTC (rev 29163)
+++ trunk/blender/source/blender/editors/sculpt_paint/sculpt.c	2010-06-02 18:04:31 UTC (rev 29164)
@@ -286,10 +286,21 @@
 static int sculpt_modifiers_active(Scene *scene, Object *ob)
 {
 	ModifierData *md;
+	MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
+
+	/* check if there are any modifiers after what we are sculpting,
+	   for a multires modifier with a deform modifier in front, we
+	   do no need to recalculate the modifier stack. note that this
+	   needs to be in sync with ccgDM_use_grid_pbvh! */
+	if(mmd)
+		md= mmd->modifier.next;
+	else
+		md= modifiers_getVirtualModifierList(ob);
 	
-	for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) {
+	/* exception for shape keys because we can edit those */
+	for(; md; md= md->next) {
 		if(modifier_isEnabled(scene, md, eModifierMode_Realtime))
-			if(!ELEM(md->type, eModifierType_Multires, eModifierType_ShapeKey))
+			if(md->type != eModifierType_ShapeKey)
 				return 1;
 	}
 	
@@ -363,7 +374,7 @@
 		BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, NULL);
 		BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw, NULL);
 
-		if((mmd=sculpt_multires_active(ob)))
+		if((mmd=sculpt_multires_active(scene, ob)))
 			multires_mark_as_modified(ob);
 
 		if(sculpt_modifiers_active(scene, ob))
@@ -1473,7 +1484,7 @@
 
 /* Sculpt mode handles multires differently from regular meshes, but only if
    it's the last modifier on the stack and it is not on the first level */
-struct MultiresModifierData *sculpt_multires_active(Object *ob)
+struct MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
 {
 	ModifierData *md, *nmd;
 	
@@ -1483,8 +1494,8 @@
 
 			/* Check if any of the modifiers after multires are active
 			 * if not it can use the multires struct */
-			for (nmd= md->next; nmd; nmd= nmd->next)
-				if(nmd->mode & eModifierMode_Realtime)
+			for(nmd= md->next; nmd; nmd= nmd->next)
+				if(modifier_isEnabled(scene, nmd, eModifierMode_Realtime))
 					break;
 
 			if(!nmd && mmd->sculptlvl > 0)
@@ -1514,10 +1525,11 @@
 {
 	DerivedMesh *dm = mesh_get_derived_final(scene, ob, 0);
 	SculptSession *ss = ob->sculpt;
-	
+	MultiresModifierData *mmd= sculpt_multires_active(scene, ob);
+
 	ss->ob= ob;
 
-	if((ob->shapeflag & OB_SHAPE_LOCK) && !sculpt_multires_active(ob)) {
+	if((ob->shapeflag & OB_SHAPE_LOCK) && !mmd) {
 		ss->kb= ob_get_keyblock(ob);
 		ss->refkb= ob_get_reference_keyblock(ob);
 	}
@@ -1529,7 +1541,8 @@

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list