summaryrefslogtreecommitdiff
path: root/tests/bullet/Extras/ConvexDecomposition/cd_vector.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/bullet/Extras/ConvexDecomposition/cd_vector.h')
-rw-r--r--tests/bullet/Extras/ConvexDecomposition/cd_vector.h1185
1 files changed, 1185 insertions, 0 deletions
diff --git a/tests/bullet/Extras/ConvexDecomposition/cd_vector.h b/tests/bullet/Extras/ConvexDecomposition/cd_vector.h
new file mode 100644
index 00000000..bd1eff25
--- /dev/null
+++ b/tests/bullet/Extras/ConvexDecomposition/cd_vector.h
@@ -0,0 +1,1185 @@
+#ifndef CD_VECTOR_H
+
+#define CD_VECTOR_H
+
+/*----------------------------------------------------------------------
+ Copyright (c) 2004 Open Dynamics Framework Group
+ www.physicstools.org
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+ be used to endorse or promote products derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff@infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+#pragma warning(disable:4786)
+
+#include <math.h>
+#include <float.h>
+#include <vector>
+
+namespace ConvexDecomposition
+{
+
+
+const float DEG_TO_RAD = ((2.0f * 3.14152654f) / 360.0f);
+const float RAD_TO_DEG = (360.0f / (2.0f * 3.141592654f));
+
+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(float a,float b,float 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 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 /= (float 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); };
+
+ float operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY.
+ { return( (i==0)?x:((i==1)?y:z) ); };
+ float & operator [] (const int i)
+ { return( (i==0)?x:((i==1)?y:z) ); };
+//
+
+ // accessor methods.
+ float GetX(void) const { return x; };
+ float GetY(void) const { return y; };
+ float GetZ(void) const { return z; };
+
+ float X(void) const { return x; };
+ float Y(void) const { return y; };
+ float Z(void) const { return z; };
+
+ void SetX(float t) { x = t; };
+ void SetY(float t) { y = t; };
+ void SetZ(float 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(float *v) const
+ {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ };
+
+ void Set(const int *p)
+ {
+ x = (float) p[0];
+ y = (float) p[1];
+ z = (float) p[2];
+ }
+
+ void Set(const float *p)
+ {
+ x = (float) p[0];
+ y = (float) p[1];
+ z = (float) p[2];
+ }
+
+
+ void Set(float a,float b,float c)
+ {
+ x = a;
+ y = b;
+ z = c;
+ };
+
+ void Zero(void)
+ {
+ x = y = z = 0;
+ };
+
+ const float* Ptr() const { return &x; }
+ float* Ptr() { return &x; }
+
+
+// return -(*this).
+ Vector3d negative(void) const
+ {
+ Vector3d result;
+ result.x = -x;
+ result.y = -y;
+ result.z = -z;
+ return result;
+ }
+
+ float Magnitude(void) const
+ {
+ return float(sqrt(x * x + y * y + z * z));
+ };
+
+ float FastMagnitude(void) const
+ {
+ return float(sqrtf(x * x + y * y + z * z));
+ };
+
+ float FasterMagnitude(void) const
+ {
+ return float(sqrtf(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<int> &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(float angle,const Vector3d& axis)
+ {
+ x = axis.x*angle;
+ y = axis.y*angle;
+ z = axis.z*angle;
+ };
+
+ float Length(void) const // length of vector.
+ {
+ return float(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;
+ }
+
+
+ float FastLength(void) const // length of vector.
+ {
+ return float(sqrtf( x*x + y*y + z*z ));
+ };
+
+
+ float FasterLength(void) const // length of vector.
+ {
+ return float(sqrtf( x*x + y*y + z*z ));
+ };
+
+ float Length2(void) const // squared distance, prior to square root.
+ {
+ float l2 = x*x+y*y+z*z;
+ return l2;
+ };
+
+ float Distance(const Vector3d &a) const // distance between two points.
+ {
+ Vector3d d(a.x-x,a.y-y,a.z-z);
+ return d.Length();
+ }
+
+ float FastDistance(const Vector3d &a) const // distance between two points.
+ {
+ Vector3d d(a.x-x,a.y-y,a.z-z);
+ return d.FastLength();
+ }
+
+ float FasterDistance(const Vector3d &a) const // distance between two points.
+ {
+ Vector3d d(a.x-x,a.y-y,a.z-z);
+ return d.FasterLength();
+ }
+
+
+ float DistanceXY(const Vector3d &a) const
+ {
+ float dx = a.x - x;
+ float dy = a.y - y;
+ float dist = dx*dx + dy*dy;
+ return dist;
+ }
+
+ float 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;
+ };
+
+ float Partial(const Vector3d &p) const
+ {
+ return (x*p.y) - (p.x*y);
+ }
+
+ float Area(const Vector3d &p1,const Vector3d &p2) const
+ {
+ float 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 = 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 = 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;
+ };
+
+
+
+
+ float 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 + lineDelta*delta;
+ }
+ }
+
+ // 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 + lineDelta*delta;
+ }
+ }
+
+ // 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 - normal*delta;
+ }
+
+ // 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 - planeNormal*delta;
+ }
+
+ // 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
+ {
+ Vector3d axis[3];
+ axis[0].NearestPointInLine(triangle0, triangle1, triangle2);
+ axis[1].NearestPointInLine(triangle1, triangle0, triangle2);
+ axis[2].NearestPointInLine(triangle2, triangle0, triangle1);
+
+ float 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;
+ float bestMagnitude2 = 0;
+ float 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 - normal*delta;
+ }
+ }
+ }
+
+
+//private:
+
+ float x;
+ float y;
+ float z;
+};
+
+
+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(float a,float b) // construct with initial point.
+ {
+ x = a;
+ y = b;
+ };
+
+ const float* Ptr() const { return &x; }
+ float* 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*(float 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;
+ };
+
+
+ float Dot(const Vector2d &a) const // computes dot product.
+ {
+ return (x * a.x + y * a.y );
+ };
+
+ float GetX(void) const { return x; };
+ float GetY(void) const { return y; };
+
+ void SetX(float t) { x = t; };
+ void SetY(float t) { y = t; };
+
+ void Set(float a,float b)
+ {
+ x = a;
+ y = b;
+ };
+
+ void Zero(void)
+ {
+ x = y = 0;
+ };
+
+ Vector2d negative(void) const
+ {
+ Vector2d result;
+ result.x = -x;
+ result.y = -y;
+ return result;
+ }
+
+ float magnitude(void) const
+ {
+ return (float) sqrtf(x * x + y * y );
+ }
+
+ float fastmagnitude(void) const
+ {
+ return (float) sqrtf(x * x + y * y );
+ }
+
+ float fastermagnitude(void) const
+ {
+ return (float) sqrtf( x * x + y * y );
+ }
+
+ void Reflection(Vector2d &a,Vector2d &b); // compute reflection vector.
+
+ float Length(void) const // length of vector.
+ {
+ return float(sqrtf( x*x + y*y ));
+ };
+
+ float FastLength(void) const // length of vector.
+ {
+ return float(sqrtf( x*x + y*y ));
+ };
+
+ float FasterLength(void) const // length of vector.
+ {
+ return float(sqrtf( x*x + y*y ));
+ };
+
+ float Length2(void) // squared distance, prior to square root.
+ {
+ return x*x+y*y;
+ }
+
+ float Distance(const Vector2d &a) const // distance between two points.
+ {
+ float dx = a.x - x;
+ float dy = a.y - y;
+ float d = dx*dx+dy*dy;
+ return sqrtf(d);
+ };
+
+ float FastDistance(const Vector2d &a) const // distance between two points.
+ {
+ float dx = a.x - x;
+ float dy = a.y - y;
+ float d = dx*dx+dy*dy;
+ return sqrtf(d);
+ };
+
+ float FasterDistance(const Vector2d &a) const // distance between two points.
+ {
+ float dx = a.x - x;
+ float dy = a.y - y;
+ float d = dx*dx+dy*dy;
+ return sqrtf(d);
+ };
+
+ float Distance2(Vector2d &a) // squared distance.
+ {
+ float dx = a.x - x;
+ float 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;
+ };
+
+ float Normalize(void) // normalize to a unit vector, returns distance.
+ {
+ float l = Length();
+ if ( l != 0 )
+ {
+ l = float( 1 ) / l;
+ x*=l;
+ y*=l;
+ }
+ else
+ {
+ x = y = 0;
+ }
+ return l;
+ };
+
+ float FastNormalize(void) // normalize to a unit vector, returns distance.
+ {
+ float l = FastLength();
+ if ( l != 0 )
+ {
+ l = float( 1 ) / l;
+ x*=l;
+ y*=l;
+ }
+ else
+ {
+ x = y = 0;
+ }
+ return l;
+ };
+
+ float FasterNormalize(void) // normalize to a unit vector, returns distance.
+ {
+ float l = FasterLength();
+ if ( l != 0 )
+ {
+ l = float( 1 ) / l;
+ x*=l;
+ y*=l;
+ }
+ else
+ {
+ x = y = 0;
+ }
+ return l;
+ };
+
+
+ float x;
+ float 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 &sect);
+private:
+ Vector3d mP1;
+ Vector3d mP2;
+
+};
+
+
+typedef std::vector< Vector3d > Vector3dVector;
+typedef std::vector< Vector2d > Vector2dVector;
+
+inline Vector3d operator * (float s, const Vector3d &v )
+{
+ Vector3d Scaled(v.x*s, v.y*s, v.z*s);
+ return(Scaled);
+}
+
+inline Vector2d operator * (float s, const Vector2d &v )
+ {
+ Vector2d Scaled(v.x*s, v.y*s);
+ return(Scaled);
+ }
+
+}
+
+#endif