Fix various issues with modifiers and edge display in edit mode #105384
|
@ -459,6 +459,9 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
mr->me = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
|
||||
mr->edit_data = is_mode_active ? mr->me->runtime->edit_data : nullptr;
|
||||
|
||||
/* If there is no distinct cage, hide unmapped edges that can't be selected. */
|
||||
mr->hide_unmapped_edges = !do_final || editmesh_eval_final == editmesh_eval_cage;
|
||||
|
||||
if (mr->edit_data) {
|
||||
EditMeshData *emd = mr->edit_data;
|
||||
if (emd->vertexCos) {
|
||||
|
@ -521,6 +524,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
|
|||
mr->me = me;
|
||||
mr->edit_bmesh = nullptr;
|
||||
mr->extract_type = MR_EXTRACT_MESH;
|
||||
mr->hide_unmapped_edges = false;
|
||||
|
||||
if (is_paint_mode && mr->me) {
|
||||
mr->v_origindex = static_cast<const int *>(
|
||||
|
|
|
@ -654,6 +654,7 @@ static void draw_subdiv_free_edit_mode_cache(DRWSubdivCache *cache)
|
|||
{
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->verts_orig_index);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->edges_orig_index);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->edges_draw_flag);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->fdots_patch_coords);
|
||||
}
|
||||
|
||||
|
@ -877,11 +878,13 @@ struct DRWCacheBuildingContext {
|
|||
int *subdiv_loop_vert_index;
|
||||
int *subdiv_loop_subdiv_vert_index;
|
||||
int *subdiv_loop_edge_index;
|
||||
int *subdiv_loop_edge_draw_flag;
|
||||
int *subdiv_loop_subdiv_edge_index;
|
||||
int *subdiv_loop_poly_index;
|
||||
|
||||
/* Temporary buffers used during traversal. */
|
||||
int *vert_origindex_map;
|
||||
int *edge_draw_flag_map;
|
||||
int *edge_origindex_map;
|
||||
|
||||
/* #CD_ORIGINDEX layers from the mesh to directly look up during traversal the original-index
|
||||
|
@ -941,6 +944,11 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
|
|||
cache->edges_orig_index, get_origindex_format(), GPU_USAGE_DYNAMIC);
|
||||
GPU_vertbuf_data_alloc(cache->edges_orig_index, cache->num_subdiv_loops);
|
||||
|
||||
cache->edges_draw_flag = GPU_vertbuf_calloc();
|
||||
GPU_vertbuf_init_with_format_ex(
|
||||
cache->edges_draw_flag, get_origindex_format(), GPU_USAGE_DYNAMIC);
|
||||
GPU_vertbuf_data_alloc(cache->edges_draw_flag, cache->num_subdiv_loops);
|
||||
|
||||
cache->subdiv_loop_subdiv_vert_index = static_cast<int *>(
|
||||
MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_vert_index"));
|
||||
|
||||
|
@ -954,6 +962,7 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
|
|||
ctx->patch_coords = (CompressedPatchCoord *)GPU_vertbuf_get_data(cache->patch_coords);
|
||||
ctx->subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(cache->verts_orig_index);
|
||||
ctx->subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(cache->edges_orig_index);
|
||||
ctx->subdiv_loop_edge_draw_flag = (int *)GPU_vertbuf_get_data(cache->edges_draw_flag);
|
||||
ctx->subdiv_loop_subdiv_vert_index = cache->subdiv_loop_subdiv_vert_index;
|
||||
ctx->subdiv_loop_subdiv_edge_index = cache->subdiv_loop_subdiv_edge_index;
|
||||
ctx->subdiv_loop_poly_index = cache->subdiv_loop_poly_index;
|
||||
|
@ -978,6 +987,8 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
|
|||
for (int i = 0; i < num_edges; i++) {
|
||||
ctx->edge_origindex_map[i] = -1;
|
||||
}
|
||||
ctx->edge_draw_flag_map = static_cast<int *>(
|
||||
MEM_callocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_draw_flag_map"));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1025,15 +1036,27 @@ static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context,
|
|||
return;
|
||||
}
|
||||
|
||||
int coarse_index = coarse_edge_index;
|
||||
|
||||
if (coarse_index != -1) {
|
||||
if (ctx->e_origindex) {
|
||||
coarse_index = ctx->e_origindex[coarse_index];
|
||||
if (coarse_edge_index == ORIGINDEX_NONE) {
|
||||
/* Not mapped to edge in the subdivision base mesh. */
|
||||
ctx->edge_origindex_map[subdiv_edge_index] = ORIGINDEX_NONE;
|
||||
if (!ctx->cache->optimal_display) {
|
||||
ctx->edge_draw_flag_map[subdiv_edge_index] = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ctx->e_origindex) {
|
||||
const int origindex = ctx->e_origindex[coarse_edge_index];
|
||||
ctx->edge_origindex_map[subdiv_edge_index] = origindex;
|
||||
if (!(origindex == ORIGINDEX_NONE && ctx->cache->hide_unmapped_edges)) {
|
||||
/* Not mapped to edge in original mesh (generated by a preceding modifier). */
|
||||
ctx->edge_draw_flag_map[subdiv_edge_index] = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx->edge_origindex_map[subdiv_edge_index] = coarse_edge_index;
|
||||
ctx->edge_draw_flag_map[subdiv_edge_index] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->edge_origindex_map[subdiv_edge_index] = coarse_index;
|
||||
}
|
||||
|
||||
static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context,
|
||||
|
@ -1084,9 +1107,11 @@ static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context,
|
|||
* subdiv-loop-to-coarse-edge map.
|
||||
*/
|
||||
for (int i = 0; i < cache_building_context->cache->num_subdiv_loops; i++) {
|
||||
const int edge_index = cache_building_context->subdiv_loop_subdiv_edge_index[i];
|
||||
cache_building_context->subdiv_loop_edge_index[i] =
|
||||
cache_building_context
|
||||
->edge_origindex_map[cache_building_context->subdiv_loop_subdiv_edge_index[i]];
|
||||
cache_building_context->edge_origindex_map[edge_index];
|
||||
cache_building_context->subdiv_loop_edge_draw_flag[i] =
|
||||
cache_building_context->edge_draw_flag_map[edge_index];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1246,6 +1271,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
|
|||
/* Cleanup. */
|
||||
MEM_SAFE_FREE(cache_building_context.vert_origindex_map);
|
||||
MEM_SAFE_FREE(cache_building_context.edge_origindex_map);
|
||||
MEM_SAFE_FREE(cache_building_context.edge_draw_flag_map);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1276,11 +1302,6 @@ struct DRWSubdivUboStorage {
|
|||
/* Refined topology information. */
|
||||
uint num_subdiv_loops;
|
||||
|
||||
/* Subdivision settings, is int in C but bool in the GLSL code, as there, bools have the same
|
||||
* size as ints, so we should use int in C to ensure that the size of the structure is what GLSL
|
||||
* expects. */
|
||||
int optimal_display;
|
||||
|
||||
/* The sculpt mask data layer may be null. */
|
||||
int has_sculpt_mask;
|
||||
|
||||
|
@ -1299,6 +1320,7 @@ struct DRWSubdivUboStorage {
|
|||
int is_edit_mode;
|
||||
int use_hide;
|
||||
int _pad3;
|
||||
int _pad4;
|
||||
};
|
||||
|
||||
static_assert((sizeof(DRWSubdivUboStorage) % 16) == 0,
|
||||
|
@ -1318,7 +1340,6 @@ static void draw_subdiv_init_ubo_storage(const DRWSubdivCache *cache,
|
|||
ubo->max_depth = cache->gpu_patch_map.max_depth;
|
||||
ubo->patches_are_triangular = cache->gpu_patch_map.patches_are_triangular;
|
||||
ubo->coarse_poly_count = cache->num_coarse_poly;
|
||||
ubo->optimal_display = cache->optimal_display;
|
||||
ubo->num_subdiv_loops = cache->num_subdiv_loops;
|
||||
ubo->edge_loose_offset = cache->num_subdiv_loops * 2;
|
||||
ubo->has_sculpt_mask = has_sculpt_mask;
|
||||
|
@ -1819,7 +1840,7 @@ void draw_subdiv_build_lines_buffer(const DRWSubdivCache *cache, GPUIndexBuf *li
|
|||
|
||||
int binding_point = 0;
|
||||
GPU_vertbuf_bind_as_ssbo(cache->subdiv_polygon_offset_buffer, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(cache->edges_orig_index, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(cache->edges_draw_flag, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(cache->extra_coarse_face_data, binding_point++);
|
||||
GPU_indexbuf_bind_as_ssbo(lines_indices, binding_point++);
|
||||
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
|
||||
|
@ -1855,7 +1876,7 @@ void draw_subdiv_build_lines_loose_buffer(const DRWSubdivCache *cache,
|
|||
|
||||
void draw_subdiv_build_edge_fac_buffer(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *pos_nor,
|
||||
GPUVertBuf *edge_idx,
|
||||
GPUVertBuf *edge_draw_flag,
|
||||
GPUVertBuf *edge_fac)
|
||||
{
|
||||
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_EDGE_FAC);
|
||||
|
@ -1863,7 +1884,7 @@ void draw_subdiv_build_edge_fac_buffer(const DRWSubdivCache *cache,
|
|||
|
||||
int binding_point = 0;
|
||||
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(edge_idx, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(edge_draw_flag, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(edge_fac, binding_point++);
|
||||
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
|
||||
|
||||
|
@ -2113,17 +2134,18 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
|
|||
}
|
||||
|
||||
DRWSubdivCache *draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache);
|
||||
|
||||
draw_cache->optimal_display = runtime_data->use_optimal_display;
|
||||
/* If there is no distinct cage, hide unmapped edges that can't be selected. */
|
||||
draw_cache->hide_unmapped_edges = is_editmode && !do_cage;
|
||||
draw_cache->bm = bm;
|
||||
draw_cache->mesh = mesh_eval;
|
||||
draw_cache->subdiv = subdiv;
|
||||
|
||||
if (!draw_subdiv_build_cache(draw_cache, subdiv, mesh_eval, runtime_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Edges which do not come from coarse edges should not be drawn in edit cage mode. */
|
||||
const bool optimal_display = runtime_data->use_optimal_display || (is_editmode && !do_cage);
|
||||
|
||||
draw_cache->bm = bm;
|
||||
draw_cache->mesh = mesh_eval;
|
||||
draw_cache->subdiv = subdiv;
|
||||
draw_cache->optimal_display = optimal_display;
|
||||
draw_cache->num_subdiv_triangles = tris_count_from_number_of_loops(draw_cache->num_subdiv_loops);
|
||||
|
||||
/* Copy topology information for stats display. */
|
||||
|
|
|
@ -101,6 +101,7 @@ typedef struct DRWSubdivCache {
|
|||
struct BMesh *bm;
|
||||
struct Subdiv *subdiv;
|
||||
bool optimal_display;
|
||||
bool hide_unmapped_edges;
|
||||
bool use_custom_loop_normals;
|
||||
|
||||
/* Coordinates used to evaluate patches for positions and normals. */
|
||||
|
@ -148,6 +149,8 @@ typedef struct DRWSubdivCache {
|
|||
struct GPUVertBuf *verts_orig_index;
|
||||
/* Maps subdivision loop to original coarse edge index, only really useful for edit mode. */
|
||||
struct GPUVertBuf *edges_orig_index;
|
||||
/* Indicates if edge should be drawn in optimal display mode. */
|
||||
struct GPUVertBuf *edges_draw_flag;
|
||||
|
||||
/* Owned by #Subdiv. Indexed by coarse polygon index, difference between value (i + 1) and (i)
|
||||
* gives the number of ptex faces for coarse polygon (i). */
|
||||
|
@ -259,7 +262,7 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache *cache,
|
|||
|
||||
void draw_subdiv_build_edge_fac_buffer(const DRWSubdivCache *cache,
|
||||
struct GPUVertBuf *pos_nor,
|
||||
struct GPUVertBuf *edge_idx,
|
||||
struct GPUVertBuf *edge_draw_flag,
|
||||
struct GPUVertBuf *edge_fac);
|
||||
|
||||
void draw_subdiv_build_tris_buffer(const DRWSubdivCache *cache,
|
||||
|
|
|
@ -49,6 +49,7 @@ struct MeshRenderData {
|
|||
bool use_hide;
|
||||
bool use_subsurf_fdots;
|
||||
bool use_final_mesh;
|
||||
bool hide_unmapped_edges;
|
||||
|
||||
/** Use for #MeshStatVis calculation which use world-space coords. */
|
||||
float obmat[4][4];
|
||||
|
|
|
@ -58,7 +58,7 @@ static void extract_lines_iter_poly_mesh(const MeshRenderData *mr,
|
|||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
|
||||
/* Using poly & loop iterator would complicate accessing the adjacent loop. */
|
||||
const MLoop *mloop = mr->mloop;
|
||||
const int *e_origindex = (mr->edit_bmesh) ? mr->e_origindex : nullptr;
|
||||
const int *e_origindex = (mr->hide_unmapped_edges) ? mr->e_origindex : nullptr;
|
||||
if (mr->use_hide || (e_origindex != nullptr)) {
|
||||
const int ml_index_last = mp->loopstart + (mp->totloop - 1);
|
||||
int ml_index = ml_index_last, ml_index_next = mp->loopstart;
|
||||
|
@ -109,7 +109,7 @@ static void extract_lines_iter_ledge_mesh(const MeshRenderData *mr,
|
|||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
|
||||
const int l_index_offset = mr->edge_len + ledge_index;
|
||||
const int e_index = mr->ledges[ledge_index];
|
||||
const int *e_origindex = (mr->edit_bmesh) ? mr->e_origindex : nullptr;
|
||||
const int *e_origindex = (mr->hide_unmapped_edges) ? mr->e_origindex : nullptr;
|
||||
if (!((mr->use_hide && mr->hide_edge && mr->hide_edge[med - mr->medge]) ||
|
||||
((e_origindex) && (e_origindex[e_index] == ORIGINDEX_NONE)))) {
|
||||
const int l_index = mr->loop_len + ledge_index * 2;
|
||||
|
@ -183,8 +183,8 @@ static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
|
||||
switch (mr->extract_type) {
|
||||
case MR_EXTRACT_MESH: {
|
||||
const int *e_origindex = (mr->edit_bmesh) ? mr->e_origindex : nullptr;
|
||||
if (mr->e_origindex == nullptr) {
|
||||
const int *e_origindex = (mr->hide_unmapped_edges) ? mr->e_origindex : nullptr;
|
||||
if (e_origindex == nullptr) {
|
||||
const bool *hide_edge = mr->hide_edge;
|
||||
if (hide_edge) {
|
||||
for (DRWSubdivLooseEdge edge : loose_edges) {
|
||||
|
|
|
@ -223,23 +223,23 @@ static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
|
||||
/* Create a temporary buffer for the edge original indices if it was not requested. */
|
||||
const bool has_edge_idx = edge_idx != nullptr;
|
||||
GPUVertBuf *loop_edge_idx = nullptr;
|
||||
GPUVertBuf *loop_edge_draw_flag = nullptr;
|
||||
if (has_edge_idx) {
|
||||
loop_edge_idx = edge_idx;
|
||||
loop_edge_draw_flag = edge_idx;
|
||||
}
|
||||
else {
|
||||
loop_edge_idx = GPU_vertbuf_calloc();
|
||||
loop_edge_draw_flag = GPU_vertbuf_calloc();
|
||||
draw_subdiv_init_origindex_buffer(
|
||||
loop_edge_idx,
|
||||
static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_orig_index)),
|
||||
loop_edge_draw_flag,
|
||||
static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_draw_flag)),
|
||||
subdiv_cache->num_subdiv_loops,
|
||||
0);
|
||||
}
|
||||
|
||||
draw_subdiv_build_edge_fac_buffer(subdiv_cache, pos_nor, loop_edge_idx, vbo);
|
||||
draw_subdiv_build_edge_fac_buffer(subdiv_cache, pos_nor, loop_edge_draw_flag, vbo);
|
||||
|
||||
if (!has_edge_idx) {
|
||||
GPU_vertbuf_discard(loop_edge_idx);
|
||||
GPU_vertbuf_discard(loop_edge_draw_flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
/* To be compiled with common_subdiv_lib.glsl */
|
||||
|
||||
layout(std430, binding = 1) readonly buffer inputEdgeOrigIndex
|
||||
layout(std430, binding = 1) readonly buffer inputEdgeDrawFlag
|
||||
{
|
||||
int input_origindex[];
|
||||
int input_edge_draw_flag[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 2) readonly restrict buffer extraCoarseFaceData
|
||||
|
@ -35,8 +35,7 @@ void emit_line(uint line_offset, uint quad_index, uint start_loop_index, uint co
|
|||
uint coarse_quad_index = coarse_polygon_index_from_subdiv_quad_index(quad_index,
|
||||
coarse_poly_count);
|
||||
|
||||
if (use_hide && is_face_hidden(coarse_quad_index) ||
|
||||
(input_origindex[vertex_index] == ORIGINDEX_NONE && optimal_display)) {
|
||||
if (use_hide && is_face_hidden(coarse_quad_index) || (input_edge_draw_flag[vertex_index] == 0)) {
|
||||
output_lines[line_offset + 0] = 0xffffffff;
|
||||
output_lines[line_offset + 1] = 0xffffffff;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,6 @@ layout(std140) uniform shader_data
|
|||
/* Subdiv topology information. */
|
||||
uint num_subdiv_loops;
|
||||
|
||||
/* Subdivision settings. */
|
||||
bool optimal_display;
|
||||
|
||||
/* Sculpt data. */
|
||||
bool has_sculpt_mask;
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ layout(std430, binding = 0) readonly buffer inputVertexData
|
|||
PosNorLoop pos_nor[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 1) readonly buffer inputEdgeIndex
|
||||
layout(std430, binding = 1) readonly buffer inputEdgeDrawFlag
|
||||
{
|
||||
uint input_edge_index[];
|
||||
uint input_edge_draw_flag[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 2) writeonly buffer outputEdgeFactors
|
||||
|
@ -51,9 +51,9 @@ float loop_edge_factor_get(vec3 f_no, vec3 v_co, vec3 v_no, vec3 v_next_co)
|
|||
float compute_line_factor(uint start_loop_index, uint corner_index, vec3 face_normal)
|
||||
{
|
||||
uint vertex_index = start_loop_index + corner_index;
|
||||
uint edge_index = input_edge_index[vertex_index];
|
||||
uint edge_draw_flag = input_edge_draw_flag[vertex_index];
|
||||
|
||||
if (edge_index == -1 && optimal_display) {
|
||||
if (edge_draw_flag == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue