[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24885] branches/sculpt25/source/blender: Sculpt: Grid based PBVH

Brecht Van Lommel brecht at blender.org
Wed Nov 25 14:40:43 CET 2009


Revision: 24885
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24885
Author:   blendix
Date:     2009-11-25 14:40:43 +0100 (Wed, 25 Nov 2009)

Log Message:
-----------
Sculpt: Grid based PBVH

* PBVH can now be created contain both from face grids or standard
  meshes. The former is much quicker to build for high res meshes.
* Moved some drawing code into pbvh (mostly for the frustum test).
* Moved ray intersection code into pbvh.
* GPU buffers also can be built from either mesh or grids now.
* Updated sculpt code to work with this. The ugly part is that there
  is now a macro for iterating over vertices, to handle both cases,
  and some duplicated code for e.g. undo.
* Smooth brush does not work yet with grids.

Modified Paths:
--------------
    branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c
    branches/sculpt25/source/blender/blenkernel/intern/subsurf_ccg.c
    branches/sculpt25/source/blender/blenlib/BLI_pbvh.h
    branches/sculpt25/source/blender/blenlib/intern/pbvh.c
    branches/sculpt25/source/blender/editors/sculpt_paint/sculpt.c
    branches/sculpt25/source/blender/gpu/gpu_buffers.h
    branches/sculpt25/source/blender/gpu/intern/gpu_buffers.c

Modified: branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c
===================================================================
--- branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c	2009-11-25 13:17:09 UTC (rev 24884)
+++ branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c	2009-11-25 13:40:43 UTC (rev 24885)
@@ -197,7 +197,7 @@
 		Mesh *me= ob->data;
 
 		cddm->pbvh = BLI_pbvh_new();
-		BLI_pbvh_build(cddm->pbvh, me->mface, me->mvert,
+		BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
 			       me->totface, me->totvert);
 	}
 
@@ -393,60 +393,6 @@
 	}
 }
 
-static int nodes_drawn = 0;
-static int is_partial = 0;
-/* XXX: Just a temporary replacement for the real drawing code */
-static void draw_partial_cb(PBVHNode *node, void *data)
-{
-	/* XXX: Just some quick code to show leaf nodes in different colors */
-	/*float col[3]; int i;
-	if(is_partial) {
-		col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
-	}
-	else {
-		srand((long long)data_v);
-		for(i = 0; i < 3; ++i)
-			col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
-	}
-	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
-
-	glColor3f(1, 0, 0);*/
-	GPU_draw_buffers(BLI_pbvh_node_get_draw_buffers(node));
-	++nodes_drawn;
-}
-
-/* Adapted from:
-   http://www.gamedev.net/community/forums/topic.asp?topic_id=512123
-   Returns true if the AABB is at least partially within the frustum
-   (ok, not a real frustum), false otherwise.
-*/
-int planes_contain_AABB(PBVHNode *node, void *data)
-{
-	float (*planes)[4] = data;
-	int i, axis;
-	float vmin[3], vmax[3], bb_min[3], bb_max[3];
-
-	BLI_pbvh_node_get_BB(node, bb_min, bb_max);
-
-	for(i = 0; i < 4; ++i) { 
-		for(axis = 0; axis < 3; ++axis) {
-			if(planes[i][axis] > 0) { 
-				vmin[axis] = bb_min[axis];
-				vmax[axis] = bb_max[axis];
-			}
-			else {
-				vmin[axis] = bb_max[axis];
-				vmax[axis] = bb_min[axis];
-			}
-		}
-		
-		if(dot_v3v3(planes[i], vmin) + planes[i][3] > 0)
-			return 0;
-	} 
-
-	return 1;
-}
-
 static void cdDM_drawFacesSolid(DerivedMesh *dm,
 				float (*partial_redraw_planes)[4],
 				int (*setMaterial)(int, void *attribs))
@@ -468,27 +414,12 @@
 	if(cddm->pbvh) {
 		float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 
-		BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers,
-			face_nors);
-
 		/* should be per face */
 		if(dm->numFaceData && mface->flag & ME_SMOOTH)
 			glShadeModel(GL_SMOOTH);
 
-		if(partial_redraw_planes) {
-			BLI_pbvh_search_callback(cddm->pbvh, planes_contain_AABB,
-					partial_redraw_planes, draw_partial_cb, NULL);
-		}
-		else {
-			BLI_pbvh_search_callback(cddm->pbvh, NULL, NULL,
-					draw_partial_cb, NULL);
-		}
+		BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors);
 
-		is_partial = !!partial_redraw_planes;
-
-		//printf("nodes drawn=%d\n", nodes_drawn);
-		nodes_drawn = 0;
-
 		glShadeModel(GL_FLAT);
 
 		return;

Modified: branches/sculpt25/source/blender/blenkernel/intern/subsurf_ccg.c
===================================================================
--- branches/sculpt25/source/blender/blenkernel/intern/subsurf_ccg.c	2009-11-25 13:17:09 UTC (rev 24884)
+++ branches/sculpt25/source/blender/blenkernel/intern/subsurf_ccg.c	2009-11-25 13:40:43 UTC (rev 24885)
@@ -819,6 +819,7 @@
 		for(x = 1; x < edgeSize - 1; x++, i++) {
 			vd= ccgSubSurf_getEdgeData(ss, e, x);
 			copy_v3_v3(mvert[i].co, vd->co);
+			/* TODO CCGSubsurf does not set these */
 			normal_float_to_short_v3(mvert[i].no, vd->no);
 		}
 	}
@@ -1230,8 +1231,7 @@
 	char *faceFlags = ccgdm->faceFlags;
 	int step = 1; //(fast)? gridSize-1: 1;
 
-#if 0
-	if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
+	if(ccgdm->pbvh && ccgdm->multires.mmd) { // && !fast) {
 		CCGFace **faces;
 		int totface;
 
@@ -1252,7 +1252,6 @@
 
 		return;
 	}
-#endif
 
 	fi = ccgSubSurf_getFaceIterator(ss);
 	for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
@@ -2135,12 +2134,12 @@
 static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
 {
 	CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
-	//int gridSize, numGrids;
+	int gridSize, numGrids;
 
 	if(ccgdm->pbvh)
 		return ccgdm->pbvh;
 
-	/*if(ccgdm->multires.mmd) {
+	if(ccgdm->multires.mmd) {
 		ccgdm_create_grids(dm);
 
 		gridSize = ccgDM_getGridSize(dm);
@@ -2150,11 +2149,11 @@
 		BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, numGrids, gridSize,
 			(void**)ccgdm->gridFaces);
 	}
-	else*/ if(ob->type == OB_MESH) {
+	else if(ob->type == OB_MESH) {
 		Mesh *me= ob->data;
 
 		ccgdm->pbvh = BLI_pbvh_new();
-		BLI_pbvh_build(ccgdm->pbvh, me->mface, me->mvert,
+		BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
 			       me->totface, me->totvert);
 	}
 

Modified: branches/sculpt25/source/blender/blenlib/BLI_pbvh.h
===================================================================
--- branches/sculpt25/source/blender/blenlib/BLI_pbvh.h	2009-11-25 13:17:09 UTC (rev 24884)
+++ branches/sculpt25/source/blender/blenlib/BLI_pbvh.h	2009-11-25 13:40:43 UTC (rev 24885)
@@ -27,6 +27,7 @@
 
 struct MFace;
 struct MVert;
+struct DMGridData;
 struct PBVH;
 struct PBVHNode;
 struct ListBase;
@@ -44,12 +45,12 @@
 /* Building */
 
 PBVH *BLI_pbvh_new(void);
-void BLI_pbvh_build(PBVH *bvh, struct MFace *faces, struct MVert *verts,
+void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
 		    int totface, int totvert);
+void BLI_pbvh_build_grids(PBVH *bvh, struct DMGridData **grids, int totgrid,
+	int gridsize, void **gridfaces);
 void BLI_pbvh_free(PBVH *bvh);
 
-void BLI_pbvh_set_source(PBVH *bvh, struct MVert *, struct MFace *mface);
-
 /* Hierarchical Search in the BVH, two methods:
    * for each hit calling a callback
    * gather nodes in an array (easy to multithread) */
@@ -69,7 +70,15 @@
 
 void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
 		      float ray_start[3], float ray_normal[3], int original);
+int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+	float ray_start[3], float ray_normal[3], float *dist);
 
+/* Drawing */
+
+void BLI_pbvh_node_draw(PBVHNode *node, void *data);
+int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
+void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3]);
+
 /* Node Access */
 
 typedef enum {
@@ -84,11 +93,11 @@
 
 void BLI_pbvh_node_mark_update(PBVHNode *node);
 
-void BLI_pbvh_node_get_verts(PBVHNode *node, int **vert_indices,
-	int *totvert, int *allverts);
-void BLI_pbvh_node_get_faces(PBVHNode *node, int **face_indices,
-	int **face_vert_indices, int *totface);
-void *BLI_pbvh_node_get_draw_buffers(PBVHNode *node);
+void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
+	int **grid_indices, int *totgrid, int *maxgrid, int *gridsize);
+void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
+	int *uniquevert, int *totvert);
+
 void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
 void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
 
@@ -96,6 +105,91 @@
 
 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, void ***gridfaces, int *totface);
 
+/* Vertex Iterator */
+
+/* this iterator has quite a lot of code, but it's designed to:
+   - allow the compiler to eliminate dead code and variables
+   - spend most of the time in the relatively simple inner loop */
+
+#define PBVH_ITER_ALL		0
+#define PBVH_ITER_UNIQUE	1
+
+typedef struct PBVHVertexIter {
+	/* iteration */
+	int g;
+	int width;
+	int height;
+	int skip;
+	int gx;
+	int gy;
+	int i;
+
+	/* grid */
+	struct DMGridData **grids;
+	struct DMGridData *grid;
+	int *grid_indices;
+	int totgrid;
+	int gridsize;
+
+	/* mesh */
+	struct MVert *mverts;
+	int totvert;
+	int *vert_indices;
+
+	/* result: these are all computed in the macro, but we assume
+	   that compiler optimizations will skip the ones we don't use */
+	struct MVert *mvert;
+	float *co;
+	short *no;
+	float *fno;
+} PBVHVertexIter;
+
+void BLI_pbvh_node_verts_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
+
+#define BLI_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
+	/* XXX breaks aliasing! */ \
+	BLI_pbvh_node_verts_iter_init(bvh, node, &vi, mode); \
+	\
+	for(vi.i=0, vi.g=0; vi.g<vi.totgrid; vi.g++) { \
+		if(vi.grids) { \
+			vi.width= vi.gridsize; \
+			vi.height= vi.gridsize; \
+			vi.grid= vi.grids[vi.grid_indices[vi.g]]; \
+			vi.skip= 0; \
+		 	\
+			/*if(mode == PVBH_ITER_UNIQUE) { \
+				vi.grid += subm->grid.offset; \
+				vi.skip= subm->grid.skip; \
+				vi.grid -= skip; \
+			}*/ \
+		} \
+		else { \
+			vi.width= vi.totvert; \
+			vi.height= 1; \
+		} \
+	 	\
+		for(vi.gy=0; vi.gy<vi.height; vi.gy++) { \
+			if(vi.grid) vi.grid += vi.skip; \
+			\
+			for(vi.gx=0; vi.gx<vi.width; vi.gx++, vi.i++) { \
+				if(vi.grid) { \
+					vi.co= vi.grid->co; \
+					vi.fno= vi.grid->no; \
+					vi.grid++; \
+				} \
+				else { \
+					vi.mvert= &vi.mverts[vi.vert_indices[vi.gx]]; \
+					vi.co= vi.mvert->co; \
+					vi.no= vi.mvert->no; \
+				} \
+
+#define BLI_pbvh_vertex_iter_end \
+			} \
+		} \
+	}
+
+
 #endif /* BLI_PBVH_H */
 

Modified: branches/sculpt25/source/blender/blenlib/intern/pbvh.c
===================================================================
--- branches/sculpt25/source/blender/blenlib/intern/pbvh.c	2009-11-25 13:17:09 UTC (rev 24884)
+++ branches/sculpt25/source/blender/blenlib/intern/pbvh.c	2009-11-25 13:40:43 UTC (rev 24885)
@@ -32,6 +32,7 @@
 #include "BLI_ghash.h"
 #include "BLI_pbvh.h"
 
+#include "BKE_DerivedMesh.h"
 #include "BKE_mesh.h"
 #include "BKE_utildefines.h"
 
@@ -87,12 +88,12 @@
 	/* For internal nodes */
 	int children_offset;
 
-	/* Pointer into bvh face_indices */
-	int *face_indices;
+	/* Pointer into bvh prim_indices */
+	int *prim_indices;
 	int *face_vert_indices;
 
-	unsigned short totface;
-	unsigned short uniq_verts, face_verts;
+	unsigned int totprim;
+	unsigned int uniq_verts, face_verts;
 
 	char flag;
 };
@@ -101,14 +102,22 @@
 	PBVHNode *nodes;
 	int node_mem_count, totnode;
 
-	int *face_indices;
-	int totface;
+	int *prim_indices;
+	int totprim;
 	int totvert;
 
+	int leaf_limit;
+
 	/* Mesh data */
 	MVert *verts;
 	MFace *faces;
 
+	/* Grid Data */
+	DMGridData **grids;
+	void **gridfaces;
+	int totgrid;
+	int gridsize;
+
 	/* Only used during BVH build and update,
 	   don't need to remain valid after */
 	BLI_bitmap vert_bitmap;
@@ -201,12 +210,12 @@
 	BB_reset(&vb);
 	
 	if(node->flag & PBVH_Leaf) {

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list