* Enable mask/fset extract for dyntopo]

* Fix nasty memory corruption bug
This commit is contained in:
Joseph Eagar 2021-06-30 21:13:24 -07:00
parent d66d5b431e
commit dcb00bf529
3 changed files with 50 additions and 212 deletions

View File

@ -3765,8 +3765,11 @@ CLANG_OPT_BUG static bool cleanup_valence_3_4(PBVH *pbvh,
vs[2] = ls[3]->v;
BMFace *f2 = pbvh_bmesh_face_create(pbvh, n, vs, NULL, v->e->l->f, false, false);
printf("%p %p %p\n", f2->l_first->prev->head.data, ls[3]->head.data);
CustomData_bmesh_swap_data_simple(
&pbvh->bm->pdata, &f2->l_first->prev->head.data, &ls[3]->head.data);
&pbvh->bm->ldata, &f2->l_first->prev->head.data, &ls[3]->head.data);
CustomData_bmesh_copy_data(
&pbvh->bm->ldata, &pbvh->bm->ldata, ls[0]->head.data, &f2->l_first->head.data);

View File

@ -61,14 +61,16 @@
#include "mesh_intern.h" /* own include */
#include "../sculpt_paint/sculpt_intern.h"
static bool geometry_extract_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob != NULL && ob->mode == OB_MODE_SCULPT) {
if (ob->sculpt->bm) {
CTX_wm_operator_poll_msg_set(C, "The geometry can not be extracted with dyntopo activated");
return false;
}
// if (ob->sculpt->bm) {
// CTX_wm_operator_poll_msg_set(C, "The geometry can not be extracted with dyntopo activated");
// return false;
//}
return ED_operator_object_active_editable_mesh(C);
}
return false;
@ -120,7 +122,8 @@ static int geometry_extract_apply(bContext *C,
.use_toolflags = true,
}));
BM_mesh_bm_from_me(NULL, bm,
BM_mesh_bm_from_me(NULL,
bm,
new_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -373,6 +376,7 @@ static int face_set_extract_invoke(bContext *C, wmOperator *op, const wmEvent *U
ED_workspace_status_text(C, TIP_("Click on the mesh to select a Face Set"));
WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EYEDROPPER);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
@ -513,7 +517,8 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(NULL, bm,
BM_mesh_bm_from_me(NULL,
bm,
new_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -544,7 +549,8 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
.use_toolflags = true,
}));
BM_mesh_bm_from_me(NULL, bm,
BM_mesh_bm_from_me(NULL,
bm,
new_ob_mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
@ -580,15 +586,42 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
if (ob->mode == OB_MODE_SCULPT) {
SculptSession *ss = ob->sculpt;
ss->face_sets = CustomData_get_layer(&((Mesh *)ob->data)->pdata, CD_SCULPT_FACE_SETS);
if (ss->face_sets) {
/* Assign a new Face Set ID to the new faces created by the slice operation. */
const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(ob->data);
ED_sculpt_face_sets_initialize_none_to_id(ob->data, next_face_set_id);
/* Assign a new Face Set ID to the new faces created by the slice operation. */
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_GRIDS:
case PBVH_FACES:
ss->face_sets = CustomData_get_layer(&((Mesh *)ob->data)->pdata, CD_SCULPT_FACE_SETS);
if (ss->face_sets) {
const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(ob->data);
ED_sculpt_face_sets_initialize_none_to_id(ob->data, next_face_set_id);
}
break;
case PBVH_BMESH: {
if (ss->bm && CustomData_has_layer(&ss->bm->pdata, CD_SCULPT_FACE_SETS)) {
const int cd_fset = CustomData_get_offset(&ss->bm->pdata, CD_SCULPT_FACE_SETS);
BMFace *f;
BMIter iter;
const int next_face_set_id = SCULPT_face_set_next_available_get(ss);
BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
int fset = BM_ELEM_CD_GET_INT(f, cd_fset);
if (fset == SCULPT_FACE_SET_NONE) {
BM_ELEM_CD_SET_INT(f, cd_fset, next_face_set_id);
}
}
}
break;
}
}
ED_sculpt_undo_geometry_end(ob);
}
ED_sculpt_undo_geometry_end(ob);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);

View File

@ -76,204 +76,6 @@
#include <stdlib.h>
#define SCULPT_GEODESIC_VERTEX_NONE -1
/*
on factor;
off period;
load_package "avector";
comment: if (dist1 != 0.0f && dist2 != 0.0f);
forall x let abs(abs(x)*abs(x)) = x**2;
forall x let abs(x*x) = x**2;
forall x let abs(abs(x)) = abs(x);
forall x let abs(x)**2 = x**2;
let v2len**2 = v2lensqr;
let abs(v2len) = v2len;
let sqrt(the_hh) = the_hh_sqrt;
v0 := avec(v0x, v0y, v0z);
v1 := avec(0, 0, 0); comment: avec(v1x, v1y, v1z);
v2 := avec(v2x, v2y, v2z);
let v2x**2 + v2y**2 + v2z**2 = v2lensqr;
let sqrt(v2lensqr) = v2len;
v10 := v0; comment: v0 - v1;
v12 := v2; comment: v2 - v1;
d12 := v2len;
comment: if d12*d12 > 0.0;
u := v12 / d12;
n := v12 cross v10;
n = n / VMOD n;
v := n cross u;
v0_0 := v10 dot u;
v0_1 := abs(v10 dot v);
a := 0.5 * (1.0 + (dist1 * dist1 - dist2 * dist2) / (d12 * d12));
hh := dist1 * dist1 - a * a * d12 * d12;
commment: if (hh > 0.0f);
h := the_hh**0.5;
S_0 := a*d12;
S_1 := -h;
x_intercept := S_0 + h * (v0_0 - S_0) / (v0_1 + h);
comment: if (x_intercept >= 0.0f && x_intercept <= d12);
on rounded;
on double;
on period;
result := ((S_0-v0_0)**2 + (S_1 - v0_1)**2)**0.5;
load_package "gentran";
gentranlang!* := 'c$
on factor;
gentran begin outhh := eval(hh); outxintercept := eval(x_intercept); outresult := eval(result) end;
*/
static float fast_geodesic_distance_propagate_across_triangle(
const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2)
{
float the_hh, the_hh_sqrt;
float v0x = v0[0] - v1[0];
float v0y = v0[1] - v1[1];
float v0z = v0[2] - v1[2];
float v2x = v2[0] - v1[0];
float v2y = v2[1] - v1[1];
float v2z = v2[2] - v1[2];
if (dist1 != 0.0f && dist2 != 0.0f) {
float v2lensqr = (v2x * v2x + v2y * v2y + v2z * v2z);
float xintercept;
if (v2lensqr > 1.0e-35f) {
float v2len = sqrtf(v2lensqr);
the_hh = -(0.25 * (dist2 + v2len + dist1) * (dist2 + v2len - dist1) *
(dist2 - v2len + dist1) * (dist2 - v2len - dist1)) /
v2lensqr;
if (the_hh > 0.0f) {
the_hh_sqrt = sqrtf(the_hh);
xintercept =
-(0.5 * (dist2 * dist2 - v2lensqr - (dist1 * dist1)) *
fabsf((float)(((v2lensqr - (v2z * v2z)) * v0z - (2 * v0y * v2y * v2z)) * v0z +
(v2lensqr - (v2y * v2y)) * (v0y * v0y) -
((2 * (v0y * v2y + v0z * v2z) * v2x -
((v2y * v2y + v2z * v2z) * v0x)) *
v0x))) -
((v0y * v2y + v0z * v2z + v0x * v2x) * the_hh_sqrt * v2len)) /
((fabsf(
(float)(((v2lensqr - (v2z * v2z)) * v0z - (2 * v0y * v2y * v2z)) * v0z +
(v2lensqr - (v2y * v2y)) * (v0y * v0y) -
((2 * (v0y * v2y + v0z * v2z) * v2x - ((v2y * v2y + v2z * v2z) * v0x)) *
v0x))) +
the_hh_sqrt * v2len) *
v2len);
if (xintercept >= 0.0 && xintercept <= v2len) {
float result =
(0.5 * sqrt((float)((2.0 * (v0y * v2y + v0z * v2z + v0x * v2x) - (dist1 * dist1) +
(dist2 + v2len) * (dist2 - v2len)) *
(2.0 * (v0y * v2y + v0z * v2z + v0x * v2x) -
(dist1 * dist1) + (dist2 + v2len) * (dist2 - v2len)) +
4.0 * ((fabsf((float)(((v2lensqr - (v2z * v2z)) * v0z -
(2 * v0y * v2y * v2z)) *
v0z +
(v2lensqr - (v2y * v2y)) * (v0y * v0y) -
((2 * (v0y * v2y + v0z * v2z) * v2x -
((v2y * v2y + v2z * v2z) * v0x)) *
v0x))) +
the_hh_sqrt * v2len) *
(fabsf((float)(((v2lensqr - (v2z * v2z)) * v0z -
(2 * v0y * v2y * v2z)) *
v0z +
(v2lensqr - (v2y * v2y)) * (v0y * v0y) -
((2 * (v0y * v2y + v0z * v2z) * v2x -
((v2y * v2y + v2z * v2z) * v0x)) *
v0x))) +
the_hh_sqrt * v2len))))) /
v2len;
/*
printf("%.7f : %.7f\n",
result*2.0,
geodesic_distance_propagate_across_triangle(v0, v1, v2, dist1, dist2));*/
return result * 4.0;
}
}
}
}
/* Fall back to Dijsktra approximation in trivial case, or if no valid source
* point found that connects to v0 across the triangle. */
return min_ff(dist1 + sqrtf(v0x * v0x + v0y * v0y + v0z * v0z), dist2 + len_v3v3(v0, v2));
}
#if 0
float geodesic_distance_propagate_across_triangle(
const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2)
{
/* Vectors along triangle edges. */
float v10[3], v12[3];
sub_v3_v3v3(v10, v0, v1);
sub_v3_v3v3(v12, v2, v1);
if (dist1 != 0.0f && dist2 != 0.0f) {
/* Local coordinate system in the triangle plane. */
float u[3], v[3], n[3];
const float d12 = normalize_v3_v3(u, v12);
if (d12 * d12 > 0.0f) {
cross_v3_v3v3(n, v12, v10);
normalize_v3(n);
cross_v3_v3v3(v, n, u);
/* v0 in local coordinates */
const float v0_[2] = {dot_v3v3(v10, u), fabsf(dot_v3v3(v10, v))};
/* Compute virtual source point in local coordinates, that we estimate the geodesic
* distance is being computed from. See figure 9 in the paper for the derivation. */
const float a = 0.5f * (1.0f + (dist1 * dist1 - dist2 * dist2) / (d12 * d12));
const float hh = dist1 * dist1 - a * a * d12 * d12;
if (hh > 0.0f) {
const float h = sqrtf(hh);
const float S_[2] = {a * d12, -h};
/* Only valid if the line between the source point and v0 crosses
* the edge between v1 and v2. */
const float x_intercept = S_[0] + h * (v0_[0] - S_[0]) / (v0_[1] + h);
if (x_intercept >= 0.0f && x_intercept <= d12) {
return len_v2v2(S_, v0_);
}
}
}
}
/* Fall back to Dijsktra approximation in trivial case, or if no valid source
* point found that connects to v0 across the triangle. */
return min_ff(dist1 + len_v3(v10), dist2 + len_v3v3(v0, v2));
}
#endif
/* Propagate distance from v1 and v2 to v0. */
static bool sculpt_geodesic_mesh_test_dist_add(
MVert *mvert, const int v0, const int v1, const int v2, float *dists, GSet *initial_vertices)