Sculpt: various uv-related fixed
* The dyntopo collapse function now properly snaps UVs, including at island boundaries. * PBVHTriBufs are now split by UVs (and face sets); this turned out to be surprising easy. * Also fixed a few bugs relating to hiding/revealing stuff.
This commit is contained in:
parent
c2f2a8260c
commit
e11ba956d2
|
@ -505,6 +505,7 @@ void BKE_pbvh_bmesh_update_all_valence(PBVH *pbvh);
|
|||
void BKE_pbvh_bmesh_flag_all_disk_sort(PBVH *pbvh);
|
||||
bool BKE_pbvh_bmesh_mark_update_valence(PBVH *pbvh, SculptVertRef vertex);
|
||||
|
||||
void BKE_pbvh_node_mark_update_triangulation(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_original_update(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node);
|
||||
void BKE_pbvh_update_all_tri_areas(PBVH *pbvh);
|
||||
|
@ -642,7 +643,8 @@ typedef struct PBVHVertexIter {
|
|||
bool visible;
|
||||
} PBVHVertexIter;
|
||||
|
||||
#define BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v) ((MSculptVert *)BM_ELEM_CD_GET_VOID_P(v, cd_sculpt_vert))
|
||||
#define BKE_PBVH_SCULPTVERT(cd_sculpt_vert, v) \
|
||||
((MSculptVert *)BM_ELEM_CD_GET_VOID_P(v, cd_sculpt_vert))
|
||||
|
||||
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
|
||||
|
||||
|
@ -851,7 +853,7 @@ void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry);
|
|||
#if 0
|
||||
typedef enum {
|
||||
SCULPT_TEXTURE_UV = 1 << 0, // per-uv
|
||||
// SCULPT_TEXTURE_PTEX?
|
||||
SCULPT_TEXTURE_GRIDS = 1<<1
|
||||
} SculptTextureType;
|
||||
|
||||
typedef int TexLayerRef;
|
||||
|
@ -870,6 +872,8 @@ typedef struct SculptTextureDef {
|
|||
|
||||
void (*build_begin)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
|
||||
void (*calc_bounds)(PBVH *pbvh, PBVHNode *node, float r_min[3], float r_max[3], TexLayerRef vdm);
|
||||
|
||||
/*vdms can cache data per node, which is freed to maintain memory limit.
|
||||
they store cache in the same structure they return in buildNodeData.*/
|
||||
void (*freeCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
|
@ -879,6 +883,8 @@ typedef struct SculptTextureDef {
|
|||
void *(*buildNodeData)(PBVH *pbvh, PBVHNode *node);
|
||||
bool (*validate)(PBVH *pbvh, TexLayerRef vdm);
|
||||
|
||||
void (*setVertexCos)(PBVH *pbvh, PBVHNode *node, SculptVertRef *verts, int totvert, TexLayerRef vdm);
|
||||
|
||||
void (*getPointsFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
|
@ -924,7 +930,7 @@ typedef struct SculptTextureDef {
|
|||
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
|
||||
/*displacement texture stuff*/
|
||||
// can be tangent, object space displacement, whatever
|
||||
// can be tangent, object space displacement
|
||||
void (*worldToDelta)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
void (*deltaToWorld)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
} SculptDisplacementDef;
|
||||
|
|
|
@ -298,6 +298,7 @@ static bool check_builtin_init()
|
|||
SETCAT(topology_rake_projection, "Smoothing");
|
||||
SETCAT(topology_rake_use_spacing, "Smoothing");
|
||||
SETCAT(topology_rake_spacing, "Smoothing");
|
||||
SETCAT(topology_rake_mode, "Smoothing");
|
||||
|
||||
SETCAT(boundary_smooth, "Smoothing");
|
||||
SETCAT(fset_slide, "Smoothing");
|
||||
|
@ -1367,6 +1368,7 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
case SCULPT_TOOL_SIMPLIFY:
|
||||
SHOWCTX(autosmooth);
|
||||
SHOWCTX(topology_rake);
|
||||
SHOWCTX(topology_rake_mode);
|
||||
break;
|
||||
case SCULPT_TOOL_LAYER:
|
||||
SHOWWRK(use_persistent);
|
||||
|
|
|
@ -3643,6 +3643,20 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
return;
|
||||
}
|
||||
|
||||
int uvidx = pbvh->bm->ldata.typemap[CD_MLOOPUV];
|
||||
CustomDataLayer *uv_layer = NULL;
|
||||
int totuv = 0;
|
||||
|
||||
if (uvidx >= 0) {
|
||||
uv_layer = pbvh->bm->ldata.layers + uvidx;
|
||||
totuv = 0;
|
||||
|
||||
while (uvidx < pbvh->bm->ldata.totlayer && pbvh->bm->ldata.layers[uvidx].type == CD_MLOOPUV) {
|
||||
uvidx++;
|
||||
totuv++;
|
||||
}
|
||||
}
|
||||
|
||||
/*have to check edge flags directly, vertex flag test above isn't specific enough and
|
||||
can sometimes let bad edges through*/
|
||||
if ((mv1->flag & SCULPTVERT_SHARP_BOUNDARY) && (e->head.hflag & BM_ELEM_SMOOTH)) {
|
||||
|
@ -3783,72 +3797,109 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
|
||||
CustomData_bmesh_interp(&pbvh->bm->vdata, v_blocks, v_ws, NULL, 2, v_conn->head.data);
|
||||
BM_ELEM_CD_SET_INT(v_conn, pbvh->cd_vert_node_offset, ni_conn);
|
||||
}
|
||||
|
||||
BMLoop **ls = NULL;
|
||||
void **blocks = NULL;
|
||||
float *ws = NULL;
|
||||
|
||||
BLI_array_staticdeclare(ls, 64);
|
||||
BLI_array_staticdeclare(blocks, 64);
|
||||
BLI_array_staticdeclare(ws, 64);
|
||||
// deal with UVs
|
||||
if (e->l) {
|
||||
const int lflag = BM_ELEM_TAG_ALT;
|
||||
|
||||
int totl = 0;
|
||||
BMLoop *l = e->l;
|
||||
|
||||
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_del) {
|
||||
MSculptVert *mv_l = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->next->v);
|
||||
MV_ADD_FLAG(mv_l, mupdateflag);
|
||||
for (int step = 0; step < 2; step++) {
|
||||
BMVert *v = step ? e->v2 : e->v1;
|
||||
BMEdge *e2 = v->e;
|
||||
|
||||
BLI_array_append(ls, l);
|
||||
totl++;
|
||||
}
|
||||
BM_LOOPS_OF_VERT_ITER_END;
|
||||
if (!e2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
|
||||
MSculptVert *mv_l = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, l->next->v);
|
||||
MV_ADD_FLAG(mv_l, mupdateflag);
|
||||
do {
|
||||
BMLoop *l2 = e2->l;
|
||||
|
||||
BLI_array_append(ls, l);
|
||||
totl++;
|
||||
}
|
||||
BM_LOOPS_OF_VERT_ITER_END;
|
||||
|
||||
float w = totl > 0 ? 1.0f / (float)(totl) : 1.0f;
|
||||
|
||||
for (int i = 0; i < totl; i++) {
|
||||
BLI_array_append(blocks, ls[i]->head.data);
|
||||
BLI_array_append(ws, w);
|
||||
}
|
||||
|
||||
// snap customdata
|
||||
if (totl > 0) {
|
||||
CustomData_bmesh_interp(
|
||||
&pbvh->bm->ldata, (const void **)blocks, ws, NULL, totl, ls[0]->head.data);
|
||||
//*
|
||||
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_del) {
|
||||
BMLoop *l2 = l->v != v_del ? l->next : l;
|
||||
|
||||
if (l2 == ls[0]) {
|
||||
if (!l2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CustomData_bmesh_copy_data(
|
||||
&pbvh->bm->ldata, &pbvh->bm->ldata, ls[0]->head.data, &l2->head.data);
|
||||
}
|
||||
BM_LOOPS_OF_VERT_ITER_END;
|
||||
do {
|
||||
bool ok = true;
|
||||
BMLoop *l3 = l2->v != v ? l2->next : l2;
|
||||
|
||||
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
|
||||
BMLoop *l2 = l->v != v_conn ? l->next : l;
|
||||
|
||||
if (l2 == ls[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CustomData_bmesh_copy_data(
|
||||
&pbvh->bm->ldata, &pbvh->bm->ldata, ls[0]->head.data, &l2->head.data);
|
||||
}
|
||||
BM_LOOPS_OF_VERT_ITER_END;
|
||||
//*/
|
||||
/* store visit bits for each uv layer in l3->head.index */
|
||||
l3->head.index = 0;
|
||||
} while ((l2 = l2->radial_next) != e2->l);
|
||||
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v)) != v->e);
|
||||
}
|
||||
|
||||
float(*uv)[2] = alloca(sizeof(float) * 4 * totuv);
|
||||
|
||||
do {
|
||||
BMLoop *ls2[2] = {l->head.data, l->next->head.data};
|
||||
float ws2[2] = {0.5f, 0.5f};
|
||||
|
||||
if (!snap) {
|
||||
const int axis = l->v == v_del ? 0 : 1;
|
||||
|
||||
ws2[axis] = 0.0f;
|
||||
ws2[axis ^ 1] = 1.0f;
|
||||
}
|
||||
|
||||
float uv[2][2];
|
||||
for (int step = 0; uv_layer && step < 2; step++) {
|
||||
BMLoop *l1 = step ? l : l->next;
|
||||
|
||||
for (int k = 0; k < totuv; k++) {
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l1, uv_layer[k].offset);
|
||||
|
||||
copy_v2_v2(uv[k * 2 + step], luv->uv);
|
||||
}
|
||||
}
|
||||
|
||||
CustomData_bmesh_interp(&pbvh->bm->ldata, ls2, ws2, NULL, 2, l->head.data);
|
||||
CustomData_bmesh_copy_data(
|
||||
&pbvh->bm->ldata, &pbvh->bm->ldata, l->head.data, &l->next->head.data);
|
||||
|
||||
for (int step = 0; totuv >= 0 && step < 2; step++) {
|
||||
BMVert *v = step ? l->next->v : l->v;
|
||||
BMLoop *l1 = step ? l->next : l;
|
||||
BMEdge *e2 = v->e;
|
||||
|
||||
do {
|
||||
BMLoop *l2 = e2->l;
|
||||
|
||||
do {
|
||||
BMLoop *l3 = l2->v != v ? l2->next : l2;
|
||||
|
||||
if (!l3 || l3 == l1 || l3 == l || l3 == l->next) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int k = 0; k < totuv; k++) {
|
||||
const int flag = 1 << k;
|
||||
|
||||
if (l3->head.index & flag) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int cd_uv = uv_layer[k].offset;
|
||||
|
||||
MLoopUV *luv1 = BM_ELEM_CD_GET_VOID_P(l1, cd_uv);
|
||||
MLoopUV *luv2 = BM_ELEM_CD_GET_VOID_P(l3, cd_uv);
|
||||
|
||||
float dx = luv2->uv[0] - uv[k * 2 + step][0];
|
||||
float dy = luv2->uv[1] - uv[k * 2 + step][1];
|
||||
|
||||
float delta = dx * dx + dy * dy;
|
||||
|
||||
if (delta < 0.001) {
|
||||
l3->head.index |= flag;
|
||||
copy_v2_v2(luv2->uv, luv1->uv);
|
||||
}
|
||||
}
|
||||
} while ((l2 = l2->radial_next) != e2->l);
|
||||
} while ((e2 = BM_DISK_EDGE_NEXT(e2, v)) != v->e);
|
||||
}
|
||||
} while ((l = l->radial_next) != e->l);
|
||||
}
|
||||
|
||||
validate_vert_faces(pbvh, pbvh->bm, v_conn, false, true);
|
||||
|
|
|
@ -4044,6 +4044,11 @@ PBVHNode *BKE_pbvh_get_node(PBVH *pbvh, int node)
|
|||
return pbvh->nodes + node;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_mark_update_triangulation(PBVHNode *node)
|
||||
{
|
||||
node->flag |= PBVH_UpdateTris;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node)
|
||||
{
|
||||
node->flag |= PBVH_UpdateTriAreas;
|
||||
|
|
|
@ -41,6 +41,7 @@ Topology rake:
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_array.h"
|
||||
#include "BLI_buffer.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
@ -2149,25 +2150,30 @@ BLI_INLINE PBVHTri *pbvh_tribuf_add_tri(PBVHTriBuf *tribuf)
|
|||
return tribuf->tris + tribuf->tottri - 1;
|
||||
}
|
||||
|
||||
BLI_INLINE void pbvh_tribuf_add_vert(PBVHTriBuf *tribuf, SculptVertRef vertex)
|
||||
BLI_INLINE void pbvh_tribuf_add_vert(PBVHTriBuf *tribuf, SculptVertRef vertex, BMLoop *l)
|
||||
{
|
||||
tribuf->totvert++;
|
||||
tribuf->totloop++;
|
||||
|
||||
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");
|
||||
tribuf->loops = MEM_mallocN(sizeof(*tribuf->loops) * newsize, "tribuf loops");
|
||||
}
|
||||
else {
|
||||
tribuf->verts = MEM_reallocN_id(
|
||||
tribuf->verts, sizeof(*tribuf->verts) * newsize, "tribuf verts");
|
||||
tribuf->loops = MEM_reallocN_id(
|
||||
tribuf->loops, sizeof(*tribuf->loops) * newsize, "tribuf loops");
|
||||
}
|
||||
|
||||
tribuf->verts_size = newsize;
|
||||
}
|
||||
|
||||
tribuf->verts[tribuf->totvert - 1] = vertex;
|
||||
tribuf->loops[tribuf->totloop - 1] = (uintptr_t)l;
|
||||
}
|
||||
|
||||
BLI_INLINE void pbvh_tribuf_add_edge(PBVHTriBuf *tribuf, int v1, int v2)
|
||||
|
@ -2239,6 +2245,30 @@ static void pbvh_init_tribuf(PBVHNode *node, PBVHTriBuf *tribuf)
|
|||
|
||||
BLI_smallhash_init_ex(&tribuf->vertmap, node->bm_unique_verts->length);
|
||||
}
|
||||
|
||||
static uintptr_t tri_loopkey(BMLoop *l, int mat_nr, int cd_fset, int cd_uvs[], int totuv)
|
||||
{
|
||||
uintptr_t key = (uintptr_t)mat_nr;
|
||||
|
||||
key ^= (uintptr_t)l->v;
|
||||
|
||||
if (cd_fset >= 0) {
|
||||
key ^= BM_ELEM_CD_GET_INT(l->f, cd_fset);
|
||||
}
|
||||
|
||||
for (int i = 0; i < totuv; i++) {
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_uvs[i]);
|
||||
float snap = 4196.0f;
|
||||
|
||||
uintptr_t x = (uintptr_t)(luv->uv[0] * snap);
|
||||
uintptr_t y = (uintptr_t)(luv->uv[1] * snap);
|
||||
|
||||
uintptr_t key2 = y * snap + x;
|
||||
key ^= key2;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
/* In order to perform operations on the original node coordinates
|
||||
* (currently just raycast), store the node's triangles and vertices.
|
||||
*
|
||||
|
@ -2251,6 +2281,14 @@ bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
|||
return false;
|
||||
}
|
||||
|
||||
int totuv = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
|
||||
int *cd_uvs = BLI_array_alloca(cd_uvs, totuv);
|
||||
|
||||
for (int i = 0; i < totuv; i++) {
|
||||
int idx = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, i);
|
||||
cd_uvs[i] = bm->ldata.layers[idx].offset;
|
||||
}
|
||||
|
||||
node->flag |= PBVH_UpdateOtherVerts;
|
||||
|
||||
int mat_map[MAXMAT];
|
||||
|
@ -2354,26 +2392,28 @@ bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
|||
mat_tri->eflag |= 1 << j;
|
||||
}
|
||||
|
||||
if (!BLI_smallhash_ensure_p(&node->tribuf->vertmap, (uintptr_t)l->v, &val)) {
|
||||
uintptr_t loopkey = tri_loopkey(l, mat_nr, pbvh->cd_faceset_offset, cd_uvs, totuv);
|
||||
|
||||
if (!BLI_smallhash_ensure_p(&node->tribuf->vertmap, loopkey, &val)) {
|
||||
SculptVertRef sv = {(intptr_t)l->v};
|
||||
|
||||
minmax_v3v3_v3(min, max, l->v->co);
|
||||
|
||||
*val = POINTER_FROM_INT(node->tribuf->totvert);
|
||||
pbvh_tribuf_add_vert(node->tribuf, sv);
|
||||
pbvh_tribuf_add_vert(node->tribuf, sv, l);
|
||||
}
|
||||
|
||||
tri->v[j] = (intptr_t)val[0];
|
||||
tri->l[j] = (intptr_t)l;
|
||||
|
||||
val = NULL;
|
||||
if (!BLI_smallhash_ensure_p(&mat_tribuf->vertmap, (uintptr_t)l->v, &val)) {
|
||||
if (!BLI_smallhash_ensure_p(&mat_tribuf->vertmap, loopkey, &val)) {
|
||||
SculptVertRef sv = {(intptr_t)l->v};
|
||||
|
||||
minmax_v3v3_v3(min, max, l->v->co);
|
||||
|
||||
*val = POINTER_FROM_INT(mat_tribuf->totvert);
|
||||
pbvh_tribuf_add_vert(mat_tribuf, sv);
|
||||
pbvh_tribuf_add_vert(mat_tribuf, sv, l);
|
||||
}
|
||||
|
||||
mat_tri->v[j] = (intptr_t)val[0];
|
||||
|
|
|
@ -281,6 +281,7 @@ static void partialvis_update_bmesh(Object *ob,
|
|||
if (any_changed) {
|
||||
BKE_pbvh_node_mark_rebuild_draw(node);
|
||||
BKE_pbvh_node_fully_hidden_set(node, !any_visible);
|
||||
BKE_pbvh_node_mark_update_triangulation(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1023,6 +1023,7 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl
|
|||
|
||||
BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
|
||||
int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
|
||||
int node = BM_ELEM_CD_GET_INT(f, ss->cd_face_node_offset);
|
||||
|
||||
if (abs(fset) != face_set) {
|
||||
continue;
|
||||
|
@ -1035,6 +1036,10 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl
|
|||
fset = -abs(fset);
|
||||
}
|
||||
|
||||
if (node != DYNTOPO_NODE_NONE) {
|
||||
BKE_pbvh_node_mark_update_triangulation(BKE_pbvh_node_from_index(ss->pbvh, node));
|
||||
}
|
||||
|
||||
BM_ELEM_CD_SET_INT(f, ss->cd_faceset_offset, fset);
|
||||
}
|
||||
break;
|
||||
|
@ -1107,6 +1112,11 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
|
|||
|
||||
BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
|
||||
int fset = BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
|
||||
int node = BM_ELEM_CD_GET_INT(f, ss->cd_face_node_offset);
|
||||
|
||||
if (node != DYNTOPO_NODE_NONE) {
|
||||
BKE_pbvh_node_mark_update_triangulation(BKE_pbvh_node_from_index(ss->pbvh, node));
|
||||
}
|
||||
|
||||
/* This can run on geometry without a face set assigned, so its ID sign can't be changed to
|
||||
* modify the visibility. Force that geometry to the ID 1 to enable changing the visibility
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct SculptDisplacer {
|
||||
|
||||
} SculptDisplacer;
|
||||
|
|
|
@ -102,7 +102,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
slide_fset = MAX2(slide_fset, bound_smooth);
|
||||
|
||||
if (check_fsets) {
|
||||
bflag |= SCULPT_BOUNDARY_FACE_SET;
|
||||
bflag |= SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SEAM;
|
||||
}
|
||||
|
||||
const SculptBoundaryType is_boundary = SCULPT_vertex_is_boundary(ss, vertex, bflag);
|
||||
|
@ -124,7 +124,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
SculptCornerType ctype = SCULPT_CORNER_MESH | SCULPT_CORNER_SHARP;
|
||||
if (check_fsets) {
|
||||
ctype |= SCULPT_CORNER_FACE_SET;
|
||||
ctype |= SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SEAM;
|
||||
}
|
||||
|
||||
// bool have_bmesh = ss->bm;
|
||||
|
@ -201,7 +201,8 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
|
||||
*/
|
||||
|
||||
bool slide = (slide_fset > 0.0f && is_boundary == SCULPT_BOUNDARY_FACE_SET) ||
|
||||
bool slide = (slide_fset > 0.0f &&
|
||||
(is_boundary & (SCULPT_BOUNDARY_FACE_SET | SCULPT_BOUNDARY_SEAM))) ||
|
||||
bound_smooth > 0.0f;
|
||||
slide = slide && !final_boundary;
|
||||
|
||||
|
@ -334,7 +335,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
|
|||
return;
|
||||
}
|
||||
|
||||
if (c & SCULPT_CORNER_FACE_SET) {
|
||||
if (c & (SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SEAM)) {
|
||||
corner_smooth = MAX2(slide_fset, bound_smooth);
|
||||
}
|
||||
else {
|
||||
|
@ -1003,7 +1004,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
|
|||
|
||||
SculptCornerType ctype = SCULPT_CORNER_MESH | SCULPT_CORNER_SHARP;
|
||||
if (check_fsets) {
|
||||
ctype |= SCULPT_CORNER_FACE_SET;
|
||||
ctype |= SCULPT_CORNER_FACE_SET | SCULPT_CORNER_SEAM;
|
||||
}
|
||||
|
||||
if (weighted || ss->cache->brush->boundary_smooth_factor > 0.0f) {
|
||||
|
|
|
@ -1179,17 +1179,21 @@ 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, int mat_nr)
|
||||
static int gpu_bmesh_face_visible_count(PBVHTriBuf *tribuf, int mat_nr)
|
||||
{
|
||||
int totface = 0;
|
||||
BMFace *f;
|
||||
|
||||
TGSET_ITER (f, bm_faces) {
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN) && f->mat_nr == mat_nr) {
|
||||
totface++;
|
||||
for (int i = 0; i < tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf->tris + i;
|
||||
|
||||
BMFace *f = (BMFace *)tri->f.i;
|
||||
if (f->mat_nr != mat_nr || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
totface++;
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
return totface;
|
||||
}
|
||||
|
@ -1485,7 +1489,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 = tribuf->tottri * 6;
|
||||
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr) * 6;
|
||||
totvert = tottri * 3;
|
||||
|
||||
if (!tottri) {
|
||||
|
@ -1667,7 +1671,7 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
|
||||
|
||||
/* Count visible triangles */
|
||||
tottri = tribuf->tottri;
|
||||
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr);
|
||||
|
||||
/* Count visible vertices */
|
||||
totvert = tribuf->totvert;
|
||||
|
@ -1685,6 +1689,12 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
|
||||
/* TODO, make mask layer optional for bmesh buffer */
|
||||
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
|
||||
int cd_fset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
|
||||
|
||||
// int totuv = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
|
||||
// int *cd_uvs = BLI_array_alloca(cd_uvs, totuv);
|
||||
const int cd_uv = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
|
||||
const bool have_uv = cd_uv >= 0;
|
||||
|
||||
bool default_face_set = true;
|
||||
|
||||
|
@ -1733,6 +1743,7 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
|
||||
for (int i = 0; i < tribuf->totvert; i++) {
|
||||
BMVert *v = (BMVert *)tribuf->verts[i].i;
|
||||
BMLoop *l = (BMLoop *)tribuf->loops[i];
|
||||
|
||||
#ifdef QUANTIZED_PERF_TEST
|
||||
float co[3];
|
||||
|
@ -1771,6 +1782,25 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
cd_vcols,
|
||||
cd_vcol_count);
|
||||
#endif
|
||||
|
||||
if (!g_vbo_id.fast_mode) {
|
||||
const uchar face_set_color[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
|
||||
/* Add default face sets color to avoid artifacts. */
|
||||
int fset = BM_ELEM_CD_GET_INT(l->f, cd_fset_offset);
|
||||
|
||||
if (fset != face_sets_color_default) {
|
||||
default_face_set = false;
|
||||
BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
|
||||
}
|
||||
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.fset, i, &face_set_color);
|
||||
}
|
||||
|
||||
if (have_uv) {
|
||||
MLoopUV *mu = BM_ELEM_CD_GET_VOID_P(l, cd_uv);
|
||||
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.uv, i, mu->uv);
|
||||
}
|
||||
}
|
||||
|
||||
if (!need_indexed) {
|
||||
|
@ -1794,6 +1824,11 @@ static void GPU_pbvh_bmesh_buffers_update_indexed(GPU_PBVH_Buffers *buffers,
|
|||
for (int i = 0; i < tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf->tris + i;
|
||||
|
||||
BMFace *f = (BMFace *)tri->f.i;
|
||||
if (f->mat_nr != mat_nr || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GPU_indexbuf_add_tri_verts(&elb, tri->v[0], tri->v[1], tri->v[2]);
|
||||
|
||||
#ifndef QUANTIZED_PERF_TEST
|
||||
|
@ -1874,7 +1909,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
|
||||
|
||||
/* Count visible triangles */
|
||||
if (buffers->smooth && !have_uv) {
|
||||
if (buffers->smooth) {
|
||||
GPU_pbvh_bmesh_buffers_update_indexed(buffers,
|
||||
bm,
|
||||
bm_faces,
|
||||
|
@ -1900,7 +1935,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
bool default_face_set = true;
|
||||
|
||||
#ifdef DYNTOPO_DYNAMIC_TESS
|
||||
tottri = tribuf->tottri;
|
||||
tottri = gpu_bmesh_face_visible_count(tribuf, mat_nr);
|
||||
totvert = tottri * 3;
|
||||
|
||||
if (!tottri) {
|
||||
|
@ -1929,7 +1964,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
BMLoop **l = (BMLoop **)tri->l;
|
||||
BMVert *v[3];
|
||||
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
if (f->mat_nr != mat_nr || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
#include "BKE_callbacks.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curvemapping_cache.h"
|
||||
#include "BKE_font.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_image.h"
|
||||
|
|
Loading…
Reference in New Issue