DRW: Support Wireframe for metaball objects
This commit is contained in:
@@ -709,7 +709,9 @@ void DRW_cache_object_face_wireframe_get(
|
||||
case OB_FONT:
|
||||
DRW_cache_text_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
|
||||
break;
|
||||
/* TODO, metaballs' */
|
||||
case OB_MBALL:
|
||||
DRW_cache_mball_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3287,6 +3289,13 @@ GPUBatch *DRW_cache_mball_surface_get(Object *ob)
|
||||
return DRW_metaball_batch_cache_get_triangles_with_normals(ob);
|
||||
}
|
||||
|
||||
void DRW_cache_mball_face_wireframe_get(
|
||||
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MBALL);
|
||||
return DRW_metaball_batch_cache_get_wireframes_face_texbuf(ob, r_vert_tx, r_faceid_tx, r_tri_count);
|
||||
}
|
||||
|
||||
GPUBatch **DRW_cache_mball_surface_shaded_get(
|
||||
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
|
||||
{
|
||||
|
||||
@@ -209,5 +209,7 @@ struct GPUBatch *DRW_cache_particles_get_prim(int type);
|
||||
/* Metaball */
|
||||
struct GPUBatch *DRW_cache_mball_surface_get(struct Object *ob);
|
||||
struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
|
||||
void DRW_cache_mball_face_wireframe_get(
|
||||
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
|
||||
|
||||
#endif /* __DRAW_CACHE_H__ */
|
||||
|
||||
@@ -82,6 +82,8 @@ void DRW_curve_batch_cache_get_wireframes_face_texbuf(
|
||||
/* Metaball */
|
||||
struct GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
|
||||
struct GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
|
||||
void DRW_metaball_batch_cache_get_wireframes_face_texbuf(
|
||||
struct Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
|
||||
|
||||
/* Curve (Font) */
|
||||
struct GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
|
||||
|
||||
@@ -91,6 +91,7 @@ typedef void (setTriIndicesFn)(void *thunk, uint v1, uint v2, uint v3);
|
||||
|
||||
static void displist_indexbufbuilder_set(
|
||||
setTriIndicesFn *set_tri_indices,
|
||||
setTriIndicesFn *set_quad_tri_indices, /* meh, find a better solution. */
|
||||
void *thunk, const DispList *dl, const int ofs)
|
||||
{
|
||||
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
|
||||
@@ -104,18 +105,20 @@ static void displist_indexbufbuilder_set(
|
||||
else if (dl->type == DL_SURF) {
|
||||
const int i_end = dl->totindex;
|
||||
for (int i = 0; i < i_end; i++, idx += 4) {
|
||||
set_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
|
||||
set_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[3] + ofs);
|
||||
set_quad_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
|
||||
set_quad_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[3] + ofs);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_assert(dl->type == DL_INDEX4);
|
||||
const int i_end = dl->parts;
|
||||
for (int i = 0; i < i_end; i++, idx += 4) {
|
||||
set_tri_indices(thunk, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
|
||||
|
||||
if (idx[2] != idx[3]) {
|
||||
set_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
|
||||
set_quad_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[1] + ofs);
|
||||
set_quad_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
|
||||
}
|
||||
else {
|
||||
set_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[1] + ofs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +176,9 @@ GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
|
||||
|
||||
int ofs = 0;
|
||||
for (const DispList *dl = lb->first; dl; dl = dl->next) {
|
||||
displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts, &elb, dl, ofs);
|
||||
displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
|
||||
(setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
|
||||
&elb, dl, ofs);
|
||||
ofs += dl_vert_len(dl);
|
||||
}
|
||||
|
||||
@@ -198,7 +203,9 @@ GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(Li
|
||||
/* calc each index buffer builder */
|
||||
int ofs = 0;
|
||||
for (const DispList *dl = lb->first; dl; dl = dl->next) {
|
||||
displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts, &elb[dl->col], dl, ofs);
|
||||
displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
|
||||
(setTriIndicesFn *)GPU_indexbuf_add_tri_verts,
|
||||
&elb[dl->col], dl, ofs);
|
||||
ofs += dl_vert_len(dl);
|
||||
}
|
||||
|
||||
@@ -219,18 +226,21 @@ typedef struct DRWDisplistWireThunk {
|
||||
static void set_overlay_wires_tri_indices(void *thunk, uint v1, uint v2, uint v3)
|
||||
{
|
||||
DRWDisplistWireThunk *dwt = (DRWDisplistWireThunk *)thunk;
|
||||
/* TODO consider non-manifold edges correctly. */
|
||||
if (dwt->dl_type == DL_SURF) {
|
||||
/* Tag real edges. */
|
||||
v2 |= (1 << 30);
|
||||
v3 |= (1 << 30);
|
||||
}
|
||||
else {
|
||||
/* Tag real edges. */
|
||||
v1 |= (1 << 30);
|
||||
v2 |= (1 << 30);
|
||||
v3 |= (1 << 30);
|
||||
}
|
||||
/* Tag real edges. */
|
||||
v1 |= (1 << 30);
|
||||
v2 |= (1 << 30);
|
||||
v3 |= (1 << 30);
|
||||
GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v1);
|
||||
GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v2);
|
||||
GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v3);
|
||||
}
|
||||
|
||||
static void set_overlay_wires_quad_tri_indices(void *thunk, uint v1, uint v2, uint v3)
|
||||
{
|
||||
DRWDisplistWireThunk *dwt = (DRWDisplistWireThunk *)thunk;
|
||||
/* Tag real edges. */
|
||||
v2 |= (1 << 30);
|
||||
v3 |= (1 << 30);
|
||||
GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v1);
|
||||
GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v2);
|
||||
GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v3);
|
||||
@@ -249,7 +259,10 @@ GPUVertBuf *DRW_displist_create_edges_overlay_texture_buf(ListBase *lb)
|
||||
int ofs = 0;
|
||||
for (const DispList *dl = lb->first; dl; dl = dl->next) {
|
||||
thunk.dl_type = dl->type;
|
||||
displist_indexbufbuilder_set(set_overlay_wires_tri_indices, &thunk, dl, ofs);
|
||||
/* TODO consider non-manifold edges correctly. */
|
||||
displist_indexbufbuilder_set(set_overlay_wires_tri_indices,
|
||||
set_overlay_wires_quad_tri_indices,
|
||||
&thunk, dl, ofs);
|
||||
ofs += dl_vert_len(dl);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
#include "GPU_batch.h"
|
||||
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "draw_cache_impl.h" /* own include */
|
||||
|
||||
|
||||
@@ -50,8 +52,19 @@ static void metaball_batch_cache_clear(MetaBall *mb);
|
||||
typedef struct MetaBallBatchCache {
|
||||
GPUBatch *batch;
|
||||
GPUBatch **shaded_triangles;
|
||||
|
||||
int mat_len;
|
||||
|
||||
/* Shared */
|
||||
GPUVertBuf *pos_nor_in_order;
|
||||
|
||||
/* Wireframe */
|
||||
struct {
|
||||
GPUVertBuf *elem_vbo;
|
||||
GPUTexture *elem_tx;
|
||||
GPUTexture *verts_tx;
|
||||
int tri_count;
|
||||
} face_wire;
|
||||
|
||||
/* settings to determine if cache is invalid */
|
||||
bool is_dirty;
|
||||
} MetaBallBatchCache;
|
||||
@@ -80,6 +93,11 @@ static void metaball_batch_cache_init(MetaBall *mb)
|
||||
cache->mat_len = 0;
|
||||
cache->shaded_triangles = NULL;
|
||||
cache->is_dirty = false;
|
||||
cache->pos_nor_in_order = NULL;
|
||||
cache->face_wire.elem_vbo = NULL;
|
||||
cache->face_wire.elem_tx = NULL;
|
||||
cache->face_wire.verts_tx = NULL;
|
||||
cache->face_wire.tri_count = 0;
|
||||
}
|
||||
|
||||
static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
|
||||
@@ -113,7 +131,12 @@ static void metaball_batch_cache_clear(MetaBall *mb)
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->face_wire.elem_vbo);
|
||||
DRW_TEXTURE_FREE_SAFE(cache->face_wire.elem_tx);
|
||||
DRW_TEXTURE_FREE_SAFE(cache->face_wire.verts_tx);
|
||||
|
||||
GPU_BATCH_DISCARD_SAFE(cache->batch);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->pos_nor_in_order);
|
||||
/* Note: shaded_triangles[0] is already freed by cache->batch */
|
||||
MEM_SAFE_FREE(cache->shaded_triangles);
|
||||
cache->mat_len = 0;
|
||||
@@ -125,6 +148,45 @@ void DRW_mball_batch_cache_free(MetaBall *mb)
|
||||
MEM_SAFE_FREE(mb->batch_cache);
|
||||
}
|
||||
|
||||
static GPUVertBuf *mball_batch_cache_get_pos_and_normals(Object *ob, MetaBallBatchCache *cache)
|
||||
{
|
||||
if (cache->pos_nor_in_order == NULL) {
|
||||
ListBase *lb = &ob->runtime.curve_cache->disp;
|
||||
cache->pos_nor_in_order = DRW_displist_vertbuf_calc_pos_with_normals(lb);
|
||||
}
|
||||
return cache->pos_nor_in_order;
|
||||
}
|
||||
|
||||
static GPUTexture *mball_batch_cache_get_edges_overlay_texture_buf(Object *ob, MetaBallBatchCache *cache)
|
||||
{
|
||||
if (cache->face_wire.elem_tx != NULL) {
|
||||
return cache->face_wire.elem_tx;
|
||||
}
|
||||
|
||||
ListBase *lb = &ob->runtime.curve_cache->disp;
|
||||
|
||||
/* We need a special index buffer. */
|
||||
GPUVertBuf *vbo = cache->face_wire.elem_vbo = DRW_displist_create_edges_overlay_texture_buf(lb);
|
||||
|
||||
/* Upload data early because we need to create the texture for it. */
|
||||
GPU_vertbuf_use(vbo);
|
||||
cache->face_wire.elem_tx = GPU_texture_create_from_vertbuf(vbo);
|
||||
cache->face_wire.tri_count = vbo->vertex_alloc / 3;
|
||||
|
||||
return cache->face_wire.elem_tx;
|
||||
}
|
||||
|
||||
static GPUTexture *mball_batch_cache_get_vert_pos_and_nor_in_order_buf(Object *ob, MetaBallBatchCache *cache)
|
||||
{
|
||||
if (cache->face_wire.verts_tx == NULL) {
|
||||
GPUVertBuf *vbo = mball_batch_cache_get_pos_and_normals(ob, cache);
|
||||
GPU_vertbuf_use(vbo); /* Upload early for buffer texture creation. */
|
||||
cache->face_wire.verts_tx = GPU_texture_create_buffer(GPU_R32F, vbo->vbo_id);
|
||||
}
|
||||
|
||||
return cache->face_wire.verts_tx;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/** \name Public Object/MetaBall API
|
||||
@@ -143,9 +205,9 @@ GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
|
||||
ListBase *lb = &ob->runtime.curve_cache->disp;
|
||||
cache->batch = GPU_batch_create_ex(
|
||||
GPU_PRIM_TRIS,
|
||||
DRW_displist_vertbuf_calc_pos_with_normals(lb),
|
||||
mball_batch_cache_get_pos_and_normals(ob, cache),
|
||||
DRW_displist_indexbuf_calc_triangles_in_order(lb),
|
||||
GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
||||
GPU_BATCH_OWNS_INDEX);
|
||||
}
|
||||
|
||||
return cache->batch;
|
||||
@@ -169,3 +231,27 @@ GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb,
|
||||
return cache->shaded_triangles;
|
||||
|
||||
}
|
||||
|
||||
void DRW_metaball_batch_cache_get_wireframes_face_texbuf(
|
||||
Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count)
|
||||
{
|
||||
if (!BKE_mball_is_basis(ob)) {
|
||||
*verts_data = NULL;
|
||||
*face_indices = NULL;
|
||||
*tri_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
MetaBall *mb = ob->data;
|
||||
MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
|
||||
|
||||
if (cache->face_wire.verts_tx == NULL) {
|
||||
*verts_data = mball_batch_cache_get_vert_pos_and_nor_in_order_buf(ob, cache);
|
||||
*face_indices = mball_batch_cache_get_edges_overlay_texture_buf(ob, cache);
|
||||
}
|
||||
else {
|
||||
*verts_data = cache->face_wire.verts_tx;
|
||||
*face_indices = cache->face_wire.elem_tx;
|
||||
}
|
||||
*tri_count = cache->face_wire.tri_count;
|
||||
}
|
||||
Reference in New Issue
Block a user