@@ -679,6 +679,17 @@ pub fn point_inside_polygon<T: Float>(p: Vec2<T>, poly: &Vec<Vec2<T>>) -> bool {
679679 c
680680}
681681
682+ /// returns true if the point p is inside the frustum defined by 6 planes packed as vec4's .xyz = normal, .w = plane distance
683+ pub fn point_inside_frustum < T : Number > ( p : Vec3 < T > , planes : & [ Vec4 < T > ; 6 ] ) -> bool {
684+ for plane in planes. iter ( ) . take ( 6 ) {
685+ let d = dot ( p, Vec3 :: from ( * plane) ) + plane. w ;
686+ if d > T :: zero ( ) {
687+ return false ;
688+ }
689+ }
690+ true
691+ }
692+
682693/// returns the classification of the 3D aabb defined as aabb_min to aabb_max vs the plane defined by point on plane x and normal n
683694pub fn aabb_vs_plane < T : SignedNumber + SignedNumberOps < T > > ( aabb_min : Vec3 < T > , aabb_max : Vec3 < T > , x : Vec3 < T > , n : Vec3 < T > ) -> Classification {
684695 let e = ( aabb_max - aabb_min) / T :: two ( ) ;
@@ -936,7 +947,7 @@ pub fn ray_vs_triangle<T: Float>(r0: Vec3<T>, rv: Vec3<T>, t0: Vec3<T>, t1: Vec3
936947 }
937948}
938949
939- /// returns true if the sphere with centre s and radius r is inside the furstum defined by 6 planes packed as vec4's .xyz = normal, .w = plane distance
950+ /// returns true if the sphere with centre s and radius r is inside the frustum defined by 6 planes packed as vec4's .xyz = normal, .w = plane distance
940951pub fn sphere_vs_frustum < T : Number > ( s : Vec3 < T > , r : T , planes : & [ Vec4 < T > ; 6 ] ) -> bool {
941952 for p in planes. iter ( ) . take ( 6 ) {
942953 let d = dot ( s, Vec3 :: from ( * p) ) + p. w ;
@@ -947,7 +958,7 @@ pub fn sphere_vs_frustum<T: Number>(s: Vec3<T>, r: T, planes: &[Vec4<T>; 6]) ->
947958 true
948959}
949960
950- /// returns true if the aabb defined by aabb_pos (centre) and aabb_extent is inside the furstum defined by 6 planes packed as vec4's .xyz = normal, .w = plane distance
961+ /// returns true if the aabb defined by aabb_pos (centre) and aabb_extent is inside the frustum defined by 6 planes packed as vec4's .xyz = normal, .w = plane distance
951962pub fn aabb_vs_frustum < T : SignedNumber + SignedNumberOps < T > > ( aabb_pos : Vec3 < T > , aabb_extent : Vec3 < T > , planes : & [ Vec4 < T > ; 6 ] ) -> bool {
952963 let mut inside = true ;
953964 for p in planes. iter ( ) . take ( 6 ) {
@@ -990,7 +1001,7 @@ pub fn line_segment_vs_line_segment<T: Float + SignedNumberOps<T> + FloatOps<T>>
9901001}
9911002
9921003/// returns the intersection point if the infinite line l1-l2 intersects with s1-s2
993- pub fn line_vs_line < T : Float + SignedNumberOps < T > + FloatOps < T > > ( l1 : Vec3 < T > , l2 : Vec3 < T > , s1 : Vec3 < T > , s2 : Vec3 < T > ) -> Option < Vec3 < T > > {
1004+ pub fn line_vs_line < T : Float + SignedNumberOps < T > + FloatOps < T > > ( l1 : Vec3 < T > , l2 : Vec3 < T > , s1 : Vec3 < T > , s2 : Vec3 < T > ) -> Option < Vec3 < T > > {
9941005 let da = l2 - l1;
9951006 let db = s2 - s1;
9961007 let dc = s1 - l1;
@@ -1033,6 +1044,43 @@ pub fn ray_vs_line_segment<T: Float + SignedNumberOps<T> + FloatOps<T>>(r0: Vec3
10331044 }
10341045}
10351046
1047+ /// returns the shortest line segment between 2 line segments (p1-p2) and (p3-p4) as an option tuple where .0 is the point on line segment 1 and .1 is the point on line segment 2
1048+ pub fn shortest_line_segment_between_line_segments < T : Float + SignedNumberOps < T > + FloatOps < T > , V : VecN < T > + SignedNumberOps < T > + FloatOps < T > + Dot < T > > ( p1 : V , p2 : V , p3 : V , p4 : V ) -> Option < ( V , V ) > {
1049+ // https://web.archive.org/web/20120404121511/http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/lineline.c
1050+
1051+ let p13 = p1 - p3;
1052+ let p43 = p4 - p3;
1053+
1054+ if approx ( abs ( p43) , V :: zero ( ) , T :: small_epsilon ( ) ) {
1055+ return None ;
1056+ }
1057+
1058+ let p21 = p2 - p1;
1059+ if approx ( abs ( p21) , V :: zero ( ) , T :: small_epsilon ( ) ) {
1060+ return None ;
1061+ }
1062+
1063+ let d1343 = dot ( p13, p43) ;
1064+ let d4321 = dot ( p43, p21) ;
1065+ let d1321 = dot ( p13, p21) ;
1066+ let d4343 = dot ( p43, p43) ;
1067+ let d2121 = dot ( p21, p21) ;
1068+
1069+ let denom = d2121 * d4343 - d4321 * d4321;
1070+ if abs ( denom) < T :: small_epsilon ( ) {
1071+ return None ;
1072+ }
1073+
1074+ let numer = d1343 * d4321 - d1321 * d4343;
1075+ let mua = numer / denom;
1076+ let mub = ( d1343 + d4321 * mua) / d4343;
1077+
1078+ Some ( (
1079+ p1 + ( p21 * mua) ,
1080+ p3 + ( p43 * mub)
1081+ ) )
1082+ }
1083+
10361084/// returns soft clipping (in a cubic fashion) of x; let m be the threshold (anything above m stays unchanged), and n the value things will take when the signal is zero
10371085pub fn almost_identity < T : Number + Float > ( x : T , m : T , n : T ) -> T {
10381086 // <https://iquilezles.org/articles/functions/>
@@ -1326,9 +1374,11 @@ pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_star
13261374 out_start + slope * ( v - in_start)
13271375}
13281376
1329- // TODO: tests
1377+ // https://web.archive.org/web/20120414063459/http://local.wasp.uwa.edu.au/~pbourke//geometry/lineline3d/
1378+
1379+ // TODO:
13301380// missing fail cases
1331- // ray triangle (test)
1381+ // closest point on line seg to line seg
13321382// projection, ndc
13331383// projection, sc
13341384// unprojection, ndc,
@@ -1340,18 +1390,20 @@ pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_star
13401390// quat from mat
13411391
13421392// TODO: new?
1393+ // ray_vs_capsule
1394+ // capsule_vs_sphere
13431395// line_vs_cone
13441396// ray_vs_cone
13451397// cone_vs_sphere
13461398// cone_vs_aabb
1347- // capsule_vs_sphere
13481399// obb_vs_aabb
13491400// obb_vs_sphere
13501401// obb_vs_obb
13511402// line_vs_sphere
13521403// line_vs_aabb
13531404
13541405// TODO c++
1406+ // point inside frustum
13551407// point inside cone test has no passes
13561408// point plane distance
13571409// point sphere distance
0 commit comments