diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 257 |
1 files changed, 115 insertions, 142 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index ed606ccb8c6..78202158852 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -729,47 +729,36 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid /** \name BMesh PBVH * \{ */ -/* Output a BMVert into a VertexBufferFormat array - * - * The vertex is skipped if hidden, otherwise the output goes into - * index '*v_index' in the 'vert_data' array and '*v_index' is - * incremented. - */ -static void gpu_bmesh_vert_to_buffer_copy__gwn(BMVert *v, - GPUVertBuf *vert_buf, - int *v_index, - const float fno[3], - const float *fmask, - const int cd_vert_mask_offset, - const bool show_mask, - const bool show_vcol, - bool *empty_mask) +/* Output a BMVert into a VertexBufferFormat array at v_index. */ +static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, + GPUVertBuf *vert_buf, + int v_index, + const float fno[3], + const float *fmask, + const int cd_vert_mask_offset, + const bool show_mask, + const bool show_vcol, + bool *empty_mask) { - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - - /* Set coord, normal, and mask */ - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co); + /* Vertex should always be visible if it's used by a visible face. */ + BLI_assert(!BM_elem_flag_test(v, BM_ELEM_HIDDEN)); - short no_short[3]; - normal_float_to_short_v3(no_short, fno ? fno : v->no); - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short); + /* Set coord, normal, and mask */ + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co); - if (show_mask) { - float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, *v_index, &effective_mask); - *empty_mask = *empty_mask && (effective_mask == 0.0f); - } - - if (show_vcol) { - static char vcol[4] = {255, 255, 255, 255}; - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, &vcol); - } + short no_short[3]; + normal_float_to_short_v3(no_short, fno ? fno : v->no); + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, v_index, no_short); - /* Assign index for use in the triangle index buffer */ - /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */ - BM_elem_index_set(v, (*v_index)); /* set_dirty! */ + if (show_mask) { + float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, v_index, &effective_mask); + *empty_mask = *empty_mask && (effective_mask == 0.0f); + } - (*v_index)++; + if (show_vcol) { + static char vcol[4] = {255, 255, 255, 255}; + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, v_index, &vcol); } } @@ -839,7 +828,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers, { const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; - int tottri, totvert, maxvert = 0; + int tottri, totvert; bool empty_mask = true; BMFace *f = NULL; @@ -869,135 +858,118 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers, const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); /* Fill vertex buffer */ - if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) { - int v_index = 0; - - if (buffers->smooth) { - GSetIterator gs_iter; - - /* Vertices get an index assigned for use in the triangle - * index buffer */ - bm->elem_index_dirty |= BM_VERT; - - GSET_ITER (gs_iter, bm_unique_verts) { - gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter), - buffers->vert_buf, - &v_index, - NULL, - NULL, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); - } - - GSET_ITER (gs_iter, bm_other_verts) { - gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter), - buffers->vert_buf, - &v_index, - NULL, - NULL, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); - } + if (!gpu_pbvh_vert_buf_data_set(buffers, totvert)) { + /* Memory map failed */ + return; + } - maxvert = v_index; - } - else { - GSetIterator gs_iter; + int v_index = 0; - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert); + if (buffers->smooth) { + /* Fill the vertex and triangle buffer in one pass over faces. */ + GPUIndexBufBuilder elb, elb_lines; + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert); + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert); - GSET_ITER (gs_iter, bm_faces) { - f = BLI_gsetIterator_getKey(&gs_iter); + GHash *bm_vert_to_index = BLI_ghash_int_new_ex("bm_vert_to_index", totvert); - BLI_assert(f->len == 3); + GSetIterator gs_iter; + GSET_ITER (gs_iter, bm_faces) { + f = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - float fmask = 0.0f; - int i; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + BMVert *v[3]; + BM_face_as_array_vert_tri(f, v); - BM_face_as_array_vert_tri(f, v); + uint idx[3]; + for (int i = 0; i < 3; i++) { + void **idx_p; + if (!BLI_ghash_ensure_p(bm_vert_to_index, v[i], &idx_p)) { + /* Add vertex to the vertex buffer each time a new one is encountered */ + *idx_p = POINTER_FROM_UINT(v_index); - /* Average mask value */ - for (i = 0; i < 3; i++) { - fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset); + gpu_bmesh_vert_to_buffer_copy(v[i], + buffers->vert_buf, + v_index, + NULL, + NULL, + cd_vert_mask_offset, + show_mask, + show_vcol, + &empty_mask); + + idx[i] = v_index; + v_index++; } - fmask /= 3.0f; - - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0); - - for (i = 0; i < 3; i++) { - gpu_bmesh_vert_to_buffer_copy__gwn(v[i], - buffers->vert_buf, - &v_index, - f->no, - &fmask, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); + else { + /* Vertex already in the vertex buffer, just get the index. */ + idx[i] = POINTER_AS_UINT(*idx_p); } } - } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->tot_tri = tottri; + GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + + GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]); + GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]); + GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]); + } } - /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */ - bm->elem_index_dirty |= BM_VERT; + BLI_ghash_free(bm_vert_to_index, NULL, NULL); + + buffers->tot_tri = tottri; + if (buffers->index_buf == NULL) { + buffers->index_buf = GPU_indexbuf_build(&elb); + } + else { + GPU_indexbuf_build_in_place(&elb, buffers->index_buf); + } + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); } else { - /* Memory map failed */ - return; - } - - if (buffers->smooth) { - /* Fill the triangle buffer */ - GPUIndexBufBuilder elb, elb_lines; - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, maxvert); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, maxvert); + GSetIterator gs_iter; - /* Fill triangle index buffer */ - { - GSetIterator gs_iter; + GPUIndexBufBuilder elb_lines; + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3); - GSET_ITER (gs_iter, bm_faces) { - f = BLI_gsetIterator_getKey(&gs_iter); + GSET_ITER (gs_iter, bm_faces) { + f = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; + BLI_assert(f->len == 3); - BM_face_as_array_vert_tri(f, v); + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + BMVert *v[3]; + float fmask = 0.0f; + int i; - const uint idx[3] = { - BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2])}; - GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + BM_face_as_array_vert_tri(f, v); - GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]); + /* Average mask value */ + for (i = 0; i < 3; i++) { + fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset); + } + fmask /= 3.0f; + + GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1); + GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2); + GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0); + + for (i = 0; i < 3; i++) { + gpu_bmesh_vert_to_buffer_copy(v[i], + buffers->vert_buf, + v_index++, + f->no, + &fmask, + cd_vert_mask_offset, + show_mask, + show_vcol, + &empty_mask); } } - - buffers->tot_tri = tottri; - - if (buffers->index_buf == NULL) { - buffers->index_buf = GPU_indexbuf_build(&elb); - } - else { - GPU_indexbuf_build_in_place(&elb, buffers->index_buf); - } - - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); } + + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + buffers->tot_tri = tottri; } /* Get material index from the last face we iterated on. */ @@ -1054,6 +1026,7 @@ void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers) GPU_BATCH_DISCARD_SAFE(buffers->triangles); GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); + buffers->clear_bmesh_on_flush = false; } /* Force flushing to the GPU. */ |