Sculpt dyntopo: Add support for multiple materials to dyntopo
pbvh drawing. * Dyntopo now stores a list of PBVHTriBufs in leaf nodes, one per material used by the node. * Actual drawing buffers live in a new mat_draw_buffers PBVHNode member.
This commit is contained in:
parent
d0759840a0
commit
57286eed8d
|
@ -64,10 +64,11 @@ typedef struct PBVHTriBuf {
|
|||
PBVHTri *tris;
|
||||
SculptVertRef *verts;
|
||||
int tottri, totvert;
|
||||
int tris_size, verts_size;
|
||||
|
||||
// private field
|
||||
intptr_t *loops;
|
||||
int totloop;
|
||||
int totloop, mat_nr;
|
||||
float min[3], max[3];
|
||||
} PBVHTriBuf;
|
||||
|
||||
|
@ -703,7 +704,7 @@ bool BKE_pbvh_curvature_update_get(PBVHNode *node);
|
|||
|
||||
int BKE_pbvh_get_totnodes(PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node);
|
||||
bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node);
|
||||
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
|
|
|
@ -705,9 +705,8 @@ void BKE_pbvh_free(PBVH *pbvh)
|
|||
PBVHNode *node = &pbvh->nodes[i];
|
||||
|
||||
if (node->flag & PBVH_Leaf) {
|
||||
if (node->draw_buffers) {
|
||||
GPU_pbvh_buffers_free(node->draw_buffers);
|
||||
}
|
||||
pbvh_free_all_draw_buffers(node);
|
||||
|
||||
if (node->vert_indices) {
|
||||
MEM_freeN((void *)node->vert_indices);
|
||||
}
|
||||
|
@ -1320,10 +1319,23 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
node->totprim,
|
||||
pbvh->mesh);
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags &
|
||||
PBVH_DYNTOPO_SMOOTH_SHADING);
|
||||
case PBVH_BMESH: {
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
|
||||
node->tot_mat_draw_buffers = node->tot_tri_buffers;
|
||||
|
||||
if (node->tot_tri_buffers) {
|
||||
node->mat_draw_buffers = MEM_malloc_arrayN(
|
||||
node->tot_tri_buffers, sizeof(void *), "node->mat_draw_buffers");
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->tot_tri_buffers; i++) {
|
||||
node->mat_draw_buffers[i] = GPU_pbvh_bmesh_buffers_build(pbvh->flags &
|
||||
PBVH_DYNTOPO_SMOOTH_SHADING);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1357,19 +1369,41 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
update_flags);
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
GPU_pbvh_bmesh_buffers_update(node->draw_buffers,
|
||||
pbvh->bm,
|
||||
node->bm_faces,
|
||||
node->bm_unique_verts,
|
||||
node->bm_other_verts,
|
||||
node->tribuf,
|
||||
update_flags,
|
||||
pbvh->cd_vert_node_offset,
|
||||
pbvh->face_sets_color_seed,
|
||||
pbvh->face_sets_color_default,
|
||||
data->flat_vcol_shading,
|
||||
data->active_vcol_only);
|
||||
if (BKE_pbvh_bmesh_check_tris(pbvh, node)) {
|
||||
pbvh_free_all_draw_buffers(node);
|
||||
node->tot_mat_draw_buffers = node->tot_tri_buffers;
|
||||
|
||||
if (node->tot_tri_buffers) {
|
||||
node->mat_draw_buffers = MEM_malloc_arrayN(
|
||||
node->tot_tri_buffers, sizeof(void *), "node->mat_draw_buffers");
|
||||
|
||||
for (int i = 0; i < node->tot_tri_buffers; i++) {
|
||||
node->mat_draw_buffers[i] = GPU_pbvh_bmesh_buffers_build(
|
||||
pbvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->tot_mat_draw_buffers; i++) {
|
||||
if (i >= node->tot_tri_buffers) {
|
||||
printf("pbvh corruption!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
GPU_pbvh_bmesh_buffers_update(node->mat_draw_buffers[i],
|
||||
pbvh->bm,
|
||||
node->bm_faces,
|
||||
node->bm_unique_verts,
|
||||
node->bm_other_verts,
|
||||
node->tri_buffers + i,
|
||||
update_flags,
|
||||
pbvh->cd_vert_node_offset,
|
||||
pbvh->face_sets_color_seed,
|
||||
pbvh->face_sets_color_default,
|
||||
data->flat_vcol_shading,
|
||||
data->active_vcol_only,
|
||||
node->tri_buffers[i].mat_nr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1392,6 +1426,36 @@ void BKE_pbvh_set_flat_vcol_shading(PBVH *pbvh, bool value)
|
|||
pbvh->flat_vcol_shading = value;
|
||||
}
|
||||
|
||||
void pbvh_free_all_draw_buffers(PBVHNode *node)
|
||||
{
|
||||
if (node->draw_buffers) {
|
||||
GPU_pbvh_buffers_free(node->draw_buffers);
|
||||
node->draw_buffers = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->tot_mat_draw_buffers; i++) {
|
||||
GPU_pbvh_buffers_free(node->mat_draw_buffers[i]);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(node->mat_draw_buffers);
|
||||
|
||||
node->mat_draw_buffers = NULL;
|
||||
node->tot_mat_draw_buffers = 0;
|
||||
}
|
||||
|
||||
void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
if (pbvh->type == PBVH_GRIDS) {
|
||||
GPU_pbvh_grid_buffers_update_free(
|
||||
node->draw_buffers, pbvh->grid_flag_mats, node->prim_indices);
|
||||
}
|
||||
else if (pbvh->type == PBVH_BMESH) {
|
||||
for (int i = 0; i < node->tot_mat_draw_buffers; i++) {
|
||||
GPU_pbvh_bmesh_buffers_update_free(node->mat_draw_buffers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pbvh_update_draw_buffers(
|
||||
PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag, bool active_vcol_only)
|
||||
{
|
||||
|
@ -1400,17 +1464,10 @@ static void pbvh_update_draw_buffers(
|
|||
for (int n = 0; n < totnode; n++) {
|
||||
PBVHNode *node = nodes[n];
|
||||
if (node->flag & PBVH_RebuildDrawBuffers) {
|
||||
GPU_pbvh_buffers_free(node->draw_buffers);
|
||||
node->draw_buffers = NULL;
|
||||
pbvh_free_all_draw_buffers(node);
|
||||
}
|
||||
else if ((node->flag & PBVH_UpdateDrawBuffers) && node->draw_buffers) {
|
||||
if (pbvh->type == PBVH_GRIDS) {
|
||||
GPU_pbvh_grid_buffers_update_free(
|
||||
node->draw_buffers, pbvh->grid_flag_mats, node->prim_indices);
|
||||
}
|
||||
else if (pbvh->type == PBVH_BMESH) {
|
||||
GPU_pbvh_bmesh_buffers_update_free(node->draw_buffers);
|
||||
}
|
||||
else if ((node->flag & PBVH_UpdateDrawBuffers)) {
|
||||
pbvh_update_free_all_draw_buffers(pbvh, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1449,7 +1506,13 @@ static void pbvh_update_draw_buffers(
|
|||
|
||||
if (node->flag & PBVH_UpdateDrawBuffers) {
|
||||
/* Flush buffers uses OpenGL, so not in parallel. */
|
||||
GPU_pbvh_buffers_update_flush(node->draw_buffers);
|
||||
if (node->draw_buffers) {
|
||||
GPU_pbvh_buffers_update_flush(node->draw_buffers);
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->tot_mat_draw_buffers; i++) {
|
||||
GPU_pbvh_buffers_update_flush(node->mat_draw_buffers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
node->flag &= ~(PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers);
|
||||
|
@ -2898,7 +2961,13 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
|
|||
for (int i = 0; i < totnode; i++) {
|
||||
PBVHNode *node = nodes[i];
|
||||
if (!(node->flag & PBVH_FullyHidden)) {
|
||||
draw_fn(user_data, node->draw_buffers);
|
||||
if (node->draw_buffers) {
|
||||
draw_fn(user_data, node->draw_buffers);
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->tot_mat_draw_buffers; i++) {
|
||||
draw_fn(user_data, node->mat_draw_buffers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ Topology rake:
|
|||
#include "PIL_time.h"
|
||||
#include "atomic_ops.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_pbvh.h"
|
||||
|
@ -506,10 +508,7 @@ static void pbvh_bmesh_node_split(
|
|||
n->bm_other_verts = NULL;
|
||||
n->layer_disp = NULL;
|
||||
|
||||
if (n->draw_buffers) {
|
||||
GPU_pbvh_buffers_free(n->draw_buffers);
|
||||
n->draw_buffers = NULL;
|
||||
}
|
||||
pbvh_free_all_draw_buffers(n);
|
||||
n->flag &= ~PBVH_Leaf;
|
||||
|
||||
/* Recurse */
|
||||
|
@ -3999,6 +3998,20 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
return modified;
|
||||
}
|
||||
|
||||
static void pbvh_free_tribuf(PBVHTriBuf *tribuf)
|
||||
{
|
||||
MEM_SAFE_FREE(tribuf->verts);
|
||||
MEM_SAFE_FREE(tribuf->tris);
|
||||
MEM_SAFE_FREE(tribuf->loops);
|
||||
|
||||
tribuf->verts = NULL;
|
||||
tribuf->tris = NULL;
|
||||
tribuf->loops = NULL;
|
||||
|
||||
tribuf->verts_size = 0;
|
||||
tribuf->tris_size = 0;
|
||||
}
|
||||
|
||||
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
|
@ -4009,12 +4022,21 @@ PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node)
|
|||
void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
if (node->tribuf) {
|
||||
MEM_SAFE_FREE(node->tribuf->verts);
|
||||
MEM_SAFE_FREE(node->tribuf->tris);
|
||||
MEM_SAFE_FREE(node->tribuf->loops);
|
||||
pbvh_free_tribuf(node->tribuf);
|
||||
MEM_freeN(node->tribuf);
|
||||
node->tribuf = NULL;
|
||||
}
|
||||
|
||||
if (node->tri_buffers) {
|
||||
for (int i = 0; i < node->tot_tri_buffers; i++) {
|
||||
pbvh_free_tribuf(node->tri_buffers + i);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(node->tri_buffers);
|
||||
|
||||
node->tri_buffers = NULL;
|
||||
node->tot_tri_buffers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4138,41 +4160,87 @@ static bool pbvh_bmesh_split_tris(PBVH *pbvh, PBVHNode *node)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT BLI_INLINE PBVHTri *pbvh_tribuf_add_tri(PBVHTriBuf *tribuf)
|
||||
{
|
||||
tribuf->tottri++;
|
||||
|
||||
if (tribuf->tottri >= tribuf->tris_size) {
|
||||
size_t newsize = (size_t)32 + (size_t)tribuf->tris_size + (size_t)(tribuf->tris_size >> 1);
|
||||
|
||||
if (!tribuf->tris) {
|
||||
tribuf->tris = MEM_mallocN(sizeof(*tribuf->tris) * newsize, "tribuf tris");
|
||||
}
|
||||
else {
|
||||
tribuf->tris = MEM_reallocN_id(tribuf->tris, sizeof(*tribuf->tris) * newsize, "tribuf tris");
|
||||
}
|
||||
|
||||
tribuf->tris_size = newsize;
|
||||
}
|
||||
|
||||
return tribuf->tris + tribuf->tottri - 1;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT BLI_INLINE void pbvh_tribuf_add_vert(PBVHTriBuf *tribuf, SculptVertRef vertex)
|
||||
{
|
||||
tribuf->totvert++;
|
||||
|
||||
if (tribuf->totvert >= tribuf->verts_size) {
|
||||
size_t newsize = (size_t)32 + (size_t)(tribuf->verts_size << 1);
|
||||
|
||||
if (!tribuf->verts) {
|
||||
tribuf->verts = MEM_mallocN(sizeof(*tribuf->verts) * newsize, "tribuf verts");
|
||||
}
|
||||
else {
|
||||
tribuf->verts = MEM_reallocN_id(
|
||||
tribuf->verts, sizeof(*tribuf->verts) * newsize, "tribuf verts");
|
||||
}
|
||||
|
||||
tribuf->verts_size = newsize;
|
||||
}
|
||||
|
||||
tribuf->verts[tribuf->totvert - 1] = vertex;
|
||||
}
|
||||
|
||||
/* In order to perform operations on the original node coordinates
|
||||
* (currently just raycast), store the node's triangles and vertices.
|
||||
*
|
||||
* Skips triangles that are hidden. */
|
||||
void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
||||
ATTR_NO_OPT bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
BMesh *bm = pbvh->bm;
|
||||
|
||||
if (!(node->flag & PBVH_UpdateTris) && node->tribuf) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
GHash *vmap = BLI_ghash_ptr_new("pbvh_bmesh.c vmap");
|
||||
GHash *mat_vmaps[MAXMAT];
|
||||
|
||||
int mat_map[MAXMAT];
|
||||
|
||||
for (int i = 0; i < MAXMAT; i++) {
|
||||
mat_map[i] = -1;
|
||||
mat_vmaps[i] = NULL;
|
||||
}
|
||||
|
||||
if (node->tribuf) {
|
||||
MEM_SAFE_FREE(node->tribuf->verts);
|
||||
MEM_SAFE_FREE(node->tribuf->tris);
|
||||
MEM_SAFE_FREE(node->tribuf->loops);
|
||||
|
||||
node->tribuf->tottri = 0;
|
||||
node->tribuf->totvert = 0;
|
||||
node->tribuf->totloop = 0;
|
||||
pbvh_free_tribuf(node->tribuf);
|
||||
}
|
||||
else {
|
||||
node->tribuf = MEM_callocN(sizeof(*node->tribuf), "node->tribuf");
|
||||
node->tribuf->loops = NULL;
|
||||
node->tribuf->totloop = 0;
|
||||
}
|
||||
|
||||
PBVHTriBuf *tribufs = NULL; // material-specific tribuffers
|
||||
BLI_array_declare(tribufs);
|
||||
|
||||
node->tribuf->mat_nr = 0;
|
||||
node->tribuf->tottri = 0;
|
||||
node->tribuf->totvert = 0;
|
||||
node->tribuf->totloop = 0;
|
||||
|
||||
node->flag &= ~PBVH_UpdateTris;
|
||||
PBVHTri *tris = NULL;
|
||||
SculptVertRef *verts = NULL;
|
||||
|
||||
BLI_array_declare(tris);
|
||||
BLI_array_declare(verts);
|
||||
|
||||
GHash *vmap = BLI_ghash_ptr_new("pbvh_bmesh.c vmap");
|
||||
BMFace *f;
|
||||
|
||||
float min[3], max[3];
|
||||
|
@ -4180,7 +4248,26 @@ void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
|||
INIT_MINMAX(min, max);
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
PBVHTri tri = {0};
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PBVHTri *tri = pbvh_tribuf_add_tri(node->tribuf);
|
||||
const int mat_nr = f->mat_nr;
|
||||
|
||||
if (mat_map[mat_nr] == -1) {
|
||||
PBVHTriBuf _tribuf = {0};
|
||||
|
||||
_tribuf.mat_nr = mat_nr;
|
||||
|
||||
mat_map[mat_nr] = BLI_array_len(tribufs);
|
||||
mat_vmaps[mat_nr] = BLI_ghash_ptr_new("pbvh_bmesh.c vmap");
|
||||
|
||||
BLI_array_append(tribufs, _tribuf);
|
||||
}
|
||||
|
||||
PBVHTriBuf *mat_tribuf = tribufs + mat_map[mat_nr];
|
||||
PBVHTri *mat_tri = pbvh_tribuf_add_tri(mat_tribuf);
|
||||
|
||||
BMLoop *l = f->l_first;
|
||||
int j = 0;
|
||||
|
@ -4193,11 +4280,23 @@ void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
|||
|
||||
minmax_v3v3_v3(min, max, l->v->co);
|
||||
|
||||
*val = (void *)BLI_array_len(verts);
|
||||
BLI_array_append(verts, sv);
|
||||
*val = (void *)node->tribuf->totvert;
|
||||
pbvh_tribuf_add_vert(node->tribuf, sv);
|
||||
}
|
||||
|
||||
tri.v[j] = (intptr_t)val[0];
|
||||
tri->v[j] = (intptr_t)val[0];
|
||||
|
||||
val = NULL;
|
||||
if (!BLI_ghash_ensure_p(mat_vmaps[mat_nr], l->v, &val)) {
|
||||
SculptVertRef sv = {(intptr_t)l->v};
|
||||
|
||||
minmax_v3v3_v3(min, max, l->v->co);
|
||||
|
||||
*val = (void *)mat_tribuf->totvert;
|
||||
pbvh_tribuf_add_vert(mat_tribuf, sv);
|
||||
}
|
||||
|
||||
mat_tri->v[j] = (intptr_t)val[0];
|
||||
|
||||
j++;
|
||||
|
||||
|
@ -4208,19 +4307,15 @@ void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
|||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
|
||||
copy_v3_v3(tri.no, f->no);
|
||||
tri.f.i = (intptr_t)f;
|
||||
|
||||
BLI_array_append(tris, tri);
|
||||
copy_v3_v3(tri->no, f->no);
|
||||
tri->f.i = (intptr_t)f;
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
bm->elem_index_dirty |= BM_VERT;
|
||||
|
||||
node->tribuf->tris = tris;
|
||||
node->tribuf->tottri = BLI_array_len(tris);
|
||||
node->tribuf->verts = verts;
|
||||
node->tribuf->totvert = BLI_array_len(verts);
|
||||
node->tri_buffers = tribufs;
|
||||
node->tot_tri_buffers = BLI_array_len(tribufs);
|
||||
|
||||
if (node->tribuf->totvert) {
|
||||
copy_v3_v3(node->tribuf->min, min);
|
||||
|
@ -4232,6 +4327,13 @@ void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
|||
}
|
||||
|
||||
BLI_ghash_free(vmap, NULL, NULL);
|
||||
for (int i = 0; i < MAXMAT; i++) {
|
||||
if (mat_vmaps[i]) {
|
||||
BLI_ghash_free(mat_vmaps[i], NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int pbvh_count_subtree_verts(PBVH *pbvh, PBVHNode *n)
|
||||
|
@ -4322,7 +4424,8 @@ static void BKE_pbvh_bmesh_correct_tree(PBVH *pbvh, PBVHNode *node, PBVHNode *pa
|
|||
BMVert *v;
|
||||
|
||||
node->children_offset = 0;
|
||||
node->draw_buffers = NULL;
|
||||
|
||||
pbvh_free_all_draw_buffers(node);
|
||||
|
||||
// rebuild bm_other_verts
|
||||
BMFace *f;
|
||||
|
@ -4433,10 +4536,9 @@ static void pbvh_bmesh_join_nodes(PBVH *bvh)
|
|||
MEM_freeN(n->layer_disp);
|
||||
n->layer_disp = NULL;
|
||||
}
|
||||
if (n->draw_buffers) {
|
||||
GPU_pbvh_buffers_free(n->draw_buffers);
|
||||
n->draw_buffers = NULL;
|
||||
}
|
||||
|
||||
pbvh_free_all_draw_buffers(n);
|
||||
|
||||
if (n->vert_indices) {
|
||||
MEM_freeN((void *)n->vert_indices);
|
||||
n->vert_indices = NULL;
|
||||
|
@ -5188,7 +5290,8 @@ BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh)
|
|||
f1->head.index = f2->head.index = BLI_array_len(faces);
|
||||
BLI_array_append(faces, f2);
|
||||
|
||||
// CustomData_bmesh_copy_data(&pbvh->bm->pdata, &bm2->pdata, f1->head.data, &f2->head.data);
|
||||
// CustomData_bmesh_copy_data(&pbvh->bm->pdata, &bm2->pdata, f1->head.data,
|
||||
// &f2->head.data);
|
||||
BM_elem_attrs_copy_ex(pbvh->bm, bm2, f1, f2, 0, 0L);
|
||||
|
||||
BMLoop *l2 = f2->l_first;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
|
@ -37,6 +38,8 @@ typedef struct {
|
|||
struct PBVHNode {
|
||||
/* Opaque handle for drawing code */
|
||||
struct GPU_PBVH_Buffers *draw_buffers;
|
||||
struct GPU_PBVH_Buffers **mat_draw_buffers; // currently only used by pbvh_bmesh
|
||||
int tot_mat_draw_buffers;
|
||||
|
||||
int id;
|
||||
|
||||
|
@ -107,7 +110,9 @@ struct PBVHNode {
|
|||
TableGSet *bm_unique_verts;
|
||||
TableGSet *bm_other_verts;
|
||||
|
||||
PBVHTriBuf *tribuf;
|
||||
PBVHTriBuf *tribuf; // all triangles
|
||||
PBVHTriBuf *tri_buffers; // tribuffers, one per material used
|
||||
int tot_tri_buffers;
|
||||
|
||||
int updategen;
|
||||
|
||||
|
@ -259,3 +264,6 @@ bool pbvh_bmesh_node_nearest_to_ray(PBVH *pbvh,
|
|||
int stroke_id);
|
||||
|
||||
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
|
||||
|
||||
void pbvh_free_all_draw_buffers(PBVHNode *node);
|
||||
void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node);
|
||||
|
|
|
@ -104,7 +104,8 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
int face_sets_color_seed,
|
||||
int face_sets_color_default,
|
||||
bool flat_vcol,
|
||||
bool active_vcol_only);
|
||||
bool active_vcol_only,
|
||||
short mat_nr);
|
||||
|
||||
void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
struct SubdivCCG *subdiv_ccg,
|
||||
|
|
|
@ -1131,13 +1131,13 @@ static int gpu_bmesh_vert_visible_count(TableGSet *bm_unique_verts, TableGSet *b
|
|||
}
|
||||
|
||||
/* Return the total number of visible faces */
|
||||
static int gpu_bmesh_face_visible_count(TableGSet *bm_faces)
|
||||
static int gpu_bmesh_face_visible_count(TableGSet *bm_faces, int mat_nr)
|
||||
{
|
||||
int totface = 0;
|
||||
BMFace *f;
|
||||
|
||||
TGSET_ITER (f, bm_faces) {
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && f->mat_nr == mat_nr) {
|
||||
totface++;
|
||||
}
|
||||
}
|
||||
|
@ -1394,7 +1394,8 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
|
|||
const int cd_vert_node_offset,
|
||||
int face_sets_color_seed,
|
||||
int face_sets_color_default,
|
||||
bool active_vcol_only)
|
||||
bool active_vcol_only,
|
||||
short mat_nr)
|
||||
{
|
||||
const bool have_uv = CustomData_has_layer(&bm->ldata, CD_MLOOPUV);
|
||||
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
|
||||
|
@ -1415,9 +1416,7 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
|
|||
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
|
||||
|
||||
/* Count visible triangles */
|
||||
tottri = gpu_bmesh_face_visible_count(bm_faces) * 6;
|
||||
|
||||
// XXX disable indexed verts for now
|
||||
tottri = gpu_bmesh_face_visible_count(bm_faces, mat_nr) * 6;
|
||||
totvert = tottri * 3;
|
||||
|
||||
if (!tottri) {
|
||||
|
@ -1452,6 +1451,10 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
|
|||
GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3);
|
||||
|
||||
TGSET_ITER (f, bm_faces) {
|
||||
if (f->mat_nr != mat_nr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_assert(f->len == 3);
|
||||
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
|
@ -1556,44 +1559,28 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
|
|||
buffers->tot_tri = tottri;
|
||||
|
||||
/* Get material index from the last face we iterated on. */
|
||||
buffers->material_index = (f) ? f->mat_nr : 0;
|
||||
buffers->material_index = mat_nr;
|
||||
|
||||
buffers->show_overlay = !empty_mask || !default_face_set;
|
||||
|
||||
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_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
BMesh *bm,
|
||||
TableGSet *bm_faces,
|
||||
TableGSet *bm_unique_verts,
|
||||
TableGSet *bm_other_verts,
|
||||
PBVHTriBuf *tribuf,
|
||||
const int update_flags,
|
||||
const int cd_vert_node_offset,
|
||||
int face_sets_color_seed,
|
||||
int face_sets_color_default,
|
||||
bool flat_vcol,
|
||||
bool active_vcol_only)
|
||||
static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
||||
BMesh *bm,
|
||||
TableGSet *bm_faces,
|
||||
TableGSet *bm_unique_verts,
|
||||
TableGSet *bm_other_verts,
|
||||
PBVHTriBuf *tribuf,
|
||||
const int update_flags,
|
||||
const int cd_vert_node_offset,
|
||||
int face_sets_color_seed,
|
||||
int face_sets_color_default,
|
||||
bool flat_vcol,
|
||||
bool active_vcol_only,
|
||||
short mat_nr)
|
||||
{
|
||||
|
||||
if (flat_vcol && CustomData_has_layer(&bm->vdata, CD_PROP_COLOR)) {
|
||||
GPU_pbvh_bmesh_buffers_update_flat_vcol(buffers,
|
||||
bm,
|
||||
bm_faces,
|
||||
bm_unique_verts,
|
||||
bm_other_verts,
|
||||
update_flags,
|
||||
cd_vert_node_offset,
|
||||
face_sets_color_seed,
|
||||
face_sets_color_default,
|
||||
active_vcol_only);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool have_uv = CustomData_has_layer(&bm->ldata, CD_MLOOPUV);
|
||||
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
|
||||
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
|
||||
|
@ -1613,16 +1600,10 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
|
||||
|
||||
/* Count visible triangles */
|
||||
const bool indexed = buffers->smooth && tribuf && !have_uv;
|
||||
tottri = indexed ? tribuf->tottri : gpu_bmesh_face_visible_count(bm_faces);
|
||||
tottri = tribuf->tottri;
|
||||
|
||||
if (indexed) {
|
||||
/* Count visible vertices */
|
||||
totvert = tribuf->totvert;
|
||||
}
|
||||
else {
|
||||
totvert = tottri * 3;
|
||||
}
|
||||
/* Count visible vertices */
|
||||
totvert = tribuf->totvert;
|
||||
|
||||
if (!tottri) {
|
||||
if (BLI_table_gset_len(bm_faces) != 0) {
|
||||
|
@ -1650,230 +1631,324 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
|
||||
int v_index = 0;
|
||||
|
||||
if (indexed) {
|
||||
/* 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);
|
||||
/* 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);
|
||||
BMFace *f;
|
||||
GPUVertBuf *vert_buf = buffers->vert_buf;
|
||||
GPUVertBuf *vert_buf = buffers->vert_buf;
|
||||
|
||||
#ifdef QUANTIZED_PERF_TEST
|
||||
float min[3];
|
||||
float max[3];
|
||||
float mat[4][4];
|
||||
float imat[4][4];
|
||||
float scale[3];
|
||||
float min[3];
|
||||
float max[3];
|
||||
float mat[4][4];
|
||||
float imat[4][4];
|
||||
float scale[3];
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
for (int i = 0; i < tribuf->totvert; i++) {
|
||||
BMVert *v = (BMVert *)tribuf->verts[i].i;
|
||||
INIT_MINMAX(min, max);
|
||||
for (int i = 0; i < tribuf->totvert; i++) {
|
||||
BMVert *v = (BMVert *)tribuf->verts[i].i;
|
||||
|
||||
minmax_v3v3_v3(min, max, v->co);
|
||||
}
|
||||
minmax_v3v3_v3(min, max, v->co);
|
||||
}
|
||||
|
||||
sub_v3_v3v3(scale, max, min);
|
||||
sub_v3_v3v3(scale, max, min);
|
||||
|
||||
scale[0] = scale[0] != 0.0f ? 1.0f / scale[0] : 0.0f;
|
||||
scale[1] = scale[1] != 0.0f ? 1.0f / scale[1] : 0.0f;
|
||||
scale[2] = scale[2] != 0.0f ? 1.0f / scale[2] : 0.0f;
|
||||
scale[0] = scale[0] != 0.0f ? 1.0f / scale[0] : 0.0f;
|
||||
scale[1] = scale[1] != 0.0f ? 1.0f / scale[1] : 0.0f;
|
||||
scale[2] = scale[2] != 0.0f ? 1.0f / scale[2] : 0.0f;
|
||||
|
||||
memset((float *)mat, 0, sizeof(float) * 16);
|
||||
memset((float *)mat, 0, sizeof(float) * 16);
|
||||
|
||||
mat[0][0] = scale[0];
|
||||
mat[1][1] = scale[1];
|
||||
mat[2][2] = scale[2];
|
||||
mat[0][0] = scale[0];
|
||||
mat[1][1] = scale[1];
|
||||
mat[2][2] = scale[2];
|
||||
|
||||
mat[3][0] = -min[0] * scale[0];
|
||||
mat[3][1] = -min[1] * scale[1];
|
||||
mat[3][2] = -min[2] * scale[2];
|
||||
mat[3][0] = -min[0] * scale[0];
|
||||
mat[3][1] = -min[1] * scale[1];
|
||||
mat[3][2] = -min[2] * scale[2];
|
||||
|
||||
mat[3][3] = 1.0f;
|
||||
mat[3][3] = 1.0f;
|
||||
|
||||
invert_m4_m4(imat, mat);
|
||||
invert_m4_m4(imat, mat);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < tribuf->totvert; i++) {
|
||||
BMVert *v = (BMVert *)tribuf->verts[i].i;
|
||||
for (int i = 0; i < tribuf->totvert; i++) {
|
||||
BMVert *v = (BMVert *)tribuf->verts[i].i;
|
||||
|
||||
#ifdef QUANTIZED_PERF_TEST
|
||||
float co[3];
|
||||
copy_v3_v3(co, v->co);
|
||||
mul_v3_m4v3(co, mat, co);
|
||||
// sub_v3_v3(co, tribuf->min);
|
||||
// mul_v3_v3(co, scale);
|
||||
float co[3];
|
||||
copy_v3_v3(co, v->co);
|
||||
mul_v3_m4v3(co, mat, co);
|
||||
// sub_v3_v3(co, tribuf->min);
|
||||
// mul_v3_v3(co, scale);
|
||||
|
||||
// normal_float_to_short_
|
||||
unsigned short co_short[3];
|
||||
co_short[0] = (unsigned short)(co[0] * 65535.0f);
|
||||
co_short[1] = (unsigned short)(co[1] * 65535.0f);
|
||||
co_short[2] = (unsigned short)(co[2] * 65535.0f);
|
||||
// normal_float_to_short_
|
||||
unsigned short co_short[3];
|
||||
co_short[0] = (unsigned short)(co[0] * 65535.0f);
|
||||
co_short[1] = (unsigned short)(co[1] * 65535.0f);
|
||||
co_short[2] = (unsigned short)(co[2] * 65535.0f);
|
||||
|
||||
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, i, co_short);
|
||||
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, i, co_short);
|
||||
|
||||
signed char no_short[3];
|
||||
// normal_float_to_short_v3(no_short, v->no);
|
||||
no_short[0] = (signed char)(v->no[0] * 127.0f);
|
||||
no_short[1] = (signed char)(v->no[1] * 127.0f);
|
||||
no_short[2] = (signed char)(v->no[2] * 127.0f);
|
||||
signed char no_short[3];
|
||||
// normal_float_to_short_v3(no_short, v->no);
|
||||
no_short[0] = (signed char)(v->no[0] * 127.0f);
|
||||
no_short[1] = (signed char)(v->no[1] * 127.0f);
|
||||
no_short[2] = (signed char)(v->no[2] * 127.0f);
|
||||
|
||||
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, i, no_short);
|
||||
GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, i, no_short);
|
||||
#else
|
||||
gpu_bmesh_vert_to_buffer_copy(v,
|
||||
buffers->vert_buf,
|
||||
i,
|
||||
NULL,
|
||||
NULL,
|
||||
cd_vert_mask_offset,
|
||||
cd_vert_node_offset,
|
||||
show_mask,
|
||||
show_vcol,
|
||||
&empty_mask,
|
||||
cd_vcols,
|
||||
cd_vcol_count);
|
||||
gpu_bmesh_vert_to_buffer_copy(v,
|
||||
buffers->vert_buf,
|
||||
i,
|
||||
NULL,
|
||||
NULL,
|
||||
cd_vert_mask_offset,
|
||||
cd_vert_node_offset,
|
||||
show_mask,
|
||||
show_vcol,
|
||||
&empty_mask,
|
||||
cd_vcols,
|
||||
cd_vcol_count);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf->tris + i;
|
||||
for (int i = 0; i < tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf->tris + i;
|
||||
|
||||
GPU_indexbuf_add_tri_verts(&elb, tri->v[0], tri->v[1], tri->v[2]);
|
||||
GPU_indexbuf_add_tri_verts(&elb, tri->v[0], tri->v[1], tri->v[2]);
|
||||
|
||||
#ifndef QUANTIZED_PERF_TEST
|
||||
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[0], tri->v[1]);
|
||||
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[1], tri->v[2]);
|
||||
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[2], tri->v[0]);
|
||||
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[0], tri->v[1]);
|
||||
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[1], tri->v[2]);
|
||||
GPU_indexbuf_add_line_verts(&elb_lines, tri->v[2], tri->v[0]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
buffers->tot_tri = tottri;
|
||||
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);
|
||||
|
||||
/* Get material index from the last face we iterated on. */
|
||||
buffers->material_index = (f) ? f->mat_nr : 0;
|
||||
buffers->show_overlay = !empty_mask || !default_face_set;
|
||||
|
||||
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
|
||||
|
||||
#ifdef QUANTIZED_PERF_TEST
|
||||
copy_m4_m4(buffers->matrix, imat);
|
||||
#endif
|
||||
if (buffers->index_buf == NULL) {
|
||||
buffers->index_buf = GPU_indexbuf_build(&elb);
|
||||
}
|
||||
else {
|
||||
GPUIndexBufBuilder elb_lines;
|
||||
GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3);
|
||||
BMFace *f;
|
||||
GPU_indexbuf_build_in_place(&elb, buffers->index_buf);
|
||||
}
|
||||
buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
|
||||
|
||||
TGSET_ITER (f, bm_faces) {
|
||||
BLI_assert(f->len == 3);
|
||||
buffers->material_index = mat_nr;
|
||||
buffers->show_overlay = !empty_mask || !default_face_set;
|
||||
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
BMVert *v[3];
|
||||
BMLoop *l[3] = {f->l_first, f->l_first->next, f->l_first->prev};
|
||||
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
|
||||
|
||||
float fmask = 0.0f;
|
||||
int i;
|
||||
#ifdef QUANTIZED_PERF_TEST
|
||||
copy_m4_m4(buffers->matrix, imat);
|
||||
#endif
|
||||
}
|
||||
|
||||
BM_face_as_array_vert_tri(f, v);
|
||||
/* 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_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
BMesh *bm,
|
||||
TableGSet *bm_faces,
|
||||
TableGSet *bm_unique_verts,
|
||||
TableGSet *bm_other_verts,
|
||||
PBVHTriBuf *tribuf,
|
||||
const int update_flags,
|
||||
const int cd_vert_node_offset,
|
||||
int face_sets_color_seed,
|
||||
int face_sets_color_default,
|
||||
bool flat_vcol,
|
||||
bool active_vcol_only,
|
||||
short mat_nr)
|
||||
{
|
||||
|
||||
/* Average mask value */
|
||||
for (i = 0; i < 3; i++) {
|
||||
fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
|
||||
}
|
||||
fmask /= 3.0f;
|
||||
if (flat_vcol && CustomData_has_layer(&bm->vdata, CD_PROP_COLOR)) {
|
||||
GPU_pbvh_bmesh_buffers_update_flat_vcol(buffers,
|
||||
bm,
|
||||
bm_faces,
|
||||
bm_unique_verts,
|
||||
bm_other_verts,
|
||||
update_flags,
|
||||
cd_vert_node_offset,
|
||||
face_sets_color_seed,
|
||||
face_sets_color_default,
|
||||
active_vcol_only,
|
||||
mat_nr);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
const bool have_uv = CustomData_has_layer(&bm->ldata, CD_MLOOPUV);
|
||||
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
|
||||
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
|
||||
const bool show_face_sets = CustomData_has_layer(&bm->pdata, CD_SCULPT_FACE_SETS) &&
|
||||
(update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0;
|
||||
|
||||
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
int tottri, totvert;
|
||||
bool empty_mask = true;
|
||||
BMFace *f = NULL;
|
||||
int cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
|
||||
int cd_fset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
|
||||
|
||||
if (show_face_sets && cd_fset_offset >= 0) {
|
||||
const int fset = BM_ELEM_CD_GET_INT(f, cd_fset_offset);
|
||||
int cd_vcols[MAX_MCOL];
|
||||
int cd_vcol_layers[MAX_MCOL];
|
||||
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (fset != face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
|
||||
default_face_set = false;
|
||||
}
|
||||
}
|
||||
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
|
||||
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
float *no = buffers->smooth ? v[i]->no : f->no;
|
||||
/* Count visible triangles */
|
||||
if (buffers->smooth && !have_uv) {
|
||||
GPU_pbvh_bmesh_buffers_update_indexed(buffers,
|
||||
bm,
|
||||
bm_faces,
|
||||
bm_unique_verts,
|
||||
bm_other_verts,
|
||||
tribuf,
|
||||
update_flags,
|
||||
cd_vert_node_offset,
|
||||
face_sets_color_seed,
|
||||
face_sets_color_default,
|
||||
flat_vcol,
|
||||
active_vcol_only,
|
||||
mat_nr);
|
||||
return;
|
||||
}
|
||||
|
||||
gpu_bmesh_vert_to_buffer_copy(v[i],
|
||||
buffers->vert_buf,
|
||||
v_index,
|
||||
no,
|
||||
&fmask,
|
||||
cd_vert_mask_offset,
|
||||
cd_vert_node_offset,
|
||||
show_mask,
|
||||
false,
|
||||
&empty_mask,
|
||||
NULL,
|
||||
0);
|
||||
tottri = gpu_bmesh_face_visible_count(bm_faces, mat_nr);
|
||||
totvert = tottri * 3;
|
||||
|
||||
if (cd_vcol_count >= 0) {
|
||||
for (int j = 0; j < cd_vcol_count; j++) {
|
||||
MPropCol *mp = BM_ELEM_CD_GET_VOID_P(l[i]->v, cd_vcols[j]);
|
||||
ushort vcol[4];
|
||||
if (!tottri) {
|
||||
/* empty node (i.e. not just hidden)? */
|
||||
if (!BLI_table_gset_len(bm_faces) != 0) {
|
||||
buffers->clear_bmesh_on_flush = true;
|
||||
}
|
||||
|
||||
// printf(
|
||||
// "%.2f %.2f %.2f %.2f\n", mp->color[0], mp->color[1], mp->color[2],
|
||||
// mp->color[3]);
|
||||
vcol[0] = unit_float_to_ushort_clamp(mp->color[0]);
|
||||
vcol[1] = unit_float_to_ushort_clamp(mp->color[1]);
|
||||
vcol[2] = unit_float_to_ushort_clamp(mp->color[2]);
|
||||
vcol[3] = unit_float_to_ushort_clamp(mp->color[3]);
|
||||
buffers->tot_tri = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[j], v_index, vcol);
|
||||
}
|
||||
}
|
||||
else if (cd_mcol_offset >= 0) {
|
||||
ushort vcol[4];
|
||||
/* TODO, make mask layer optional for bmesh buffer */
|
||||
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
|
||||
const int cd_mcol_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
|
||||
const int cd_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
|
||||
|
||||
MLoopCol *ml = BM_ELEM_CD_GET_VOID_P(l[i], cd_mcol_offset);
|
||||
bool default_face_set = true;
|
||||
|
||||
vcol[0] = ml->r * 257;
|
||||
vcol[1] = ml->g * 257;
|
||||
vcol[2] = ml->b * 257;
|
||||
vcol[3] = ml->a * 257;
|
||||
/* Fill vertex buffer */
|
||||
if (!gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
|
||||
/* Memory map failed */
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], v_index, vcol);
|
||||
}
|
||||
int v_index = 0;
|
||||
|
||||
if (have_uv) {
|
||||
MLoopUV *mu = BM_ELEM_CD_GET_VOID_P(l[i], cd_uv_offset);
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.uv, v_index, mu->uv);
|
||||
}
|
||||
GPUIndexBufBuilder elb_lines;
|
||||
GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3);
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, v_index, face_set_color);
|
||||
TGSET_ITER (f, bm_faces) {
|
||||
BLI_assert(f->len == 3);
|
||||
if (f->mat_nr != mat_nr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
v_index++;
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
BMVert *v[3];
|
||||
BMLoop *l[3] = {f->l_first, f->l_first->next, f->l_first->prev};
|
||||
|
||||
float fmask = 0.0f;
|
||||
int i;
|
||||
|
||||
BM_face_as_array_vert_tri(f, v);
|
||||
|
||||
/* 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);
|
||||
|
||||
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
|
||||
if (show_face_sets && cd_fset_offset >= 0) {
|
||||
const int fset = BM_ELEM_CD_GET_INT(f, cd_fset_offset);
|
||||
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (fset != face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
|
||||
default_face_set = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
float *no = buffers->smooth ? v[i]->no : f->no;
|
||||
|
||||
gpu_bmesh_vert_to_buffer_copy(v[i],
|
||||
buffers->vert_buf,
|
||||
v_index,
|
||||
no,
|
||||
&fmask,
|
||||
cd_vert_mask_offset,
|
||||
cd_vert_node_offset,
|
||||
show_mask,
|
||||
false,
|
||||
&empty_mask,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (cd_vcol_count >= 0) {
|
||||
for (int j = 0; j < cd_vcol_count; j++) {
|
||||
MPropCol *mp = BM_ELEM_CD_GET_VOID_P(l[i]->v, cd_vcols[j]);
|
||||
ushort vcol[4];
|
||||
|
||||
// printf(
|
||||
// "%.2f %.2f %.2f %.2f\n", mp->color[0], mp->color[1], mp->color[2],
|
||||
// mp->color[3]);
|
||||
vcol[0] = unit_float_to_ushort_clamp(mp->color[0]);
|
||||
vcol[1] = unit_float_to_ushort_clamp(mp->color[1]);
|
||||
vcol[2] = unit_float_to_ushort_clamp(mp->color[2]);
|
||||
vcol[3] = unit_float_to_ushort_clamp(mp->color[3]);
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[j], v_index, vcol);
|
||||
}
|
||||
}
|
||||
else if (cd_mcol_offset >= 0) {
|
||||
ushort vcol[4];
|
||||
|
||||
MLoopCol *ml = BM_ELEM_CD_GET_VOID_P(l[i], cd_mcol_offset);
|
||||
|
||||
vcol[0] = ml->r * 257;
|
||||
vcol[1] = ml->g * 257;
|
||||
vcol[2] = ml->b * 257;
|
||||
vcol[3] = ml->a * 257;
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col[0], v_index, vcol);
|
||||
}
|
||||
|
||||
if (have_uv) {
|
||||
MLoopUV *mu = BM_ELEM_CD_GET_VOID_P(l[i], cd_uv_offset);
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.uv, v_index, mu->uv);
|
||||
}
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, v_index, face_set_color);
|
||||
|
||||
v_index++;
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
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 || !default_face_set;
|
||||
|
||||
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
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 = mat_nr;
|
||||
buffers->show_overlay = !empty_mask || !default_face_set;
|
||||
|
||||
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
Loading…
Reference in New Issue