* Fixed SCULPT_dynamic_topology_sync_layers to properly sync

active/render/clone/mask layers indices.
* Fixed sculpt color bugs in pbvh drawing for bmesh.
This commit is contained in:
Joseph Eagar 2021-04-25 14:02:39 -07:00
parent 97fc606c65
commit 0386350de6
7 changed files with 154 additions and 143 deletions

View File

@ -1415,7 +1415,7 @@ static void pbvh_update_draw_buffers(
ldata = pbvh->ldata;
}
GPU_pbvh_update_attribute_names(vdata, ldata);
GPU_pbvh_update_attribute_names(vdata, ldata, active_vcol_only);
/* Parallel creation and update of draw buffers. */
PBVHUpdateData data = {.pbvh = pbvh,

View File

@ -2260,7 +2260,7 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx,
return any_subdivided;
}
ATTR_NO_OPT static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
BMEdge *e,
BMVert *v1,
BMVert *v2,

View File

@ -86,31 +86,6 @@ typedef struct BoundaryInitialVertexFloodFillData {
int *floodfill_steps;
float radius_sq;
} BoundaryInitialVertexFloodFillData;
#if 0
ATTR_NO_OPT static bool validVert(SculptSession *ss, SculptVertRef v)
{
if (v.i == -1) {
return false;
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH && v.i < 1000000) {
return false;
}
int totvert = SCULPT_vertex_count_get(ss);
int idx = BKE_pbvh_vertex_index_to_table(ss->pbvh, v);
return idx >= 0 && idx < totvert;
}
ATTR_NO_OPT static void validateVert(SculptSession *ss, SculptVertRef v)
{
if (!validVert(ss, v)) {
printf("Error! %p\n", v.i);
}
}
#endif
// XXX remove all calls to validateVert before final merge
#define validateVert(ss, vertex)
static bool boundary_initial_vertex_floodfill_cb(SculptSession *ss,
SculptVertRef from_vref,
@ -120,9 +95,6 @@ static bool boundary_initial_vertex_floodfill_cb(SculptSession *ss,
{
BoundaryInitialVertexFloodFillData *data = userdata;
validateVert(ss, from_vref);
validateVert(ss, to_vref);
int to_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, to_vref);
int from_v = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_vref);
@ -157,8 +129,6 @@ static SculptVertRef sculpt_boundary_get_closest_boundary_vertex(
const int initial_vertex_index,
const float radius)
{
validateVert(ss, initial_vertex);
if (SCULPT_vertex_is_boundary(ss, initial_vertex)) {
return initial_vertex;
}
@ -320,8 +290,6 @@ static void sculpt_boundary_indices_init(SculptSession *ss,
const SculptVertRef initial_boundary_index)
{
validateVert(ss, initial_boundary_index);
const int totvert = SCULPT_vertex_count_get(ss);
boundary->vertices = MEM_malloc_arrayN(
BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptVertRef) * TSTN, "boundary vrefs");
@ -386,8 +354,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
const bool has_duplicates = BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS;
validateVert(ss, initial_vertex);
boundary->edit_info = MEM_malloc_arrayN(
totvert, sizeof(SculptBoundaryEditInfo) * TSTN, "Boundary edit info");
@ -443,8 +409,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
BLI_gsqueue_pop(current_iteration, &from_v);
const int from_v_i = BKE_pbvh_vertex_index_to_table(ss->pbvh, from_v);
validateVert(ss, from_v);
SculptVertexNeighborIter ni;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) {
const bool is_visible = SCULPT_vertex_visible_get(ss, ni.vertex);
@ -459,8 +423,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
boundary->edit_info[ni.index].original_vertex_i =
boundary->edit_info[from_v_i].original_vertex_i;
validateVert(ss, boundary->edit_info[ni.index].original_vertex);
BLI_BITMAP_ENABLE(visited_vertices, ni.index);
if (ni.is_duplicate) {
@ -474,8 +436,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
BLI_gsqueue_push(next_iteration, &ni.vertex);
validateVert(ss, ni.vertex);
/* When copying the data to the neighbor for the next iteration, it has to be copied to
* all its duplicates too. This is because it is not possible to know if the updated
* neighbor or one if its uninitialized duplicates is going to come first in order to
@ -483,8 +443,6 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss,
if (has_duplicates) {
SculptVertexNeighborIter ni_duplis;
SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.vertex, ni_duplis) {
validateVert(ss, ni_duplis.vertex);
if (ni_duplis.is_duplicate) {
boundary->edit_info[ni_duplis.index].original_vertex =
boundary->edit_info[from_v_i].original_vertex;
@ -690,8 +648,6 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo
SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex),
SCULPT_vertex_co_get(ss, vertex));
validateVert(ss, boundary->edit_info[i].original_vertex);
#if 0
/*strategy to increase accuracy for non-quad topologies:
use principle curvature direction. Since SCULPT_curvature_dir_get
@ -948,8 +904,6 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
float t_orig_co[3];
float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
validateVert(ss, vd.vertex);
sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]);
rotate_v3_v3v3fl(target_co,
t_orig_co,

View File

@ -259,15 +259,6 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
continue;
}
modified = modified || CustomData_get_active_layer_index(data1, cl1->type) !=
CustomData_get_active_layer_index(data2, cl1->type);
modified = modified || CustomData_get_render_layer_index(data1, cl1->type) !=
CustomData_get_render_layer_index(data2, cl1->type);
modified = modified || CustomData_get_stencil_layer_index(data1, cl1->type) !=
CustomData_get_stencil_layer_index(data2, cl1->type);
modified = modified || CustomData_get_clone_layer_index(data1, cl1->type) !=
CustomData_get_clone_layer_index(data2, cl1->type);
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
if (idx < 0) {
BLI_array_append(newlayers, cl1);
@ -276,16 +267,13 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
for (int j = 0; j < BLI_array_len(newlayers); j++) {
BM_data_layer_add_named(bm, data2, newlayers[j]->type, newlayers[j]->name);
modified |= true;
modified = true;
}
char typemap[CD_NUMTYPES] = {
0,
};
bool typemap[CD_NUMTYPES] = {0};
for (int j = 0; j < data1->totlayer; j++) {
CustomDataLayer *cl = data1->layers + j;
CustomDataLayer *cl1 = cl;
CustomDataLayer *cl1 = data1->layers + j;
if ((1 << cl1->type) & badmask) {
continue;
@ -295,23 +283,56 @@ void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me)
continue;
}
typemap[cl1->type] = 1;
cl1 = cl + CustomData_get_active_layer(data1, cl1->type);
typemap[cl1->type] = true;
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
CustomData_set_layer_active_index(data2, cl1->type, idx);
// find first layer
int baseidx = CustomData_get_layer_index(data2, cl1->type);
cl1 = cl + CustomData_get_render_layer(data1, cl1->type);
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
CustomData_set_layer_render_index(data2, cl1->type, idx);
if (baseidx < 0) {
modified |= true;
continue;
}
cl1 = cl + CustomData_get_stencil_layer(data1, cl1->type);
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
CustomData_set_layer_stencil_index(data2, cl1->type, idx);
CustomDataLayer *cl2 = data2->layers + baseidx;
cl1 = cl + CustomData_get_clone_layer(data1, cl1->type);
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1->name);
CustomData_set_layer_clone_index(data2, cl1->type, idx);
int idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active].name);
if (idx >= 0) {
modified |= idx - baseidx != cl2->active;
cl2->active = idx - baseidx;
}
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_rnd].name);
if (idx >= 0) {
modified |= idx - baseidx != cl2->active_rnd;
cl2->active_rnd = idx - baseidx;
}
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_mask].name);
if (idx >= 0) {
modified |= idx - baseidx != cl2->active_mask;
cl2->active_mask = idx - baseidx;
}
idx = CustomData_get_named_layer_index(data2, cl1->type, cl1[cl1->active_clone].name);
if (idx >= 0) {
modified |= idx - baseidx != cl2->active_clone;
cl2->active_clone = idx - baseidx;
}
for (int k = baseidx; k < data2->totlayer; k++) {
CustomDataLayer *cl3 = data2->layers + k;
if (cl3->type != cl2->type) {
break;
}
//based off of how CustomData_set_layer_XXXX_index works
cl3->active = (cl2->active + baseidx) - k;
cl3->active_rnd = (cl2->active_rnd + baseidx) - k;
cl3->active_mask = (cl2->active_mask + baseidx) - k;
cl3->active_clone = (cl2->active_clone + baseidx) - k;
}
}
BLI_array_free(newlayers);

View File

@ -87,7 +87,10 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
const struct MPropCol *vtcol,
const int update_flags);
void GPU_pbvh_update_attribute_names(struct CustomData *vdata, struct CustomData *ldata);
/** if active_vcol_only is true, only the active (not render!) layer will
be uploaded to GPU*/
void GPU_pbvh_update_attribute_names(struct CustomData *vdata, struct CustomData *ldata, bool active_vcol_only);
void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
struct BMesh *bm,
struct TableGSet *bm_faces,

View File

@ -116,7 +116,7 @@ static struct {
void gpu_pbvh_init()
{
GPU_pbvh_update_attribute_names(NULL, NULL);
GPU_pbvh_update_attribute_names(NULL, NULL, false);
}
void gpu_pbvh_exit()
@ -896,7 +896,64 @@ void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers)
}
}
void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata)
static int gpu_pbvh_bmesh_make_vcol_offs(CustomData *vdata,
int r_cd_vcols[MAX_MCOL],
int r_cd_layers[MAX_MCOL],
bool active_only)
{
if (active_only) {
int idx = CustomData_get_offset(vdata, CD_PROP_COLOR);
if (idx >= 0) {
r_cd_vcols[0] = idx;
r_cd_layers[0] = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
return 1;
}
return 0;
}
int count = 0;
int tot = CustomData_number_of_layers(vdata, CD_PROP_COLOR);
for (int i = 0; i < tot; i++) {
int idx = CustomData_get_layer_index_n(vdata, CD_PROP_COLOR, i);
// idx = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
if (idx < 0) {
printf("eek, corruption in customdata!\n");
break;
}
CustomDataLayer *cl = vdata->layers + idx;
if (cl->flag & CD_FLAG_TEMPORARY) {
continue; // ignore original color layer
}
r_cd_layers[count] = idx;
r_cd_vcols[count] = CustomData_get_n_offset(vdata, CD_PROP_COLOR, i);
count++;
}
// ensure render layer is last
// draw cache code seems to need this
int render = CustomData_get_render_layer_index(vdata, CD_PROP_COLOR);
for (int i = 0; i < count; i++) {
if (r_cd_layers[i] == render) {
SWAP(int, r_cd_layers[i], r_cd_layers[count - 1]);
SWAP(int, r_cd_vcols[i], r_cd_vcols[count - 1]);
break;
}
}
return count;
}
void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata, bool active_only)
{
GPU_vertformat_clear(&g_vbo_id.format);
@ -910,42 +967,45 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata)
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[0] = GPU_vertformat_attr_add(
&g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.totcol = 1;
g_vbo_id.totcol = 0;
if (vdata && CustomData_has_layer(vdata, CD_PROP_COLOR)) {
for (int i = 0; i < vdata->totlayer; i++) {
}
const int cd_vcol_index = CustomData_get_layer_index(vdata, CD_PROP_COLOR);
const int act = CustomData_get_active_layer_index(vdata, CD_PROP_COLOR);
int ci = 0;
int ci = 1;
int cd_vcol_offs[MAX_MCOL];
int cd_vcol_layers[MAX_MCOL];
int totlayer = gpu_pbvh_bmesh_make_vcol_offs(
vdata, cd_vcol_offs, cd_vcol_layers, active_only);
for (int i = cd_vcol_index; i < vdata->totlayer; i++) {
CustomDataLayer *cl = vdata->layers + i;
for (int i = 0; i < totlayer; i++) {
int idx = cd_vcol_layers[i];
CustomDataLayer *cl = vdata->layers + idx;
// ignore original color temporary layer
if (cl->flag & CD_FLAG_TEMPORARY) {
continue;
}
if (cl->type != CD_PROP_COLOR) {
break;
}
if (i > cd_vcol_index && g_vbo_id.totcol < MAX_MCOL) {
if (g_vbo_id.totcol < MAX_MCOL) {
g_vbo_id.col[ci++] = GPU_vertformat_attr_add(
&g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.totcol++;
}
DRW_make_cdlayer_attr_aliases(&g_vbo_id.format, "c", vdata, cl);
if (i == act) {
GPU_vertformat_alias_add(&g_vbo_id.format, "ac");
DRW_make_cdlayer_attr_aliases(&g_vbo_id.format, "c", vdata, cl);
if (idx == act) {
GPU_vertformat_alias_add(&g_vbo_id.format, "ac");
}
}
}
}
// ensure at least one vertex color layer
if (g_vbo_id.totcol == 0) {
g_vbo_id.col[0] = GPU_vertformat_attr_add(
&g_vbo_id.format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
g_vbo_id.totcol = 1;
GPU_vertformat_alias_add(&g_vbo_id.format, "ac");
}
g_vbo_id.fset = GPU_vertformat_attr_add(
&g_vbo_id.format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
@ -963,42 +1023,6 @@ void GPU_pbvh_update_attribute_names(CustomData *vdata, CustomData *ldata)
}
}
static int gpu_pbvh_bmesh_make_vcol_offs(BMesh *bm, int r_cd_vcols[MAX_MCOL], bool active_only)
{
if (active_only) {
int idx = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
if (idx >= 0) {
r_cd_vcols[0] = idx;
return 1;
}
return 0;
}
int count = 0;
int tot = CustomData_number_of_layers(&bm->vdata, CD_PROP_COLOR);
for (int i = 0; i < tot; i++) {
int idx = CustomData_get_layer_index_n(&bm->vdata, CD_PROP_COLOR, i);
// idx = CustomData_get_active_layer_index(&bm->vdata, CD_PROP_COLOR);
if (idx < 0) {
printf("eek, corruption in customdata!\n");
break;
}
CustomDataLayer *cl = bm->vdata.layers + idx;
if (cl->flag & CD_FLAG_TEMPORARY) {
continue; // ignore original color layer
}
r_cd_vcols[count++] = CustomData_get_n_offset(&bm->vdata, CD_PROP_COLOR, i);
}
return count;
}
static void gpu_flat_vcol_make_vert(float co[3],
BMVert *v,
GPUVertBuf *vert_buf,
@ -1057,7 +1081,10 @@ static void GPU_pbvh_bmesh_buffers_update_flat_vcol(GPU_PBVH_Buffers *buffers,
int cd_fset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
int cd_vcols[MAX_MCOL];
const int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(bm, cd_vcols, active_vcol_only);
int cd_vcol_layers[MAX_MCOL];
const int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
/* Count visible triangles */
tottri = gpu_bmesh_face_visible_count(bm_faces) * 6;
@ -1252,7 +1279,10 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
int cd_fset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
int cd_vcols[MAX_MCOL];
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(bm, cd_vcols, active_vcol_only);
int cd_vcol_layers[MAX_MCOL];
int cd_vcol_count = gpu_pbvh_bmesh_make_vcol_offs(
&bm->vdata, cd_vcols, cd_vcol_layers, active_vcol_only);
/* Count visible triangles */
const bool indexed = buffers->smooth && tribuf && !have_uv;
@ -1391,7 +1421,8 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
show_mask,
false,
&empty_mask,
NULL, 0);
NULL,
0);
if (cd_vcol_count >= 0) {
for (int j = 0; j < cd_vcol_count; j++) {

View File

@ -1209,10 +1209,12 @@ static void rna_def_dyntopo_settings(BlenderRNA *brna) {
prop = RNA_def_property(srna, "constant_detail", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "constant_detail");
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.001, 4);
RNA_def_property_ui_text(
prop, "Constant Detail", "");
RNA_def_property_range(prop, 0.0001, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001, 1000.0, 10, 2);
RNA_def_property_ui_text(prop,
"Resolution",
"Maximum edge length for dynamic topology sculpting (as divisor "
"of blender unit - higher value means smaller edge length)");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "subdivide", PROP_BOOLEAN, PROP_NONE);