[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [24257] branches/sculpt25/source/blender: Sculpt: Multithreading & PBVH Changes

Brecht Van Lommel brecht at blender.org
Mon Nov 2 19:47:03 CET 2009


Revision: 24257
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=24257
Author:   blendix
Date:     2009-11-02 19:47:03 +0100 (Mon, 02 Nov 2009)

Log Message:
-----------
Sculpt: Multithreading & PBVH Changes

* Sculpting, normal update and bounding box code is now multithreaded
  using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
  bounding boxes, partial redraw, .. . There's probably still a few
  left, but should be better now.
* Clicking once now does a single paint instead of two (was also
  painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
  uses it (so it can be tested at least).

Implementation Notes:

* PBVH search can now be done either using a callback or bt gathering the
  nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
  should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
  to indicate what needs to be updated for them, found that this makes it
  easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
  clear what is happening than having it's data passed as part of callback
  functions.
* Active_verts list was replaced by looping over nodes and the vertices
  inside them. However the grab brush still uses the active_verts system,
  will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
  using local variables instead of pointers, or looping over fewer vertices
  to update the bounding boxes.

Modified Paths:
--------------
    branches/sculpt25/source/blender/blenkernel/BKE_mesh.h
    branches/sculpt25/source/blender/blenkernel/intern/brush.c
    branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c
    branches/sculpt25/source/blender/blenlib/BLI_pbvh.h
    branches/sculpt25/source/blender/blenlib/intern/arithb.c
    branches/sculpt25/source/blender/blenlib/intern/pbvh.c
    branches/sculpt25/source/blender/editors/sculpt_paint/paint_stroke.c
    branches/sculpt25/source/blender/editors/sculpt_paint/sculpt.c

Modified: branches/sculpt25/source/blender/blenkernel/BKE_mesh.h
===================================================================
--- branches/sculpt25/source/blender/blenkernel/BKE_mesh.h	2009-11-02 17:35:23 UTC (rev 24256)
+++ branches/sculpt25/source/blender/blenkernel/BKE_mesh.h	2009-11-02 18:47:03 UTC (rev 24257)
@@ -47,6 +47,7 @@
 struct MTFace;
 struct VecNor;
 struct CustomData;
+struct Scene;
 
 #ifdef __cplusplus
 extern "C" {

Modified: branches/sculpt25/source/blender/blenkernel/intern/brush.c
===================================================================
--- branches/sculpt25/source/blender/blenkernel/intern/brush.c	2009-11-02 17:35:23 UTC (rev 24256)
+++ branches/sculpt25/source/blender/blenkernel/intern/brush.c	2009-11-02 18:47:03 UTC (rev 24257)
@@ -83,7 +83,7 @@
 	brush->clone.alpha= 0.5;
 	brush->sculpt_tool = SCULPT_TOOL_DRAW;
 
-	brush_curve_preset(brush, BRUSH_PRESET_SHARP);
+	brush_curve_preset(brush, BRUSH_PRESET_SMOOTH);
 
 	/* enable fake user by default */
 	brush->id.flag |= LIB_FAKEUSER;

Modified: branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c
===================================================================
--- branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c	2009-11-02 17:35:23 UTC (rev 24256)
+++ branches/sculpt25/source/blender/blenkernel/intern/cdderivedmesh.c	2009-11-02 18:47:03 UTC (rev 24257)
@@ -177,55 +177,6 @@
 	no_r[2] = no[2]/32767.f;
 }
 
-/* Updates all the face and vertex normals in a node
-
-   Note: the correctness of some vertex normals will be a little
-   off, not sure if this will be noticeable or not */
-static void update_node_normals(const int *face_indices,
-				const int *vert_indices,
-				int totface, int totvert, void *data)
-{
-	DerivedMesh *dm = data;
-	CDDerivedMesh *cddm = data;
-	float (*face_nors)[3];
-	int i;
-
-	/* make a face normal layer if not present */
-	face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
-	if(!face_nors)
-		face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
-		                                 NULL, dm->numFaceData);
-
-	/* Update face normals */
-	for(i = 0; i < totface; ++i) {
-		MFace *f = cddm->mface + face_indices[i];
-		float *fn = face_nors[face_indices[i]];
-
-		if(f->v4)
-			CalcNormFloat4(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co,
-			               cddm->mvert[f->v3].co, cddm->mvert[f->v4].co, fn);
-		else
-			CalcNormFloat(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co,
-			              cddm->mvert[f->v3].co, fn);
-	}
-
-	/* Update vertex normals */
-	for(i = 0; i < totvert; ++i) {
-		const int v = vert_indices[i];
-		float no[3] = {0,0,0};
-		IndexNode *face;
-
-		for(face = cddm->fmap[v].first; face; face = face->next)
-			VecAddf(no, no, face_nors[face->index]);
-
-		Normalize(no);
-		
-		cddm->mvert[v].no[0] = no[0] * 32767;
-		cddm->mvert[v].no[1] = no[1] * 32767;
-		cddm->mvert[v].no[2] = no[2] * 32767;
-	}
-}
-
 static ListBase *cdDM_getFaceMap(DerivedMesh *dm)
 {
 	CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@ -244,7 +195,7 @@
 	CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
 
 	if(!cddm->pbvh) {
-		cddm->pbvh = BLI_pbvh_new(update_node_normals, cddm);
+		cddm->pbvh = BLI_pbvh_new();
 		BLI_pbvh_build(cddm->pbvh, cddm->mface, cddm->mvert,
 			       dm->getNumFaces(dm), dm->getNumVerts(dm));
 		printf("rebuild pbvh\n");
@@ -445,9 +396,7 @@
 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(const int *face_indices,
-			    const int *vert_indices,
-			    int totface, int totvert, void *data_v)
+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;
@@ -462,21 +411,16 @@
 	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
 
 	glColor3f(1, 0, 0);*/
-	GPU_draw_buffers(data_v);
+	GPU_draw_buffers(BLI_pbvh_node_get_draw_buffers(node));
 	++nodes_drawn;
 }
 
-int find_all(float bb_min[3], float bb_max[3], void *data)
-{
-	return 1;
-}
-
 /* 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(float bb_min[3], float bb_max[3], void *data)
+int planes_contain_AABB(PBVHNode *node, float bb_min[3], float bb_max[3], void *data)
 {
 	float (*planes)[4] = data;
 	int i, axis;
@@ -520,21 +464,28 @@
 }
 
 	if(cddm->pbvh) {
-		BLI_pbvh_search(cddm->pbvh, BLI_pbvh_update_search_cb,
-				PBVH_NodeData, NULL, NULL,
-				PBVH_SEARCH_UPDATE);
+		float (*face_nors)[3];
 
+		/* make a face normal layer if not present */
+		face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+		if(!face_nors)
+			face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
+											 NULL, dm->numFaceData);
+
+		BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals|PBVH_UpdateDrawBuffers,
+			face_nors, cdDM_getFaceMap(dm));
+
+		/* should be per face */
+		if(dm->numFaceData && mface->flag & ME_SMOOTH)
+			glShadeModel(GL_SMOOTH);
+
 		if(partial_redraw_planes) {
-			BLI_pbvh_search(cddm->pbvh, planes_contain_AABB,
-					partial_redraw_planes,
-					draw_partial_cb, PBVH_DrawData,
-					PBVH_SEARCH_MODIFIED);
+			BLI_pbvh_search_callback(cddm->pbvh, planes_contain_AABB,
+					partial_redraw_planes, draw_partial_cb, NULL);
 		}
 		else {
-			BLI_pbvh_search(cddm->pbvh, find_all, NULL,
-					draw_partial_cb, PBVH_DrawData,
-					PBVH_SEARCH_NORMAL);
-
+			BLI_pbvh_search_callback(cddm->pbvh, NULL, NULL,
+					draw_partial_cb, NULL);
 		}
 
 		is_partial = !!partial_redraw_planes;
@@ -542,6 +493,8 @@
 		//printf("nodes drawn=%d\n", nodes_drawn);
 		nodes_drawn = 0;
 
+		glShadeModel(GL_FLAT);
+
 		return;
 	}
 

Modified: branches/sculpt25/source/blender/blenlib/BLI_pbvh.h
===================================================================
--- branches/sculpt25/source/blender/blenlib/BLI_pbvh.h	2009-11-02 17:35:23 UTC (rev 24256)
+++ branches/sculpt25/source/blender/blenlib/BLI_pbvh.h	2009-11-02 18:47:03 UTC (rev 24257)
@@ -1,62 +1,98 @@
+/**
+ * A BVH for high poly meshes.
+ * 
+ * $Id$
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BLI_PBVH_H
+#define BLI_PBVH_H
+
 struct MFace;
 struct MVert;
 struct PBVH;
+struct PBVHNode;
+struct ListBase;
 
-/* Returns 1 if the search should continue from this node, 0 otherwise */
-typedef int (*BLI_pbvh_SearchCallback)(float bb_min[3], float bb_max[3],
-				       void *data);
+typedef struct PBVH PBVH;
+typedef struct PBVHNode PBVHNode;
 
-typedef void (*BLI_pbvh_HitCallback)(const int *face_indices,
-				     const int *vert_indices,
-				     int totface, int totvert, void *data);
-int BLI_pbvh_search_range(float bb_min[3], float bb_max[3], void *data_v);
+/* Callbacks */
 
-typedef enum {
-	PBVH_SEARCH_NORMAL,
+/* returns 1 if the search should continue from this node, 0 otherwise */
+typedef int (*BLI_pbvh_SearchCallback)(PBVHNode *node,
+	float bb_min[3], float bb_max[3], void *data);
 
-	/* When the callback returns a 1 for a leaf node, that node will be
-	   marked as modified */
-	PBVH_SEARCH_MARK_MODIFIED,
-	
-	/* Update gpu data for modified nodes. Also clears the Modified flag. */
-	PBVH_SEARCH_MODIFIED,
+typedef void (*BLI_pbvh_HitCallback)(PBVHNode *node, void *data);
 
-	
-	PBVH_SEARCH_UPDATE
-} PBVH_SearchMode;
+/* Building */
 
-/* Pass the node as data to the callback */
-#define PBVH_NodeData (void*)0xa
-/* Pass the draw buffers as data to the callback */
-#define PBVH_DrawData (void*)0xb
+PBVH *BLI_pbvh_new(void);
+void BLI_pbvh_build(PBVH *bvh, struct MFace *faces, struct MVert *verts,
+		    int totface, int totvert);
+void BLI_pbvh_free(PBVH *bvh);
 
-void BLI_pbvh_search(struct PBVH *bvh, BLI_pbvh_SearchCallback scb,
-		     void *search_data, BLI_pbvh_HitCallback hcb,
-		     void *hit_data, PBVH_SearchMode mode);
+void BLI_pbvh_set_source(PBVH *bvh, struct MVert *, struct MFace *mface);
 
-/* The hit callback is called for all leaf nodes intersecting the ray;
+/* Hierarchical Search in the BVH, two methods:
+   * for each hit calling a callback
+   * gather nodes in an array (easy to multithread) */
+
+void BLI_pbvh_search_callback(PBVH *bvh,
+	BLI_pbvh_SearchCallback scb, void *search_data,
+	BLI_pbvh_HitCallback hcb, void *hit_data);
+
+void BLI_pbvh_search_gather(PBVH *bvh,
+	BLI_pbvh_SearchCallback scb, void *search_data,
+	PBVHNode ***array, int *tot);
+
+/* Raycast
+   the hit callback is called for all leaf nodes intersecting the ray;
    it's up to the callback to find the primitive within the leaves that is
    hit first */
-void BLI_pbvh_raycast(struct PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
+
+void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
 		      float ray_start[3], float ray_normal[3]);
 
+/* Node Access */
 
-int BLI_pbvh_update_search_cb(float bb_min[3], float bb_max[3], void *data_v);
+typedef enum {
+	PBVH_Leaf = 1,
 
-/* Get the bounding box around all nodes that have been marked as modified. */
-void BLI_pbvh_modified_bounding_box(struct PBVH *bvh,
-				    float bb_min[3], float bb_max[3]);
-void BLI_pbvh_reset_modified_bounding_box(struct PBVH *bvh);
+	PBVH_UpdateNormals = 2,
+	PBVH_UpdateBB = 4,
+	PBVH_UpdateDrawBuffers = 8,
+	PBVH_UpdateRedraw = 16
+} PBVHNodeFlags;
 
-/* Lock is off by default, turn on to stop redraw from clearing the modified
-   flag from nodes */
-void BLI_pbvh_toggle_modified_lock(struct PBVH *bvh);
+void BLI_pbvh_node_mark_update(PBVHNode *node);
 
+void BLI_pbvh_node_get_verts(PBVHNode *node, int **vert_indices, int *totvert);
+void BLI_pbvh_node_get_faces(PBVHNode *node, int **face_indices, int *totface);

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list