Transform: Use the new BLI_bvhtree_find_nearest_projected function to snap.

This commit is contained in:
Germano Cavalcante 2018-05-14 16:08:17 -03:00
parent 8cbf402eb6
commit bf7c46cae0
1 changed files with 102 additions and 121 deletions

View File

@ -897,8 +897,8 @@ static void cb_mlooptri_verts_get(
static bool test_projected_vert_dist(
struct DistProjectedAABBPrecalc *neasrest_precalc,
const float depth_range[2], const float co[3],
const bool is_persp,
const float depth_range[2],
const bool is_persp, const float co[3],
float *dist_px_sq, float r_co[3])
{
float w;
@ -934,15 +934,15 @@ static bool test_projected_edge_dist(
float *dist_px_sq, float r_co[3])
{
float tmp_co[3], dummy_depth;
float near_co[3], dummy_depth;
dist_squared_ray_to_seg_v3(
neasrest_precalc->ray_origin,
neasrest_precalc->ray_direction,
va, vb, tmp_co, &dummy_depth);
va, vb, near_co, &dummy_depth);
return test_projected_vert_dist(
neasrest_precalc, depth_range,
tmp_co, is_persp, dist_px_sq, r_co);
is_persp, near_co, dist_px_sq, r_co);
}
/** \} */
@ -958,8 +958,6 @@ typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], vo
typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
typedef struct Nearest2dUserData {
struct DistProjectedAABBPrecalc data_precalc;
bool r_axis_closest[3];
bool is_persp;
float depth_range[2];
short snap_to;
@ -971,32 +969,13 @@ typedef struct Nearest2dUserData {
Nearest2DGetTriEdgesCallback get_tri_edges_index;
Nearest2DCopyVertNoCallback copy_vert_no;
float dist_px_sq;
int index;
float co[3];
float no[3];
} Nearest2dUserData;
static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
{
Nearest2dUserData *data = user_data;
const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
const float rdist = dist_squared_to_projected_aabb(
&data->data_precalc, bbmin, bbmax, data->r_axis_closest);
return rdist < data->dist_px_sq;
}
static bool cb_nearest_walk_order(
const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
{
const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest;
return r_axis_closest[axis];
}
static bool cb_walk_leaf_snap_vert(
const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
static void cb_walk_leaf_snap_vert(
void *userdata, int index,
struct DistProjectedAABBPrecalc *precalc,
BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@ -1004,20 +983,22 @@ static bool cb_walk_leaf_snap_vert(
data->get_vert_co(index, &co, data->userdata);
if (test_projected_vert_dist(
&data->data_precalc,
data->depth_range, co,
precalc,
data->depth_range,
data->is_persp,
&data->dist_px_sq,
data->co))
co,
&nearest->dist_sq,
nearest->co))
{
data->copy_vert_no(index, data->no, data->userdata);
data->index = index;
data->copy_vert_no(index, nearest->no, data->userdata);
nearest->index = index;
}
return true;
}
static bool cb_walk_leaf_snap_edge(
const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
static void cb_walk_leaf_snap_edge(
void *userdata, int index,
struct DistProjectedAABBPrecalc *precalc,
BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@ -1030,31 +1011,31 @@ static bool cb_walk_leaf_snap_edge(
data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
if (test_projected_edge_dist(
&data->data_precalc,
precalc,
data->depth_range,
data->is_persp,
v_pair[0], v_pair[1],
&data->dist_px_sq,
data->co))
&nearest->dist_sq,
nearest->co))
{
sub_v3_v3v3(data->no, v_pair[0], v_pair[1]);
data->index = index;
sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
nearest->index = index;
}
}
else {
for (int i = 0; i < 2; i++) {
if (vindex[i] == data->index) {
if (vindex[i] == nearest->index) {
continue;
}
cb_walk_leaf_snap_vert(NULL, vindex[i], userdata);
cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest);
}
}
return true;
}
static bool cb_walk_leaf_snap_tri(
const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
static void cb_walk_leaf_snap_tri(
void *userdata, int index,
struct DistProjectedAABBPrecalc *precalc,
BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@ -1063,10 +1044,10 @@ static bool cb_walk_leaf_snap_tri(
data->get_tri_edges_index(index, eindex, data->userdata);
for (int i = 0; i < 3; i++) {
if (eindex[i] != -1) {
if (eindex[i] == data->index) {
if (eindex[i] == nearest->index) {
continue;
}
cb_walk_leaf_snap_edge(NULL, eindex[i], userdata);
cb_walk_leaf_snap_edge(userdata, eindex[i], precalc, nearest);
}
}
}
@ -1074,13 +1055,12 @@ static bool cb_walk_leaf_snap_tri(
int vindex[3];
data->get_tri_verts_index(index, vindex, data->userdata);
for (int i = 0; i < 3; i++) {
if (vindex[i] == data->index) {
if (vindex[i] == nearest->index) {
continue;
}
cb_walk_leaf_snap_vert(NULL, vindex[i], userdata);
cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest);
}
}
return true;
}
/** \} */
@ -1134,10 +1114,10 @@ static bool snapArmature(
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
eBone->head, is_persp, &dist_px_sq, r_loc);
is_persp, eBone->head, &dist_px_sq, r_loc);
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
eBone->tail, is_persp, &dist_px_sq, r_loc);
is_persp, eBone->tail, &dist_px_sq, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
@ -1162,10 +1142,10 @@ static bool snapArmature(
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
head_vec, is_persp, &dist_px_sq, r_loc);
is_persp, head_vec, &dist_px_sq, r_loc);
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
tail_vec, is_persp, &dist_px_sq, r_loc);
is_persp, tail_vec, &dist_px_sq, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
@ -1239,7 +1219,7 @@ static bool snapCurve(
}
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
nu->bezt[u].vec[1], is_persp, &dist_px_sq,
is_persp, nu->bezt[u].vec[1], &dist_px_sq,
r_loc);
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
if (!(nu->bezt[u].f1 & SELECT) &&
@ -1247,7 +1227,7 @@ static bool snapCurve(
{
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
nu->bezt[u].vec[0], is_persp, &dist_px_sq,
is_persp, nu->bezt[u].vec[0], &dist_px_sq,
r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
@ -1255,7 +1235,7 @@ static bool snapCurve(
{
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
nu->bezt[u].vec[2], is_persp, &dist_px_sq,
is_persp, nu->bezt[u].vec[2], &dist_px_sq,
r_loc);
}
}
@ -1266,7 +1246,7 @@ static bool snapCurve(
}
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
nu->bp[u].vec, is_persp, &dist_px_sq,
is_persp, nu->bp[u].vec, &dist_px_sq,
r_loc);
}
}
@ -1276,13 +1256,13 @@ static bool snapCurve(
if (nu->bezt) {
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
nu->bezt[u].vec[1], is_persp, &dist_px_sq,
is_persp, nu->bezt[u].vec[1], &dist_px_sq,
r_loc);
}
else {
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
nu->bp[u].vec, is_persp, &dist_px_sq,
is_persp, nu->bp[u].vec, &dist_px_sq,
r_loc);
}
}
@ -1328,11 +1308,11 @@ static bool snapEmpty(
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
float dist_px_sq = SQUARE(*dist_px);
float tmp_co[3];
copy_v3_v3(tmp_co, obmat[3]);
float co[3];
copy_v3_v3(co, obmat[3]);
if (test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
tmp_co, is_persp, &dist_px_sq, r_loc))
is_persp, co, &dist_px_sq, r_loc))
{
*dist_px = sqrtf(dist_px_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
@ -1423,7 +1403,7 @@ static bool snapCamera(
mul_m4_v3(vertex_obmat, bundle_pos);
retval |= test_projected_vert_dist(
&neasrest_precalc, snapdata->depth_range,
bundle_pos, is_persp, &dist_px_sq, r_loc);
is_persp, bundle_pos, &dist_px_sq, r_loc);
}
}
@ -1465,23 +1445,22 @@ static bool snapMesh(
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
Nearest2dUserData neasrest2d;
dist_squared_to_projected_aabb_precalc(
&neasrest2d.data_precalc, lpmat, snapdata->win_size, snapdata->mval);
neasrest2d.r_axis_closest[0] = true;
neasrest2d.r_axis_closest[1] = true;
neasrest2d.r_axis_closest[2] = true;
neasrest2d.dist_px_sq = SQUARE(*dist_px);
float dist_px_sq = SQUARE(*dist_px);
/* Test BoundBox */
BoundBox *bb = BKE_mesh_boundbox_get(ob);
if (bb) {
/* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
float dist_px_sq = dist_squared_to_projected_aabb(
&neasrest2d.data_precalc, bb->vec[0], bb->vec[6], neasrest2d.r_axis_closest);
if (dist_px_sq > neasrest2d.dist_px_sq) {
struct DistProjectedAABBPrecalc data_precalc;
dist_squared_to_projected_aabb_precalc(
&data_precalc, lpmat, snapdata->win_size, snapdata->mval);
bool dummy[3];
float bb_dist_px_sq = dist_squared_to_projected_aabb(
&data_precalc, bb->vec[0], bb->vec[6], dummy);
if (bb_dist_px_sq > dist_px_sq) {
return retval;
}
}
@ -1582,56 +1561,58 @@ static bool snapMesh(
* And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
neasrest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
neasrest2d.depth_range[0] = snapdata->depth_range[0];
neasrest2d.depth_range[1] = ray_depth_max_global;
neasrest2d.snap_to = snapdata->snap_to;
neasrest2d.userdata = treedata;
neasrest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
neasrest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
neasrest2d.get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get;
neasrest2d.get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get;
neasrest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
neasrest2d.index = -1;
Nearest2dUserData neasrest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.depth_range = {snapdata->depth_range[0], ray_depth_max_global},
.snap_to = snapdata->snap_to,
.userdata = treedata,
.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
.get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
.get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
};
BVHTreeNearest nearest = {
.index = -1,
.dist_sq = dist_px_sq,
};
if (bvhtree[1]) {
/* snap to loose verts */
BLI_bvhtree_walk_dfs(
bvhtree[1],
cb_walk_parent_snap_project, cb_walk_leaf_snap_vert, cb_nearest_walk_order, &neasrest2d);
BLI_bvhtree_find_nearest_projected(
bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
NULL, 0, &nearest, cb_walk_leaf_snap_vert, &neasrest2d);
}
if (bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_walk_dfs(
bvhtree[0],
cb_walk_parent_snap_project, cb_walk_leaf_snap_edge, cb_nearest_walk_order, &neasrest2d);
BLI_bvhtree_find_nearest_projected(
bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
NULL, 0, &nearest, cb_walk_leaf_snap_edge, &neasrest2d);
}
if (treedata->tree) {
/* snap to looptris */
BLI_bvhtree_walk_dfs(
treedata->tree,
cb_walk_parent_snap_project, cb_walk_leaf_snap_tri, cb_nearest_walk_order, &neasrest2d);
BLI_bvhtree_find_nearest_projected(
treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
NULL, 0, &nearest, cb_walk_leaf_snap_tri, &neasrest2d);
}
if (neasrest2d.index != -1) {
if (nearest.index != -1) {
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
copy_v3_v3(r_loc, neasrest2d.co);
copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
if (r_no) {
copy_v3_v3(r_no, neasrest2d.no);
copy_v3_v3(r_no, nearest.no);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
*dist_px = sqrtf(neasrest2d.dist_px_sq);
*dist_px = sqrtf(nearest.dist_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
@ -1733,7 +1714,6 @@ static bool snapEditMesh(
}
Nearest2dUserData neasrest2d = {
.r_axis_closest = {true, true, true},
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
.snap_to = snapdata->snap_to,
@ -1741,36 +1721,37 @@ static bool snapEditMesh(
.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
.dist_px_sq = SQUARE(*dist_px),
.index = -1};
};
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
dist_squared_to_projected_aabb_precalc(
&neasrest2d.data_precalc, lpmat, snapdata->win_size, snapdata->mval);
BVHTreeNearest nearest = {
.index = -1,
.dist_sq = SQUARE(*dist_px),
};
BVHTree_WalkLeafCallback cb_walk_leaf =
BVHTree_NearestProjectedCallback cb_walk_leaf =
(snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
BLI_bvhtree_walk_dfs(
treedata->tree,
cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
BLI_bvhtree_find_nearest_projected(
treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
NULL, 0, &nearest, cb_walk_leaf, &neasrest2d);
if (neasrest2d.index != -1) {
if (nearest.index != -1) {
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
copy_v3_v3(r_loc, neasrest2d.co);
copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
if (r_no) {
copy_v3_v3(r_no, neasrest2d.no);
copy_v3_v3(r_no, nearest.no);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
*dist_px = sqrtf(neasrest2d.dist_px_sq);
*dist_px = sqrtf(nearest.dist_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;