Remove struct PreDefProject and store all immutable parameters within the new struct SnapData

In order to simplify the reading of these functions, the parameters: `snap_to`, `mval`, `ray_start`, `ray_dir`, `view_proj` and `depth_range` are now stored in the struct `SnapData`
This commit is contained in:
Germano Cavalcante
2017-01-29 12:07:14 -03:00
parent d6f965b99c
commit cd596fa1c7

View File

@@ -59,6 +59,18 @@
#include "transform.h"
typedef struct SnapData {
short snap_to;
float mval[2];
float ray_origin[3];
float ray_start[3];
float ray_dir[3];
float pmat[4][4]; /* perspective matrix */
float win_half[2];/* win x and y */
enum eViewProj view_proj;
float depth_range[2];
} SnapData;
typedef struct SnapObjectData {
enum {
SNAP_MESH = 1,
@@ -232,26 +244,40 @@ typedef struct BVHTreeFromMeshType {
char type;
} BVHTreeFromMeshType;
typedef struct PreDefProject {
float pmat[4][4]; /* perspective matrix multiplied by object matrix */
float win_half[2];
float dist_px_sq;
} PreDefProject;
static void precalc_project(
PreDefProject *projectdefs, const ARegion *ar,
const float dist_px, float obmat[4][4])
/*
* Generates a struct with the immutable parameters that will be used on all objects.
*
* \param snap_to: Element to snap, Vertice, Edge or Face.
* \param view_proj: ORTHO or PERSP.
* Currently only works one at a time, but can eventually operate as flag.
*
* \param mval: Mouse coords.
* (When NULL, ray-casting is handled without any projection matrix correction.)
* \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
* \param ray_start: ray_origin moved for the start clipping plane (clip_min).
* \param ray_direction: Unit length direction of the ray.
* \param depth_range: distances of clipe plane min and clip plane max;
*/
static void set_SnapData(
SnapData *snapdata,
const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
const float mval[2], const float ray_origin[3], const float ray_start[3],
const float ray_direction[3], const float depth_range[2])
{
float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat;
if (obmat) {
mul_m4_m4m4(projectdefs->pmat, pmat, obmat);
if (ar) {
copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
snapdata->win_half[0] = ar->winx / 2;
snapdata->win_half[1] = ar->winy / 2;
}
else {
copy_m4_m4(projectdefs->pmat, pmat);
if (mval) {
copy_v2_v2(snapdata->mval, mval);
}
projectdefs->win_half[0] = ar->winx / 2;
projectdefs->win_half[1] = ar->winy / 2;
projectdefs->dist_px_sq = SQUARE(dist_px);
snapdata->snap_to = snap_to;
copy_v3_v3(snapdata->ray_origin, ray_origin);
copy_v3_v3(snapdata->ray_start, ray_start);
copy_v3_v3(snapdata->ray_dir, ray_direction);
snapdata->view_proj = view_proj;
copy_v2_v2(snapdata->depth_range, depth_range);
}
static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index)
@@ -322,14 +348,12 @@ static void get_edge_verts(
}
static bool test_projected_vert_dist(
PreDefProject *projectdefs,
const float co[3], const enum eViewProj view_proj,
const float mval[2], const float depth_range[2],
float r_co[3])
const float depth_range[2], const float mval[2], const float co[3],
float pmat[4][4], const float win_half[2], const bool is_persp,
float *dist_px_sq, float r_co[3])
{
float depth;
float(*pmat)[4] = projectdefs->pmat;
if (view_proj == VIEW_PROJ_PERSP) {
if (is_persp) {
depth = mul_project_m4_v3_zfac(pmat, co);
if (depth < depth_range[0] || depth > depth_range[1]) {
return false;
@@ -341,34 +365,35 @@ static bool test_projected_vert_dist(
(dot_m4_v3_row_y(pmat, co) + pmat[3][1]),
};
if (view_proj == VIEW_PROJ_PERSP) {
if (is_persp) {
mul_v2_fl(co2d, 1 / depth);
}
co2d[0] += 1.0f;
co2d[1] += 1.0f;
co2d[0] *= projectdefs->win_half[0];
co2d[1] *= projectdefs->win_half[1];
co2d[0] *= win_half[0];
co2d[1] *= win_half[1];
const float dist_sq = len_squared_v2v2(mval, co2d);
if (dist_sq < projectdefs->dist_px_sq) {
if (dist_sq < *dist_px_sq) {
copy_v3_v3(r_co, co);
projectdefs->dist_px_sq = dist_sq;
*dist_px_sq = dist_sq;
return true;
}
return false;
}
static bool test_projected_edge_dist(
PreDefProject *projectdefs,
const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3],
const enum eViewProj view_proj, const float mval[2], const float depth_range[2],
float r_co[3])
const float depth_range[2], const float mval[2],
float pmat[4][4], const float win_half[2], const bool is_persp,
const float ray_start[3], const float ray_dir[3],
const float va[3], const float vb[3],
float *dist_px_sq, float r_co[3])
{
float tmp_co[3], depth;
dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth);
return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co);
dist_squared_ray_to_seg_v3(ray_start, ray_dir, va, vb, tmp_co, &depth);
return test_projected_vert_dist(depth_range, mval, tmp_co, pmat, win_half, is_persp, dist_px_sq, r_co);
}
/** \} */
@@ -383,11 +408,15 @@ typedef struct Object_Nearest2dPrecalc {
float ray_direction_local[3];
float ray_inv_dir[3];
PreDefProject projectdefs;
float depth_range[2];
float pmat[4][4]; /* perspective matrix multiplied by object matrix */
float win_half[2];
bool is_persp;
float dist_px_sq;
float mval[2];
bool sign[3];
bool r_axis_closest[3];
float depth_range[2];
void *userdata;
int index;
@@ -397,16 +426,24 @@ typedef struct Object_Nearest2dPrecalc {
static void nearest2d_precalc(
Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar,
Object_Nearest2dPrecalc *neasrest_precalc, SnapData *snapdata,
const float dist_px, float obmat[4][4],
const float ray_origin_local[3], const float ray_direction_local[3],
const float mval[2], const float depth_range[2])
const float ray_origin_local[3], const float ray_direction_local[3])
{
precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat);
if (obmat) {
mul_m4_m4m4(neasrest_precalc->pmat, snapdata->pmat, obmat);
}
else {
copy_m4_m4(neasrest_precalc->pmat, snapdata->pmat);
}
copy_v2_v2(neasrest_precalc->win_half, snapdata->win_half);
neasrest_precalc->dist_px_sq = SQUARE(dist_px);
neasrest_precalc->is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
copy_v2_v2(neasrest_precalc->depth_range, snapdata->depth_range);
copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local);
copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local);
copy_v2_v2(neasrest_precalc->mval, mval);
copy_v2_v2(neasrest_precalc->depth_range, depth_range);
copy_v2_v2(neasrest_precalc->mval, snapdata->mval);
for (int i = 0; i < 3; i++) {
neasrest_precalc->ray_inv_dir[i] =
@@ -456,9 +493,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
(local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
(local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
};
/* va[3] and vb[3] are the coordinates of the AABB edge closest to the ray */
/* `va` and `vb` are the coordinates of the AABB edge closest to the ray */
float va[3], vb[3];
/* rtmin and rtmax are the distances of the minimum and maximum ray hits on the AABB */
/* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */
float rtmin, rtmax;
int main_axis;
@@ -506,10 +543,10 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
/* if rtmin < rtmax, ray intersect `AABB` */
if (rtmin <= rtmax) {
#ifdef IGNORE_BEHIND_RAY
/* `if rtmax < depth_min`, the hit is behind us
* TODO: Check if the entire AABB is behind ray
* this will prevent unnecessary leaf testing*/
if (rtmax < depth_range[0]) {
/* `if rtmax < depth_min`, the hit is behind us */
if (rtmax < data->depth_range[0]) {
/* TODO: TODO: Check if the entire AABB is behind ray
* this will prevent unnecessary leaf testing */
return false;
}
#endif
@@ -518,9 +555,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
return true;
}
#ifdef IGNORE_BEHIND_RAY
/* `if rtmin < depth_min`, the hit is behing us
* TODO: Check if the entire AABB is behind ray */
else if (rtmin < depth_range[0]) {
/* `if rtmin < depth_min`, the hit is behing us */
else if (rtmin < data->depth_range[0]) {
/* TODO: Test if the AABB is totally behind ray */
return false;
}
#endif
@@ -534,7 +571,7 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
}
float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
float (*pmat)[4] = data->projectdefs.pmat;
float (*pmat)[4] = data->pmat;
float depth_a = mul_project_m4_v3_zfac(pmat, va);
float depth_b = depth_a + pmat[main_axis][3] * scale;
@@ -555,10 +592,10 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
vb2d[0] += 1.0f;
vb2d[1] += 1.0f;
va2d[0] *= data->projectdefs.win_half[0];
va2d[1] *= data->projectdefs.win_half[1];
vb2d[0] *= data->projectdefs.win_half[0];
vb2d[1] *= data->projectdefs.win_half[1];
va2d[0] *= data->win_half[0];
va2d[1] *= data->win_half[1];
vb2d[0] *= data->win_half[0];
vb2d[1] *= data->win_half[1];
//float dvec[2], edge[2], rdist;
//sub_v2_v2v2(dvec, data->mval, va2d);
@@ -587,7 +624,7 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
else {
rdist = len_squared_v2v2(data->mval, va2d);
}
return rdist < data->projectdefs.dist_px_sq;
return rdist < data->dist_px_sq;
}
static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata)
@@ -599,12 +636,13 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo
(bounds[2].min + bounds[2].max) / 2,
};
/* Although this function is also used in the Othogonal view (VIEW_PROJ_ORTHO),
* we put `eViewProj view_proj` as` VIEW_PROJ_PERSP` because it works in both cases
* (with the disadvantage of executing unnecessary calculations) */
if (test_projected_vert_dist(
&neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP,
neasrest_precalc->mval, neasrest_precalc->depth_range,
neasrest_precalc->depth_range,
neasrest_precalc->mval, co,
neasrest_precalc->pmat,
neasrest_precalc->win_half,
neasrest_precalc->is_persp,
&neasrest_precalc->dist_px_sq,
neasrest_precalc->co))
{
copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no);
@@ -620,13 +658,16 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i
const float *v_pair[2];
get_edge_verts(neasrest_precalc->userdata, index, v_pair);
/* Although this function is also used in the Othogonal view (VIEW_PROJ_ORTHO),
* we put `eViewProj view_proj` as` VIEW_PROJ_PERSP` because it works in both cases
* (with the disadvantage of executing unnecessary calculations) */
if (test_projected_edge_dist(
&neasrest_precalc->projectdefs, v_pair[0], v_pair[1],
neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local,
VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range,
neasrest_precalc->depth_range,
neasrest_precalc->mval,
neasrest_precalc->pmat,
neasrest_precalc->win_half,
neasrest_precalc->is_persp,
neasrest_precalc->ray_origin_local,
neasrest_precalc->ray_direction_local,
v_pair[0], v_pair[1],
&neasrest_precalc->dist_px_sq,
neasrest_precalc->co))
{
sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]);
@@ -649,9 +690,8 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a
* \{ */
static bool snapArmature(
const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
const short snap_to, const float origin[3], const float dir[3],
const float mval[2], const enum eViewProj view_proj, const float depth_range[2],
SnapData *snapdata,
Object *ob, bArmature *arm, float obmat[4][4],
/* read/write args */
float *dist_px,
/* return args */
@@ -659,36 +699,47 @@ static bool snapArmature(
{
bool retval = false;
float ray_start_local[3], ray_normal_local[3];
if (snap_to != SCE_SNAP_MODE_VERTEX) {
float ray_start_local[3], ray_normal_local[3]; /* Used only in the snap to edges */
if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
float imat[4][4];
invert_m4_m4(imat, obmat);
copy_v3_v3(ray_start_local, origin);
copy_v3_v3(ray_normal_local, dir);
copy_v3_v3(ray_start_local, snapdata->ray_origin);
copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
}
else if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { /* Currently only edge and vert */
return retval;
}
PreDefProject projectdefs;
precalc_project(&projectdefs, ar, *dist_px, obmat);
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
float lpmat[4][4], dist_px_sq;
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
dist_px_sq = SQUARE(*dist_px);
if (arm->edbo) {
for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->layer & arm->layer) {
/* skip hidden or moving (selected) bones */
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
&projectdefs, eBone->head, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, eBone->head,
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
retval |= test_projected_vert_dist(
&projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, eBone->tail,
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
&projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local,
view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, lpmat,
snapdata->win_half, is_persp, ray_start_local, ray_normal_local,
eBone->head, eBone->tail,
&dist_px_sq, r_loc);
break;
}
}
@@ -703,24 +754,30 @@ static bool snapArmature(
const float *head_vec = pchan->pose_head;
const float *tail_vec = pchan->pose_tail;
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
&projectdefs, head_vec, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, head_vec,
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
retval |= test_projected_vert_dist(
&projectdefs, tail_vec, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, tail_vec,
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
&projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local,
view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, lpmat,
snapdata->win_half, is_persp, ray_start_local, ray_normal_local,
head_vec, tail_vec,
&dist_px_sq, r_loc);
break;
}
}
}
}
if (retval) {
*dist_px = sqrtf(projectdefs.dist_px_sq);
*dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
return true;
}
@@ -728,9 +785,8 @@ static bool snapArmature(
}
static bool snapCurve(
const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
const short snap_to, const float mval[2], const enum eViewProj view_proj,
const float depth_range[2],
SnapData *snapdata,
Object *ob, Curve *cu, float obmat[4][4],
/* read/write args */
float *dist_px,
/* return args */
@@ -739,16 +795,18 @@ static bool snapCurve(
bool retval = false;
/* only vertex snapping mode (eg control points and handles) supported for now) */
if (snap_to != SCE_SNAP_MODE_VERTEX) {
if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) {
return retval;
}
PreDefProject projectdefs;
precalc_project(&projectdefs, ar, *dist_px, obmat);
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
float lpmat[4][4], dist_px_sq;
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
dist_px_sq = SQUARE(*dist_px);
for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (int u = 0; u < nu->pntsu; u++) {
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
if (ob->mode == OB_MODE_EDIT) {
@@ -758,19 +816,25 @@ static bool snapCurve(
break;
}
retval |= test_projected_vert_dist(
&projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1],
lpmat, snapdata->win_half, is_persp, &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) &&
!(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
{
retval |= test_projected_vert_dist(
&projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[0],
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
!(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
{
retval |= test_projected_vert_dist(
&projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[2],
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
}
}
else {
@@ -779,7 +843,9 @@ static bool snapCurve(
break;
}
retval |= test_projected_vert_dist(
&projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, nu->bp[u].vec,
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
}
}
else {
@@ -787,11 +853,15 @@ static bool snapCurve(
if (nu->pntsu > 1) {
if (nu->bezt) {
retval |= test_projected_vert_dist(
&projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1],
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
}
else {
retval |= test_projected_vert_dist(
&projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, nu->bp[u].vec,
lpmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
}
}
}
@@ -803,7 +873,7 @@ static bool snapCurve(
}
}
if (retval) {
*dist_px = sqrtf(projectdefs.dist_px_sq);
*dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
return true;
}
@@ -812,9 +882,8 @@ static bool snapCurve(
/* may extend later (for now just snaps to empty center) */
static bool snapEmpty(
const ARegion *ar, Object *ob, float obmat[4][4],
const short snap_to, const float mval[2], const enum eViewProj view_proj,
const float depth_range[2],
SnapData *snapdata,
Object *ob, float obmat[4][4],
/* read/write args */
float *dist_px,
/* return args */
@@ -827,15 +896,18 @@ static bool snapEmpty(
}
/* for now only vertex supported */
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
PreDefProject projectdefs;
precalc_project(&projectdefs, ar, *dist_px, NULL);
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]);
if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) {
*dist_px = sqrtf(projectdefs.dist_px_sq);
if (test_projected_vert_dist(
snapdata->depth_range, snapdata->mval, tmp_co,
snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc)) {
*dist_px = sqrtf(dist_px_sq);
retval = true;
}
break;
@@ -848,9 +920,8 @@ static bool snapEmpty(
}
static bool snapCamera(
const SnapObjectContext *sctx, Object *object, float obmat[4][4],
const short snap_to, const float mval[2], const enum eViewProj view_proj,
const float depth_range[2],
const SnapObjectContext *sctx, SnapData *snapdata,
Object *object, float obmat[4][4],
/* read/write args */
float *dist_px,
/* return args */
@@ -858,8 +929,8 @@ static bool snapCamera(
{
Scene *scene = sctx->scene;
PreDefProject projectdefs;
precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL);
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
float dist_px_sq = SQUARE(*dist_px);
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
bool retval = false;
@@ -880,7 +951,7 @@ static bool snapCamera(
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
MovieTrackingObject *tracking_object;
@@ -920,7 +991,9 @@ static bool snapCamera(
mul_m4_v3(vertex_obmat, bundle_pos);
retval |= test_projected_vert_dist(
&projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc);
snapdata->depth_range, snapdata->mval, bundle_pos,
snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
r_loc);
}
}
@@ -931,7 +1004,7 @@ static bool snapCamera(
}
if (retval) {
*dist_px = sqrtf(projectdefs.dist_px_sq);
*dist_px = sqrtf(dist_px_sq);
return true;
}
return false;
@@ -943,18 +1016,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
struct NearestDM_Data {
void *bvhdata;
const float *depth_range;
float *ray_depth;
};
static bool snapDerivedMesh(
SnapObjectContext *sctx,
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb,
const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
const float depth_range[2],
bool do_bb,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -963,12 +1028,12 @@ static bool snapDerivedMesh(
{
bool retval = false;
if (snap_to == SCE_SNAP_MODE_FACE) {
if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
if (dm->getNumPolys(dm) == 0) {
return retval;
}
}
else if (snap_to == SCE_SNAP_MODE_EDGE) {
else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -980,7 +1045,9 @@ static bool snapDerivedMesh(
}
{
bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO);
bool need_ray_start_correction_init =
(snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
(snapdata->view_proj == VIEW_PROJ_ORTHO);
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
@@ -990,8 +1057,8 @@ static bool snapDerivedMesh(
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
copy_v3_v3(ray_start_local, ray_start);
copy_v3_v3(ray_normal_local, ray_normal);
copy_v3_v3(ray_start_local, snapdata->ray_start);
copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
@@ -1015,7 +1082,7 @@ static bool snapDerivedMesh(
/* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'),
* scale up so we can snap against verts & edges on the boundbox, see T46816. */
if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f);
bb = &bb_temp;
}
@@ -1044,7 +1111,7 @@ static bool snapDerivedMesh(
}
int tree_index = -1;
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
tree_index = 2;
break;
@@ -1075,7 +1142,7 @@ static bool snapDerivedMesh(
}
if (treedata && treedata->tree == NULL) {
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
break;
@@ -1092,12 +1159,12 @@ static bool snapDerivedMesh(
return retval;
}
if (snap_to == SCE_SNAP_MODE_FACE) {
if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
/* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
* been *inside* boundbox, leading to snap failures (see T38409).
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
if (need_ray_start_correction_init) {
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
@@ -1116,7 +1183,7 @@ static bool snapDerivedMesh(
}
float ray_org_local[3];
copy_v3_v3(ray_org_local, ray_origin);
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
/* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
@@ -1124,7 +1191,8 @@ static bool snapDerivedMesh(
*/
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
madd_v3_v3v3fl(
ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale);
ray_start_local, ray_org_local, ray_normal_local,
len_diff + snapdata->depth_range[0] * local_scale);
local_depth -= len_diff;
}
else {
@@ -1186,7 +1254,7 @@ static bool snapDerivedMesh(
const ARegion *ar = sctx->v3d_data.ar;
float ray_org_local[3];
copy_v3_v3(ray_org_local, ray_origin);
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
@@ -1195,11 +1263,11 @@ static bool snapDerivedMesh(
neasrest_precalc.userdata = &treedata_type;
neasrest_precalc.index = -1;
nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
ray_org_local, ray_normal_local, mval, depth_range);
nearest2d_precalc(&neasrest_precalc, snapdata, *dist_px, obmat,
ray_org_local, ray_normal_local);
BVHTree_WalkLeafCallback cb_walk_leaf =
(snap_to == SCE_SNAP_MODE_VERTEX) ?
(snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
BLI_bvhtree_walk_dfs(
@@ -1214,7 +1282,7 @@ static bool snapDerivedMesh(
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
*dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
*dist_px = sqrtf(neasrest_precalc.dist_px_sq);
retval = true;
}
@@ -1231,11 +1299,8 @@ static bool snapDerivedMesh(
}
static bool snapEditMesh(
SnapObjectContext *sctx,
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
const short snap_to, const float mval[2], const enum eViewProj view_proj,
const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
const float depth_range[2],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1244,12 +1309,12 @@ static bool snapEditMesh(
{
bool retval = false;
if (snap_to == SCE_SNAP_MODE_FACE) {
if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
if (em->bm->totface == 0) {
return retval;
}
}
if (snap_to == SCE_SNAP_MODE_EDGE) {
if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
return retval;
}
@@ -1268,7 +1333,7 @@ static bool snapEditMesh(
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
copy_v3_v3(ray_normal_local, ray_normal);
copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_mat3_m4_v3(imat, ray_normal_local);
@@ -1287,7 +1352,7 @@ static bool snapEditMesh(
}
int tree_index = -1;
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
tree_index = 2;
break;
@@ -1311,7 +1376,7 @@ static bool snapEditMesh(
}
if (treedata && treedata->tree == NULL) {
switch (snap_to) {
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
{
BLI_bitmap *looptri_mask = NULL;
@@ -1369,9 +1434,9 @@ static bool snapEditMesh(
return retval;
}
if (snap_to == SCE_SNAP_MODE_FACE) {
if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
float ray_start_local[3];
copy_v3_v3(ray_start_local, ray_start);
copy_v3_v3(ray_start_local, snapdata->ray_start);
mul_m4_v3(imat, ray_start_local);
/* local scale in normal direction */
@@ -1386,7 +1451,7 @@ static bool snapEditMesh(
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
float len_diff = 0.0f;
if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
*/
@@ -1402,7 +1467,7 @@ static bool snapEditMesh(
len_diff = dot_v3v3(dvec, ray_normal_local);
float ray_org_local[3];
copy_v3_v3(ray_org_local, ray_origin);
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
/* We pass a temp ray_start, set from object's boundbox,
@@ -1411,7 +1476,8 @@ static bool snapEditMesh(
*/
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
madd_v3_v3v3fl(
ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale);
ray_start_local, ray_org_local, ray_normal_local,
len_diff + snapdata->depth_range[0] * local_scale);
local_depth -= len_diff;
}
}
@@ -1470,7 +1536,7 @@ static bool snapEditMesh(
const ARegion *ar = sctx->v3d_data.ar;
float ray_org_local[3];
copy_v3_v3(ray_org_local, ray_origin);
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
@@ -1479,11 +1545,11 @@ static bool snapEditMesh(
neasrest_precalc.userdata = &treedata_type;
neasrest_precalc.index = -1;
nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
ray_org_local, ray_normal_local, mval, depth_range);
nearest2d_precalc(&neasrest_precalc, snapdata, *dist_px, obmat,
ray_org_local, ray_normal_local);
BVHTree_WalkLeafCallback cb_walk_leaf =
(snap_to == SCE_SNAP_MODE_VERTEX) ?
(snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
BLI_bvhtree_walk_dfs(
@@ -1498,7 +1564,7 @@ static bool snapEditMesh(
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
*dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
*dist_px = sqrtf(neasrest_precalc.dist_px_sq);
retval = true;
}
@@ -1520,11 +1586,9 @@ static bool snapEditMesh(
* \note Duplicate args here are documented at #snapObjectsRay
*/
static bool snapObject(
SnapObjectContext *sctx,
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, float obmat[4][4], const unsigned int ob_index,
bool use_obedit, const short snap_to, const float mval[2],
const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
const float depth_range[2],
bool use_obedit,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1532,12 +1596,6 @@ static bool snapObject(
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
const enum eViewProj view_proj =
((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE :
(((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO);
const ARegion *ar = sctx->v3d_data.ar;
bool retval = false;
if (ob->type == OB_MESH) {
@@ -1546,9 +1604,7 @@ static bool snapObject(
if (use_obedit) {
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
sctx, ob, em, obmat, ob_index,
snap_to, mval, view_proj,
ray_origin, ray_start, ray_normal, depth_range,
sctx, snapdata, ob, em, obmat, ob_index,
ray_depth, dist_px,
r_loc, r_no, r_index,
r_hit_list);
@@ -1565,9 +1621,8 @@ static bool snapObject(
dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(
sctx, ob, dm, obmat, ob_index,
snap_to, mval, view_proj, true,
ray_origin, ray_start, ray_normal, depth_range,
sctx, snapdata, ob, dm, obmat, ob_index,
true,
ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
@@ -1575,31 +1630,30 @@ static bool snapObject(
dm->release(dm);
}
}
else if (snap_to != SCE_SNAP_MODE_FACE) {
else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) {
if (ob->type == OB_ARMATURE) {
retval = snapArmature(
ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal,
mval, view_proj, depth_range, dist_px,
snapdata,
ob, ob->data, obmat, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_CURVE) {
retval = snapCurve(
ar, ob, ob->data, obmat, snap_to, mval, view_proj,
depth_range,
snapdata,
ob, ob->data, obmat,
dist_px,
r_loc, r_no);
}
else if (ob->type == OB_EMPTY) {
retval = snapEmpty(
ar, ob, obmat, snap_to, mval, view_proj,
depth_range,
snapdata,
ob, obmat,
dist_px,
r_loc, r_no);
}
else if (ob->type == OB_CAMERA) {
retval = snapCamera(
sctx, ob, obmat, snap_to, mval, view_proj,
depth_range,
sctx, snapdata, ob, obmat,
dist_px,
r_loc, r_no);
}
@@ -1622,18 +1676,9 @@ static bool snapObject(
* Walks through all objects in the scene to find the closest snap element ray.
*
* \param sctx: Snap context to store data.
* \param snap_to: Element to snap, Vertice, Edge or Face.
* Currently only works one at a time, but can eventually operate as flag.
*
* \param snapdata: struct generated in `get_snapdata`.
* \param snap_select: from enum SnapSelect.
*
* \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
* \param mval: Mouse coords.
* When NULL, ray-casting is handled without any projection matrix correction.
* \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
* \param ray_start: ray_origin moved for the start clipping plane (clip_min).
* \param ray_normal: Unit length direction of the ray.
* \param depth_range: distances of clipe plane min and clip plane max;
*
* Read/Write Args
* ---------------
@@ -1654,11 +1699,9 @@ static bool snapObject(
*
*/
static bool snapObjectsRay(
SnapObjectContext *sctx,
const unsigned short snap_to, const SnapSelect snap_select,
const bool use_object_edit_cage, const float mval[2],
const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
const float depth_range[2],
SnapObjectContext *sctx, SnapData *snapdata,
const SnapSelect snap_select,
const bool use_object_edit_cage,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1681,9 +1724,7 @@ static bool snapObjectsRay(
Object *ob = base_act->object;
retval |= snapObject(
sctx, ob, ob->obmat, ob_index++,
false, snap_to, mval,
ray_origin, ray_start, ray_normal, depth_range,
sctx, snapdata, ob, ob->obmat, ob_index++, false,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1717,9 +1758,8 @@ static bool snapObjectsRay(
Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
retval |= snapObject(
sctx, dupli_snap, dupli_ob->mat, ob_index++,
use_obedit_dupli, snap_to, mval,
ray_origin, ray_start, ray_normal, depth_range,
sctx, snapdata, dupli_snap, dupli_ob->mat,
ob_index++, use_obedit_dupli,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1731,9 +1771,7 @@ static bool snapObjectsRay(
Object *ob_snap = use_obedit ? obedit : ob;
retval |= snapObject(
sctx, ob_snap, ob->obmat, ob_index++,
use_obedit, snap_to, mval,
ray_origin, ray_start, ray_normal, depth_range,
sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1842,10 +1880,13 @@ bool ED_transform_snap_object_project_ray_ex(
Object **r_ob, float r_obmat[4][4])
{
const float depth_range[2] = {0.0f, FLT_MAX};
SnapData snapdata;
set_SnapData(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range);
return snapObjectsRay(
sctx,
snap_to, params->snap_select, params->use_object_edit_cage, NULL,
ray_start, ray_start, ray_normal, depth_range,
sctx, &snapdata,
params->snap_select, params->use_object_edit_cage,
ray_depth, NULL,
r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
@@ -1874,10 +1915,13 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth_prev = ray_depth;
#endif
SnapData snapdata;
set_SnapData(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL,
ray_start, ray_start, ray_normal, depth_range);
bool retval = snapObjectsRay(
sctx,
snap_to, params->snap_select, params->use_object_edit_cage, NULL,
ray_start, ray_start, ray_normal, depth_range,
sctx, &snapdata,
params->snap_select, params->use_object_edit_cage,
&ray_depth, NULL,
NULL, NULL, NULL, NULL, NULL,
r_hit_list);
@@ -2037,10 +2081,14 @@ bool ED_transform_snap_object_project_view3d_ex(
ray_depth = &ray_depth_fallback;
}
SnapData snapdata;
const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
set_SnapData(&snapdata, ar, snap_to, view_proj, mval,
ray_start, ray_start, ray_normal, depth_range);
return snapObjectsRay(
sctx,
snap_to, params->snap_select, params->use_object_edit_cage,
mval, ray_origin, ray_start, ray_normal, depth_range,
sctx, &snapdata,
params->snap_select, params->use_object_edit_cage,
ray_depth, dist_px,
r_loc, r_no, r_index, NULL, NULL, NULL);
}