From 68b8f3b0a84d79ca75e3c4708836be6c83985abe Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 14 Mar 2012 06:32:25 +0000 Subject: Skip hidden elements in PBVH iterator, raycast, and drawing. --- source/blender/gpu/GPU_buffers.h | 7 +- source/blender/gpu/intern/gpu_buffers.c | 212 ++++++++++++++++++++++++++------ 2 files changed, 177 insertions(+), 42 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 33055b5efd5..cee9039e3f9 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -42,6 +42,7 @@ struct DerivedMesh; struct DMFlagMat; struct DMGridData; +struct CustomData; struct GHash; struct DMGridData; struct GPUVertPointLink; @@ -159,12 +160,14 @@ int GPU_buffer_legacy(struct DerivedMesh *dm ); typedef struct GPU_Buffers GPU_Buffers; GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], - struct MFace *mface, int *face_indices, int totface); + struct MFace *mface, struct MVert *mvert, + int *face_indices, int totface); void GPU_update_mesh_buffers(GPU_Buffers *buffers, struct MVert *mvert, int *vert_indices, int totvert); -GPU_Buffers *GPU_build_grid_buffers(int totgrid, int gridsize); +GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, + unsigned int **grid_hidden, int gridsize); void GPU_update_grid_buffers(GPU_Buffers *buffers, struct DMGridData **grids, const struct DMFlagMat *grid_flag_mats, diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 23bc79e4187..65eefe6bc1e 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -38,6 +38,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -46,6 +47,8 @@ #include "DNA_meshdata_types.h" #include "BKE_DerivedMesh.h" +#include "BKE_paint.h" +#include "BKE_subsurf.h" #include "DNA_userdef_types.h" @@ -1278,9 +1281,11 @@ struct GPU_Buffers { /* grid pointers */ DMGridData **grids; const DMFlagMat *grid_flag_mats; + const BLI_bitmap *grid_hidden; int *grid_indices; int totgrid; int gridsize; + int has_hidden; unsigned int tot_tri, tot_quad; }; @@ -1322,7 +1327,8 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, } GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], - MFace *mface, int *face_indices, + MFace *mface, MVert *mvert, + int *face_indices, int totface) { GPU_Buffers *buffers; @@ -1332,9 +1338,12 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers"); buffers->index_type = GL_UNSIGNED_SHORT; - /* Count the number of triangles */ - for(i = 0, tottri = 0; i < totface; ++i) - tottri += mface[face_indices[i]].v4 ? 2 : 1; + /* Count the number of visible triangles */ + for(i = 0, tottri = 0; i < totface; ++i) { + const MFace *f = &mface[face_indices[i]]; + if(!paint_is_face_hidden(f, mvert)) + tottri += f->v4 ? 2 : 1; + } if(GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) glGenBuffersARB(1, &buffers->index_buf); @@ -1349,9 +1358,13 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); if(tri_data) { for(i = 0; i < totface; ++i) { - MFace *f = mface + face_indices[i]; + const MFace *f = mface + face_indices[i]; int v[3]; + /* Skip hidden faces */ + if(paint_is_face_hidden(f, mvert)) + continue; + v[0]= 0; v[1]= 1; v[2]= 2; @@ -1448,34 +1461,79 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, DMGridData **grids, //printf("node updated %p\n", buffers); } +/* Returns the number of visible quads in the nodes' grids. */ +static int gpu_count_grid_quads(BLI_bitmap *grid_hidden, + int *grid_indices, int totgrid, + int gridsize) +{ + int gridarea = (gridsize-1) * (gridsize-1); + int i, x, y, totquad; + + /* grid hidden layer is present, so have to check each grid for + visiblity */ + + for(i = 0, totquad = 0; i < totgrid; i++) { + const BLI_bitmap gh = grid_hidden[grid_indices[i]]; + + if(gh) { + /* grid hidden are present, have to check each element */ + for(y = 0; y < gridsize-1; y++) { + for(x = 0; x < gridsize-1; x++) { + if(paint_is_grid_face_hidden(gh, gridsize, x, y)) + totquad++; + } + } + } + else + totquad += gridarea; + } + + return totquad; +} + /* Build the element array buffer of grid indices using either unsigned shorts or unsigned ints. */ -#define FILL_QUAD_BUFFER(type_) \ +#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \ { \ type_ *quad_data; \ - int i, j; \ + int offset = 0; \ + int i, j, k; \ \ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \ - sizeof(type_) * (*totquad) * 4, NULL, \ + sizeof(type_) * (tot_quad_) * 4, NULL, \ GL_STATIC_DRAW_ARB); \ \ /* Fill the quad buffer */ \ quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \ GL_WRITE_ONLY_ARB); \ if(quad_data) { \ - for(i = 0; i < gridsize-1; ++i) { \ + for(i = 0; i < totgrid; ++i) { \ + BLI_bitmap gh = NULL; \ + if(grid_hidden) \ + gh = grid_hidden[(grid_indices)[i]]; \ + \ for(j = 0; j < gridsize-1; ++j) { \ - *(quad_data++)= i*gridsize + j+1; \ - *(quad_data++)= i*gridsize + j; \ - *(quad_data++)= (i+1)*gridsize + j; \ - *(quad_data++)= (i+1)*gridsize + j+1; \ + for(k = 0; k < gridsize-1; ++k) { \ + /* Skip hidden grid face */ \ + if(gh && \ + paint_is_grid_face_hidden(gh, \ + gridsize, k, j)) \ + continue; \ + \ + *(quad_data++)= offset + j*gridsize + k+1; \ + *(quad_data++)= offset + j*gridsize + k; \ + *(quad_data++)= offset + (j+1)*gridsize + k; \ + *(quad_data++)= offset + (j+1)*gridsize + k+1; \ + } \ } \ + \ + offset += gridsize*gridsize; \ } \ glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \ } \ else { \ - glDeleteBuffersARB(1, &buffer); \ - buffer = 0; \ + glDeleteBuffersARB(1, &(buffer_)); \ + (buffer_) = 0; \ } \ } /* end FILL_QUAD_BUFFER */ @@ -1487,6 +1545,11 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to static GLuint buffer = 0; static unsigned prev_totquad; + /* used in the FILL_QUAD_BUFFER macro */ + const BLI_bitmap *grid_hidden = NULL; + int *grid_indices = NULL; + int totgrid = 1; + /* VBO is disabled; delete the previous buffer (if it exists) and return an invalid handle */ if(!GLEW_ARB_vertex_buffer_object || (U.gameflags & USER_DISABLE_VBO)) { @@ -1511,11 +1574,11 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to if(*totquad < USHRT_MAX) { *index_type = GL_UNSIGNED_SHORT; - FILL_QUAD_BUFFER(unsigned short); + FILL_QUAD_BUFFER(unsigned short, *totquad, buffer); } else { *index_type = GL_UNSIGNED_INT; - FILL_QUAD_BUFFER(unsigned int); + FILL_QUAD_BUFFER(unsigned int, *totquad, buffer); } glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); @@ -1527,16 +1590,47 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to return buffer; } -GPU_Buffers *GPU_build_grid_buffers(int totgrid, int gridsize) +GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, + BLI_bitmap *grid_hidden, int gridsize) { GPU_Buffers *buffers; + int totquad; + int fully_visible_totquad = (gridsize-1) * (gridsize-1); buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers"); - - /* Build index VBO */ - buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad); - buffers->totgrid = totgrid; + buffers->grid_hidden = grid_hidden; buffers->gridsize = gridsize; + buffers->totgrid = totgrid; + + /* Count the number of quads */ + totquad= gpu_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); + + if(totquad == fully_visible_totquad) { + gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad); + buffers->has_hidden = 0; + } + else if(!GLEW_ARB_vertex_buffer_object || (U.gameflags & USER_DISABLE_VBO)) { + /* Build new VBO */ + glGenBuffersARB(1, &buffers->index_buf); + if(buffers->index_buf) { + buffers->tot_quad= totquad; + + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); + + if(totquad < USHRT_MAX) { + buffers->index_type = GL_UNSIGNED_SHORT; + FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf); + } + else { + buffers->index_type = GL_UNSIGNED_INT; + FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf); + } + + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + + buffers->has_hidden = 1; + } /* Build coord/normal VBO */ if(buffers->index_buf) @@ -1557,6 +1651,9 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth) int S = f->v4 ? 4 : 3; unsigned int *fv = &f->v1; + if(paint_is_face_hidden(f, buffers->mvert)) + continue; + glBegin((f->v4)? GL_QUADS: GL_TRIANGLES); if(smooth) { @@ -1587,17 +1684,56 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth) static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) { - int i, x, y, gridsize = buffers->gridsize; + int i, j, x, y, gridsize = buffers->gridsize; + + for(i = 0; i < buffers->totgrid; ++i) { + int g = buffers->grid_indices[i]; + const DMGridData *grid = buffers->grids[g]; + BLI_bitmap gh = buffers->grid_hidden[g]; - if(smooth) { - for(i = 0; i < buffers->totgrid; ++i) { - DMGridData *grid = buffers->grids[buffers->grid_indices[i]]; + /* TODO: could use strips with hiding as well */ + if(gh) { + glBegin(GL_QUADS); + + for(y = 0; y < gridsize-1; y++) { + for(x = 0; x < gridsize-1; x++) { + const DMGridData *e[4] = { + &grid[y*gridsize + x], + &grid[(y+1)*gridsize + x], + &grid[(y+1)*gridsize + x+1], + &grid[y*gridsize + x+1] + }; + + /* skip face if any of its corners are hidden */ + if(paint_is_grid_face_hidden(gh, gridsize, x, y)) + continue; + + if(smooth) { + for(j = 0; j < 4; j++) { + glNormal3fv(e[j]->no); + glVertex3fv(e[j]->co); + } + } + else { + float fno[3]; + normal_quad_v3(fno, e[0]->co, e[1]->co, e[2]->co, e[3]->co); + glNormal3fv(fno); + + for(j = 0; j < 4; j++) + glVertex3fv(e[j]->co); + } + } + } + + glEnd(); + } + else if(smooth) { for(y = 0; y < gridsize-1; y++) { glBegin(GL_QUAD_STRIP); for(x = 0; x < gridsize; x++) { - DMGridData *a = &grid[y*gridsize + x]; - DMGridData *b = &grid[(y+1)*gridsize + x]; + const DMGridData *a = &grid[y*gridsize + x]; + const DMGridData *b = &grid[(y+1)*gridsize + x]; glNormal3fv(a->no); glVertex3fv(a->co); @@ -1607,20 +1743,16 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) glEnd(); } } - } - else { - for(i = 0; i < buffers->totgrid; ++i) { - DMGridData *grid = buffers->grids[buffers->grid_indices[i]]; - + else { for(y = 0; y < gridsize-1; y++) { glBegin(GL_QUAD_STRIP); for(x = 0; x < gridsize; x++) { - DMGridData *a = &grid[y*gridsize + x]; - DMGridData *b = &grid[(y+1)*gridsize + x]; + const DMGridData *a = &grid[y*gridsize + x]; + const DMGridData *b = &grid[(y+1)*gridsize + x]; if(x > 0) { - DMGridData *c = &grid[y*gridsize + x-1]; - DMGridData *d = &grid[(y+1)*gridsize + x-1]; + const DMGridData *c = &grid[y*gridsize + x-1]; + const DMGridData *d = &grid[(y+1)*gridsize + x-1]; float fno[3]; normal_quad_v3(fno, d->co, b->co, a->co, c->co); glNormal3fv(fno); @@ -1665,8 +1797,8 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) if(buffers->tot_quad) { unsigned offset = 0; - int i; - for(i = 0; i < buffers->totgrid; i++) { + int i, last = buffers->has_hidden ? 1 : buffers->totgrid; + for(i = 0; i < last; i++) { glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), offset + (char*)offsetof(DMGridData, co)); glNormalPointer(GL_FLOAT, sizeof(DMGridData), offset + (char*)offsetof(DMGridData, no)); @@ -1702,7 +1834,7 @@ void GPU_free_buffers(GPU_Buffers *buffers) if(buffers) { if(buffers->vert_buf) glDeleteBuffersARB(1, &buffers->vert_buf); - if(buffers->index_buf && buffers->tot_tri) + if(buffers->index_buf && (buffers->tot_tri || buffers->has_hidden)) glDeleteBuffersARB(1, &buffers->index_buf); MEM_freeN(buffers); -- cgit v1.2.3