/* ** collision.h ** ** Some nice vector functions and stuff... for PixelMachine ** by SuperJer ** ** Email = superjer@superjer.com ** Web = http://www.superjer.com/ ** ** You can do whatever you like with this code, I don't care, ** just please recognize me as the original author. :) ** */ #define NO_COLLISION -1.0 struct V { double x; double y; double z; }; struct COLOR { double r; double g; double b; double a; }; struct SPHERE { V center; double radius; COLOR color; }; V &add( V &out, const V &a, const V &b ); V &subtract( V &out, const V &a, const V &b ); V &cross( V &out, const V &a, const V &b ); V &scale( V &out, double n ); V &normalize( V &out, double n ); V &mirror( V &out, const V &in, const V &mirror ); void CollideRaySphere( double &t, const V &o, const V &v, const V &p, const double &r ); V &add( V &out, const V &a, const V &b ) { out.x = a.x + b.x; out.y = a.y + b.y; out.z = a.z + b.z; return out; } V &subtract( V &out, const V &a, const V &b ) { out.x = a.x - b.x; out.y = a.y - b.y; out.z = a.z - b.z; return out; } V &cross( V &out, const V &a, const V &b ) { out.x = a.y*b.z - a.z*b.y; out.y = a.z*b.x - a.x*b.z; out.z = a.x*b.y - a.y*b.x; return out; } V &scale( V &out, double n ) { out.x *= n; out.y *= n; out.z *= n; return out; } V &normalize( V &out, double n ) { double l = sqrt(out.x*out.x + out.y*out.y + out.z*out.z); out.x *= n/l; out.y *= n/l; out.z *= n/l; return out; } V &mirror( V &out, const V &in, const V &mirror ) { V perp1, perp2; cross( perp1, in, mirror ); cross( perp2, perp1, mirror ); const double &a = mirror.x; const double &b = perp2.x; const double &c = in.x; const double &x = mirror.y; const double &y = perp2.y; const double &z = in.y; const double &i = mirror.z; const double &j = perp2.z; const double &k = in.z; double n, m; if( a > -0.0001 && a < 0.0001 ) { if( i > -0.0001 && i < 0.0001 ) { out.x = -in.x; out.y = in.y; out.z = -in.z; return out; } else { n = (z - (x*k)/i)/(y - (x*j)/i); m = (k - (j*n))/i; } } else { n = (z - (x*c)/a)/(y - (x*b)/a); m = (c - (b*n))/a; } V v1, v2; v1 = mirror; v2 = perp2; scale( v1, m ); scale( v2, n ); subtract( out, v1, v2 ); return out; } // This function is part of the SPARToR game engine by SuperJer.com void CollideRaySphere( double &t, const V &o, const V &v, const V &p, const double &r ) { double a, b, c, d, ox, oy, oz; // quadratic formula ox = o.x - p.x; oy = o.y - p.y; oz = o.z - p.z; a = 2.0*(v.x*v.x + v.y*v.y + v.z*v.z); b = 2.0*(v.x*ox + v.y*oy + v.z*oz); c = ox*ox + oy*oy + oz*oz - r*r; d = b*b - 2.0*a*c; // determinant if( d < 0.0 ) // no intersection at all { t = NO_COLLISION; return; } a = 1.0 / a; d = sqrt( d ); t = (-d - b) * a; if( t >= 0.0 ) return; // smaller root wins t = ( d - b) * a; if( t >= 0.0 ) return; // bigger root wins t = NO_COLLISION; return; // no root in range }