Math Lib: optimize segment-plane clipping

Calculate the clipped min/max factor along the segment,
only applying to the coordinates at the end (will give better precision too).

Also make split input/output args.
This commit is contained in:
Campbell Barton 2016-01-23 13:44:20 +11:00
parent 456e7be9d2
commit 90293a8da3
5 changed files with 70 additions and 65 deletions

View File

@ -288,8 +288,12 @@ bool isect_ray_aabb_v3(
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius,
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]);
bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4]);
bool clip_segment_v3_plane_n(float p1[3], float p2[3], float plane_array[][4], const int plane_tot);
bool clip_segment_v3_plane(
const float p1[3], const float p2[3], const float plane[4],
float r_p1[3], float r_p2[3]);
bool clip_segment_v3_plane_n(
const float p1[3], const float p2[3], const float plane_array[][4], const int plane_tot,
float r_p1[3], float r_p2[3]);
void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData);
void fill_poly_v2i_n(

View File

@ -2476,9 +2476,12 @@ bool isect_point_tri_v3(
}
}
bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
bool clip_segment_v3_plane(
const float p1[3], const float p2[3],
const float plane[4],
float r_p1[3], float r_p2[3])
{
float dp[3], div, t, pc[3];
float dp[3], div;
sub_v3_v3v3(dp, p2, p1);
div = dot_v3v3(dp, plane);
@ -2486,98 +2489,96 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
if (div == 0.0f) /* parallel */
return true;
t = -plane_point_side_v3(plane, p1) / div;
float t = -plane_point_side_v3(plane, p1);
if (div > 0.0f) {
/* behind plane, completely clipped */
if (t >= 1.0f) {
zero_v3(p1);
zero_v3(p2);
if (t >= div) {
return false;
}
/* intersect plane */
if (t > 0.0f) {
madd_v3_v3v3fl(pc, p1, dp, t);
copy_v3_v3(p1, pc);
else if (t > 0.0f) {
const float p1_copy[3] = {UNPACK3(p1)};
copy_v3_v3(r_p2, p2);
madd_v3_v3v3fl(r_p1, p1_copy, dp, t / div);
return true;
}
return true;
}
else {
/* behind plane, completely clipped */
if (t <= 0.0f) {
zero_v3(p1);
zero_v3(p2);
if (t >= 0.0f) {
return false;
}
/* intersect plane */
if (t < 1.0f) {
madd_v3_v3v3fl(pc, p1, dp, t);
copy_v3_v3(p2, pc);
else if (t > div) {
const float p1_copy[3] = {UNPACK3(p1)};
copy_v3_v3(r_p1, p1);
madd_v3_v3v3fl(r_p2, p1_copy, dp, t / div);
return true;
}
return true;
}
/* incase input/output values match (above also) */
const float p1_copy[3] = {UNPACK3(p1)};
copy_v3_v3(r_p2, p2);
copy_v3_v3(r_p1, p1_copy);
return true;
}
bool clip_segment_v3_plane_n(float r_p1[3], float r_p2[3], float plane_array[][4], const int plane_tot)
bool clip_segment_v3_plane_n(
const float p1[3], const float p2[3],
const float plane_array[][4], const int plane_tot,
float r_p1[3], float r_p2[3])
{
/* intersect from both directions */
float p1[3], p2[3], dp[3], dp_orig[3];
int i;
copy_v3_v3(p1, r_p1);
copy_v3_v3(p2, r_p2);
float p1_fac = 0.0f, p2_fac = 1.0f;
float dp[3];
sub_v3_v3v3(dp, p2, p1);
copy_v3_v3(dp_orig, dp);
for (i = 0; i < plane_tot; i++) {
for (int i = 0; i < plane_tot; i++) {
const float *plane = plane_array[i];
const float div = dot_v3v3(dp, plane);
if (div != 0.0f) {
const float t = -plane_point_side_v3(plane, p1) / div;
float t = -plane_point_side_v3(plane, p1);
if (div > 0.0f) {
/* clip a */
if (t >= 1.0f) {
/* clip p1 lower bounds */
if (t >= div) {
return false;
}
/* intersect plane */
if (t > 0.0f) {
madd_v3_v3v3fl(p1, p1, dp, t);
/* recalc direction and test for flipping */
sub_v3_v3v3(dp, p2, p1);
if (dot_v3v3(dp, dp_orig) < 0.0f) {
return false;
else if (t > 0.0f) {
t /= div;
if (t > p1_fac) {
p1_fac = t;
if (p1_fac > p2_fac) {
return false;
}
}
}
}
else if (div < 0.0f) {
/* clip b */
if (t <= 0.0f) {
/* clip p2 upper bounds */
if (t >= 0.0f) {
return false;
}
/* intersect plane */
if (t < 1.0f) {
madd_v3_v3v3fl(p2, p1, dp, t);
/* recalc direction and test for flipping */
sub_v3_v3v3(dp, p2, p1);
if (dot_v3v3(dp, dp_orig) < 0.0f) {
return false;
else if (t > div) {
t /= div;
if (t < p2_fac) {
p2_fac = t;
if (p1_fac > p2_fac) {
return false;
}
}
}
}
}
}
copy_v3_v3(r_p1, p1);
copy_v3_v3(r_p2, p2);
/* incase input/output values match */
const float p1_copy[3] = {UNPACK3(p1)};
madd_v3_v3v3fl(r_p1, p1_copy, dp, p1_fac);
madd_v3_v3v3fl(r_p2, p1_copy, dp, p2_fac);
return true;
}

View File

@ -1439,7 +1439,10 @@ static bool point_is_visible(
copy_v3_v3(view_clip[0], p_ofs);
madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist);
if (clip_segment_v3_plane_n(view_clip[0], view_clip[1], kcd->vc.rv3d->clip_local, 6)) {
if (clip_segment_v3_plane_n(
view_clip[0], view_clip[1], kcd->vc.rv3d->clip_local, 6,
view_clip[0], view_clip[1]))
{
dist = len_v3v3(p_ofs, view_clip[1]);
}
}

View File

@ -3311,10 +3311,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
copy_v3_v3(v2, eed->v2->co);
}
copy_v3_v3(v1_clip, v1);
copy_v3_v3(v2_clip, v2);
if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
if (do_edge_textpair) {
interp_v3_v3v3(vmid, v1, v2, edge_texpair_sep);
@ -3378,10 +3375,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
copy_v3_v3(v2, eed->v2->co);
}
copy_v3_v3(v1_clip, v1);
copy_v3_v3(v2_clip, v2);
if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
float no_a[3], no_b[3];
float angle;

View File

@ -348,7 +348,10 @@ static void view3d_win_to_ray_segment(const ARegion *ar, View3D *v3d, const floa
BLI_INLINE bool view3d_clip_segment(RegionView3D *rv3d, float ray_start[3], float ray_end[3])
{
if ((rv3d->rflag & RV3D_CLIPPING) && !clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6)) {
if ((rv3d->rflag & RV3D_CLIPPING) &&
(clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6,
ray_start, ray_end) == false))
{
return false;
}
return true;