mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-14 05:40:05 +00:00
ab8f16961e
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
1193 lines
25 KiB
C++
1193 lines
25 KiB
C++
#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 §);
|
|
|
|
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
|