@@ -128,6 +128,16 @@ pub fn powi<T: Float, V: FloatOps<T>>(a: V, b: i32) -> V {
128128 V :: powi ( a, b)
129129}
130130
131+ /// returns a squared (raised to the power 2)
132+ pub fn sqr < T : Float , V : FloatOps < T > + Base < T > > ( a : V ) -> V {
133+ a * a
134+ }
135+
136+ /// returns a cubed (raised to the power 3)
137+ pub fn cube < T : Float , V : FloatOps < T > + Base < T > > ( a : V ) -> V {
138+ a * a * a
139+ }
140+
131141/// returns a raised to the floating point power b
132142pub fn powf < T : Float , V : FloatOps < T > > ( a : V , b : T ) -> V {
133143 V :: powf ( a, b)
@@ -824,6 +834,13 @@ pub fn sphere_vs_sphere<T: Float, V: VecN<T> + VecFloatOps<T>>(s1: V, r1: T, s2:
824834 d2 < r22 * r22
825835}
826836
837+ /// returns true if the sphere or circle at centre s1 with radius r1 intsercts capsule c0-c1 with radius cr
838+ pub fn sphere_vs_capsule < T : Float + FloatOps < T > , V : VecN < T > + VecFloatOps < T > + FloatOps < T > > ( s1 : V , r1 : T , c0 : V , c1 : V , cr : T ) -> bool {
839+ let cp = closest_point_on_line_segment ( s1, c0, c1) ;
840+ let r2 = sqr ( r1 + cr) ;
841+ dist2 ( s1, cp) < r2
842+ }
843+
827844/// returns ture if the aabb defined by aabb_min to aabb_max intersects the sphere (or circle) centred at s with radius r
828845pub fn aabb_vs_sphere < T : Float , V : VecN < T > + VecFloatOps < T > + NumberOps < T > > ( aabb_min : V , aabb_max : V , s : V , r : T ) -> bool {
829846 let cp = closest_point_on_aabb ( s, aabb_min, aabb_max) ;
@@ -869,6 +886,7 @@ pub fn ray_vs_sphere<T: Float + FloatOps<T> + NumberOps<T>, V: VecN<T> + VecFloa
869886
870887/// returns the intersection point of the ray with origin r0 and direction rv with the aabb defined by aabb_min and aabb_max
871888pub fn ray_vs_aabb < T : Number + NumberOps < T > , V : VecN < T > > ( r0 : V , rv : V , aabb_min : V , aabb_max : V ) -> Option < V > {
889+ // http://gamedev.stackexchange.com/a/18459
872890 // min / max's from aabb axes
873891 let dirfrac = V :: one ( ) / rv;
874892 let tx = ( aabb_min[ 0 ] - r0[ 0 ] ) * dirfrac[ 0 ] ;
@@ -947,6 +965,22 @@ pub fn ray_vs_triangle<T: Float>(r0: Vec3<T>, rv: Vec3<T>, t0: Vec3<T>, t1: Vec3
947965 }
948966}
949967
968+ /// returns the intersection point of ray wih origin r0 and direction rv against the capsule with line c0 - c1 and radius cr
969+ pub fn ray_vs_capsule < T : Float + FloatOps < T > + NumberOps < T > + SignedNumberOps < T > , V : VecN < T > + VecFloatOps < T > + SignedNumberOps < T > + FloatOps < T > > ( r0 : V , rv : V , c0 : V , c1 : V , cr : T ) -> Option < V > {
970+ let sl = shortest_line_segment_between_lines ( r0, rv, c0, c1) ;
971+ if let Some ( line) = sl {
972+ if dist2 ( line. 0 , line. 1 ) < sqr ( cr) {
973+ Some ( line. 0 )
974+ }
975+ else {
976+ None
977+ }
978+ }
979+ else {
980+ None
981+ }
982+ }
983+
950984/// 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
951985pub fn sphere_vs_frustum < T : Number > ( s : Vec3 < T > , r : T , planes : & [ Vec4 < T > ; 6 ] ) -> bool {
952986 for p in planes. iter ( ) . take ( 6 ) {
@@ -1081,6 +1115,43 @@ pub fn shortest_line_segment_between_line_segments<T: Float + SignedNumberOps<T>
10811115 ) )
10821116}
10831117
1118+ /// returns the shortest line segment between 2 lines (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
1119+ pub fn shortest_line_segment_between_lines < 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 ) > {
1120+ // https://web.archive.org/web/20120404121511/http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/lineline.c
1121+
1122+ let p13 = p1 - p3;
1123+ let p43 = p4 - p3;
1124+
1125+ if approx ( abs ( p43) , V :: zero ( ) , T :: small_epsilon ( ) ) {
1126+ return None ;
1127+ }
1128+
1129+ let p21 = p2 - p1;
1130+ if approx ( abs ( p21) , V :: zero ( ) , T :: small_epsilon ( ) ) {
1131+ return None ;
1132+ }
1133+
1134+ let d1343 = dot ( p13, p43) ;
1135+ let d4321 = dot ( p43, p21) ;
1136+ let d1321 = dot ( p13, p21) ;
1137+ let d4343 = dot ( p43, p43) ;
1138+ let d2121 = dot ( p21, p21) ;
1139+
1140+ let denom = d2121 * d4343 - d4321 * d4321;
1141+ if abs ( denom) < T :: small_epsilon ( ) {
1142+ return None ;
1143+ }
1144+
1145+ let numer = d1343 * d4321 - d1321 * d4343;
1146+ let mua = numer / denom;
1147+ let mub = ( d1343 + d4321 * mua) / d4343;
1148+
1149+ Some ( (
1150+ p1 + ( p21 * mua) ,
1151+ p3 + ( p43 * mub)
1152+ ) )
1153+ }
1154+
10841155/// 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
10851156pub fn almost_identity < T : Number + Float > ( x : T , m : T , n : T ) -> T {
10861157 // <https://iquilezles.org/articles/functions/>
@@ -1374,12 +1445,11 @@ pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_star
13741445 out_start + slope * ( v - in_start)
13751446}
13761447
1377- // https://web.archive.org/web/20120414063459/http://local.wasp.uwa.edu.au/~pbourke//geometry/lineline3d/
1378-
13791448// TODO:
1380- // line_segment_between_line_segment_test
1449+ // line_segment_between_line_segment (test)
1450+ // sphere_vs_capsule (test)
1451+ // ray_vs_capsule (test)
13811452// missing fail cases
1382- // closest point on line seg to line seg
13831453// projection, ndc
13841454// projection, sc
13851455// unprojection, ndc,
@@ -1390,18 +1460,13 @@ pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_star
13901460// mat from quat
13911461// quat from mat
13921462
1393- // TODO: new ?
1394- // ray_vs_capsule
1395- // capsule_vs_sphere
1396- // line_vs_cone
1463+ // ADDITIONS ?
1464+ // obb_vs_sphere - easy
1465+ // obb_vs_aabb
1466+ // obb_vs_obb
13971467// ray_vs_cone
13981468// cone_vs_sphere
13991469// cone_vs_aabb
1400- // obb_vs_aabb
1401- // obb_vs_sphere
1402- // obb_vs_obb
1403- // line_vs_sphere
1404- // line_vs_aabb
14051470
14061471// TODO c++
14071472// point inside frustum
@@ -1425,4 +1490,7 @@ pub fn map_to_range<T: Float, X: Base<T>>(v: X, in_start: X, in_end: X, out_star
14251490// point hull distance
14261491// point poly distance
14271492// capsule_vs_plane
1428- // cone_vs_plane
1493+ // cone_vs_plane
1494+ // line_segment_between_line_segment
1495+ // sphere_vs_capsule
1496+ // ray_vs_capsule
0 commit comments