Overlay to show concave/convex edges #115335
|
@ -776,10 +776,13 @@ set(GLSL_SRC
|
|||
engines/overlay/shaders/overlay_edit_lattice_wire_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_analysis_frag.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_analysis_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_analysis_v2_frag.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_analysis_v2_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_common_lib.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_depth_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_frag.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_geom.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_analysis_v2_geom.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_normal_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_skin_root_vert.glsl
|
||||
engines/overlay/shaders/overlay_edit_mesh_vert.glsl
|
||||
|
|
|
@ -138,6 +138,17 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
|
|||
pd->edit_mesh_analysis_grp = grp = DRW_shgroup_create(sh, psl->edit_mesh_analysis_ps);
|
||||
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
|
||||
}
|
||||
|
||||
{
|
||||
/* Mesh Analysis Pass */
|
||||
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
|
||||
DRW_PASS_CREATE(psl->edit_mesh_analysis_v2_ps, state | pd->clipping_state);
|
||||
|
||||
sh = OVERLAY_shader_edit_mesh_analysis_v2();
|
||||
pd->edit_mesh_analysis_v2_grp = grp = DRW_shgroup_create(sh, psl->edit_mesh_analysis_v2_ps);
|
||||
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
|
||||
}
|
||||
|
||||
/* Run Twice for in-front passes. */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert);
|
||||
|
@ -288,9 +299,19 @@ void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
|||
bool lnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
|
||||
|
||||
if (do_show_mesh_analysis && !pd->xray_enabled) {
|
||||
geom = DRW_cache_mesh_surface_mesh_analysis_get(ob);
|
||||
if (geom) {
|
||||
DRW_shgroup_call_no_cull(pd->edit_mesh_analysis_grp, geom, ob);
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
auto type = draw_ctx->scene->toolsettings->statvis.type;
|
||||
if (type == SCE_STATVIS_ANGLE || type == SCE_STATVIS_SHARP) {
|
||||
geom = DRW_cache_mesh_surface_mesh_analysis_v2_get(ob);
|
||||
if (geom) {
|
||||
DRW_shgroup_call_no_cull(pd->edit_mesh_analysis_v2_grp, geom, ob);
|
||||
}
|
||||
}
|
||||
else {
|
||||
geom = DRW_cache_mesh_surface_mesh_analysis_get(ob);
|
||||
if (geom) {
|
||||
DRW_shgroup_call_no_cull(pd->edit_mesh_analysis_grp, geom, ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,6 +383,7 @@ void OVERLAY_edit_mesh_draw(OVERLAY_Data *vedata)
|
|||
}
|
||||
|
||||
DRW_draw_pass(psl->edit_mesh_analysis_ps);
|
||||
DRW_draw_pass(psl->edit_mesh_analysis_v2_ps);
|
||||
|
||||
DRW_draw_pass(psl->edit_mesh_depth_ps[NOT_IN_FRONT]);
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ struct OVERLAY_PassList {
|
|||
DRWPass *edit_curves_handles_ps;
|
||||
DRWPass *edit_curves_lines_ps[2];
|
||||
DRWPass *edit_mesh_analysis_ps;
|
||||
DRWPass *edit_mesh_analysis_v2_ps;
|
||||
DRWPass *edit_mesh_normals_ps;
|
||||
DRWPass *edit_particle_ps;
|
||||
DRWPass *edit_text_cursor_ps;
|
||||
|
@ -265,6 +266,7 @@ struct OVERLAY_PrivateData {
|
|||
DRWShadingGroup *edit_mesh_skin_roots_grp[2];
|
||||
DRWShadingGroup *edit_mesh_normals_grp;
|
||||
DRWShadingGroup *edit_mesh_analysis_grp;
|
||||
DRWShadingGroup *edit_mesh_analysis_v2_grp;
|
||||
DRWShadingGroup *edit_particle_strand_grp;
|
||||
DRWShadingGroup *edit_particle_point_grp;
|
||||
DRWShadingGroup *edit_text_cursor_grp;
|
||||
|
@ -746,6 +748,7 @@ GPUShader *OVERLAY_shader_edit_gpencil_wire();
|
|||
GPUShader *OVERLAY_shader_edit_lattice_point();
|
||||
GPUShader *OVERLAY_shader_edit_lattice_wire();
|
||||
GPUShader *OVERLAY_shader_edit_mesh_analysis();
|
||||
GPUShader *OVERLAY_shader_edit_mesh_analysis_v2();
|
||||
GPUShader *OVERLAY_shader_edit_mesh_depth();
|
||||
GPUShader *OVERLAY_shader_edit_mesh_edge(bool use_flat_interp);
|
||||
GPUShader *OVERLAY_shader_edit_mesh_face();
|
||||
|
|
|
@ -52,6 +52,7 @@ struct OVERLAY_Shaders {
|
|||
GPUShader *edit_mesh_normals;
|
||||
GPUShader *edit_mesh_fnormals;
|
||||
GPUShader *edit_mesh_analysis;
|
||||
GPUShader *edit_mesh_analysis_v2;
|
||||
GPUShader *edit_particle_strand;
|
||||
GPUShader *edit_particle_point;
|
||||
GPUShader *edit_uv_verts;
|
||||
|
@ -465,6 +466,18 @@ GPUShader *OVERLAY_shader_edit_mesh_analysis()
|
|||
return sh_data->edit_mesh_analysis;
|
||||
}
|
||||
|
||||
GPUShader *OVERLAY_shader_edit_mesh_analysis_v2()
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
|
||||
if (!sh_data->edit_mesh_analysis_v2) {
|
||||
sh_data->edit_mesh_analysis_v2 = GPU_shader_create_from_info_name(
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_edit_mesh_analysis_v2_clipped" :
|
||||
"overlay_edit_mesh_analysis_v2");
|
||||
}
|
||||
return sh_data->edit_mesh_analysis_v2;
|
||||
}
|
||||
|
||||
GPUShader *OVERLAY_shader_edit_mesh_skin_root()
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
|
|
|
@ -178,6 +178,26 @@ GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis)
|
|||
.fragment_source("overlay_edit_mesh_analysis_frag.glsl")
|
||||
.additional_info("draw_modelmat");
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_analysis_v2_iface, "geometry_in")
|
||||
.smooth(Type::VEC4, "weightColor")
|
||||
.flat(Type::IVEC2, "vid");
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_analysis_geo_out_v2_iface, "geometry_out")
|
||||
.smooth(Type::VEC4, "weightColorGeo");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis_v2)
|
||||
.do_static_compilation(true)
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.vertex_in(1, Type::VEC3, "weight")
|
||||
.vertex_out(overlay_edit_mesh_analysis_v2_iface)
|
||||
.geometry_out(overlay_edit_mesh_analysis_geo_out_v2_iface)
|
||||
.sampler(0, ImageType::FLOAT_1D, "weightTex")
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.vertex_source("overlay_edit_mesh_analysis_v2_vert.glsl")
|
||||
.fragment_source("overlay_edit_mesh_analysis_v2_frag.glsl")
|
||||
.geometry_layout(PrimitiveIn::TRIANGLES, PrimitiveOut::TRIANGLE_STRIP, 15)
|
||||
.geometry_source("overlay_edit_mesh_analysis_v2_geom.glsl")
|
||||
.additional_info("draw_modelmat");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_skin_root)
|
||||
.do_static_compilation(true)
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
|
@ -231,6 +251,10 @@ GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis_clipped)
|
|||
.do_static_compilation(true)
|
||||
.additional_info("overlay_edit_mesh_analysis", "drw_clipped");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis_v2_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_edit_mesh_analysis_v2", "drw_clipped");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_skin_root_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_edit_mesh_skin_root", "drw_clipped");
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = geometry_out.weightColorGeo;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* SPDX-FileCopyrightText: 2018-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
void draw_edge(vec4 a, vec4 b, vec4 c, vec4 color)
|
||||
{
|
||||
vec4 trans = c - (a + b) * 0.5f;
|
||||
vec4 eps = vec4(0.0f, 0.0f, -1e-5f, 0.0f);
|
||||
|
||||
gl_Position = a;
|
||||
geometry_out.weightColorGeo = color;
|
||||
gpu_EmitVertex();
|
||||
|
||||
gl_Position = a * 0.80f + b * 0.10f + c * 0.10f + eps;
|
||||
geometry_out.weightColorGeo = color;
|
||||
gpu_EmitVertex();
|
||||
|
||||
gl_Position = b;
|
||||
geometry_out.weightColorGeo = color;
|
||||
gpu_EmitVertex();
|
||||
|
||||
gl_Position = b * 0.80f + a * 0.10f + c * 0.10f + eps;
|
||||
geometry_out.weightColorGeo = color;
|
||||
gpu_EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 gray = vec4(0.25f, 0.25f, 0.25f, 1.0f);
|
||||
vec4 red = vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
vec4 green = vec4(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
vec4 w[3] = {gray, gray, gray};
|
||||
|
||||
ivec2 vid0 = geometry_in[0].vid;
|
||||
ivec2 vid1 = geometry_in[1].vid;
|
||||
ivec2 vid2 = geometry_in[2].vid;
|
||||
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
geometry_out.weightColorGeo = gray;
|
||||
gpu_EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
geometry_out.weightColorGeo = gray;
|
||||
gpu_EmitVertex();
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
geometry_out.weightColorGeo = gray;
|
||||
gpu_EmitVertex();
|
||||
EndPrimitive();
|
||||
|
||||
if (vid0[1] == vid1[0])
|
||||
draw_edge(gl_in[0].gl_Position,
|
||||
gl_in[1].gl_Position,
|
||||
gl_in[2].gl_Position,
|
||||
geometry_in[0].weightColor);
|
||||
if (vid1[1] == vid2[0])
|
||||
draw_edge(gl_in[1].gl_Position,
|
||||
gl_in[2].gl_Position,
|
||||
gl_in[0].gl_Position,
|
||||
geometry_in[1].weightColor);
|
||||
if (vid2[1] == vid0[0])
|
||||
draw_edge(gl_in[2].gl_Position,
|
||||
gl_in[0].gl_Position,
|
||||
gl_in[1].gl_Position,
|
||||
geometry_in[2].weightColor);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* SPDX-FileCopyrightText: 2016-2022 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
vec3 hsv_to_rgb(vec3 hsv)
|
||||
{
|
||||
vec3 nrgb = abs(hsv.x * 6.0 - vec3(3.0, 2.0, 4.0)) * vec3(1, -1, -1) + vec3(-1, 2, 2);
|
||||
nrgb = clamp(nrgb, 0.0, 1.0);
|
||||
return ((nrgb - 1.0) * hsv.y + 1.0) * hsv.z;
|
||||
}
|
||||
|
||||
vec3 weight_to_rgb(float x)
|
||||
{
|
||||
if (x >= 1.0f) // angle overlay
|
||||
{
|
||||
x -= 1.5f;
|
||||
float t;
|
||||
if (x > -0.001f && x < 0.001f)
|
||||
return hsv_to_rgb(vec3(0.333, 0, 0.25));
|
||||
else {
|
||||
t = x;
|
||||
}
|
||||
|
||||
float h = clamp(0.333 + t + (t > 0 ? 0.20f : -0.20f), 0, 0.666);
|
||||
float s = clamp((t > 0 ? t : -t) * 6, 0.10, 1);
|
||||
float v = 0.25;
|
||||
return hsv_to_rgb(vec3(h, s, v));
|
||||
}
|
||||
|
||||
// sharp overlay
|
||||
|
||||
if (x < 0.0) {
|
||||
/* Minimum color, gray */
|
||||
return vec3(0.25, 0.25, 0.25);
|
||||
}
|
||||
return texture(weightTex, x).rgb;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
GPU_INTEL_VERTEX_SHADER_WORKAROUND
|
||||
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
geometry_in.weightColor = vec4(weight_to_rgb(weight.x), 1);
|
||||
geometry_in.vid.x = floatBitsToInt(weight.y);
|
||||
if (weight.x < 0) {
|
||||
/* sharp mode, unmarked edge */
|
||||
geometry_in.vid.y = -1;
|
||||
}
|
||||
else {
|
||||
geometry_in.vid.y = floatBitsToInt(weight.z);
|
||||
}
|
||||
view_clipping_distances(world_pos);
|
||||
}
|
|
@ -2983,6 +2983,13 @@ blender::gpu::Batch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
|
|||
return DRW_mesh_batch_cache_get_edit_mesh_analysis(static_cast<Mesh *>(ob->data));
|
||||
}
|
||||
|
||||
blender::gpu::Batch *DRW_cache_mesh_surface_mesh_analysis_v2_get(Object *ob)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
return DRW_mesh_batch_cache_get_edit_mesh_analysis_v2(static_cast<Mesh *>(ob->data));
|
||||
}
|
||||
|
||||
blender::gpu::Batch *DRW_cache_mesh_surface_viewer_attribute_get(Object *ob)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
|
|
|
@ -174,6 +174,7 @@ blender::gpu::Batch *DRW_cache_mesh_surface_vertpaint_get(Object *ob);
|
|||
blender::gpu::Batch *DRW_cache_mesh_surface_sculptcolors_get(Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_mesh_surface_weights_get(Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_mesh_surface_mesh_analysis_v2_get(Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_mesh_face_wireframe_get(Object *ob);
|
||||
blender::gpu::Batch *DRW_cache_mesh_surface_viewer_attribute_get(Object *ob);
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ struct MeshBatchList {
|
|||
gpu::Batch *surface;
|
||||
gpu::Batch *surface_weights;
|
||||
/* Edit mode */
|
||||
<<<<<<< HEAD
|
||||
gpu::Batch *edit_triangles;
|
||||
gpu::Batch *edit_vertices;
|
||||
gpu::Batch *edit_edges;
|
||||
|
@ -142,6 +143,17 @@ struct MeshBatchList {
|
|||
gpu::Batch *edit_fdots;
|
||||
gpu::Batch *edit_mesh_analysis;
|
||||
gpu::Batch *edit_skin_roots;
|
||||
=======
|
||||
GPUBatch *edit_triangles;
|
||||
GPUBatch *edit_vertices;
|
||||
GPUBatch *edit_edges;
|
||||
GPUBatch *edit_vnor;
|
||||
GPUBatch *edit_lnor;
|
||||
GPUBatch *edit_fdots;
|
||||
GPUBatch *edit_mesh_analysis;
|
||||
GPUBatch *edit_mesh_analysis_v2;
|
||||
GPUBatch *edit_skin_roots;
|
||||
>>>>>>> 5559ab6f6de (Edge painting overlay shader)
|
||||
/* Edit UVs */
|
||||
gpu::Batch *edituv_faces_stretch_area;
|
||||
gpu::Batch *edituv_faces_stretch_angle;
|
||||
|
|
|
@ -274,6 +274,7 @@ blender::gpu::Batch *DRW_mesh_batch_cache_get_edituv_facedots(Object *object, Me
|
|||
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_uv_edges(Object *object, Mesh *mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_edit_mesh_analysis_v2(Mesh *mesh);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -952,6 +952,13 @@ gpu::Batch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *mesh)
|
|||
return DRW_batch_request(&cache.batch.edit_mesh_analysis);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis_v2(Mesh *mesh)
|
||||
{
|
||||
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
|
||||
mesh_batch_cache_add_request(cache, MBC_EDIT_MESH_ANALYSIS);
|
||||
return DRW_batch_request(&cache.batch.edit_mesh_analysis_v2);
|
||||
}
|
||||
|
||||
void DRW_mesh_get_attributes(const Object *object,
|
||||
const Mesh *mesh,
|
||||
const GPUMaterial *const *gpumat_array,
|
||||
|
@ -1626,6 +1633,11 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
|
|||
DRW_vbo_request(cache.batch.edit_mesh_analysis, &mbuflist->vbo.pos);
|
||||
DRW_vbo_request(cache.batch.edit_mesh_analysis, &mbuflist->vbo.mesh_analysis);
|
||||
}
|
||||
if (DRW_batch_requested(cache.batch.edit_mesh_analysis_v2, GPU_PRIM_TRIS)) {
|
||||
DRW_ibo_request(cache.batch.edit_mesh_analysis_v2, &mbuflist->ibo.tris);
|
||||
DRW_vbo_request(cache.batch.edit_mesh_analysis_v2, &mbuflist->vbo.pos_nor);
|
||||
DRW_vbo_request(cache.batch.edit_mesh_analysis_v2, &mbuflist->vbo.mesh_analysis);
|
||||
}
|
||||
|
||||
/* Per Material */
|
||||
assert_deps_valid(
|
||||
|
|
|
@ -32,12 +32,17 @@ static void extract_mesh_analysis_init(const MeshRenderData &mr,
|
|||
void * /*tls_data*/)
|
||||
{
|
||||
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
|
||||
static GPUVertFormat format = {0};
|
||||
static GPUVertFormat format = {0}, format_v2 = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format_v2, "weight", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
if (mr.toolsettings->statvis.type == SCE_STATVIS_ANGLE ||
|
||||
mr.toolsettings->statvis.type == SCE_STATVIS_SHARP)
|
||||
GPU_vertbuf_init_with_format(vbo, &format_v2);
|
||||
else
|
||||
GPU_vertbuf_init_with_format(vbo, &format);
|
||||
GPU_vertbuf_data_alloc(vbo, mr.corners_num);
|
||||
}
|
||||
|
||||
|
@ -486,7 +491,7 @@ BLI_INLINE float sharp_remap(float fac, float min, float /*max*/, float minmax_i
|
|||
/* important not '>=' */
|
||||
if (fac > min) {
|
||||
fac = (fac - min) * minmax_irange;
|
||||
CLAMP(fac, 0.0f, 1.0f);
|
||||
CLAMP(fac, 0.001f, 0.999f);
|
||||
}
|
||||
else {
|
||||
/* fallback */
|
||||
|
@ -589,6 +594,116 @@ static void statvis_calc_sharp(const MeshRenderData &mr, float *r_sharp)
|
|||
MEM_freeN(vert_angles);
|
||||
}
|
||||
|
||||
BLI_INLINE float angle_remap(float angle)
|
||||
{
|
||||
angle /= 2 * 3.1415926f;
|
||||
CLAMP(angle, -0.4999f, 0.4999f);
|
||||
return 1.5f + angle;
|
||||
}
|
||||
|
||||
struct angle_data {
|
||||
float angle;
|
||||
int vs[2];
|
||||
};
|
||||
|
||||
static void statvis_calc_angle(const MeshRenderData &mr, float *data, bool sharp)
|
||||
{
|
||||
BMEditMesh *em = mr.edit_bmesh;
|
||||
const MeshStatVis *statvis = &mr.toolsettings->statvis;
|
||||
|
||||
const float min = statvis->sharp_min;
|
||||
const float max = statvis->sharp_max;
|
||||
const float minmax_irange = 1.0f / (max - min);
|
||||
|
||||
angle_data *r_angle = (angle_data *)data;
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
for (int l_index = 0; l_index < mr.loop_len; l_index++) {
|
||||
r_angle[l_index].angle = 0.0f;
|
||||
r_angle[l_index].vs[0] = -1;
|
||||
r_angle[l_index].vs[1] = -1;
|
||||
}
|
||||
|
||||
BMIter iter;
|
||||
BMesh *bm = em->bm;
|
||||
BMFace *efa;
|
||||
BMEdge *e;
|
||||
|
||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
|
||||
do {
|
||||
BMEdge *e = l_iter->e;
|
||||
int l_index = BM_elem_index_get(l_iter);
|
||||
int v_index = BM_elem_index_get(l_iter->v);
|
||||
float angle = BM_edge_calc_face_angle_signed_ex(e, 0.0f);
|
||||
if (sharp)
|
||||
angle = sharp_remap(angle, min, max, minmax_irange);
|
||||
else
|
||||
angle = angle_remap(angle);
|
||||
r_angle[l_index].angle = angle;
|
||||
r_angle[l_index].vs[0] = BM_elem_index_get(l_iter->v);
|
||||
r_angle[l_index].vs[1] = BM_elem_index_get(l_iter->next->v);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: this is untested: how can I trigger this pathway?
|
||||
angle_data *vert_angles = (angle_data *)MEM_mallocN(sizeof(angle_data) * mr.vert_len,
|
||||
__func__);
|
||||
memset(vert_angles, 0, sizeof(angle_data) * mr.vert_len);
|
||||
|
||||
Map<OrderedEdge, int> eh;
|
||||
eh.reserve(mr.edge_len);
|
||||
|
||||
for (int face_index = 0; face_index < mr.face_len; face_index++) {
|
||||
const IndexRange face = mr.faces[face_index];
|
||||
for (int i = 0; i < face.size(); i++) {
|
||||
const int vert_curr = mr.corner_verts[face.start() + (i + 0) % face.size()];
|
||||
const int vert_next = mr.corner_verts[face.start() + (i + 1) % face.size()];
|
||||
float angle;
|
||||
bool angle_set = false;
|
||||
eh.add_or_modify(
|
||||
{vert_curr, vert_next},
|
||||
[&](int *value) { *value = face_index; },
|
||||
[&](int *value) {
|
||||
const int other_face_index = *value;
|
||||
if (other_face_index == -1) {
|
||||
/* non-manifold edge */
|
||||
// angle = DEG2RADF(90.0f);
|
||||
return;
|
||||
}
|
||||
const float *f1_no = mr.face_normals[face_index];
|
||||
const float *f2_no = mr.face_normals[other_face_index];
|
||||
angle = angle_normalized_v3v3(f1_no, f2_no);
|
||||
angle = is_edge_convex_v3(mr.vert_positions[vert_curr],
|
||||
mr.vert_positions[vert_next],
|
||||
f1_no,
|
||||
f2_no) ?
|
||||
angle :
|
||||
-angle;
|
||||
/* Tag as manifold. */
|
||||
*value = -1;
|
||||
angle_set = true;
|
||||
});
|
||||
if (angle_set) {
|
||||
if (sharp)
|
||||
angle = sharp_remap(angle, min, max, minmax_irange);
|
||||
else
|
||||
angle = angle_remap(angle);
|
||||
vert_angles[vert_curr] = angle_data{angle, vert_curr, vert_next};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int l_index = 0; l_index < mr.loop_len; l_index++) {
|
||||
const int vert = mr.corner_verts[l_index];
|
||||
r_angle[l_index] = vert_angles[vert];
|
||||
}
|
||||
MEM_freeN(vert_angles);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_analysis_iter_finish_mesh(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
|
@ -613,7 +728,10 @@ static void extract_analysis_iter_finish_mesh(const MeshRenderData &mr,
|
|||
statvis_calc_distort(mr, l_weight);
|
||||
break;
|
||||
case SCE_STATVIS_SHARP:
|
||||
statvis_calc_sharp(mr, l_weight);
|
||||
statvis_calc_angle(mr, l_weight, true);
|
||||
break;
|
||||
case SCE_STATVIS_ANGLE:
|
||||
statvis_calc_angle(mr, l_weight, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2461,6 +2461,7 @@ enum {
|
|||
SCE_STATVIS_INTERSECT = 2,
|
||||
SCE_STATVIS_DISTORT = 3,
|
||||
SCE_STATVIS_SHARP = 4,
|
||||
SCE_STATVIS_ANGLE = 5,
|
||||
};
|
||||
|
||||
/** #ParticleEditSettings::selectmode for particles */
|
||||
|
|
|
@ -4440,6 +4440,7 @@ static void rna_def_statvis(BlenderRNA *brna)
|
|||
{SCE_STATVIS_INTERSECT, "INTERSECT", 0, "Intersect", ""},
|
||||
{SCE_STATVIS_DISTORT, "DISTORT", 0, "Distortion", ""},
|
||||
{SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""},
|
||||
{SCE_STATVIS_ANGLE, "ANGLE", 0, "Angle", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue