- pyapi mathutils.geometry.intersect_plane_plane

- isect_plane_plane_v3 uses better method
- minor refactor - arg name changes & some args as const.
This commit is contained in:
Campbell Barton 2011-11-20 05:56:21 +00:00
parent acf30220c9
commit e5f40a1aac
4 changed files with 206 additions and 139 deletions

@ -456,7 +456,7 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
unsigned int i; unsigned int i;
for (i= 0; i < 4; i++) { for (i= 0; i < 4; i++) {
float nd= -dist_to_plane_v3(co, data->frame_tx[i], data->normal_tx[i]); float nd= dist_to_plane_v3(co, data->frame_tx[i], data->normal_tx[i]);
if (nd < data->dist_vals[i]) { if (nd < data->dist_vals[i]) {
data->dist_vals[i]= nd; data->dist_vals[i]= nd;
} }
@ -530,55 +530,49 @@ int camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *cam
mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]); mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]);
} }
if ( (isect_plane_plane_v3(plane_isect_1, plane_isect_1_no, isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
plane_tx[0], data_cb.normal_tx[0], plane_tx[0], data_cb.normal_tx[0],
plane_tx[2], data_cb.normal_tx[2]) == 0) || plane_tx[2], data_cb.normal_tx[2]);
(isect_plane_plane_v3(plane_isect_2, plane_isect_2_no, isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
plane_tx[1], data_cb.normal_tx[1], plane_tx[1], data_cb.normal_tx[1],
plane_tx[3], data_cb.normal_tx[3]) == 0)) plane_tx[3], data_cb.normal_tx[3]);
add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);
if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
plane_isect_2, plane_isect_2_other,
plane_isect_pt_1, plane_isect_pt_2) == 0)
{ {
/* this is very unlikely */
return FALSE; return FALSE;
} }
else { else {
float cam_plane_no[3]= {0.0f, 0.0f, -1.0f};
float plane_isect_delta[3];
float plane_isect_delta_len;
add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no); mul_m3_v3(rot_obmat, cam_plane_no);
add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);
if (isect_line_line_v3(plane_isect_1, plane_isect_1_other, sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
plane_isect_2, plane_isect_2_other, plane_isect_delta_len= len_v3(plane_isect_delta);
plane_isect_pt_1, plane_isect_pt_2) == 0)
{ if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
return FALSE; copy_v3_v3(r_co, plane_isect_pt_1);
/* offset shift */
normalize_v3(plane_isect_1_no);
madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
} }
else { else {
float cam_plane_no[3]= {0.0f, 0.0f, -1.0f}; copy_v3_v3(r_co, plane_isect_pt_2);
float plane_isect_delta[3];
float plane_isect_delta_len;
mul_m3_v3(rot_obmat, cam_plane_no); /* offset shift */
normalize_v3(plane_isect_2_no);
sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1); madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
plane_isect_delta_len= len_v3(plane_isect_delta);
if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
copy_v3_v3(r_co, plane_isect_pt_1);
/* offset shift */
normalize_v3(plane_isect_1_no);
madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
}
else {
copy_v3_v3(r_co, plane_isect_pt_2);
/* offset shift */
normalize_v3(plane_isect_2_no);
madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
}
return TRUE;
} }
return TRUE;
} }
} }
} }

@ -60,6 +60,7 @@ float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2]);
float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]); float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]);
void closest_to_line_segment_v2(float closest[2], const float p[2], const float l1[2], const float l2[2]); void closest_to_line_segment_v2(float closest[2], const float p[2], const float l1[2], const float l2[2]);
float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3]);
float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]); float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]);
float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]); float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]);
float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]); float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]);
@ -96,12 +97,13 @@ int isect_line_line_v3(const float v1[3], const float v2[3],
float i1[3], float i2[3]); float i1[3], float i2[3]);
int isect_line_line_strict_v3(const float v1[3], const float v2[3], int isect_line_line_strict_v3(const float v1[3], const float v2[3],
const float v3[3], const float v4[3], const float v3[3], const float v4[3],
float vi[3], float *lambda); float vi[3], float *r_lambda);
/*if clip is nonzero, will only return true if lambda is >= 0.0 /*if clip is nonzero, will only return true if lambda is >= 0.0
(i.e. intersection point is along positive d)*/ (i.e. intersection point is along positive d)*/
int isect_ray_plane_v3(float p1[3], float d[3], float v0[3], int isect_ray_plane_v3(const float p1[3], const float d[3],
float v1[3], float v2[3], float *lambda, int clip); const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, const int clip);
/** /**
* Intersect line/plane, optionally treat line as directional (like a ray) with the no_flip argument. * Intersect line/plane, optionally treat line as directional (like a ray) with the no_flip argument.
@ -126,19 +128,19 @@ int isect_line_plane_v3(float out[3], const float l1[3], const float l2[3],
* @param plane_b_co The point on the second plane. * @param plane_b_co The point on the second plane.
* @param plane_b_no The normal of the second plane. * @param plane_b_no The normal of the second plane.
*/ */
int isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
const float plane_a_co[3], const float plane_a_no[3], const float plane_a_co[3], const float plane_a_no[3],
const float plane_b_co[3], const float plane_b_no[3]); const float plane_b_co[3], const float plane_b_no[3]);
/* line/ray triangle */ /* line/ray triangle */
int isect_line_tri_v3(const float p1[3], const float p2[3], int isect_line_tri_v3(const float p1[3], const float p2[3],
const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2]); const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]);
int isect_ray_tri_v3(const float p1[3], const float d[3], int isect_ray_tri_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2]); const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]);
int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], int isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2], const float threshold); const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float threshold);
int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2], const float epsilon); const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon);
/* point in polygon */ /* point in polygon */
int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]); int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]);
@ -148,16 +150,16 @@ int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y
int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]); int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]);
void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2], void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2],
const float pt[2], float *uv); const float pt[2], float r_uv[2]);
void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2], void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2],
const float v3[2], const float pt[2], float *uv); const float v3[2], const float pt[2], float r_uv[2]);
/* other */ /* other */
int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, int 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 *lambda, float ipoint[3]); const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]);
int isect_axial_line_tri_v3(const int axis, const float co1[3], const float co2[3], int isect_axial_line_tri_v3(const int axis, const float co1[3], const float co2[3],
const float v0[3], const float v1[3], const float v2[3], float *lambda); const float v0[3], const float v1[3], const float v2[3], float *r_lambda);
int isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]); int isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]);
@ -184,7 +186,7 @@ void barycentric_transform(float pt_tar[3], float const pt_src[3],
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2],
const float co[2], float w[3]); const float co[2], float w[3]);
void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]); void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]);
void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]);
/***************************** View & Projection *****************************/ /***************************** View & Projection *****************************/

@ -238,6 +238,15 @@ void closest_to_line_segment_v3(float closest[3], const float v1[3], const float
} }
/* signed distance from the point to the plane in 3D */ /* signed distance from the point to the plane in 3D */
float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3])
{
float plane_co_other[3];
add_v3_v3v3(plane_co_other, plane_co, plane_no_unit);
return line_point_factor_v3(p, plane_co, plane_co_other);
}
float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]) float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3])
{ {
float plane_no_unit[3]; float plane_no_unit[3];
@ -246,7 +255,7 @@ float dist_to_plane_v3(const float p[3], const float plane_co[3], const float pl
normalize_v3_v3(plane_no_unit, plane_no); normalize_v3_v3(plane_no_unit, plane_no);
add_v3_v3v3(plane_co_other, plane_co, plane_no_unit); add_v3_v3v3(plane_co_other, plane_co, plane_no_unit);
return -line_point_factor_v3(p, plane_co, plane_co_other); return line_point_factor_v3(p, plane_co, plane_co_other);
} }
/* distance v1 to line-piece v2-v3 in 3D */ /* distance v1 to line-piece v2-v3 in 3D */
@ -601,7 +610,9 @@ int isect_point_quad_v2(const float pt[2], const float v1[2], const float v2[2],
test if the line starting at p1 ending at p2 intersects the triangle v0..v2 test if the line starting at p1 ending at p2 intersects the triangle v0..v2
return non zero if it does return non zero if it does
*/ */
int isect_line_tri_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2]) int isect_line_tri_v3(const float p1[3], const float p2[3],
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, float r_uv[2])
{ {
float p[3], s[3], d[3], e1[3], e2[3], q[3]; float p[3], s[3], d[3], e1[3], e2[3], q[3];
@ -626,12 +637,12 @@ int isect_line_tri_v3(const float p1[3], const float p2[3], const float v0[3], c
v = f * dot_v3v3(d, q); v = f * dot_v3v3(d, q);
if ((v < 0.0f)||((u + v) > 1.0f)) return 0; if ((v < 0.0f)||((u + v) > 1.0f)) return 0;
*lambda = f * dot_v3v3(e2, q); *r_lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0f)||(*lambda > 1.0f)) return 0; if ((*r_lambda < 0.0f)||(*r_lambda > 1.0f)) return 0;
if(uv) { if(r_uv) {
uv[0]= u; r_uv[0]= u;
uv[1]= v; r_uv[1]= v;
} }
return 1; return 1;
@ -640,7 +651,9 @@ int isect_line_tri_v3(const float p1[3], const float p2[3], const float v0[3], c
test if the ray starting at p1 going in d direction intersects the triangle v0..v2 test if the ray starting at p1 going in d direction intersects the triangle v0..v2
return non zero if it does return non zero if it does
*/ */
int isect_ray_tri_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2]) int isect_ray_tri_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, float r_uv[2])
{ {
float p[3], s[3], e1[3], e2[3], q[3]; float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v; float a, f, u, v;
@ -665,18 +678,20 @@ int isect_ray_tri_v3(const float p1[3], const float d[3], const float v0[3], con
v = f * dot_v3v3(d, q); v = f * dot_v3v3(d, q);
if ((v < 0.0f)||((u + v) > 1.0f)) return 0; if ((v < 0.0f)||((u + v) > 1.0f)) return 0;
*lambda = f * dot_v3v3(e2, q); *r_lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0f)) return 0; if ((*r_lambda < 0.0f)) return 0;
if(uv) { if(r_uv) {
uv[0]= u; r_uv[0]= u;
uv[1]= v; r_uv[1]= v;
} }
return 1; return 1;
} }
int isect_ray_plane_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, int clip) int isect_ray_plane_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, const int clip)
{ {
float p[3], s[3], e1[3], e2[3], q[3]; float p[3], s[3], e1[3], e2[3], q[3];
float a, f; float a, f;
@ -700,13 +715,15 @@ int isect_ray_plane_v3(float p1[3], float d[3], float v0[3], float v1[3], float
/* v = f * dot_v3v3(d, q); */ /*UNUSED*/ /* v = f * dot_v3v3(d, q); */ /*UNUSED*/
*lambda = f * dot_v3v3(e2, q); *r_lambda = f * dot_v3v3(e2, q);
if (clip && (*lambda < 0.0f)) return 0; if (clip && (*r_lambda < 0.0f)) return 0;
return 1; return 1;
} }
int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *lambda, float uv[2], const float epsilon) int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, float uv[2], const float epsilon)
{ {
float p[3], s[3], e1[3], e2[3], q[3]; float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v; float a, f, u, v;
@ -729,8 +746,8 @@ int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], const float v0
v = f * dot_v3v3(d, q); v = f * dot_v3v3(d, q);
if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0; if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0;
*lambda = f * dot_v3v3(e2, q); *r_lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0f)) return 0; if ((*r_lambda < 0.0f)) return 0;
if(uv) { if(uv) {
uv[0]= u; uv[0]= u;
@ -740,7 +757,9 @@ int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], const float v0
return 1; return 1;
} }
int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *lambda, float *uv, const float threshold) int isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
const float v0[3], const float v1[3], const float v2[3],
float *r_lambda, float r_uv[2], const float threshold)
{ {
float p[3], s[3], e1[3], e2[3], q[3]; float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v; float a, f, u, v;
@ -757,8 +776,8 @@ int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], const float
sub_v3_v3v3(s, p1, v0); sub_v3_v3v3(s, p1, v0);
cross_v3_v3v3(q, s, e1); cross_v3_v3v3(q, s, e1);
*lambda = f * dot_v3v3(e2, q); *r_lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0f)) return 0; if ((*r_lambda < 0.0f)) return 0;
u = f * dot_v3v3(s, p); u = f * dot_v3v3(s, p);
v = f * dot_v3v3(d, q); v = f * dot_v3v3(d, q);
@ -782,9 +801,9 @@ int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], const float
return 0; return 0;
} }
if(uv) { if(r_uv) {
uv[0]= u; r_uv[0]= u;
uv[1]= v; r_uv[1]= v;
} }
return 1; return 1;
@ -833,24 +852,16 @@ int isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], cons
} }
} }
int isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], /* note: return normal isnt unit length */
void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
const float plane_a_co[3], const float plane_a_no[3], const float plane_a_co[3], const float plane_a_no[3],
const float plane_b_co[3], const float plane_b_no[3]) const float plane_b_co[3], const float plane_b_no[3])
{ {
float p1_co_other[3], p2_co_other[3]; float plane_a_co_other[3];
float isect_co_dummy[3]; cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */
cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no);
cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); add_v3_v3(plane_a_co_other, plane_a_co);
cross_v3_v3v3(p1_co_other, plane_a_no, r_isect_no); isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no, FALSE);
cross_v3_v3v3(p2_co_other, plane_b_no, r_isect_no);
add_v3_v3(p1_co_other, plane_a_co);
add_v3_v3(p2_co_other, plane_b_co);
/* we could use either ix_1, ix_2 - doesnt matter in this case */
return isect_line_line_v3(plane_a_co, p1_co_other,
plane_b_co, p2_co_other,
r_isect_co, isect_co_dummy);
} }
@ -893,7 +904,10 @@ static int getLowestRoot(const float a, const float b, const float c, const floa
return 0; return 0;
} }
int 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 *lambda, float ipoint[3]) int 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])
{ {
float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3]; float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3];
float a, b, c, d, e, x, y, z, radius2=radius*radius; float a, b, c, d, e, x, y, z, radius2=radius*radius;
@ -960,14 +974,14 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
if(z <= 0.0f && (x >= 0.0f && y >= 0.0f)) if(z <= 0.0f && (x >= 0.0f && y >= 0.0f))
{ {
//(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000){ //(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000){
*lambda=t0; *r_lambda=t0;
copy_v3_v3(ipoint,point); copy_v3_v3(ipoint,point);
return 1; return 1;
} }
} }
*lambda=1.0f; *r_lambda=1.0f;
/*---test points---*/ /*---test points---*/
a=dot_v3v3(vel,vel); a=dot_v3v3(vel,vel);
@ -977,7 +991,7 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
b=2.0f*dot_v3v3(vel,temp); b=2.0f*dot_v3v3(vel,temp);
c=dot_v3v3(temp,temp)-radius2; c=dot_v3v3(temp,temp)-radius2;
if(getLowestRoot(a, b, c, *lambda, lambda)) if(getLowestRoot(a, b, c, *r_lambda, r_lambda))
{ {
copy_v3_v3(ipoint,v0); copy_v3_v3(ipoint,v0);
found_by_sweep=1; found_by_sweep=1;
@ -988,7 +1002,7 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
b=2.0f*dot_v3v3(vel,temp); b=2.0f*dot_v3v3(vel,temp);
c=dot_v3v3(temp,temp)-radius2; c=dot_v3v3(temp,temp)-radius2;
if(getLowestRoot(a, b, c, *lambda, lambda)) if(getLowestRoot(a, b, c, *r_lambda, r_lambda))
{ {
copy_v3_v3(ipoint,v1); copy_v3_v3(ipoint,v1);
found_by_sweep=1; found_by_sweep=1;
@ -999,7 +1013,7 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
b=2.0f*dot_v3v3(vel,temp); b=2.0f*dot_v3v3(vel,temp);
c=dot_v3v3(temp,temp)-radius2; c=dot_v3v3(temp,temp)-radius2;
if(getLowestRoot(a, b, c, *lambda, lambda)) if(getLowestRoot(a, b, c, *r_lambda, r_lambda))
{ {
copy_v3_v3(ipoint,v2); copy_v3_v3(ipoint,v2);
found_by_sweep=1; found_by_sweep=1;
@ -1020,13 +1034,13 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv); b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv);
c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv; c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv;
if(getLowestRoot(a, b, c, *lambda, &newLambda)) if(getLowestRoot(a, b, c, *r_lambda, &newLambda))
{ {
e=(edotv*newLambda-edotbv)/elen2; e=(edotv*newLambda-edotbv)/elen2;
if(e >= 0.0f && e <= 1.0f) if(e >= 0.0f && e <= 1.0f)
{ {
*lambda = newLambda; *r_lambda = newLambda;
copy_v3_v3(ipoint,e1); copy_v3_v3(ipoint,e1);
mul_v3_fl(ipoint,e); mul_v3_fl(ipoint,e);
add_v3_v3(ipoint, v0); add_v3_v3(ipoint, v0);
@ -1044,13 +1058,13 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv); b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv);
c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv; c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv;
if(getLowestRoot(a, b, c, *lambda, &newLambda)) if(getLowestRoot(a, b, c, *r_lambda, &newLambda))
{ {
e=(edotv*newLambda-edotbv)/elen2; e=(edotv*newLambda-edotbv)/elen2;
if(e >= 0.0f && e <= 1.0f) if(e >= 0.0f && e <= 1.0f)
{ {
*lambda = newLambda; *r_lambda = newLambda;
copy_v3_v3(ipoint,e2); copy_v3_v3(ipoint,e2);
mul_v3_fl(ipoint,e); mul_v3_fl(ipoint,e);
add_v3_v3(ipoint, v0); add_v3_v3(ipoint, v0);
@ -1073,13 +1087,13 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv); b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv);
c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv; c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv;
if(getLowestRoot(a, b, c, *lambda, &newLambda)) if(getLowestRoot(a, b, c, *r_lambda, &newLambda))
{ {
e=(edotv*newLambda-edotbv)/elen2; e=(edotv*newLambda-edotbv)/elen2;
if(e >= 0.0f && e <= 1.0f) if(e >= 0.0f && e <= 1.0f)
{ {
*lambda = newLambda; *r_lambda = newLambda;
copy_v3_v3(ipoint,e3); copy_v3_v3(ipoint,e3);
mul_v3_fl(ipoint,e); mul_v3_fl(ipoint,e);
add_v3_v3(ipoint, v1); add_v3_v3(ipoint, v1);
@ -1090,7 +1104,8 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
return found_by_sweep; return found_by_sweep;
} }
int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *lambda) int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3],
const float v0[3], const float v1[3], const float v2[3], float *r_lambda)
{ {
float p[3], e1[3], e2[3]; float p[3], e1[3], e2[3];
float u, v, f; float u, v, f;
@ -1127,9 +1142,9 @@ int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3]
if ((u < 0.0f) || ((u + v) > 1.0f)) return 0; if ((u < 0.0f) || ((u + v) > 1.0f)) return 0;
*lambda = (p[a0]+u*e1[a0]+v*e2[a0])/(p2[a0]-p1[a0]); *r_lambda = (p[a0]+u*e1[a0]+v*e2[a0])/(p2[a0]-p1[a0]);
if ((*lambda < 0.0f) || (*lambda > 1.0f)) return 0; if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
return 1; return 1;
} }
@ -1203,7 +1218,7 @@ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3],
/* Intersection point strictly between the two lines /* Intersection point strictly between the two lines
* 0 when no intersection is found * 0 when no intersection is found
* */ * */
int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float vi[3], float *lambda) int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float vi[3], float *r_lambda)
{ {
float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3]; float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3];
float d; float d;
@ -1237,12 +1252,9 @@ int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float
{ {
mul_v3_fl(a, f1); mul_v3_fl(a, f1);
add_v3_v3v3(vi, v1, a); add_v3_v3v3(vi, v1, a);
if (lambda != NULL) if (r_lambda) *r_lambda = f1;
{
*lambda = f1;
}
return 1; /* intersection found */ return 1; /* intersection found */
} }
else else
@ -1306,7 +1318,7 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2
} }
/* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */ /* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */
void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float *uv) void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2])
{ {
float x0,y0, x1,y1, wtot, v2d[2], w1, w2; float x0,y0, x1,y1, wtot, v2d[2], w1, w2;
@ -1331,7 +1343,7 @@ void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2
wtot = w1+w2; wtot = w1+w2;
/*w1 = w1/wtot;*/ /*w1 = w1/wtot;*/
/*w2 = w2/wtot;*/ /*w2 = w2/wtot;*/
uv[0] = w1/wtot; r_uv[0] = w1/wtot;
} else { } else {
/* lines are parallel, lambda_cp_line_ex is 3d grrr */ /* lines are parallel, lambda_cp_line_ex is 3d grrr */
/*printf("\tparallel1\n");*/ /*printf("\tparallel1\n");*/
@ -1353,7 +1365,7 @@ void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2
v2d[1] = pt[1]-pt_on_line[1]; v2d[1] = pt[1]-pt_on_line[1];
w2 = len_v2(v2d); w2 = len_v2(v2d);
wtot = w1+w2; wtot = w1+w2;
uv[0] = w1/wtot; r_uv[0] = w1/wtot;
} }
/* Same as above to calc the uv[1] value, alternate calculation */ /* Same as above to calc the uv[1] value, alternate calculation */
@ -1371,7 +1383,7 @@ void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2
v2d[1] = y1-v1[1]; v2d[1] = y1-v1[1];
w2 = len_v2(v2d); w2 = len_v2(v2d);
wtot = w1+w2; wtot = w1+w2;
uv[1] = w1/wtot; r_uv[1] = w1/wtot;
} else { } else {
/* lines are parallel, lambda_cp_line_ex is 3d grrr */ /* lines are parallel, lambda_cp_line_ex is 3d grrr */
/*printf("\tparallel2\n");*/ /*printf("\tparallel2\n");*/
@ -1394,23 +1406,23 @@ void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2
v2d[1] = pt[1]-pt_on_line[1]; v2d[1] = pt[1]-pt_on_line[1];
w2 = len_v2(v2d); w2 = len_v2(v2d);
wtot = w1+w2; wtot = w1+w2;
uv[1] = w1/wtot; r_uv[1] = w1/wtot;
} }
/* may need to flip UV's here */ /* may need to flip UV's here */
} }
/* same as above but does tri's and quads, tri's are a bit of a hack */ /* same as above but does tri's and quads, tri's are a bit of a hack */
void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float *uv) void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2])
{ {
if (isquad) { if (isquad) {
isect_point_quad_uv_v2(v0, v1, v2, v3, pt, uv); isect_point_quad_uv_v2(v0, v1, v2, v3, pt, r_uv);
} }
else { else {
/* not for quads, use for our abuse of LineIntersectsTriangleUV */ /* not for quads, use for our abuse of LineIntersectsTriangleUV */
float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3], lambda; float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3], lambda;
p1_3d[0] = p2_3d[0] = uv[0]; p1_3d[0] = p2_3d[0] = r_uv[0];
p1_3d[1] = p2_3d[1] = uv[1]; p1_3d[1] = p2_3d[1] = r_uv[1];
p1_3d[2] = 1.0f; p1_3d[2] = 1.0f;
p2_3d[2] = -1.0f; p2_3d[2] = -1.0f;
v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0; v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0;
@ -1427,7 +1439,7 @@ void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[
copy_v2_v2(v2_3d, v2); copy_v2_v2(v2_3d, v2);
/* Doing this in 3D is not nice */ /* Doing this in 3D is not nice */
isect_line_tri_v3(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, uv); isect_line_tri_v3(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, r_uv);
} }
} }
@ -1993,7 +2005,7 @@ void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3
#define IS_ZERO(x) ((x>(-DBL_EPSILON) && x<DBL_EPSILON) ? 1 : 0) #define IS_ZERO(x) ((x>(-DBL_EPSILON) && x<DBL_EPSILON) ? 1 : 0)
/* Barycentric reverse */ /* Barycentric reverse */
void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]) void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
{ {
/* find UV such that /* find UV such that
t= u*t0 + v*t1 + (1-u-v)*t2 t= u*t0 + v*t1 + (1-u-v)*t2
@ -2005,13 +2017,13 @@ void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const fl
if(IS_ZERO(det)==0) { /* det should never be zero since the determinant is the signed ST area of the triangle. */ if(IS_ZERO(det)==0) { /* det should never be zero since the determinant is the signed ST area of the triangle. */
const double x[]= {st[0]-st2[0], st[1]-st2[1]}; const double x[]= {st[0]-st2[0], st[1]-st2[1]};
uv[0]= (float)((d*x[0] - b*x[1])/det); r_uv[0]= (float)((d*x[0] - b*x[1])/det);
uv[1]= (float)(((-c)*x[0] + a*x[1])/det); r_uv[1]= (float)(((-c)*x[0] + a*x[1])/det);
} else zero_v2(uv); } else zero_v2(r_uv);
} }
/* bilinear reverse */ /* bilinear reverse */
void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]) void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
{ {
const double signed_area= (st0[0]*st1[1] - st0[1]*st1[0]) + (st1[0]*st2[1] - st1[1]*st2[0]) + const double signed_area= (st0[0]*st1[1] - st0[1]*st1[0]) + (st1[0]*st2[1] - st1[1]*st2[0]) +
(st2[0]*st3[1] - st2[1]*st3[0]) + (st3[0]*st0[1] - st3[1]*st0[0]); (st2[0]*st3[1] - st2[1]*st3[0]) + (st3[0]*st0[1] - st3[1]*st0[0]);
@ -2029,25 +2041,25 @@ void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const f
const double denom= a - 2*b + fC; const double denom= a - 2*b + fC;
// clear outputs // clear outputs
zero_v2(uv); zero_v2(r_uv);
if(IS_ZERO(denom)!=0) { if(IS_ZERO(denom)!=0) {
const double fDen= a-fC; const double fDen= a-fC;
if(IS_ZERO(fDen)==0) if(IS_ZERO(fDen)==0)
uv[0]= (float)(a / fDen); r_uv[0]= (float)(a / fDen);
} else { } else {
const double desc_sq= b*b - a*fC; const double desc_sq= b*b - a*fC;
const double desc= sqrt(desc_sq<0.0?0.0:desc_sq); const double desc= sqrt(desc_sq<0.0?0.0:desc_sq);
const double s= signed_area>0 ? (-1.0) : 1.0; const double s= signed_area>0 ? (-1.0) : 1.0;
uv[0]= (float)(( (a-b) + s * desc ) / denom); r_uv[0]= (float)(( (a-b) + s * desc ) / denom);
} }
/* find UV such that /* find UV such that
fST = (1-u)(1-v)*ST0 + u*(1-v)*ST1 + u*v*ST2 + (1-u)*v*ST3 */ fST = (1-u)(1-v)*ST0 + u*(1-v)*ST1 + u*v*ST2 + (1-u)*v*ST3 */
{ {
const double denom_s= (1-uv[0])*(st0[0]-st3[0]) + uv[0]*(st1[0]-st2[0]); const double denom_s= (1-r_uv[0])*(st0[0]-st3[0]) + r_uv[0]*(st1[0]-st2[0]);
const double denom_t= (1-uv[0])*(st0[1]-st3[1]) + uv[0]*(st1[1]-st2[1]); const double denom_t= (1-r_uv[0])*(st0[1]-st3[1]) + r_uv[0]*(st1[1]-st2[1]);
int i= 0; double denom= denom_s; int i= 0; double denom= denom_s;
if(fabs(denom_s)<fabs(denom_t)) { if(fabs(denom_s)<fabs(denom_t)) {
@ -2056,7 +2068,7 @@ void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const f
} }
if(IS_ZERO(denom)==0) if(IS_ZERO(denom)==0)
uv[1]= (float) (( (1.0f-uv[0])*(st0[i]-st[i]) + uv[0]*(st1[i]-st[i]) ) / denom); r_uv[1]= (float) (( (1.0f-r_uv[0])*(st0[i]-st[i]) + r_uv[0]*(st1[i]-st[i]) ) / denom);
} }
} }

@ -497,6 +497,65 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
} }
} }
PyDoc_STRVAR(M_Geometry_intersect_plane_plane_doc,
".. function:: intersect_plane_plane(plane_a_co, plane_a_no, plane_b_co, plane_b_no)\n"
"\n"
" Return the intersection between two planes\n"
"\n"
" :arg plane_a_co: Point on the first plane\n"
" :type plane_a_co: :class:`mathutils.Vector`\n"
" :arg plane_a_no: Normal of the first plane\n"
" :type plane_a_no: :class:`mathutils.Vector`\n"
" :arg plane_b_co: Point on the second plane\n"
" :type plane_b_co: :class:`mathutils.Vector`\n"
" :arg plane_b_no: Normal of the second plane\n"
" :type plane_b_no: :class:`mathutils.Vector`\n"
" :return: The line of the intersection represented as a point and a vector\n"
" :rtype: tuple pair of :class:`mathutils.Vector`\n"
);
static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObject* args)
{
PyObject *ret;
VectorObject *plane_a_co, *plane_a_no, *plane_b_co, *plane_b_no;
float isect_co[3];
float isect_no[3];
if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_plane_plane",
&vector_Type, &plane_a_co,
&vector_Type, &plane_a_no,
&vector_Type, &plane_b_co,
&vector_Type, &plane_b_no))
{
return NULL;
}
if ( BaseMath_ReadCallback(plane_a_co) == -1 ||
BaseMath_ReadCallback(plane_a_no) == -1 ||
BaseMath_ReadCallback(plane_b_co) == -1 ||
BaseMath_ReadCallback(plane_b_no) == -1)
{
return NULL;
}
if (ELEM4(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_plane_plane(...): "
" can't use 2D Vectors");
return NULL;
}
isect_plane_plane_v3(isect_co, isect_no,
plane_a_co->vec, plane_a_no->vec,
plane_b_co->vec, plane_b_no->vec);
normalize_v3(isect_no);
ret= PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, newVectorObject(isect_co, 3, Py_NEW, NULL));
PyTuple_SET_ITEM(ret, 1, newVectorObject(isect_no, 3, Py_NEW, NULL));
return ret;
}
PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc, PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n" ".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n"
@ -1211,7 +1270,7 @@ static PyMethodDef M_Geometry_methods[]= {
{"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc}, {"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc},
{"intersect_line_line_2d", (PyCFunction) M_Geometry_intersect_line_line_2d, METH_VARARGS, M_Geometry_intersect_line_line_2d_doc}, {"intersect_line_line_2d", (PyCFunction) M_Geometry_intersect_line_line_2d, METH_VARARGS, M_Geometry_intersect_line_line_2d_doc},
{"intersect_line_plane", (PyCFunction) M_Geometry_intersect_line_plane, METH_VARARGS, M_Geometry_intersect_line_plane_doc}, {"intersect_line_plane", (PyCFunction) M_Geometry_intersect_line_plane, METH_VARARGS, M_Geometry_intersect_line_plane_doc},
/* TODO: isect_plane_plane_v3 --> intersect_plane_plane */ {"intersect_plane_plane", (PyCFunction) M_Geometry_intersect_plane_plane, METH_VARARGS, M_Geometry_intersect_plane_plane_doc},
{"intersect_line_sphere", (PyCFunction) M_Geometry_intersect_line_sphere, METH_VARARGS, M_Geometry_intersect_line_sphere_doc}, {"intersect_line_sphere", (PyCFunction) M_Geometry_intersect_line_sphere, METH_VARARGS, M_Geometry_intersect_line_sphere_doc},
{"intersect_line_sphere_2d", (PyCFunction) M_Geometry_intersect_line_sphere_2d, METH_VARARGS, M_Geometry_intersect_line_sphere_2d_doc}, {"intersect_line_sphere_2d", (PyCFunction) M_Geometry_intersect_line_sphere_2d, METH_VARARGS, M_Geometry_intersect_line_sphere_2d_doc},
{"distance_point_to_plane", (PyCFunction) M_Geometry_distance_point_to_plane, METH_VARARGS, M_Geometry_distance_point_to_plane_doc}, {"distance_point_to_plane", (PyCFunction) M_Geometry_distance_point_to_plane, METH_VARARGS, M_Geometry_distance_point_to_plane_doc},