Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/transform/transform_snap_object.c')
-rw-r--r--source/blender/editors/transform/transform_snap_object.c186
1 files changed, 165 insertions, 21 deletions
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index f35a2808f22..14e8b8f97e0 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -201,8 +201,12 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext
return *sod_p;
}
-typedef void (*IterSnapObjsCallback)(
- SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
+typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
+ bool is_obedit,
+ bool use_backface_culling,
+ Object *ob,
+ float obmat[4][4],
+ void *data);
/**
* Walks through all objects in the scene to create the list of objects to snap.
@@ -219,6 +223,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
const View3D *v3d = sctx->v3d_data.v3d;
const eSnapSelect snap_select = params->snap_select;
const bool use_object_edit_cage = params->use_object_edit_cage;
+ const bool use_backface_culling = params->use_backface_culling;
Base *base_act = view_layer->basact;
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
@@ -250,12 +255,14 @@ static void iter_snap_objects(SnapObjectContext *sctx,
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
+ sob_callback(
+ sctx, use_object_edit_cage, use_backface_culling, dupli_ob->ob, dupli_ob->mat, data);
}
free_object_duplilist(lb);
}
- sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
+ sob_callback(
+ sctx, use_object_edit_cage, use_backface_culling, obj_eval, obj_eval->obmat, data);
}
}
@@ -350,6 +357,70 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
}
}
+static bool raycast_tri_backface_culling_test(
+ const float dir[3], const float v0[3], const float v1[3], const float v2[3], float no[3])
+{
+ cross_tri_v3(no, v0, v1, v2);
+ return dot_v3v3(no, dir) < 0.0f;
+}
+
+/* Callback to raycast with backface culling (Mesh). */
+static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
+ int index,
+ const BVHTreeRay *ray,
+ BVHTreeRayHit *hit)
+{
+ const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
+ const MVert *vert = data->vert;
+ const MLoopTri *lt = &data->looptri[index];
+ const float *vtri_co[3] = {
+ vert[data->loop[lt->tri[0]].v].co,
+ vert[data->loop[lt->tri[1]].v].co,
+ vert[data->loop[lt->tri[2]].v].co,
+ };
+ float dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
+
+ if (dist >= 0 && dist < hit->dist) {
+ float no[3];
+ if (raycast_tri_backface_culling_test(ray->direction, UNPACK3(vtri_co), no)) {
+ hit->index = index;
+ hit->dist = dist;
+ madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
+ normalize_v3_v3(hit->no, no);
+ }
+ }
+}
+
+/* Callback to raycast with backface culling (EditMesh). */
+static void editmesh_looptri_raycast_backface_culling_cb(void *userdata,
+ int index,
+ const BVHTreeRay *ray,
+ BVHTreeRayHit *hit)
+{
+ const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata;
+ BMEditMesh *em = data->em;
+ const BMLoop **ltri = (const BMLoop **)em->looptris[index];
+
+ const float *t0, *t1, *t2;
+ t0 = ltri[0]->v->co;
+ t1 = ltri[1]->v->co;
+ t2 = ltri[2]->v->co;
+
+ {
+ float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
+
+ if (dist >= 0 && dist < hit->dist) {
+ float no[3];
+ if (raycast_tri_backface_culling_test(ray->direction, t0, t1, t2, no)) {
+ hit->index = index;
+ hit->dist = dist;
+ madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
+ normalize_v3_v3(hit->no, no);
+ }
+ }
+ }
+}
+
static bool raycastMesh(SnapObjectContext *sctx,
const float ray_start[3],
const float ray_dir[3],
@@ -358,6 +429,7 @@ static bool raycastMesh(SnapObjectContext *sctx,
const float obmat[4][4],
const unsigned int ob_index,
bool use_hide,
+ bool use_backface_culling,
/* read/write args */
float *ray_depth,
/* return args */
@@ -494,7 +566,8 @@ static bool raycastMesh(SnapObjectContext *sctx,
ray_normal_local,
0.0f,
&hit,
- treedata->raycast_callback,
+ use_backface_culling ? mesh_looptri_raycast_backface_culling_cb :
+ treedata->raycast_callback,
treedata) != -1) {
hit.dist += len_diff;
hit.dist /= local_scale;
@@ -530,6 +603,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
BMEditMesh *em,
const float obmat[4][4],
const unsigned int ob_index,
+ bool use_backface_culling,
/* read/write args */
float *ray_depth,
/* return args */
@@ -670,7 +744,8 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
ray_normal_local,
0.0f,
&hit,
- treedata->raycast_callback,
+ use_backface_culling ? editmesh_looptri_raycast_backface_culling_cb :
+ treedata->raycast_callback,
treedata) != -1) {
hit.dist += len_diff;
hit.dist /= local_scale;
@@ -715,6 +790,7 @@ static bool raycastObj(SnapObjectContext *sctx,
const unsigned int ob_index,
bool use_obedit,
bool use_occlusion_test,
+ bool use_backface_culling,
/* read/write args */
float *ray_depth,
/* return args */
@@ -753,6 +829,7 @@ static bool raycastObj(SnapObjectContext *sctx,
em,
obmat,
ob_index,
+ use_backface_culling,
ray_depth,
r_loc,
r_no,
@@ -773,6 +850,7 @@ static bool raycastObj(SnapObjectContext *sctx,
obmat,
ob_index,
use_hide,
+ use_backface_culling,
ray_depth,
r_loc,
r_no,
@@ -792,6 +870,7 @@ static bool raycastObj(SnapObjectContext *sctx,
obmat,
ob_index,
false,
+ use_backface_culling,
ray_depth,
r_loc,
r_no,
@@ -832,8 +911,12 @@ struct RaycastObjUserData {
bool ret;
};
-static void raycast_obj_cb(
- SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
+static void raycast_obj_cb(SnapObjectContext *sctx,
+ bool use_obedit,
+ bool use_backface_culling,
+ Object *ob,
+ float obmat[4][4],
+ void *data)
{
struct RaycastObjUserData *dt = data;
@@ -845,6 +928,7 @@ static void raycast_obj_cb(
dt->ob_index++,
use_obedit,
dt->use_occlusion_test,
+ use_backface_culling,
dt->ray_depth,
dt->r_loc,
dt->r_no,
@@ -1088,8 +1172,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 {
- bool is_persp;
-
void *userdata;
Nearest2DGetVertCoCallback get_vert_co;
Nearest2DGetEdgeVertsCallback get_edge_verts_index;
@@ -1097,6 +1179,8 @@ typedef struct Nearest2dUserData {
Nearest2DGetTriEdgesCallback get_tri_edges_index;
Nearest2DCopyVertNoCallback copy_vert_no;
+ bool is_persp;
+ bool use_backface_culling;
} Nearest2dUserData;
static void cb_snap_vert(void *userdata,
@@ -1181,6 +1265,20 @@ static void cb_snap_tri_edges(void *userdata,
{
struct Nearest2dUserData *data = userdata;
+ if (data->use_backface_culling) {
+ int vindex[3];
+ data->get_tri_verts_index(index, vindex, data->userdata);
+
+ const float *t0, *t1, *t2;
+ data->get_vert_co(vindex[0], &t0, data->userdata);
+ data->get_vert_co(vindex[1], &t1, data->userdata);
+ data->get_vert_co(vindex[2], &t2, data->userdata);
+ float dummy[3];
+ if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
+ return;
+ }
+ }
+
int eindex[3];
data->get_tri_edges_index(index, eindex, data->userdata);
for (int i = 3; i--;) {
@@ -1204,6 +1302,18 @@ static void cb_snap_tri_verts(void *userdata,
int vindex[3];
data->get_tri_verts_index(index, vindex, data->userdata);
+
+ if (data->use_backface_culling) {
+ const float *t0, *t1, *t2;
+ data->get_vert_co(vindex[0], &t0, data->userdata);
+ data->get_vert_co(vindex[1], &t1, data->userdata);
+ data->get_vert_co(vindex[2], &t2, data->userdata);
+ float dummy[3];
+ if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
+ return;
+ }
+ }
+
for (int i = 3; i--;) {
if (vindex[i] == nearest->index) {
continue;
@@ -1222,6 +1332,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
SnapData *snapdata,
Object *ob,
const float obmat[4][4],
+ bool use_backface_culling,
/* read/write args */
float *dist_px,
/* return args */
@@ -1246,6 +1357,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
Nearest2dUserData nearest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .use_backface_culling = use_backface_culling,
};
BVHTreeNearest nearest = {
@@ -1366,6 +1478,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
const float obmat[4][4],
float original_dist_px,
const float prev_co[3],
+ bool use_backface_culling,
/* read/write args */
float *dist_px,
/* return args */
@@ -1392,6 +1505,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
Nearest2dUserData nearest2d;
{
nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ nearest2d.use_backface_culling = use_backface_culling;
if (sod->type == SNAP_MESH) {
nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
@@ -1995,6 +2109,7 @@ static short snapMesh(SnapObjectContext *sctx,
Object *ob,
Mesh *me,
const float obmat[4][4],
+ bool use_backface_culling,
/* read/write args */
float *dist_px,
/* return args */
@@ -2107,13 +2222,14 @@ static short snapMesh(SnapObjectContext *sctx,
}
Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.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,
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .use_backface_culling = use_backface_culling,
};
BVHTreeNearest nearest = {
@@ -2233,6 +2349,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
Object *ob,
BMEditMesh *em,
const float obmat[4][4],
+ bool use_backface_culling,
/* read/write args */
float *dist_px,
/* return args */
@@ -2346,11 +2463,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
.userdata = em,
.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,
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .use_backface_culling = use_backface_culling,
};
BVHTreeNearest nearest = {
@@ -2436,6 +2554,7 @@ static short snapObject(SnapObjectContext *sctx,
Object *ob,
float obmat[4][4],
bool use_obedit,
+ bool use_backface_culling,
/* read/write args */
float *dist_px,
/* return args */
@@ -2453,7 +2572,8 @@ static short snapObject(SnapObjectContext *sctx,
if (BKE_object_is_in_editmode(ob)) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
if (use_obedit) {
- retval = snapEditMesh(sctx, snapdata, ob, em, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapEditMesh(
+ sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
break;
}
else if (em->mesh_eval_final) {
@@ -2465,7 +2585,8 @@ static short snapObject(SnapObjectContext *sctx,
return 0;
}
- retval = snapMesh(sctx, snapdata, ob, me, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapMesh(
+ sctx, snapdata, ob, me, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
break;
}
case OB_ARMATURE:
@@ -2477,8 +2598,16 @@ static short snapObject(SnapObjectContext *sctx,
case OB_SURF:
case OB_FONT: {
if (ob->runtime.mesh_eval) {
- retval |= snapMesh(
- sctx, snapdata, ob, ob->runtime.mesh_eval, obmat, dist_px, r_loc, r_no, r_index);
+ retval |= snapMesh(sctx,
+ snapdata,
+ ob,
+ ob->runtime.mesh_eval,
+ obmat,
+ use_backface_culling,
+ dist_px,
+ r_loc,
+ r_no,
+ r_index);
}
break;
}
@@ -2519,8 +2648,12 @@ struct SnapObjUserData {
short ret;
};
-static void sanp_obj_cb(
- SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
+static void sanp_obj_cb(SnapObjectContext *sctx,
+ bool is_obedit,
+ bool use_backface_culling,
+ Object *ob,
+ float obmat[4][4],
+ void *data)
{
struct SnapObjUserData *dt = data;
@@ -2529,6 +2662,7 @@ static void sanp_obj_cb(
ob,
obmat,
is_obedit,
+ use_backface_culling,
/* read/write args */
dt->dist_px,
/* return args */
@@ -2881,7 +3015,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
new_clipplane[3] += 0.01f;
/* Try to snap only to the polygon. */
- elem_test = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index);
+ elem_test = snap_mesh_polygon(
+ sctx, &snapdata, ob, obmat, params->use_backface_culling, &dist_px_tmp, loc, no, &index);
if (elem_test) {
elem = elem_test;
}
@@ -2904,8 +3039,17 @@ static short transform_snap_context_project_view3d_mixed_impl(
(snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT |
SCE_SNAP_MODE_EDGE_PERPENDICULAR))) {
snapdata.snap_to_flag = snap_to_flag;
- elem = snap_mesh_edge_verts_mixed(
- sctx, &snapdata, ob, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index);
+ elem = snap_mesh_edge_verts_mixed(sctx,
+ &snapdata,
+ ob,
+ obmat,
+ *dist_px,
+ prev_co,
+ params->use_backface_culling,
+ &dist_px_tmp,
+ loc,
+ no,
+ &index);
}
if (elem & snap_to_flag) {