#ifndef VECTOR_H #define VECTOR_H /*! ** ** Copyright (c) 2007 by John W. Ratcliff mailto:jratcliff@infiniplex.net ** ** Portions of this source has been released with the PhysXViewer application, as well as ** Rocket, CreateDynamics, ODF, and as a number of sample code snippets. ** ** If you find this code useful or you are feeling particularily generous I would ** ask that you please go to http://www.amillionpixels.us and make a donation ** to Troy DeMolay. ** ** DeMolay is a youth group for young men between the ages of 12 and 21. ** It teaches strong moral principles, as well as leadership skills and ** public speaking. The donations page uses the 'pay for pixels' paradigm ** where, in this case, a pixel is only a single penny. Donations can be ** made for as small as $4 or as high as a $100 block. Each person who donates ** will get a link to their own site as well as acknowledgement on the ** donations blog located here http://www.amillionpixels.blogspot.com/ ** ** If you wish to contact me you can use the following methods: ** ** Skype Phone: 636-486-4040 (let it ring a long time while it goes through switches) ** Skype ID: jratcliff63367 ** Yahoo: jratcliff63367 ** AOL: jratcliff1961 ** email: jratcliff@infiniplex.net ** Personal website: http://jratcliffscarab.blogspot.com ** Coding Website: http://codesuppository.blogspot.com ** FundRaising Blog: http://amillionpixels.blogspot.com ** Fundraising site: http://www.amillionpixels.us ** New Temple Site: http://newtemple.blogspot.com ** ** ** The MIT license: ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal ** in the Software without restriction, including without limitation the rights ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is furnished ** to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in all ** copies or substantial portions of the Software. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma warning(disable:4786) #include #include #include const float DEG_TO_RAD = ((2.0f * 3.14152654f) / 360.0f); const float RAD_TO_DEG = (360.0f / (2.0f * 3.141592654f)); template class Vector3d { public: Vector3d(void) { }; // null constructor, does not inialize point. Vector3d(const Vector3d &a) // constructor copies existing vector. { x = a.x; y = a.y; z = a.z; }; Vector3d(Type a,Type b,Type c) // construct with initial point. { x = a; y = b; z = c; }; Vector3d(const float *t) { x = t[0]; y = t[1]; z = t[2]; }; Vector3d(const double *t) { x = (float)t[0]; y = (float)t[1]; z = (float)t[2]; }; Vector3d(const int *t) { x = t[0]; y = t[1]; z = t[2]; }; bool operator==(const Vector3d &a) const { return( a.x == x && a.y == y && a.z == z ); }; bool operator!=(const Vector3d &a) const { return( a.x != x || a.y != y || a.z != z ); }; // Operators Vector3d& operator = (const Vector3d& A) // ASSIGNMENT (=) { x=A.x; y=A.y; z=A.z; return(*this); }; Vector3d operator + (const Vector3d& A) const // ADDITION (+) { Vector3d Sum(x+A.x, y+A.y, z+A.z); return(Sum); }; Vector3d operator - (const Vector3d& A) const // SUBTRACTION (-) { Vector3d Diff(x-A.x, y-A.y, z-A.z); return(Diff); }; Vector3d operator * (const float s) const // MULTIPLY BY SCALAR (*) { Vector3d Scaled(x*s, y*s, z*s); return(Scaled); }; Vector3d operator + (const float s) const // ADD CONSTANT TO ALL 3 COMPONENTS (*) { Vector3d Scaled(x+s, y+s, z+s); return(Scaled); }; Vector3d operator / (const float s) const // DIVIDE BY SCALAR (/) { float r = 1.0f / s; Vector3d Scaled(x*r, y*r, z*r); return(Scaled); }; void operator /= (Type A) // ACCUMULATED VECTOR ADDITION (/=) { x/=A; y/=A; z/=A; }; void operator += (const Vector3d A) // ACCUMULATED VECTOR ADDITION (+=) { x+=A.x; y+=A.y; z+=A.z; }; void operator -= (const Vector3d A) // ACCUMULATED VECTOR SUBTRACTION (+=) { x-=A.x; y-=A.y; z-=A.z; }; void operator *= (const float s) // ACCUMULATED SCALAR MULTIPLICATION (*=) (bpc 4/24/2000) {x*=s; y*=s; z*=s;} void operator += (const float A) // ACCUMULATED VECTOR ADDITION (+=) { x+=A; y+=A; z+=A; }; Vector3d operator - (void) const // NEGATION (-) { Vector3d Negated(-x, -y, -z); return(Negated); }; Type operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY. { return( (i==0)?x:((i==1)?y:z) ); }; Type & operator [] (const int i) { return( (i==0)?x:((i==1)?y:z) ); }; // // accessor methods. Type GetX(void) const { return x; }; Type GetY(void) const { return y; }; Type GetZ(void) const { return z; }; Type X(void) const { return x; }; Type Y(void) const { return y; }; Type Z(void) const { return z; }; void SetX(Type t) { x = t; }; void SetY(Type t) { y = t; }; void SetZ(Type t) { z = t; }; bool IsSame(const Vector3d &v,float epsilon) const { float dx = fabsf( x - v.x ); if ( dx > epsilon ) return false; float dy = fabsf( y - v.y ); if ( dy > epsilon ) return false; float dz = fabsf( z - v.z ); if ( dz > epsilon ) return false; return true; } float ComputeNormal(const Vector3d &A, const Vector3d &B, const Vector3d &C) { float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag; vx = (B.x - C.x); vy = (B.y - C.y); vz = (B.z - C.z); wx = (A.x - B.x); wy = (A.y - B.y); wz = (A.z - B.z); vw_x = vy * wz - vz * wy; vw_y = vz * wx - vx * wz; vw_z = vx * wy - vy * wx; mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); if ( mag < 0.000001f ) { mag = 0; } else { mag = 1.0f/mag; } x = vw_x * mag; y = vw_y * mag; z = vw_z * mag; return mag; } void ScaleSumScale(float c0,float c1,const Vector3d &pos) { x = (x*c0) + (pos.x*c1); y = (y*c0) + (pos.y*c1); z = (z*c0) + (pos.z*c1); } void SwapYZ(void) { float t = y; y = z; z = t; }; void Get(Type *v) const { v[0] = x; v[1] = y; v[2] = z; }; void Set(const int *p) { x = (Type) p[0]; y = (Type) p[1]; z = (Type) p[2]; } void Set(const float *p) { x = (Type) p[0]; y = (Type) p[1]; z = (Type) p[2]; } void Set(Type a,Type b,Type c) { x = a; y = b; z = c; }; void Zero(void) { x = y = z = 0; }; const Type* Ptr() const { return &x; } Type* Ptr() { return &x; } // return -(*this). Vector3d negative(void) const { Vector3d result; result.x = -x; result.y = -y; result.z = -z; return result; } Type Magnitude(void) const { return Type(sqrt(x * x + y * y + z * z)); }; Type FastMagnitude(void) const { return Type(fast_sqrt(x * x + y * y + z * z)); }; Type FasterMagnitude(void) const { return Type(faster_sqrt(x * x + y * y + z * z)); }; void Lerp(const Vector3d& from,const Vector3d& to,float slerp) { x = ((to.x - from.x) * slerp) + from.x; y = ((to.y - from.y) * slerp) + from.y; z = ((to.z - from.z) * slerp) + from.z; }; // Highly specialized interpolate routine. Will compute the interpolated position // shifted forward or backwards along the ray defined between (from) and (to). // Reason for existance is so that when a bullet collides with a wall, for // example, you can generate a graphic effect slightly *before* it hit the // wall so that the effect doesn't sort into the wall itself. void Interpolate(const Vector3d &from,const Vector3d &to,float offset) { x = to.x-from.x; y = to.y-from.y; z = to.z-from.z; float d = sqrtf( x*x + y*y + z*z ); float recip = 1.0f / d; x*=recip; y*=recip; z*=recip; // normalize vector d+=offset; // shift along ray x = x*d + from.x; y = y*d + from.y; z = z*d + from.z; }; bool BinaryEqual(const Vector3d &p) const { const int *source = (const int *) &x; const int *dest = (const int *) &p.x; if ( source[0] == dest[0] && source[1] == dest[1] && source[2] == dest[2] ) return true; return false; }; bool BinaryEqual(const Vector3d &p) const { if ( x == p.x && y == p.y && z == p.z ) return true; return false; } /** Computes the reflection vector between two vectors.*/ void Reflection(const Vector3d &a,const Vector3d &b)// compute reflection vector. { Vector3d c; Vector3d d; float dot = a.Dot(b) * 2.0f; c = b * dot; d = c - a; x = -d.x; y = -d.y; z = -d.z; }; void AngleAxis(Type angle,const Vector3d& axis) { x = axis.x*angle; y = axis.y*angle; z = axis.z*angle; }; Type Length(void) const // length of vector. { return Type(sqrt( x*x + y*y + z*z )); }; float ComputePlane(const Vector3d &A, const Vector3d &B, const Vector3d &C) { float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag; vx = (B.x - C.x); vy = (B.y - C.y); vz = (B.z - C.z); wx = (A.x - B.x); wy = (A.y - B.y); wz = (A.z - B.z); vw_x = vy * wz - vz * wy; vw_y = vz * wx - vx * wz; vw_z = vx * wy - vy * wx; mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); if ( mag < 0.000001f ) { mag = 0; } else { mag = 1.0f/mag; } x = vw_x * mag; y = vw_y * mag; z = vw_z * mag; float D = 0.0f - ((x*A.x)+(y*A.y)+(z*A.z)); return D; } Type FastLength(void) const // length of vector. { return Type(fast_sqrt( x*x + y*y + z*z )); }; Type FasterLength(void) const // length of vector. { return Type(faster_sqrt( x*x + y*y + z*z )); }; Type Length2(void) const // squared distance, prior to square root. { Type l2 = x*x+y*y+z*z; return l2; }; Type Distance(const Vector3d &a) const // distance between two points. { Vector3d d(a.x-x,a.y-y,a.z-z); return d.Length(); } Type FastDistance(const Vector3d &a) const // distance between two points. { Vector3d d(a.x-x,a.y-y,a.z-z); return d.FastLength(); } Type FasterDistance(const Vector3d &a) const // distance between two points. { Vector3d d(a.x-x,a.y-y,a.z-z); return d.FasterLength(); } Type DistanceXY(const Vector3d &a) const { float dx = a.x - x; float dy = a.y - y; float dist = dx*dx + dy*dy; return dist; } Type Distance2(const Vector3d &a) const // squared distance. { float dx = a.x - x; float dy = a.y - y; float dz = a.z - z; return dx*dx + dy*dy + dz*dz; }; Type Partial(const Vector3d &p) const { return (x*p.y) - (p.x*y); } Type Area(const Vector3d &p1,const Vector3d &p2) const { Type A = Partial(p1); A+= p1.Partial(p2); A+= p2.Partial(*this); return A*0.5f; } inline float Normalize(void) // normalize to a unit vector, returns distance. { float d = sqrtf( static_cast< float >( x*x + y*y + z*z ) ); if ( d > 0 ) { float r = 1.0f / d; x *= r; y *= r; z *= r; } else { x = y = z = 1; } return d; }; inline float FastNormalize(void) // normalize to a unit vector, returns distance. { float d = fast_sqrt( static_cast< float >( x*x + y*y + z*z ) ); if ( d > 0 ) { float r = 1.0f / d; x *= r; y *= r; z *= r; } else { x = y = z = 1; } return d; }; inline float FasterNormalize(void) // normalize to a unit vector, returns distance. { float d = faster_sqrt( static_cast< float >( x*x + y*y + z*z ) ); if ( d > 0 ) { float r = 1.0f / d; x *= r; y *= r; z *= r; } else { x = y = z = 1; } return d; }; Type Dot(const Vector3d &a) const // computes dot product. { return (x * a.x + y * a.y + z * a.z ); }; Vector3d Cross( const Vector3d& other ) const { Vector3d result( y*other.z - z*other.y, z*other.x - x*other.z, x*other.y - y*other.x ); return result; } void Cross(const Vector3d &a,const Vector3d &b) // cross two vectors result in this one. { x = a.y*b.z - a.z*b.y; y = a.z*b.x - a.x*b.z; z = a.x*b.y - a.y*b.x; }; /******************************************/ // Check if next edge (b to c) turns inward // // Edge from a to b is already in face // Edge from b to c is being considered for addition to face /******************************************/ bool Concave(const Vector3d& a,const Vector3d& b) { float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag,nx,ny,nz,mag_a,mag_b; wx = b.x - a.x; wy = b.y - a.y; wz = b.z - a.z; mag_a = (float) sqrtf((wx * wx) + (wy * wy) + (wz * wz)); vx = x - b.x; vy = y - b.y; vz = z - b.z; mag_b = (float) sqrtf((vx * vx) + (vy * vy) + (vz * vz)); vw_x = (vy * wz) - (vz * wy); vw_y = (vz * wx) - (vx * wz); vw_z = (vx * wy) - (vy * wx); mag = (float) sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z)); // Check magnitude of cross product, which is a sine function // i.e., mag (a x b) = mag (a) * mag (b) * sin (theta); // If sin (theta) small, then angle between edges is very close to // 180, which we may want to call a concavity. Setting the // CONCAVITY_TOLERANCE value greater than about 0.01 MAY cause // face consolidation to get stuck on particular face. Most meshes // convert properly with a value of 0.0 if (mag/(mag_a*mag_b) <= 0.0f ) return true; mag = 1.0f / mag; nx = vw_x * mag; ny = vw_y * mag; nz = vw_z * mag; // Dot product of tri normal with cross product result will // yield positive number if edges are convex (+1.0 if two tris // are coplanar), negative number if edges are concave (-1.0 if // two tris are coplanar.) mag = ( x * nx) + ( y * ny) + ( z * nz); if (mag > 0.0f ) return false; return(true); }; bool PointTestXY(const Vector3d &i,const Vector3d &j) const { if (((( i.y <= y ) && ( y < j.y )) || (( j.y <= y ) && ( y < i.y ))) && ( x < (j.x - i.x) * (y - i.y) / (j.y - i.y) + i.x)) return true; return false; } // test to see if this point is inside the triangle specified by // these three points on the X/Y plane. bool PointInTriXY(const Vector3d &p1, const Vector3d &p2, const Vector3d &p3) const { float ax = p3.x - p2.x; float ay = p3.y - p2.y; float bx = p1.x - p3.x; float by = p1.y - p3.y; float cx = p2.x - p1.x; float cy = p2.y - p1.y; float apx = x - p1.x; float apy = y - p1.y; float bpx = x - p2.x; float bpy = y - p2.y; float cpx = x - p3.x; float cpy = y - p3.y; float aCROSSbp = ax*bpy - ay*bpx; float cCROSSap = cx*apy - cy*apx; float bCROSScp = bx*cpy - by*cpx; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); }; // test to see if this point is inside the triangle specified by // these three points on the X/Y plane. bool PointInTriYZ(const Vector3d &p1, const Vector3d &p2, const Vector3d &p3) const { float ay = p3.y - p2.y; float az = p3.z - p2.z; float by = p1.y - p3.y; float bz = p1.z - p3.z; float cy = p2.y - p1.y; float cz = p2.z - p1.z; float apy = y - p1.y; float apz = z - p1.z; float bpy = y - p2.y; float bpz = z - p2.z; float cpy = y - p3.y; float cpz = z - p3.z; float aCROSSbp = ay*bpz - az*bpy; float cCROSSap = cy*apz - cz*apy; float bCROSScp = by*cpz - bz*cpy; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); }; // test to see if this point is inside the triangle specified by // these three points on the X/Y plane. bool PointInTriXZ(const Vector3d &p1, const Vector3d &p2, const Vector3d &p3) const { float az = p3.z - p2.z; float ax = p3.x - p2.x; float bz = p1.z - p3.z; float bx = p1.x - p3.x; float cz = p2.z - p1.z; float cx = p2.x - p1.x; float apz = z - p1.z; float apx = x - p1.x; float bpz = z - p2.z; float bpx = x - p2.x; float cpz = z - p3.z; float cpx = x - p3.x; float aCROSSbp = az*bpx - ax*bpz; float cCROSSap = cz*apx - cx*apz; float bCROSScp = bz*cpx - bx*cpz; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); }; // Given a point and a line (defined by two points), compute the closest point // in the line. (The line is treated as infinitely long.) void NearestPointInLine(const Vector3d &point, const Vector3d &line0, const Vector3d &line1) { Vector3d &nearestPoint = *this; Vector3d lineDelta = line1 - line0; // Handle degenerate lines if ( lineDelta == Vector3d(0, 0, 0) ) { nearestPoint = line0; } else { float delta = (point-line0).Dot(lineDelta) / (lineDelta).Dot(lineDelta); nearestPoint = line0 + delta*lineDelta; } } // Given a point and a line segment (defined by two points), compute the closest point // in the line. Cap the point at the endpoints of the line segment. void NearestPointInLineSegment(const Vector3d &point, const Vector3d &line0, const Vector3d &line1) { Vector3d &nearestPoint = *this; Vector3d lineDelta = line1 - line0; // Handle degenerate lines if ( lineDelta == Vector3d(0, 0, 0) ) { nearestPoint = line0; } else { float delta = (point-line0).Dot(lineDelta) / (lineDelta).Dot(lineDelta); // Clamp the point to conform to the segment's endpoints if ( delta < 0 ) delta = 0; else if ( delta > 1 ) delta = 1; nearestPoint = line0 + delta*lineDelta; } } // Given a point and a plane (defined by three points), compute the closest point // in the plane. (The plane is unbounded.) void NearestPointInPlane(const Vector3d &point, const Vector3d &triangle0, const Vector3d &triangle1, const Vector3d &triangle2) { Vector3d &nearestPoint = *this; Vector3d lineDelta0 = triangle1 - triangle0; Vector3d lineDelta1 = triangle2 - triangle0; Vector3d pointDelta = point - triangle0; Vector3d normal; // Get the normal of the polygon (doesn't have to be a unit vector) normal.Cross(lineDelta0, lineDelta1); float delta = normal.Dot(pointDelta) / normal.Dot(normal); nearestPoint = point - delta*normal; } // Given a point and a plane (defined by a coplanar point and a normal), compute the closest point // in the plane. (The plane is unbounded.) void NearestPointInPlane(const Vector3d &point, const Vector3d &planePoint, const Vector3d &planeNormal) { Vector3d &nearestPoint = *this; Vector3d pointDelta = point - planePoint; float delta = planeNormal.Dot(pointDelta) / planeNormal.Dot(planeNormal); nearestPoint = point - delta*planeNormal; } // Given a point and a triangle (defined by three points), compute the closest point // in the triangle. Clamp the point so it's confined to the area of the triangle. void NearestPointInTriangle(const Vector3d &point, const Vector3d &triangle0, const Vector3d &triangle1, const Vector3d &triangle2) { static const Vector3d zeroVector(0, 0, 0); Vector3d &nearestPoint = *this; Vector3d lineDelta0 = triangle1 - triangle0; Vector3d lineDelta1 = triangle2 - triangle0; // Handle degenerate triangles if ( (lineDelta0 == zeroVector) || (lineDelta1 == zeroVector) ) { nearestPoint.NearestPointInLineSegment(point, triangle1, triangle2); } else if ( lineDelta0 == lineDelta1 ) { nearestPoint.NearestPointInLineSegment(point, triangle0, triangle1); } else { static Vector3d axis[3]; axis[0].NearestPointInLine(triangle0, triangle1, triangle2); axis[1].NearestPointInLine(triangle1, triangle0, triangle2); axis[2].NearestPointInLine(triangle2, triangle0, triangle1); Type axisDot[3]; axisDot[0] = (triangle0-axis[0]).Dot(point-axis[0]); axisDot[1] = (triangle1-axis[1]).Dot(point-axis[1]); axisDot[2] = (triangle2-axis[2]).Dot(point-axis[2]); bool bForce = true; Type bestMagnitude2 = 0; Type closeMagnitude2; Vector3d closePoint; if ( axisDot[0] < 0 ) { closePoint.NearestPointInLineSegment(point, triangle1, triangle2); closeMagnitude2 = point.Distance2(closePoint); if ( bForce || (bestMagnitude2 > closeMagnitude2) ) { bForce = false; bestMagnitude2 = closeMagnitude2; nearestPoint = closePoint; } } if ( axisDot[1] < 0 ) { closePoint.NearestPointInLineSegment(point, triangle0, triangle2); closeMagnitude2 = point.Distance2(closePoint); if ( bForce || (bestMagnitude2 > closeMagnitude2) ) { bForce = false; bestMagnitude2 = closeMagnitude2; nearestPoint = closePoint; } } if ( axisDot[2] < 0 ) { closePoint.NearestPointInLineSegment(point, triangle0, triangle1); closeMagnitude2 = point.Distance2(closePoint); if ( bForce || (bestMagnitude2 > closeMagnitude2) ) { bForce = false; bestMagnitude2 = closeMagnitude2; nearestPoint = closePoint; } } // If bForce is true at this point, it means the nearest point lies // inside the triangle; use the nearest-point-on-a-plane equation if ( bForce ) { Vector3d normal; // Get the normal of the polygon (doesn't have to be a unit vector) normal.Cross(lineDelta0, lineDelta1); Vector3d pointDelta = point - triangle0; float delta = normal.Dot(pointDelta) / normal.Dot(normal); nearestPoint = point - delta*normal; } } } //private: Type x; Type y; Type z; }; template class Vector2d { public: Vector2d(void) { }; // null constructor, does not inialize point. Vector2d(const Vector2d &a) // constructor copies existing vector. { x = a.x; y = a.y; }; Vector2d(const float *t) { x = t[0]; y = t[1]; }; Vector2d(Type a,Type b) // construct with initial point. { x = a; y = b; }; const Type* Ptr() const { return &x; } Type* Ptr() { return &x; } Vector2d & operator+=(const Vector2d &a) // += operator. { x+=a.x; y+=a.y; return *this; }; Vector2d & operator-=(const Vector2d &a) { x-=a.x; y-=a.y; return *this; }; Vector2d & operator*=(const Vector2d &a) { x*=a.x; y*=a.y; return *this; }; Vector2d & operator/=(const Vector2d &a) { x/=a.x; y/=a.y; return *this; }; bool operator==(const Vector2d &a) const { if ( a.x == x && a.y == y ) return true; return false; }; bool operator!=(const Vector2d &a) const { if ( a.x != x || a.y != y ) return true; return false; }; Vector2d operator+(Vector2d a) const { a.x+=x; a.y+=y; return a; }; Vector2d operator-(Vector2d a) const { a.x = x-a.x; a.y = y-a.y; return a; }; Vector2d operator - (void) const { return negative(); }; Vector2d operator*(Vector2d a) const { a.x*=x; a.y*=y; return a; }; Vector2d operator*(Type c) const { Vector2d a; a.x = x * c; a.y = y * c; return a; }; Vector2d operator/(Vector2d a) const { a.x = x/a.x; a.y = y/a.y; return a; }; Type Dot(const Vector2d &a) const // computes dot product. { return (x * a.x + y * a.y ); }; Type GetX(void) const { return x; }; Type GetY(void) const { return y; }; void SetX(Type t) { x = t; }; void SetY(Type t) { y = t; }; void Set(const int *p) { x = (Type) p[0]; y = (Type) p[1]; } void Set(const float *p) { x = (Type) p[0]; y = (Type) p[1]; } void Set(Type a,Type b) { x = a; y = b; }; void Zero(void) { x = y = z = 0; }; Vector2d negative(void) const { Vector2d result; result.x = -x; result.y = -y; return result; } Type magnitude(void) const { return (Type) sqrtf(x * x + y * y ); } Type fastmagnitude(void) const { return (Type) fast_sqrt(x * x + y * y ); } Type fastermagnitude(void) const { return (Type) faster_sqrt( x * x + y * y ); } void Reflection(Vector2d &a,Vector2d &b); // compute reflection vector. Type Length(void) const // length of vector. { return Type(sqrtf( x*x + y*y )); }; Type FastLength(void) const // length of vector. { return Type(fast_sqrt( x*x + y*y )); }; Type FasterLength(void) const // length of vector. { return Type(faster_sqrt( x*x + y*y )); }; Type Length2(void) // squared distance, prior to square root. { return x*x+y*y; } Type Distance(const Vector2d &a) const // distance between two points. { Type dx = a.x - x; Type dy = a.y - y; Type d = dx*dx+dy*dy; return sqrtf(d); }; Type FastDistance(const Vector2d &a) const // distance between two points. { Type dx = a.x - x; Type dy = a.y - y; Type d = dx*dx+dy*dy; return fast_sqrt(d); }; Type FasterDistance(const Vector2d &a) const // distance between two points. { Type dx = a.x - x; Type dy = a.y - y; Type d = dx*dx+dy*dy; return faster_sqrt(d); }; Type Distance2(Vector2d &a) // squared distance. { Type dx = a.x - x; Type dy = a.y - y; return dx*dx + dy *dy; }; void Lerp(const Vector2d& from,const Vector2d& to,float slerp) { x = ((to.x - from.x)*slerp) + from.x; y = ((to.y - from.y)*slerp) + from.y; }; void Cross(const Vector2d &a,const Vector2d &b) // cross two vectors result in this one. { x = a.y*b.x - a.x*b.y; y = a.x*b.x - a.x*b.x; }; Type Normalize(void) // normalize to a unit vector, returns distance. { Type l = Length(); if ( l != 0 ) { l = Type( 1 ) / l; x*=l; y*=l; } else { x = y = 0; } return l; }; Type FastNormalize(void) // normalize to a unit vector, returns distance. { Type l = FastLength(); if ( l != 0 ) { l = Type( 1 ) / l; x*=l; y*=l; } else { x = y = 0; } return l; }; Type FasterNormalize(void) // normalize to a unit vector, returns distance. { Type l = FasterLength(); if ( l != 0 ) { l = Type( 1 ) / l; x*=l; y*=l; } else { x = y = 0; } return l; }; Type x; Type y; }; class Line { public: Line(const Vector3d &from,const Vector3d &to) { mP1 = from; mP2 = to; }; // JWR Test for the intersection of two lines. bool Intersect(const Line& src,Vector3d §); private: Vector3d mP1; Vector3d mP2; }; typedef std::vector< Vector3d > Vector3dVector; typedef std::vector< Vector2d > Vector2dVector; template Vector3d operator * (Type s, const Vector3d &v ) { Vector3d Scaled(v.x*s, v.y*s, v.z*s); return(Scaled); }; template Vector2d operator * (Type s, const Vector2d &v ) { Vector2d Scaled(v.x*s, v.y*s); return(Scaled); }; class MyMatrix; class BoundingBox { public: void InitMinMax(void) { bmin.Set(FLT_MAX,FLT_MAX,FLT_MAX); bmax.Set(-FLT_MAX,-FLT_MAX,-FLT_MAX); } void MinMax(const Vector3d &p) { if ( p.x < bmin.x ) bmin.x = p.x; if ( p.y < bmin.y ) bmin.y = p.y; if ( p.z < bmin.z ) bmin.z = p.z; if ( p.x > bmax.x ) bmax.x = p.x; if ( p.y > bmax.y ) bmax.y = p.y; if ( p.z > bmax.z ) bmax.z = p.z; } void MinMax(const BoundingBox &b) { if ( b.bmin.x < bmin.x ) bmin.x = b.bmin.x; if ( b.bmin.y < bmin.y ) bmin.y = b.bmin.y; if ( b.bmin.z < bmin.z ) bmin.z = b.bmin.z; if ( b.bmax.x > bmax.x ) bmax.x = b.bmax.x; if ( b.bmax.y > bmax.y ) bmax.y = b.bmax.y; if ( b.bmax.z > bmax.z ) bmax.z = b.bmax.z; } void GetCenter(Vector3d ¢er) const { center.x = (bmax.x - bmin.x)*0.5f + bmin.x; center.y = (bmax.y - bmin.y)*0.5f + bmin.y; center.z = (bmax.z - bmin.z)*0.5f + bmin.z; } void GetSides(Vector3d &sides) const { sides.x = bmax.x - bmin.x; sides.y = bmax.y - bmin.y; sides.z = bmax.z - bmin.z; } float GetLength(void) const { return bmin.Distance(bmax); } void TransformBoundAABB(const MyMatrix &t,const BoundingBox &b); void BoundTest(const MyMatrix &transform,float x,float y,float z); Vector3d bmin; Vector3d bmax; }; #endif