[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [46520] trunk/blender/source/blender: Add mask support to CCGSubSurf and multires.

Nicholas Bishop nicholasbishop at gmail.com
Thu May 10 22:34:08 CEST 2012


Revision: 46520
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=46520
Author:   nicholasbishop
Date:     2012-05-10 20:34:08 +0000 (Thu, 10 May 2012)
Log Message:
-----------
Add mask support to CCGSubSurf and multires.

* Add new CCG function ccgSubSurf_setAllocMask(). Similar to to
  ccgSubSurf_setCalcVertexNormals(), it sets whether the CCG elements
  have a mask layer and what that layer's offset is. Unlike normals
  however, it doesn't change any behavior during CCG calculation; it's
  there only to give CCGKey information on the mask.

* Add a new flag to _getSubSurf(), CCG_ALLOC_MASK. If set, space for
  an extra layer is allocated, but the number of CCG layers is not set
  to include it. This is done because GridPaintMasks are absolute,
  rather than being relative to the subdivided output (as MDisp
  displacements are), so we skip subdividing paint masks here.

* Add a new flag to subsurf_make_derived_from_derived(),
  SUBSURF_ALLOC_PAINT_MASK. This controls whether CCG_ALLOC_MASK is
  set for _getSubSurf(). Related, masks are never loaded in during
  ss_sync_from_derivedmesh(). After subdivision is finished, if the
  alloc mask flag is set, the number of CCG layers is increase to 4
  with ccgSubSurf_setNumLayers().

* Add a new flag to multires_make_from_derived(),
  MULTIRES_ALLOC_PAINT_MASK. Not all multires functions need paint
  mask data (e.g. multiresModifier_base_apply.) This flag is always
  set in MOD_multires.c so that subdividing a mesh with a mask updates
  properly even when not in sculpt mode.

* Update multiresModifier_disp_run() to apply, calculate, and add mask
  elements. It's almost the same as the existing operations with xyz
  coordinates, but treats masks as absolute rather than displacements
  relative to subdivided values.

* Update multires_customdata_delete to free CD_GRID_PAINT_MASK in
  addition to CD_MDISPS.

* Update multires_del_higher() to call the new function
  multires_grid_paint_mask_downsample(), which allocates a
  lower-resolution paint mask grid and copies values over from the
  high-resolution grid.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_multires.h
    trunk/blender/source/blender/blenkernel/BKE_subsurf.h
    trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.c
    trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.h
    trunk/blender/source/blender/blenkernel/intern/multires.c
    trunk/blender/source/blender/blenkernel/intern/subsurf_ccg.c
    trunk/blender/source/blender/modifiers/intern/MOD_multires.c

Modified: trunk/blender/source/blender/blenkernel/BKE_multires.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_multires.h	2012-05-10 20:33:55 UTC (rev 46519)
+++ trunk/blender/source/blender/blenkernel/BKE_multires.h	2012-05-10 20:34:08 UTC (rev 46520)
@@ -44,7 +44,7 @@
 struct Object;
 struct Scene;
 
-/* Delete mesh mdisps */
+/* Delete mesh mdisps and grid paint masks */
 void multires_customdata_delete(struct Mesh *me);
 
 void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags);
@@ -62,6 +62,7 @@
 typedef enum {
 	MULTIRES_USE_LOCAL_MMD = 1,
 	MULTIRES_USE_RENDER_PARAMS = 2,
+	MULTIRES_ALLOC_PAINT_MASK = 4
 } MultiresFlags;
 
 struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm,

Modified: trunk/blender/source/blender/blenkernel/BKE_subsurf.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_subsurf.h	2012-05-10 20:33:55 UTC (rev 46519)
+++ trunk/blender/source/blender/blenkernel/BKE_subsurf.h	2012-05-10 20:34:08 UTC (rev 46520)
@@ -59,7 +59,8 @@
 	SUBSURF_USE_RENDER_PARAMS = 1,
 	SUBSURF_IS_FINAL_CALC = 2,
 	SUBSURF_FOR_EDIT_MODE = 4,
-	SUBSURF_IN_EDIT_MODE = 8
+	SUBSURF_IN_EDIT_MODE = 8,
+	SUBSURF_ALLOC_PAINT_MASK = 16
 } SubsurfFlags;
 
 struct DerivedMesh *subsurf_make_derived_from_derived(

Modified: trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.c	2012-05-10 20:33:55 UTC (rev 46519)
+++ trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.c	2012-05-10 20:34:08 UTC (rev 46520)
@@ -387,6 +387,10 @@
 	int calcVertNormals;
 	int normalDataOffset;
 
+	/* data for paint masks */
+	int allocMask;
+	int maskDataOffset;
+
 	/* data for age'ing (to debug sync) */
 	int currentAge;
 	int useAgeCounts;
@@ -852,6 +856,8 @@
 		ss->calcVertNormals = 0;
 		ss->normalDataOffset = 0;
 
+		ss->allocMask = 0;
+
 		ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
 		ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
 
@@ -996,6 +1002,12 @@
 	return eCCGError_None;
 }
 
+void ccgSubSurf_setAllocMask(CCGSubSurf *ss, int allocMask, int maskOffset)
+{
+	ss->allocMask = allocMask;
+	ss->maskDataOffset = maskOffset;
+}
+
 void ccgSubSurf_setNumLayers(CCGSubSurf *ss, int numLayers)
 {
 	ss->meshIFC.numLayers = numLayers;
@@ -3123,6 +3135,12 @@
 	key->grid_size = ccgSubSurf_getGridLevelSize(ss, level);
 	key->grid_area = key->grid_size * key->grid_size;
 	key->grid_bytes = key->elem_size * key->grid_area;
+
+	key->has_mask = ss->allocMask;
+	if (key->has_mask)
+		key->mask_offset = ss->maskDataOffset;
+	else
+		key->mask_offset = -1;
 }
 
 void CCG_key_top_level(CCGKey *key, const CCGSubSurf *ss)

Modified: trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.h
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.h	2012-05-10 20:33:55 UTC (rev 46519)
+++ trunk/blender/source/blender/blenkernel/intern/CCGSubSurf.h	2012-05-10 20:34:08 UTC (rev 46520)
@@ -76,6 +76,7 @@
 CCGError	ccgSubSurf_setUseAgeCounts			(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset);
 
 CCGError	ccgSubSurf_setCalcVertexNormals		(CCGSubSurf *ss, int useVertNormals, int normalDataOffset);
+void		ccgSubSurf_setAllocMask				(CCGSubSurf *ss, int allocMask, int maskOffset);
 
 void		ccgSubSurf_setNumLayers				(CCGSubSurf *ss, int numLayers);
 

Modified: trunk/blender/source/blender/blenkernel/intern/multires.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/multires.c	2012-05-10 20:33:55 UTC (rev 46519)
+++ trunk/blender/source/blender/blenkernel/intern/multires.c	2012-05-10 20:34:08 UTC (rev 46520)
@@ -90,12 +90,17 @@
 		CustomData_external_remove(&em->bm->ldata, &me->id,
 		                           CD_MDISPS, 0);
 		BM_data_layer_free(em->bm, &em->bm->ldata, CD_MDISPS);
+
+		BM_data_layer_free(em->bm, &em->bm->ldata, CD_GRID_PAINT_MASK);
 	}
 	else {
 		CustomData_external_remove(&me->ldata, &me->id,
 		                           CD_MDISPS, me->totloop);
 		CustomData_free_layer_active(&me->ldata, CD_MDISPS,
-		                             me->totloop);
+									 me->totloop);
+
+		CustomData_free_layer_active(&me->ldata, CD_GRID_PAINT_MASK,
+									 me->totloop);
 	}
 }
 
@@ -594,15 +599,40 @@
 	}
 }
 
+/* Reallocate gpm->data at a lower resolution and copy values over
+   from the original high-resolution data */
+static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level)
+{
+	if (level < gpm->level) {
+		int gridsize = ccg_gridsize(level);
+		float *data = MEM_callocN(sizeof(float) * gridsize * gridsize,
+								  "multires_grid_paint_mask_downsample");
+		int x, y;
+
+		for (y = 0; y < gridsize; y++) {
+			for (x = 0; x < gridsize; x++) {
+				data[y * gridsize + x] =
+					paint_grid_paint_mask(gpm, level, x, y);
+			}
+		}
+
+		MEM_freeN(gpm->data);
+		gpm->data = data;
+		gpm->level = level;
+	}
+}
+
 static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
 {
 	Mesh *me = (Mesh *)ob->data;
 	int levels = mmd->totlvl - lvl;
 	MDisps *mdisps;
+	GridPaintMask *gpm;
 
 	multires_set_tot_mdisps(me, mmd->totlvl);
 	CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
 	mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+	gpm = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
 
 	multires_force_update(ob);
 
@@ -615,7 +645,8 @@
 
 			for (i = 0; i < me->totpoly; ++i) {
 				for (j = 0; j < me->mpoly[i].totloop; j++) {
-					MDisps *mdisp = &mdisps[me->mpoly[i].loopstart + j];
+					int g = me->mpoly[i].loopstart + j;
+					MDisps *mdisp = &mdisps[g];
 					float (*disps)[3], (*ndisps)[3], (*hdisps)[3];
 					int totdisp = multires_grid_tot[lvl];
 
@@ -641,6 +672,8 @@
 					mdisp->disps = disps;
 					mdisp->totdisp = totdisp;
 					mdisp->level = lvl;
+
+					multires_grid_paint_mask_downsample(&gpm[g], lvl);
 				}
 			}
 		}
@@ -673,9 +706,10 @@
 	multires_set_tot_level(ob, mmd, lvl);
 }
 
-static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple)
+static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple, int alloc_paint_mask)
 {
 	MultiresModifierData mmd = {{NULL}};
+	MultiresFlags flags = MULTIRES_USE_LOCAL_MMD;
 
 	mmd.lvl = lvl;
 	mmd.sculptlvl = lvl;
@@ -683,10 +717,13 @@
 	mmd.totlvl = totlvl;
 	mmd.simple = simple;
 
-	return multires_make_derived_from_derived(dm, &mmd, ob, MULTIRES_USE_LOCAL_MMD);
+	if (alloc_paint_mask)
+		flags |= MULTIRES_ALLOC_PAINT_MASK;
+
+	return multires_make_derived_from_derived(dm, &mmd, ob, flags);
 }
 
-static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv)
+static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv, int alloc_paint_mask)
 {
 	SubsurfModifierData smd = {{NULL}};
 	SubsurfFlags flags = 0;
@@ -701,6 +738,10 @@
 
 	if (ob->mode & OB_MODE_EDIT)
 		flags |= SUBSURF_IN_EDIT_MODE;
+
+	if (alloc_paint_mask)
+		flags |= SUBSURF_ALLOC_PAINT_MASK;
+	
 	return subsurf_make_derived_from_derived(dm, &smd, NULL, flags);
 }
 
@@ -737,7 +778,7 @@
 	/* generate highest level with displacements */
 	cddm = CDDM_from_mesh(me, NULL);
 	DM_set_only_copy(cddm, CD_MASK_BAREMESH);
-	dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0);
+	dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0, 0);
 	cddm->release(cddm);
 
 	/* copy the new locations of the base verts into the mesh */
@@ -827,7 +868,7 @@
 	/* subdivide the mesh to highest level without displacements */
 	cddm = CDDM_from_mesh(me, NULL);
 	DM_set_only_copy(cddm, CD_MASK_BAREMESH);
-	origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+	origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0);
 	cddm->release(cddm);
 
 	/* calc disps */
@@ -863,10 +904,11 @@
 		/* create subsurf DM from original mesh at high level */
 		cddm = CDDM_from_mesh(me, NULL);
 		DM_set_only_copy(cddm, CD_MASK_BAREMESH);
-		highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv);
+		highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE);
+		ss = ((CCGDerivedMesh*)highdm)->ss;
 
 		/* create multires DM from original mesh at low level */
-		lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple);
+		lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, TRUE);
 		cddm->release(cddm);
 
 		/* copy subsurf grids and replace them with low displaced grids */
@@ -892,7 +934,6 @@
 		lowdm->release(lowdm);
 
 		/* subsurf higher levels again with displaced data */
-		ss = ((CCGDerivedMesh *)highdm)->ss;
 		ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0);
 		ccgSubSurf_updateLevels(ss, lvl, NULL, 0);
 
@@ -952,6 +993,7 @@
 	CCGKey key;
 	MPoly *mpoly = me->mpoly;
 	MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
+	GridPaintMask *grid_paint_mask = NULL;
 	int *gridOffset;
 	int i, k, /*numGrids, */ gridSize, dGridSize, dSkip;
 	int totloop, totpoly;
@@ -985,6 +1027,10 @@
 	dGridSize = multires_side_tot[totlvl];
 	dSkip = (dGridSize - 1) / (gridSize - 1);
 
+	/* multires paint masks */
+	if (key.has_mask)
+		grid_paint_mask = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
+
 	k = 0; /*current loop/mdisp index within the mloop array*/
 
 	#pragma omp parallel for private(i) if (totloop*gridSize*gridSize >= CCG_OMP_LIMIT)
@@ -994,6 +1040,7 @@
 		int S, x, y, gIndex = gridOffset[i];
 
 		for (S = 0; S < numVerts; ++S, ++gIndex, ++k) {
+			GridPaintMask *gpm = grid_paint_mask ? &grid_paint_mask[gIndex] : NULL;
 			MDisps *mdisp = &mdisps[mpoly[i].loopstart + S];
 			CCGElem *grid = gridData[gIndex];
 			CCGElem *subgrid = subGridData[gIndex];
@@ -1008,13 +1055,22 @@
 
 			dispgrid = mdisp->disps;
 
+			/* if needed, reallocate multires paint mask */
+			if (gpm && op == CALC_DISPLACEMENTS) {
+				if (gpm->level < key.level) {
+					gpm->level = key.level;
+					MEM_freeN(gpm->data);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list