Overlay: Mesh Analysis

Enabling the drawing of the mesh analysis overlay.
Currently the settings are part of the scene toolsettings. What makes sense,
for 3d printing, but does not fit well with the per viewport blender 2.80
overlays.

Reviewers: brecht, fclem

Differential Revision: https://developer.blender.org/D4707
This commit is contained in:
2019-04-18 08:00:59 +02:00
parent 486d9356ba
commit 38a0896f15
8 changed files with 186 additions and 0 deletions

View File

@@ -277,6 +277,8 @@ data_to_c_simple(modes/shaders/edit_mesh_overlay_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mesh_analysis_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_handle_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_handle_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC)

View File

@@ -3283,6 +3283,12 @@ GPUBatch *DRW_cache_mesh_face_wireframe_get(Object *ob)
return DRW_mesh_batch_cache_get_wireframes_face(ob->data);
}
GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
return DRW_mesh_batch_cache_get_edit_mesh_analysis(ob->data);
}
void DRW_cache_mesh_sculpt_coords_ensure(Object *ob)
{
BLI_assert(ob->type == OB_MESH);

View File

@@ -140,6 +140,7 @@ struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_vertpaint_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob);
void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);

View File

@@ -157,6 +157,7 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me);
/* For Image UV editor. */
struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me);
void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);

View File

@@ -1911,6 +1911,7 @@ typedef struct MeshBatchCache {
GPUVertBuf *loop_data;
GPUVertBuf *loop_lnor;
GPUVertBuf *facedots_pos_nor_data;
GPUVertBuf *loop_mesh_analysis;
/* UV data without modifier applied.
* Vertex count is always the one of the cage. */
GPUVertBuf *loop_uv;
@@ -1958,6 +1959,7 @@ typedef struct MeshBatchCache {
GPUBatch *edit_edges;
GPUBatch *edit_lnor;
GPUBatch *edit_facedots;
GPUBatch *edit_mesh_analysis;
/* Edit UVs */
GPUBatch *edituv_faces_strech_area;
GPUBatch *edituv_faces_strech_angle;
@@ -2169,6 +2171,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_vertices);
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges);
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_facedots);
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_mesh_analysis);
/* Paint mode selection */
/* TODO only do that in paint mode. */
GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_pos_nor);
@@ -3383,6 +3386,72 @@ static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_fac
}
}
static void mesh_create_edit_mesh_analysis(MeshRenderData *rdata,
GPUVertBuf *vbo_mesh_analysis)
{
const MeshStatVis *mesh_stat_vis = &rdata->toolsettings->statvis;
int mesh_analysis_len_used = 0;
const uint loops_len = mesh_render_data_loops_len_get(rdata);
BMesh *bm = rdata->edit_bmesh->bm;
BMIter iter_efa, iter_loop;
BMFace *efa;
BMLoop *loop;
static struct {
uint weight;
} attr_id;
static GPUVertFormat mesh_analysis_format = {0};
if (mesh_analysis_format.attr_len == 0) {
attr_id.weight = GPU_vertformat_attr_add(
&mesh_analysis_format, "weight_color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
/* TODO(jbakker): Maybe move data generation to mesh_render_data_create() */
BKE_editmesh_statvis_calc(rdata->edit_bmesh, rdata->edit_data, mesh_stat_vis);
if (DRW_TEST_ASSIGN_VBO(vbo_mesh_analysis)) {
GPU_vertbuf_init_with_format(vbo_mesh_analysis, &mesh_analysis_format);
GPU_vertbuf_data_alloc(vbo_mesh_analysis, loops_len);
}
const bool is_vertex_data = mesh_stat_vis->type == SCE_STATVIS_SHARP;
if (is_vertex_data) {
BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
uint vertex_index = BM_elem_index_get(loop->v);
GPU_vertbuf_attr_set(vbo_mesh_analysis,
attr_id.weight,
mesh_analysis_len_used,
&rdata->edit_bmesh->derivedVertColor[vertex_index]);
mesh_analysis_len_used += 1;
}
}
}
else {
uint face_index;
BM_ITER_MESH_INDEX (efa, &iter_efa, bm, BM_FACES_OF_MESH, face_index) {
BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
GPU_vertbuf_attr_set(vbo_mesh_analysis,
attr_id.weight,
mesh_analysis_len_used,
&rdata->edit_bmesh->derivedFaceColor[face_index]);
mesh_analysis_len_used += 1;
}
}
}
// Free temp data in edit bmesh
BKE_editmesh_color_free(rdata->edit_bmesh);
/* Resize & Finish */
if (mesh_analysis_len_used != loops_len) {
if (vbo_mesh_analysis != NULL) {
GPU_vertbuf_data_resize(vbo_mesh_analysis, mesh_analysis_len_used);
}
}
}
/* Indices */
#define NO_EDGE INT_MAX
@@ -4195,6 +4264,12 @@ GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me)
return DRW_batch_request(&cache->batch.wire_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
return DRW_batch_request(&cache->batch.edit_mesh_analysis);
}
GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me,
struct GPUMaterial **gpumat_array,
uint gpumat_array_len,
@@ -4898,6 +4973,13 @@ void DRW_mesh_batch_cache_create_requested(
DRW_vbo_request(cache->batch.edit_facedots, &cache->edit.facedots_pos_nor_data);
}
/* Mesh Analysis */
if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache->batch.edit_mesh_analysis, &cache->ibo.edit_loops_tris);
DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_mesh_analysis);
}
/* Edit UV */
if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRI_FAN)) {
DRW_ibo_request(cache->batch.edituv_faces, &cache->ibo.edituv_loops_tri_fans);
@@ -5050,6 +5132,9 @@ void DRW_mesh_batch_cache_create_requested(
cache->edit.facedots_pos_nor_data,
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY |
MR_DATATYPE_OVERLAY);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag,
cache->edit.loop_mesh_analysis,
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_stretch_angle, combined_edit_flag);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_stretch_area, combined_edit_flag);
DRW_ADD_FLAG_FROM_VBO_REQUEST(
@@ -5177,6 +5262,9 @@ void DRW_mesh_batch_cache_create_requested(
if (DRW_ibo_requested(cache->ibo.edit_loops_tris)) {
mesh_create_edit_loops_tris(rdata, cache->ibo.edit_loops_tris);
}
if (DRW_vbo_requested(cache->edit.loop_mesh_analysis)) {
mesh_create_edit_mesh_analysis(rdata, cache->edit.loop_mesh_analysis);
}
/* UV editor */
/**

View File

@@ -55,6 +55,8 @@ extern char datatoc_edit_mesh_overlay_geom_glsl[];
extern char datatoc_edit_mesh_overlay_mix_frag_glsl[];
extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[];
extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[];
extern char datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl[];
extern char datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl[];
extern char datatoc_edit_normals_vert_glsl[];
extern char datatoc_edit_normals_geom_glsl[];
extern char datatoc_common_globals_lib_glsl[];
@@ -75,6 +77,7 @@ typedef struct EDIT_MESH_PassList {
struct DRWPass *edit_face_occluded;
struct DRWPass *mix_occlude;
struct DRWPass *facefill_occlude;
struct DRWPass *mesh_analysis_pass;
struct DRWPass *normals;
} EDIT_MESH_PassList;
@@ -115,6 +118,10 @@ typedef struct EDIT_MESH_Shaders {
GPUShader *normals_loop;
GPUShader *normals;
GPUShader *depth;
/* Mesh analysis shader */
GPUShader *mesh_analysis_face;
GPUShader *mesh_analysis_vertex;
} EDIT_MESH_Shaders;
/* *********** STATIC *********** */
@@ -149,6 +156,7 @@ typedef struct EDIT_MESH_PrivateData {
DRWShadingGroup *facedot_shgrp_in_front;
DRWShadingGroup *facefill_occluded_shgrp;
DRWShadingGroup *mesh_analysis_shgrp;
int data_mask[4];
int ghost_ob;
@@ -278,6 +286,22 @@ static void EDIT_MESH_engine_init(void *vedata)
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
/* Mesh Analysis */
sh_data->mesh_analysis_face = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define FACE_COLOR\n", NULL},
});
sh_data->mesh_analysis_vertex = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define VERTEX_COLOR\n", NULL},
});
sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
}
}
@@ -509,6 +533,18 @@ static void EDIT_MESH_cache_init(void *vedata)
}
}
{
/* Mesh Analysis Pass */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
psl->mesh_analysis_pass = DRW_pass_create("Mesh Analysis", state);
const bool is_vertex_color = scene->toolsettings->statvis.type == SCE_STATVIS_SHARP;
stl->g_data->mesh_analysis_shgrp = DRW_shgroup_create(
is_vertex_color ? sh_data->mesh_analysis_vertex : sh_data->mesh_analysis_face,
psl->mesh_analysis_pass);
if (rv3d->rflag & RV3D_CLIPPING) {
DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->mesh_analysis_shgrp, rv3d);
}
}
/* For in front option */
psl->edit_face_overlay_in_front = edit_mesh_create_overlay_pass(
&face_mod,
@@ -628,6 +664,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
bool do_show_weight = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT) != 0;
bool do_show_mesh_analysis = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_STATVIS) != 0;
bool fnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0;
bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0;
bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
@@ -656,6 +693,19 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add(g_data->fweights_shgrp, geom, ob->obmat);
}
if (do_show_mesh_analysis) {
Mesh *me = (Mesh *)ob->data;
BMEditMesh *embm = me->edit_mesh;
const bool is_original = embm->mesh_eval_final && \
(embm->mesh_eval_final->runtime.is_original == true);
if (is_original) {
geom = DRW_cache_mesh_surface_mesh_analysis_get(ob);
if (geom) {
DRW_shgroup_call_add(g_data->mesh_analysis_shgrp, geom, ob->obmat);
}
}
}
if (do_occlude_wire || do_in_front) {
geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_add(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front :
@@ -731,6 +781,7 @@ static void EDIT_MESH_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DRW_draw_pass(psl->weight_faces);
DRW_draw_pass(psl->mesh_analysis_pass);
DRW_draw_pass(psl->depth_hidden_wire);

View File

@@ -0,0 +1,14 @@
out vec4 fragColor;
#ifdef FACE_COLOR
flat in vec4 weightColor;
#endif
#ifdef VERTEX_COLOR
in vec4 weightColor;
#endif
void main()
{
fragColor = weightColor;
}

View File

@@ -0,0 +1,23 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelMatrix;
in vec3 pos;
in vec4 weight_color;
#ifdef FACE_COLOR
flat out vec4 weightColor;
#endif
#ifdef VERTEX_COLOR
out vec4 weightColor;
#endif
void main()
{
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
weightColor = vec4(weight_color.rgb, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
#endif
}