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:
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c327
1 files changed, 325 insertions, 2 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 13d0139e406..9ca965373f4 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -53,6 +53,7 @@
#include "gpu_private.h"
#include "bmesh.h"
+#include "trimesh.h"
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
@@ -84,7 +85,7 @@ struct GPU_PBVH_Buffers {
const int *grid_indices;
int totgrid;
- bool use_bmesh;
+ bool use_bmesh, use_trimesh;
bool clear_bmesh_on_flush;
uint tot_tri, tot_quad;
@@ -121,7 +122,7 @@ void gpu_pbvh_init()
g_vbo_id.msk = GPU_vertformat_attr_add(
&g_vbo_id.format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.col = GPU_vertformat_attr_add(
- &g_vbo_id.format, "ac", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ &g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.fset = GPU_vertformat_attr_add(
&g_vbo_id.format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
@@ -824,6 +825,111 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.fset, v_index, &face_set);
}
+/* Output a BMVert into a VertexBufferFormat array at v_index. */
+static void gpu_trimesh_vert_to_buffer_copy(TMVert *v,
+ GPUVertBuf *vert_buf,
+ int v_index,
+ const float fno[3],
+ const float *fmask,
+ const int cd_vert_mask_offset,
+ const int cd_vert_node_offset,
+ const bool show_mask,
+ const bool show_vcol,
+ bool *empty_mask,
+ int cd_vcol_offset)
+{
+ /* Vertex should always be visible if it's used by a visible face. */
+ BLI_assert(!TM_elem_flag_test(v, TM_ELEM_HIDDEN));
+
+ /* Set coord, normal, and mask */
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
+
+ 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);
+
+ if (show_mask) {
+ float effective_mask = fmask ? *fmask : TM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ // int ni = TM_ELEM_CD_GET_INT(v, cd_vert_node_offset);
+ // float effective_mask = (float)(ni % 64) / 64.0f;
+
+ uchar cmask = (uchar)(effective_mask * 255);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, v_index, &cmask);
+ *empty_mask = *empty_mask && (cmask == 0);
+ }
+
+ if (show_vcol && cd_vcol_offset >= 0) {
+ ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
+ int col[4] = {0, 0, 0, 0};
+ int tot = 0;
+
+ for (int i = 0; i < v->edges.length; i++) {
+ TMEdge *e = v->edges.items[i];
+
+ for (int j = 0; j < e->tris.length; j++) {
+ TMFace *t = e->tris.items[j];
+
+ TMLoopData *l = TM_GET_TRI_LOOP_EDGE(t, e);
+ MLoopCol *ml = TM_ELEM_CD_GET_VOID_P(l, cd_vcol_offset);
+
+ col[0] += ml->r;
+ col[1] += ml->g;
+ col[2] += ml->b;
+ col[3] += ml->a;
+ tot++;
+ }
+ }
+
+ if (tot) {
+ col[0] /= tot;
+ col[1] /= tot;
+ col[2] /= tot;
+ col[3] /= tot;
+
+ vcol[0] = (ushort)(col[0] * 257);
+ vcol[1] = (ushort)(col[1] * 257);
+ vcol[2] = (ushort)(col[2] * 257);
+ vcol[3] = (ushort)(col[3] * 257);
+ //printf("%d %d %d %d %d\n", vcol[0], vcol[1], vcol[2], vcol[3], tot);
+ }
+ //const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, v_index, vcol);
+ }
+ else if (show_vcol) {
+ const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, v_index, vcol);
+ }
+
+ /* Add default face sets color to avoid artifacts. */
+
+ const uchar face_set[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.fset, v_index, face_set);
+}
+
+/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
+static int gpu_trimesh_vert_visible_count(TMElemSet *bm_unique_verts, TMElemSet *bm_other_verts)
+{
+ int totvert = 0;
+ TMVert *v;
+
+ TMS_ITER (v, bm_unique_verts) {
+ if (!TM_elem_flag_test(v, TM_ELEM_HIDDEN)) {
+ totvert++;
+ }
+ }
+ TMS_ITER_END
+
+ TMS_ITER (v, bm_other_verts) {
+ if (!TM_elem_flag_test(v, TM_ELEM_HIDDEN)) {
+ totvert++;
+ }
+ }
+ TMS_ITER_END
+
+ return totvert;
+}
+
/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts, GSet *bm_other_verts)
{
@@ -863,6 +969,23 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces)
return totface;
}
+/* Return the total number of visible faces */
+static int gpu_trimesh_face_visible_count(GSet *bm_faces)
+{
+ GSetIterator gh_iter;
+ int totface = 0;
+
+ GSET_ITER (gh_iter, bm_faces) {
+ TMFace *f = BLI_gsetIterator_getKey(&gh_iter);
+
+ if (!TM_elem_flag_test(f, TM_ELEM_HIDDEN)) {
+ totface++;
+ }
+ }
+
+ return totface;
+}
+
void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
{
if (buffers->smooth) {
@@ -878,6 +1001,21 @@ void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
}
}
+void GPU_pbvh_trimesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
+{
+ if (buffers->smooth) {
+ /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */
+ GPU_BATCH_DISCARD_SAFE(buffers->triangles);
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ }
+ else {
+ GPU_BATCH_DISCARD_SAFE(buffers->lines);
+ GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf);
+ }
+}
+
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
* shading, an element index buffer.
* Threaded - do not call any functions that use OpenGL calls! */
@@ -1042,6 +1180,178 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
}
+/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
+ * shading, an element index buffer.
+ * Threaded - do not call any functions that use OpenGL calls! */
+void GPU_pbvh_trimesh_buffers_update(GPU_PBVH_Buffers *buffers,
+ TM_TriMesh *bm,
+ GSet *tm_faces,
+ TMElemSet *bm_unique_verts,
+ TMElemSet *bm_other_verts,
+ const int update_flags,
+ const int cd_vert_node_offset)
+{
+ const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+ const bool show_vcol = true; //(update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
+ int tottri, totvert;
+ bool empty_mask = true;
+ TMFace *f = NULL;
+
+ /* Count visible triangles */
+ tottri = gpu_trimesh_face_visible_count(tm_faces);
+
+ if (buffers->smooth) {
+ /* Count visible vertices */
+ totvert = gpu_trimesh_vert_visible_count(bm_unique_verts, bm_other_verts);
+ }
+ else {
+ totvert = tottri * 3;
+ }
+
+ if (!tottri) {
+ if (BLI_gset_len(tm_faces) != 0) {
+ /* Node is just hidden. */
+ }
+ else {
+ buffers->clear_bmesh_on_flush = true;
+ }
+ buffers->tot_tri = 0;
+ return;
+ }
+
+ /* TODO, make mask layer optional for bmesh buffer */
+ 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)) {
+ /* Memory map failed */
+ return;
+ }
+
+ int v_index = 0;
+
+ int cd_vcol_off = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
+
+ 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);
+
+ GHash *bm_vert_to_index = BLI_ghash_int_new_ex("bm_vert_to_index", totvert);
+
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, tm_faces) {
+ f = BLI_gsetIterator_getKey(&gs_iter);
+
+ if (!TM_elem_flag_test(f, TM_ELEM_HIDDEN)) {
+ uint idx[3];
+ for (int i = 0; i < 3; i++) {
+ TMVert *v = TM_GET_TRI_VERT(f, i);
+
+ void **idx_p;
+ if (!BLI_ghash_ensure_p(bm_vert_to_index, v, &idx_p)) {
+ /* Add vertex to the vertex buffer each time a new one is encountered */
+ *idx_p = POINTER_FROM_UINT(v_index);
+
+ gpu_trimesh_vert_to_buffer_copy(v,
+ buffers->vert_buf,
+ v_index,
+ NULL,
+ NULL,
+ cd_vert_mask_offset,
+ cd_vert_node_offset,
+ show_mask,
+ show_vcol,
+ &empty_mask,
+ cd_vcol_off);
+
+ idx[i] = v_index;
+ v_index++;
+ }
+ else {
+ /* Vertex already in the vertex buffer, just get the index. */
+ idx[i] = POINTER_AS_UINT(*idx_p);
+ }
+ }
+
+ 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]);
+ }
+ }
+
+ 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 {
+ GSetIterator gs_iter;
+
+ GPUIndexBufBuilder elb_lines;
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3);
+
+ int cd_vcol_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
+
+ GSET_ITER (gs_iter, tm_faces) {
+ f = BLI_gsetIterator_getKey(&gs_iter);
+
+ BLI_assert(f->len == 3);
+
+ if (!TM_elem_flag_test(f, TM_ELEM_HIDDEN)) {
+ float fmask = 0.0f;
+ int i;
+
+ /* Average mask value */
+ for (i = 0; i < 3; i++) {
+ TMVert *v2 = TM_GET_TRI_VERT(f, i);
+
+ fmask += TM_ELEM_CD_GET_FLOAT(v2, 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++) {
+ TMVert *v2 = TM_GET_TRI_VERT(f, i);
+
+ gpu_trimesh_vert_to_buffer_copy(v2,
+ buffers->vert_buf,
+ v_index++,
+ f->no,
+ &fmask,
+ cd_vert_mask_offset,
+ cd_vert_node_offset,
+ show_mask,
+ show_vcol,
+ &empty_mask,
+ cd_vcol_offset);
+ }
+ }
+ }
+
+ buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
+ buffers->tot_tri = tottri;
+ }
+
+ /* Get material index from the last face we iterated on. */
+ buffers->material_index = (f) ? f->mat_nr : 0;
+
+ buffers->show_overlay = !empty_mask;
+
+ gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
+}
/** \} */
/* -------------------------------------------------------------------- */
@@ -1061,6 +1371,19 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
return buffers;
}
+/* Threaded - do not call any functions that use OpenGL calls! */
+GPU_PBVH_Buffers *GPU_pbvh_trimesh_buffers_build(bool smooth_shading)
+{
+ GPU_PBVH_Buffers *buffers;
+
+ buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
+ buffers->use_trimesh = true;
+ buffers->smooth = smooth_shading;
+ buffers->show_overlay = true;
+
+ return buffers;
+}
+
GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires)
{
if (wires) {