Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2012-03-06 06:40:08 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2012-03-06 06:40:08 +0400
commitc7ffe7f621810f61e53343850ce42f367830fad9 (patch)
treefb1559aeac12e64ab91bedd25a8bf6c153d68dbb /source/blender/blenlib
parent9c7e8e837d07ef4b6e296e6effd6eea2c53945e6 (diff)
Draw individual face's material and shading correctly in the PBVH.
Previously, the shading and material was set once per PBVHNode when drawing. This is still the case, but PBVHNodes are now built to contain only one material and shading mode. This is done with an extra partitioning step; once the number of primitives in the node falls below the PBVH leaf limit, it's primitives are checked for matching materials. If more than one material or shading mode is present in the node, it is split and partitioned (partitioned by material rather than 3D location.) Given a sufficiently 'annoying' input, like a dense mesh with thousands of materials randomly scattered across it, this could greatly increase PBVH build time (since nodes might end up containing a single primitive), but in general this shouldn't come up. In order to support materials for grids, the CCGDM is building another grid array (of DMFaceMat structs). This could be used to replace CCGDM.faceFlag for some small memory savings (TODO).
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_pbvh.h12
-rw-r--r--source/blender/blenlib/intern/pbvh.c149
2 files changed, 125 insertions, 36 deletions
diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h
index 85dd1c1a197..f0d56a3cf52 100644
--- a/source/blender/blenlib/BLI_pbvh.h
+++ b/source/blender/blenlib/BLI_pbvh.h
@@ -26,13 +26,14 @@
* \brief A BVH for high poly meshes.
*/
-struct MFace;
-struct MVert;
+struct DMFlagMat;
struct DMGridAdjacency;
struct DMGridData;
+struct ListBase;
+struct MFace;
+struct MVert;
struct PBVH;
struct PBVHNode;
-struct ListBase;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
@@ -56,7 +57,7 @@ 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,
struct DMGridAdjacency *gridadj, int totgrid,
- int gridsize, void **gridfaces);
+ int gridsize, void **gridfaces, struct DMFlagMat *flagmats);
void BLI_pbvh_free(PBVH *bvh);
/* Hierarchical Search in the BVH, two methods:
@@ -85,7 +86,8 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
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], int smooth);
+void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
+ int (*setMaterial)(int, void *attribs));
/* Node Access */
diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c
index f8562df07a8..46d38e10585 100644
--- a/source/blender/blenlib/intern/pbvh.c
+++ b/source/blender/blenlib/intern/pbvh.c
@@ -136,6 +136,7 @@ struct PBVH {
DMGridData **grids;
DMGridAdjacency *gridadj;
void **gridfaces;
+ const DMFlagMat *grid_flag_mats;
int totgrid;
int gridsize;
@@ -261,6 +262,17 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
// BB_expand(&node->vb, co);
//}
+static int face_materials_match(const MFace *f1, const MFace *f2)
+{
+ return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
+ (f1->mat_nr == f2->mat_nr));
+}
+
+static int grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
+{
+ return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
+ (f1->mat_nr == f2->mat_nr));
+}
/* Adapted from BLI_kdopbvh.c */
/* Returns the index of the first element on the right of the partition */
@@ -280,6 +292,38 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis,
}
}
+/* Returns the index of the first element on the right of the partition */
+static int partition_indices_material(PBVH *bvh, int lo, int hi)
+{
+ const MFace *faces = bvh->faces;
+ const DMFlagMat *flagmats = bvh->grid_flag_mats;
+ const int *indices = bvh->prim_indices;
+ const void *first;
+ int i=lo, j=hi;
+
+ if(bvh->faces)
+ first = &faces[bvh->prim_indices[lo]];
+ else
+ first = &flagmats[bvh->prim_indices[lo]];
+
+ for(;;) {
+ if(bvh->faces) {
+ for(; face_materials_match(first, &faces[indices[i]]); i++);
+ for(; !face_materials_match(first, &faces[indices[j]]); j--);
+ }
+ else {
+ for(; grid_materials_match(first, &flagmats[indices[i]]); i++);
+ for(; !grid_materials_match(first, &flagmats[indices[j]]); j--);
+ }
+
+ if(!(i < j))
+ return i;
+
+ SWAP(int, bvh->prim_indices[i], bvh->prim_indices[j]);
+ i++;
+ }
+}
+
static void grow_nodes(PBVH *bvh, int totnode)
{
if(totnode > bvh->node_mem_count) {
@@ -431,6 +475,38 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
build_grids_leaf_node(bvh, bvh->nodes + node_index);
}
+/* Return zero if all primitives in the node can be drawn with the
+ same material (including flat/smooth shading), non-zerootherwise */
+int leaf_needs_material_split(PBVH *bvh, int offset, int count)
+{
+ int i, prim;
+
+ if(count <= 1)
+ return 0;
+
+ if(bvh->faces) {
+ const MFace *first = &bvh->faces[bvh->prim_indices[offset]];
+
+ for(i = offset + count - 1; i > offset; --i) {
+ prim = bvh->prim_indices[i];
+ if(!face_materials_match(first, &bvh->faces[prim]))
+ return 1;
+ }
+ }
+ else {
+ const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
+
+ for(i = offset + count - 1; i > offset; --i) {
+ prim = bvh->prim_indices[i];
+ if(!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
/* Recursively build a node in the tree
*
* vb is the voxel box around all of the primitives contained in
@@ -443,15 +519,18 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
*/
static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
- int offset, int count)
+ int offset, int count)
{
- int i, axis, end;
+ int i, axis, end, below_leaf_limit;
BB cb_backing;
/* Decide whether this is a leaf or not */
- if(count <= bvh->leaf_limit) {
- build_leaf(bvh, node_index, prim_bbc, offset, count);
- return;
+ below_leaf_limit = count <= bvh->leaf_limit;
+ if(below_leaf_limit) {
+ if(!leaf_needs_material_split(bvh, offset, count)) {
+ build_leaf(bvh, node_index, prim_bbc, offset, count);
+ return;
+ }
}
/* Add two child nodes */
@@ -461,26 +540,33 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
/* Update parent node bounding box */
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
- /* Find axis with widest range of primitive centroids */
- if(!cb) {
- cb = &cb_backing;
- BB_reset(cb);
- for(i = offset + count - 1; i >= offset; --i)
- BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
+ if(!below_leaf_limit) {
+ /* Find axis with widest range of primitive centroids */
+ if(!cb) {
+ cb = &cb_backing;
+ BB_reset(cb);
+ for(i = offset + count - 1; i >= offset; --i)
+ BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
+ }
+ axis = BB_widest_axis(cb);
+
+ /* Partition primitives along that axis */
+ end = partition_indices(bvh->prim_indices,
+ offset, offset + count - 1,
+ axis,
+ (cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
+ prim_bbc);
+ }
+ else {
+ /* Partition primitives by material */
+ end = partition_indices_material(bvh, offset, offset + count - 1);
}
- axis = BB_widest_axis(cb);
-
- /* Partition primitives along that axis */
- end = partition_indices(bvh->prim_indices, offset, offset + count - 1,
- axis,
- (cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
- prim_bbc);
/* Build children */
build_sub(bvh, bvh->nodes[node_index].children_offset, NULL,
- prim_bbc, offset, end - offset);
+ prim_bbc, offset, end - offset);
build_sub(bvh, bvh->nodes[node_index].children_offset + 1, NULL,
- prim_bbc, end, offset + count - end);
+ prim_bbc, end, offset + count - end);
}
static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
@@ -550,7 +636,7 @@ void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
/* Do a full rebuild with on Grids data structure */
void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj,
- int totgrid, int gridsize, void **gridfaces)
+ int totgrid, int gridsize, void **gridfaces, DMFlagMat *flagmats)
{
BBC *prim_bbc = NULL;
BB cb;
@@ -559,6 +645,7 @@ void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridad
bvh->grids= grids;
bvh->gridadj= gridadj;
bvh->gridfaces= gridfaces;
+ bvh->grid_flag_mats= flagmats;
bvh->totgrid= totgrid;
bvh->gridsize= gridsize;
bvh->leaf_limit = MAX2(LEAF_LIMIT/((gridsize-1)*(gridsize-1)), 1);
@@ -1027,7 +1114,7 @@ static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes,
}
}
-static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int smooth)
+static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
{
PBVHNode *node;
int n;
@@ -1040,18 +1127,17 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
if(bvh->grids) {
GPU_update_grid_buffers(node->draw_buffers,
bvh->grids,
+ bvh->grid_flag_mats,
node->prim_indices,
node->totprim,
- bvh->gridsize,
- smooth);
+ bvh->gridsize);
}
else {
GPU_update_mesh_buffers(node->draw_buffers,
bvh->verts,
node->vert_indices,
node->uniq_verts +
- node->face_verts,
- smooth);
+ node->face_verts);
}
node->flag &= ~PBVH_UpdateDrawBuffers;
@@ -1420,7 +1506,7 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
//#include <GL/glew.h>
-void BLI_pbvh_node_draw(PBVHNode *node, void *UNUSED(data))
+void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial)
{
#if 0
/* XXX: Just some quick code to show leaf nodes in different colors */
@@ -1438,7 +1524,7 @@ void BLI_pbvh_node_draw(PBVHNode *node, void *UNUSED(data))
glColor3f(1, 0, 0);
#endif
- GPU_draw_buffers(node->draw_buffers);
+ GPU_draw_buffers(node->draw_buffers, setMaterial);
}
/* Adapted from:
@@ -1473,7 +1559,8 @@ int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
return 1;
}
-void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], int smooth)
+void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
+ int (*setMaterial)(int, void *attribs))
{
PBVHNode **nodes;
int totnode;
@@ -1482,7 +1569,7 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], int smo
&nodes, &totnode);
pbvh_update_normals(bvh, nodes, totnode, face_nors);
- pbvh_update_draw_buffers(bvh, nodes, totnode, smooth);
+ pbvh_update_draw_buffers(bvh, nodes, totnode);
if(nodes) MEM_freeN(nodes);
@@ -1491,7 +1578,7 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], int smo
planes, BLI_pbvh_node_draw, NULL);
}
else {
- BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, NULL);
+ BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, setMaterial);
}
}