Fix multires sculpt not setting the active vertex correctly

Also cleanup code to remove duplicated min_depth tracking, ray intersection
already does it.
This commit is contained in:
Brecht Van Lommel 2019-10-08 17:07:18 +02:00
parent 899b7ff1de
commit 52c02dc311
2 changed files with 89 additions and 59 deletions

@ -1905,14 +1905,11 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
const MVert *vert = bvh->verts; const MVert *vert = bvh->verts;
const MLoop *mloop = bvh->mloop; const MLoop *mloop = bvh->mloop;
const int *faces = node->prim_indices; const int *faces = node->prim_indices;
int i, totface = node->totprim; int totface = node->totprim;
bool hit = false; bool hit = false;
float min_depth = FLT_MAX; float nearest_vertex_co[3] = {0.0f};
float location[3] = {0.0f};
float nearest_vertex_co[3];
copy_v3_fl(nearest_vertex_co, 0.0f);
for (i = 0; i < totface; i++) { for (int i = 0; i < totface; i++) {
const MLoopTri *lt = &bvh->looptri[faces[i]]; const MLoopTri *lt = &bvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i]; const int *face_verts = node->face_vert_indices[i];
@ -1920,35 +1917,33 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
continue; continue;
} }
const float *co[3];
if (origco) { if (origco) {
/* intersect with backuped original coordinates */ /* intersect with backuped original coordinates */
hit |= ray_face_intersection_tri(ray_start, co[0] = origco[face_verts[0]];
isect_precalc, co[1] = origco[face_verts[1]];
origco[face_verts[0]], co[2] = origco[face_verts[2]];
origco[face_verts[1]],
origco[face_verts[2]],
depth);
} }
else { else {
/* intersect with current coordinates */ /* intersect with current coordinates */
hit |= ray_face_intersection_tri(ray_start, co[0] = vert[mloop[lt->tri[0]].v].co;
isect_precalc, co[1] = vert[mloop[lt->tri[1]].v].co;
vert[mloop[lt->tri[0]].v].co, co[2] = vert[mloop[lt->tri[2]].v].co;
vert[mloop[lt->tri[1]].v].co, }
vert[mloop[lt->tri[2]].v].co,
depth);
if (hit && *depth < min_depth) { if (ray_face_intersection_tri(ray_start, isect_precalc, co[0], co[1], co[2], depth)) {
min_depth = *depth; hit = true;
normal_tri_v3(r_face_normal,
vert[mloop[lt->tri[0]].v].co, if (r_face_normal) {
vert[mloop[lt->tri[1]].v].co, normal_tri_v3(r_face_normal, co[0], co[1], co[2]);
vert[mloop[lt->tri[2]].v].co); }
if (r_active_vertex_index) {
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth); madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
if (len_squared_v3v3(location, vert[mloop[lt->tri[j]].v].co) < if (len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
len_squared_v3v3(location, nearest_vertex_co)) { copy_v3_v3(nearest_vertex_co, co[j]);
copy_v3_v3(nearest_vertex_co, vert[mloop[lt->tri[j]].v].co);
*r_active_vertex_index = mloop[lt->tri[j]].v; *r_active_vertex_index = mloop[lt->tri[j]].v;
} }
} }
@ -1963,22 +1958,28 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
PBVHNode *node, PBVHNode *node,
float (*origco)[3], float (*origco)[3],
const float ray_start[3], const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc, struct IsectRayPrecalc *isect_precalc,
float *depth) float *depth,
int *r_active_vertex_index,
float *r_face_normal)
{ {
const int totgrid = node->totprim; const int totgrid = node->totprim;
const int gridsize = bvh->gridkey.grid_size; const int gridsize = bvh->gridkey.grid_size;
bool hit = false; bool hit = false;
float nearest_vertex_co[3] = {0.0};
const CCGKey *gridkey = &bvh->gridkey;
for (int i = 0; i < totgrid; i++) { for (int i = 0; i < totgrid; i++) {
CCGElem *grid = bvh->grids[node->prim_indices[i]]; const int grid_index = node->prim_indices[i];
CCGElem *grid = bvh->grids[grid_index];
BLI_bitmap *gh; BLI_bitmap *gh;
if (!grid) { if (!grid) {
continue; continue;
} }
gh = bvh->grid_hidden[node->prim_indices[i]]; gh = bvh->grid_hidden[grid_index];
for (int y = 0; y < gridsize - 1; y++) { for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) { for (int x = 0; x < gridsize - 1; x++) {
@ -1989,23 +1990,40 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
} }
} }
const float *co[4];
if (origco) { if (origco) {
hit |= ray_face_intersection_quad(ray_start, co[0] = origco[y * gridsize + x];
isect_precalc, co[1] = origco[y * gridsize + x + 1];
origco[y * gridsize + x], co[2] = origco[(y + 1) * gridsize + x + 1];
origco[y * gridsize + x + 1], co[3] = origco[(y + 1) * gridsize + x];
origco[(y + 1) * gridsize + x + 1],
origco[(y + 1) * gridsize + x],
depth);
} }
else { else {
hit |= ray_face_intersection_quad(ray_start, co[0] = CCG_grid_elem_co(gridkey, grid, x, y);
isect_precalc, co[1] = CCG_grid_elem_co(gridkey, grid, x + 1, y);
CCG_grid_elem_co(&bvh->gridkey, grid, x, y), co[2] = CCG_grid_elem_co(gridkey, grid, x + 1, y + 1);
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y), co[3] = CCG_grid_elem_co(gridkey, grid, x, y + 1);
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1), }
CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
depth); if (ray_face_intersection_quad(
ray_start, isect_precalc, co[0], co[1], co[2], co[3], depth)) {
hit = true;
if (r_face_normal) {
normal_quad_v3(r_face_normal, co[0], co[1], co[2], co[3]);
}
if (r_active_vertex_index) {
float location[3] = {0.0};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 4; j++) {
if (len_squared_v3v3(location, co[j]) <
len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, co[j]);
*r_active_vertex_index = gridkey->grid_area * grid_index + y * gridkey->grid_size +
x;
}
}
}
} }
} }
} }
@ -2048,7 +2066,15 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
face_normal); face_normal);
break; break;
case PBVH_GRIDS: case PBVH_GRIDS:
hit |= pbvh_grids_node_raycast(bvh, node, origco, ray_start, isect_precalc, depth); hit |= pbvh_grids_node_raycast(bvh,
node,
origco,
ray_start,
ray_normal,
isect_precalc,
depth,
active_vertex_index,
face_normal);
break; break;
case PBVH_BMESH: case PBVH_BMESH:
BM_mesh_elem_index_ensure(bvh->bm, BM_VERT); BM_mesh_elem_index_ensure(bvh->bm, BM_VERT);

@ -1516,10 +1516,8 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
float *r_face_normal) float *r_face_normal)
{ {
bool hit = false; bool hit = false;
float min_depth = FLT_MAX;
float nearest_vertex_co[3] = {0.0f}; float nearest_vertex_co[3] = {0.0f};
float location[3] = {0.0f};
if (use_original && node->bm_tot_ortri) { if (use_original && node->bm_tot_ortri) {
for (int i = 0; i < node->bm_tot_ortri; i++) { for (int i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i]; const int *t = node->bm_ortri[i];
@ -1542,18 +1540,24 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
BMVert *v_tri[3]; BMVert *v_tri[3];
BM_face_as_array_vert_tri(f, v_tri); BM_face_as_array_vert_tri(f, v_tri);
hit |= ray_face_intersection_tri(
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth);
if (hit && *depth < min_depth) { if (ray_face_intersection_tri(
min_depth = *depth; ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co); hit = true;
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) { if (r_face_normal) {
if (len_squared_v3v3(location, v_tri[j]->co) < normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
len_squared_v3v3(location, nearest_vertex_co)) { }
copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
*r_active_vertex_index = BM_elem_index_get(v_tri[j]); if (r_active_vertex_index) {
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
if (len_squared_v3v3(location, v_tri[j]->co) <
len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
*r_active_vertex_index = BM_elem_index_get(v_tri[j]);
}
} }
} }
} }