From 14f9f167b2686a92883b754d111adbb5efec2515 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2013 09:27:23 +0000 Subject: [PATCH] display options to help with 3d printing. editmesh debug info, - overhang (with axis angle options) - wall thickness (with min/max distance) - self-intersections. access below 'Mesh Display' panel. --- release/scripts/startup/bl_ui/space_view3d.py | 38 +++ source/blender/blenkernel/BKE_editmesh.h | 7 + .../blender/blenkernel/intern/DerivedMesh.c | 37 +++ .../blenkernel/intern/editderivedmesh.c | 305 +++++++++++++++++- source/blender/blenkernel/intern/editmesh.c | 2 + source/blender/blenkernel/intern/scene.c | 6 + source/blender/blenloader/intern/readfile.c | 14 + source/blender/editors/include/ED_mesh.h | 6 + source/blender/makesdna/DNA_mesh_types.h | 3 + source/blender/makesdna/DNA_scene_types.h | 22 ++ source/blender/makesrna/intern/rna_mesh.c | 5 + source/blender/makesrna/intern/rna_scene.c | 99 ++++++ 12 files changed, 540 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 1c05bc7e556..40309067549 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2607,6 +2607,44 @@ class VIEW3D_PT_view3d_meshdisplay(Panel): layout.prop(mesh, "show_extra_indices") +class VIEW3D_PT_view3d_meshstatvis(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_label = "Mesh Debug" + + @classmethod + def poll(cls, context): + # The active object check is needed because of local-mode + return (context.active_object and (context.mode == 'EDIT_MESH')) + + def draw_header(self, context): + mesh = context.active_object.data + + self.layout.prop(mesh, "show_statvis", text="") + + def draw(self, context): + layout = self.layout + + mesh = context.active_object.data + statvis = context.tool_settings.statvis + layout.active = mesh.show_statvis + + layout.prop(statvis, "type") + statvis_type = statvis.type + if statvis_type == 'OVERHANG': + row = layout.row(align=True) + row.prop(statvis, "overhang_min", text="") + row.prop(statvis, "overhang_max", text="") + layout.prop(statvis, "overhang_axis", expand=True) + elif statvis_type == 'THICKNESS': + row = layout.row(align=True) + row.prop(statvis, "thickness_min", text="") + row.prop(statvis, "thickness_max", text="") + layout.prop(statvis, "thickness_samples") + elif statvis_type == 'INTERSECT': + pass + + class VIEW3D_PT_view3d_curvedisplay(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 934689424fa..7052cb6012c 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -30,6 +30,8 @@ struct BMesh; struct BMLoop; struct BMFace; struct Mesh; +struct DerivedMesh; +struct MeshStatVis; /* ok: the EDBM module is for editmode bmesh stuff. in contrast, the * BMEdit module is for code shared with blenkernel that concerns @@ -61,6 +63,8 @@ typedef struct BMEditMesh { CustomDataMask lastDataMask; unsigned char (*derivedVertColor)[4]; int derivedVertColorLen; + unsigned char (*derivedFaceColor)[4]; + int derivedFaceColorLen; /* index tables, to map indices to elements via * EDBM_index_arrays_init and associated functions. don't @@ -89,5 +93,8 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em); BMEditMesh *BKE_editmesh_from_object(struct Object *ob); void BKE_editmesh_free(BMEditMesh *em); void BKE_editmesh_update_linked_customdata(BMEditMesh *em); +void BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm, + struct MeshStatVis *statvis, + unsigned char (*r_face_colors)[4]); #endif /* __BKE_EDITMESH_H__ */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d1a1163d5c7..255723b0977 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1204,6 +1204,14 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, int i; if (em) { + + /* no need to store both */ + if (em->derivedFaceColor) { + MEM_freeN(em->derivedFaceColor); + em->derivedFaceColor = NULL; + em->derivedFaceColorLen = 0; + } + if (em->derivedVertColor && em->derivedVertColorLen == numVerts) { wtcol_v = em->derivedVertColor; } @@ -1283,6 +1291,30 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, } } +static void DM_update_statvis_color(Scene *scene, Object *ob, DerivedMesh *dm) +{ + BMEditMesh *em = BKE_editmesh_from_object(ob); + int numFaces = em->bm->totface; + unsigned char (*wtcol_f)[4]; + + /* no need to store both */ + if (em->derivedVertColor) { + MEM_freeN(em->derivedVertColor); + em->derivedVertColor = NULL; + em->derivedVertColorLen = 0; + } + + if (em->derivedFaceColor && em->derivedFaceColorLen == numFaces) { + wtcol_f = em->derivedFaceColor; + } + else { + if (em->derivedFaceColor) MEM_freeN(em->derivedFaceColor); + wtcol_f = em->derivedFaceColor = MEM_mallocN(sizeof(*wtcol_f) * numFaces, __func__); + em->derivedFaceColorLen = numFaces; + } + + BKE_editmesh_statvis_calc(em, dm, &scene->toolsettings->statvis, wtcol_f); +} static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid) { @@ -1939,6 +1971,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D #endif const int do_final_wmcol = FALSE; int do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol); + int do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol); modifiers_clearErrors(ob); @@ -2127,6 +2160,8 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D /* In this case, we should never have weight-modifying modifiers in stack... */ if (do_init_wmcol) DM_update_weight_mcol(ob, *final_r, draw_flag, NULL, 0, NULL); + if (do_init_statvis) + DM_update_statvis_color(scene, ob, *final_r); } else { /* this is just a copy of the editmesh, no need to calc normals */ @@ -2136,6 +2171,8 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D /* In this case, we should never have weight-modifying modifiers in stack... */ if (do_init_wmcol) DM_update_weight_mcol(ob, *final_r, draw_flag, NULL, 0, NULL); + if (do_init_statvis) + DM_update_statvis_color(scene, ob, *final_r); } /* --- */ diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 447dd88a0a6..6435e6e98a7 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -44,12 +44,15 @@ #include "GL/glew.h" #include "BLI_math.h" +#include "BLI_jitter.h" #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" #include "BKE_editmesh.h" +#include "BKE_editmesh_bvh.h" #include "DNA_mesh_types.h" +#include "DNA_scene_types.h" #include "DNA_object_types.h" #include "MEM_guardedalloc.h" @@ -320,8 +323,10 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, const int skip_normals = !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */ MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */; - unsigned char(*color_vert_array)[4] = (((Mesh *)em->ob->data)->drawflag & ME_DRAWEIGHT) ? em->derivedVertColor : NULL; + unsigned char(*color_vert_array)[4] = (((Mesh *)em->ob->data)->drawflag & ME_DRAWEIGHT) ? em->derivedVertColor : NULL; + unsigned char(*color_face_array)[4] = (((Mesh *)em->ob->data)->drawflag & ME_DRAW_STATVIS) ? em->derivedFaceColor : NULL; bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals; + bool has_fcol_preview = (color_face_array != NULL) && !skip_normals; bool has_vcol_any = has_vcol_preview; /* GL_ZERO is used to detect if drawing has started or not */ @@ -336,6 +341,11 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, /* call again below is ok */ if (has_vcol_preview) { BM_mesh_elem_index_ensure(bm, BM_VERT); + } + if (has_fcol_preview) { + BM_mesh_elem_index_ensure(bm, BM_FACE); + } + if (has_vcol_preview || has_fcol_preview) { flag |= DM_DRAW_ALWAYS_SMOOTH; glDisable(GL_LIGHTING); /* grr */ } @@ -370,8 +380,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, glPolygonStipple(stipple_quarttone); } - if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - + if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); + else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)])); if (skip_normals) { if (poly_type != poly_prev) { if (poly_prev != GL_ZERO) glEnd(); @@ -455,7 +465,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, glPolygonStipple(stipple_quarttone); } - if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); + if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); + else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)])); if (skip_normals) { if (poly_type != poly_prev) { @@ -1530,3 +1541,289 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, return (DerivedMesh *)bmdm; } + + + +/* -------------------------------------------------------------------- */ +/* StatVis Functions */ + +static void axis_from_enum_v3(float v[3], const char axis) +{ + zero_v3(v); + if (axis < 3) v[axis] = 1.0f; + else v[axis - 3] = -1.0f; +} + +static void statvis_calc_overhang( + BMEditMesh *em, + float (*polyNos)[3], + /* values for calculating */ + const float min, const float max, const char axis, + /* result */ + unsigned char (*r_face_colors)[4]) +{ + BMIter iter; + BMesh *bm = em->bm; + BMFace *f; + float dir[3]; + int index; + const float minmax_irange = 1.0f / (max - min); + + /* fallback */ + const char col_fallback[4] = {64, 64, 64, 255}; + + BLI_assert(min <= max); + + axis_from_enum_v3(dir, axis); + + /* now convert into global space */ + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) { + float fac = angle_normalized_v3v3(polyNos ? polyNos[index] : f->no, dir) / (float)M_PI; + + /* remap */ + if (fac >= min && fac <= max) { + float fcol[3]; + fac = (fac - min) * minmax_irange; + fac = 1.0f - fac; + CLAMP(fac, 0.0f, 1.0f); + weight_to_rgb(fcol, fac); + rgb_float_to_uchar(r_face_colors[index], fcol); + } + else { + copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback); + } + } +} + +/* so we can use jitter values for face interpolation */ +static void uv_from_jitter_v2(float uv[2]) +{ + uv[0] += 0.5f; + uv[1] += 0.5f; + if (uv[0] + uv[1] > 1.0f) { + uv[0] = 1.0f - uv[0]; + uv[1] = 1.0f - uv[1]; + } + + CLAMP(uv[0], 0.0f, 1.0f); + CLAMP(uv[1], 0.0f, 1.0f); +} + +static void statvis_calc_thickness( + BMEditMesh *em, + float (*vertexCos)[3], + /* values for calculating */ + const float min, const float max, const int samples, + /* result */ + unsigned char (*r_face_colors)[4]) +{ + const float eps_offset = FLT_EPSILON * 10.0f; + float *face_dists = (float *)r_face_colors; /* cheating */ + const bool use_jit = samples < 32; + float jit_ofs[32][2]; + BMesh *bm = em->bm; + const int tottri = em->tottri; + const float minmax_irange = 1.0f / (max - min); + int i; + + struct BMLoop *(*looptris)[3] = em->looptris; + + /* fallback */ + const char col_fallback[4] = {64, 64, 64, 255}; + + struct BMBVHTree *bmtree; + + BLI_assert(min <= max); + + fill_vn_fl(face_dists, em->bm->totface, max); + + if (use_jit) { + int j; + BLI_assert(samples < 32); + BLI_jitter_init(jit_ofs[0], samples); + + for (j = 0; j < samples; j++) { + uv_from_jitter_v2(jit_ofs[j]); + } + } + + (void)vertexCos; + + BM_mesh_elem_index_ensure(bm, BM_FACE); + if (vertexCos) { + BM_mesh_elem_index_ensure(bm, BM_VERT); + } + + bmtree = BKE_bmbvh_new(em, 0, NULL); + + for (i = 0; i < tottri; i++) { + BMFace *f_hit; + BMLoop **ltri = looptris[i]; + const int index = BM_elem_index_get(ltri[0]->f); + const float *cos[3]; + float ray_co[3]; + float ray_no[3]; + + if (vertexCos) { + cos[0] = vertexCos[BM_elem_index_get(ltri[0]->v)]; + cos[1] = vertexCos[BM_elem_index_get(ltri[1]->v)]; + cos[3] = vertexCos[BM_elem_index_get(ltri[2]->v)]; + } + else { + cos[0] = ltri[0]->v->co; + cos[1] = ltri[1]->v->co; + cos[2] = ltri[2]->v->co; + } + + normal_tri_v3(ray_no, cos[2], cos[1], cos[0]); + + if (use_jit) { + int j; + for (j = 0; j < samples; j++) { + interp_v3_v3v3v3_uv(ray_co, cos[0], cos[1], cos[2], jit_ofs[j]); + madd_v3_v3fl(ray_co, ray_no, eps_offset); + + f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, + &face_dists[index], NULL, NULL); + /* duplicate */ + if (f_hit) { + const int index_hit = BM_elem_index_get(f_hit); + face_dists[index] = face_dists[index_hit] = min_ff(face_dists[index], face_dists[index_hit]); + } + } + } + else { + mid_v3_v3v3v3(ray_co, cos[0], cos[1], cos[2]); + madd_v3_v3fl(ray_co, ray_no, eps_offset); + + f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, + &face_dists[index], NULL, NULL); + /* duplicate */ + if (f_hit) { + const int index_hit = BM_elem_index_get(f_hit); + face_dists[index] = face_dists[index_hit] = min_ff(face_dists[index], face_dists[index_hit]); + } + } + } + + /* convert floats into color! */ + for (i = 0; i < bm->totface; i++) { + float fac = face_dists[i]; + + /* important not '<=' */ + if (fac < max) { + float fcol[3]; + fac = (fac - min) * minmax_irange; + fac = 1.0f - fac; + CLAMP(fac, 0.0f, 1.0f); + weight_to_rgb(fcol, fac); + rgb_float_to_uchar(r_face_colors[i], fcol); + } + else { + copy_v4_v4_char((char *)r_face_colors[i], (const char *)col_fallback); + } + } + + BKE_bmbvh_free(bmtree); +} + +static void statvis_calc_intersect( + BMEditMesh *em, + float (*vertexCos)[3], + /* result */ + unsigned char (*r_face_colors)[4]) +{ + BMIter iter; + BMesh *bm = em->bm; + BMEdge *e; + int index; + + /* fallback */ + // const char col_fallback[4] = {64, 64, 64, 255}; + + struct BMBVHTree *bmtree; + + memset(r_face_colors, 64, sizeof(int) * em->bm->totface); + + (void)vertexCos; + + BM_mesh_elem_index_ensure(bm, BM_FACE); + if (vertexCos) { + BM_mesh_elem_index_ensure(bm, BM_VERT); + } + + bmtree = BKE_bmbvh_new(em, 0, NULL); + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMFace *f_hit; + float cos[2][3]; + float cos_mid[3]; + float ray_no[3]; + + if (vertexCos) { + copy_v3_v3(cos[0], vertexCos[BM_elem_index_get(e->v1)]); + copy_v3_v3(cos[1], vertexCos[BM_elem_index_get(e->v2)]); + } + else { + copy_v3_v3(cos[0], e->v1->co); + copy_v3_v3(cos[1], e->v2->co); + } + + mid_v3_v3v3(cos_mid, cos[0], cos[1]); + sub_v3_v3v3(ray_no, cos[1], cos[0]); + + f_hit = BKE_bmbvh_find_face_segment(bmtree, cos[0], cos[1], + NULL, NULL, NULL); + + if (f_hit) { + BMLoop *l_iter, *l_first; + float fcol[3]; + + index = BM_elem_index_get(f_hit); + weight_to_rgb(fcol, 1.0f); + rgb_float_to_uchar(r_face_colors[index], fcol); + + l_iter = l_first = e->l; + do { + index = BM_elem_index_get(l_iter->f); + weight_to_rgb(fcol, 1.0f); + rgb_float_to_uchar(r_face_colors[index], fcol); + } while ((l_iter = l_iter->radial_next) != l_first); + } + + } + + BKE_bmbvh_free(bmtree); +} + +void BKE_editmesh_statvis_calc(BMEditMesh *em, DerivedMesh *dm, + MeshStatVis *statvis, + unsigned char (*r_face_colors)[4]) +{ + EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; + BLI_assert(dm == NULL || dm->type == DM_TYPE_EDITBMESH); + + switch (statvis->type) { + case SCE_STATVIS_OVERHANG: + statvis_calc_overhang( + em, bmdm ? bmdm->polyNos : NULL, + statvis->overhang_min / (float)M_PI, + statvis->overhang_max / (float)M_PI, + statvis->overhang_axis, + r_face_colors); + break; + case SCE_STATVIS_THICKNESS: + statvis_calc_thickness( + em, bmdm ? bmdm->vertexCos : NULL, + statvis->thickness_min, + statvis->thickness_max, + statvis->thickness_samples, + r_face_colors); + break; + case SCE_STATVIS_INTERSECT: + statvis_calc_intersect( + em, bmdm ? bmdm->vertexCos : NULL, + r_face_colors); + break; + } +} diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 2782cecfd8d..6ddc7c07d0a 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -61,6 +61,7 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em) em_copy->derivedCage = em_copy->derivedFinal = NULL; em_copy->derivedVertColor = NULL; + em_copy->derivedFaceColor = NULL; em_copy->bm = BM_mesh_copy(em->bm); @@ -327,6 +328,7 @@ void BKE_editmesh_free(BMEditMesh *em) } if (em->derivedVertColor) MEM_freeN(em->derivedVertColor); + if (em->derivedFaceColor) MEM_freeN(em->derivedFaceColor); if (em->looptris) MEM_freeN(em->looptris); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 2685484b576..86dbc2a36b3 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -520,6 +520,12 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; + sce->toolsettings->statvis.overhang_axis = OB_NEGZ; + sce->toolsettings->statvis.overhang_min = 0; + sce->toolsettings->statvis.overhang_max = DEG2RADF(45.0f); + sce->toolsettings->statvis.thickness_max = 0.1f; + sce->toolsettings->statvis.thickness_samples = 1; + sce->toolsettings->proportional_size = 1.0f; sce->physics_settings.gravity[0] = 0.0f; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e7e8d6f3b99..48d412f8a26 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9320,6 +9320,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main) srl->freestyleConfig.flags |= FREESTYLE_CULLING; } } + + /* not freestyle */ + { + MeshStatVis *statvis = &sce->toolsettings->statvis; + if (statvis->thickness_samples == 0) { + statvis->overhang_axis = OB_NEGZ; + statvis->overhang_min = 0; + statvis->overhang_max = DEG2RADF(45.0f); + + statvis->thickness_max = 0.1f; + statvis->thickness_samples = 1; + } + } + } for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) { #if 1 diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 2c79f12de49..aa9178ee3fc 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -72,6 +72,7 @@ struct ToolSettings; struct Material; struct Object; struct rcti; +struct MeshStatVis; /* editmesh_utils.c */ @@ -176,6 +177,11 @@ void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */ bool EDBM_select_interior_faces(struct BMEditMesh *em); void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename? */ +/* editmesh_statvis.c */ +void EDBM_statvis_calc(struct BMEditMesh *em, struct MeshStatVis *statvis, + unsigned char (*r_face_colors)[4]); + + extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; /* mesh_ops.c */ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 6bd92ac9da8..499b8176e1d 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -206,6 +206,9 @@ typedef struct TFace { #define ME_DRAW_FREESTYLE_EDGE (1 << 15) #define ME_DRAW_FREESTYLE_FACE (1 << 16) +/* draw stats */ +#define ME_DRAW_STATVIS (1 << 17) + /* Subsurf Type */ #define ME_CC_SUBSURF 0 #define ME_SIMPLE_SUBSURF 1 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b306bc9a64f..2626c128b3a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -934,6 +934,21 @@ typedef enum { UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE = (1 << 4) } UnifiedPaintSettingsFlags; +typedef struct MeshStatVis { + char type; + char _pad1[2]; + + /* overhang */ + char overhang_axis; + float overhang_min, overhang_max; + + /* thickness */ + float thickness_min, thickness_max; + char thickness_samples; + char _pad2[3]; +} MeshStatVis; + + /* *************************************************************** */ /* Tool Settings */ @@ -1071,6 +1086,8 @@ typedef struct ToolSettings { /* Unified Paint Settings */ struct UnifiedPaintSettings unified_paint_settings; + + struct MeshStatVis statvis; } ToolSettings; /* *************************************************************** */ @@ -1445,6 +1462,11 @@ typedef struct Scene { #define SCE_SELECT_EDGE 2 #define SCE_SELECT_FACE 4 +/* toolsettings->statvis->type */ +#define SCE_STATVIS_OVERHANG 0 +#define SCE_STATVIS_THICKNESS 1 +#define SCE_STATVIS_INTERSECT 2 + /* toolsettings->particle.selectmode for particles */ #define SCE_SELECT_PATH 1 #define SCE_SELECT_POINT 2 diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 8a0f73eedda..56d93cc1d3b 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2954,6 +2954,11 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Freestyle Face Marks", "Display Freestyle face marks, used with the Freestyle renderer"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); + prop = RNA_def_property(srna, "show_statvis", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_STATVIS); + RNA_def_property_ui_text(prop, "Stat Vis", "Display statistical information about the mesh"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + prop = RNA_def_property(srna, "show_extra_edge_length", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_EDGELEN); RNA_def_property_ui_text(prop, "Edge Length", diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 12dbb514290..e931b35f83f 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1426,6 +1426,28 @@ static char *rna_UnifiedPaintSettings_path(PointerRNA *ptr) return BLI_strdup("tool_settings.unified_paint_settings"); } +/* generic function to recalc geometry */ +static void rna_EditMesh_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + Mesh *me = NULL; + + if (scene->basact) { + me = BKE_mesh_from_object(scene->basact->object); + if (me && me->edit_btmesh == NULL) + me = NULL; + } + + if (me) { + DAG_id_tag_update(&me->id, OB_RECALC_DATA); + WM_main_add_notifier(NC_GEOM | ND_DATA, me); + } +} + +static char *rna_MeshStatVis_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.statvis"); +} + /* note: without this, when Multi-Paint is activated/deactivated, the colors * will not change right away when multiple bones are selected, this function * is not for general use and only for the few cases where changing scene @@ -1900,6 +1922,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UnifiedPaintSettings"); RNA_def_property_ui_text(prop, "Unified Paint Settings", NULL); + + /* Mesh Statistics */ + prop = RNA_def_property(srna, "statvis", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "MeshStatVis"); + RNA_def_property_ui_text(prop, "Mesh Statistics Visualization", NULL); } static void rna_def_unified_paint_settings(BlenderRNA *brna) @@ -1972,6 +2000,76 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna) "when unlocked brush size is given in pixels"); } +static void rna_def_statvis(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem stat_type[] = { + {SCE_STATVIS_OVERHANG, "OVERHANG", 0, "Overhang", ""}, + {SCE_STATVIS_THICKNESS, "THICKNESS", 0, "Thickness", ""}, + {SCE_STATVIS_INTERSECT, "INTERSECT", 0, "Intersect", ""}, + {0, NULL, 0, NULL, NULL}}; + + srna = RNA_def_struct(brna, "MeshStatVis", NULL); + RNA_def_struct_path_func(srna, "rna_MeshStatVis_path"); + RNA_def_struct_ui_text(srna, "Mesh Visualize Statistics", ""); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, stat_type); + RNA_def_property_ui_text(prop, "Type", "XXX"); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); + + + /* overhang */ + prop = RNA_def_property(srna, "overhang_min", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "overhang_min"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); + RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3); + RNA_def_property_ui_text(prop, "Overhang Min", "Minimum angle to display"); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); + + prop = RNA_def_property(srna, "overhang_max", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "overhang_max"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); + RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3); + RNA_def_property_ui_text(prop, "Overhang Max", "Maximum angle to display"); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); + + prop = RNA_def_property(srna, "overhang_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "overhang_axis"); + RNA_def_property_enum_items(prop, object_axis_items); + RNA_def_property_ui_text(prop, "Axis", ""); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); + + + /* thickness */ + prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "thickness_min"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 100.0); + RNA_def_property_ui_range(prop, 0.0f, 10.0, 0.001, 3); + RNA_def_property_ui_text(prop, "Thickness Min", "Minimum for measuring thickness"); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); + + prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "thickness_max"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 100.0); + RNA_def_property_ui_range(prop, 0.0f, 10.0, 0.001, 3); + RNA_def_property_ui_text(prop, "Thickness Max", "Maximum for measuring thickness"); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); + + /* intersect */ + prop = RNA_def_property(srna, "thickness_samples", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "thickness_samples"); + RNA_def_property_range(prop, 1, 32); + RNA_def_property_ui_text(prop, "Samples", "Number of samples to test per face"); + RNA_def_property_update(prop, 0, "rna_EditMesh_update"); +} + static void rna_def_unit_settings(BlenderRNA *brna) { StructRNA *srna; @@ -5211,6 +5309,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_define_animate_sdna(false); rna_def_tool_settings(brna); rna_def_unified_paint_settings(brna); + rna_def_statvis(brna); rna_def_unit_settings(brna); rna_def_scene_image_format_data(brna); rna_def_scene_game_data(brna);