| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192 |
- #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: [email protected]
- //
- // 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 §);
- 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);
- }
- } // namespace ConvexDecomposition
- #endif
|