adding more math/common helper stuff

This commit is contained in:
gered 2011-04-22 16:04:05 -04:00
parent 09471fb57d
commit 0d28d5950b
7 changed files with 1976 additions and 158 deletions

View file

@ -90,6 +90,10 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\assets\material.h" />
<ClInclude Include="src\common.h" />
<ClInclude Include="src\geometry\common.h" />
<ClInclude Include="src\geometry\matrix4x4.h" />
<ClInclude Include="src\geometry\quaternion.h" />
<ClInclude Include="src\geometry\vector2.h" />
<ClInclude Include="src\geometry\vector3.h" />
<ClInclude Include="src\md2\md2.h" />

View file

@ -0,0 +1,27 @@
#ifndef __COMMON_H_INCLUDED__
#define __COMMON_H_INCLUDED__
#include <stdint.h>
#if !defined(TRUE) && !defined(FALSE)
typedef int32_t BOOL;
const BOOL TRUE = 1;
const BOOL FALSE = 0;
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = NULL; }
#endif
#ifndef SAFE_DELETE
#define SAFE_DELETE(x) if (x) { delete (x); (x) = NULL; }
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(x) if (x) { delete [] (x); (x) = NULL; }
#endif
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
#endif

View file

@ -0,0 +1,19 @@
#ifndef __GEOMETRY_COMMON_H_INCLUDED__
#define __GEOMETRY_COMMON_H_INCLUDED__
#include <math.h>
#define PI 3.141593f
#define PI_OVER_180 (PI / 180.0f)
#define DEG_TO_RAD(x) ((x) * PI_OVER_180)
#define RAD_TO_DEG(x) ((x) * (1.0f / (PI_OVER_180)))
#define TOLERANCE 0.00001f
#define IS_CLOSE_ENOUGH(a, b) (fabs((a - b) / ((b == 0.0f) ? 1.0f : b)) < EPSILON)
#define EPSILON 0.0005f
#define ISPOWEROF2(x) (((x) != 0) && !((x) & ((x) - 1)))
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,491 @@
#ifndef __GEOMETRY_QUATERNION_H_INCLUDED__
#define __GEOMETRY_QUATERNION_H_INCLUDED__
#include <math.h>
#include "common.h"
#include "vector3.h"
#include "matrix4x4.h"
/**
* Represents a quaternion to store an orientation or angular
* displacement and provides methods for conversion/manipulation
* <p>Referenced/based on code from:</p>
* <ul>
* <li>3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)</li>
* <li>More OpenGL Game Programming (Dave Astle, 2006)</li>
* <li>http://www.dhpoware.com/source/mathlib.html</li>
* </ul>
* @author Gered
*/
class Quaternion
{
public:
Quaternion() {}
Quaternion(float w, float x, float y, float z)
{
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
Quaternion(float w, const Vector3 &v)
{
this->w = w;
this->x = v.x;
this->y = v.y;
this->z = v.z;
}
Quaternion(const float *q)
{
w = q[0];
x = q[1];
y = q[2];
z = q[3];
}
~Quaternion() {}
void Set(float w, float x, float y, float z);
Matrix4x4 ToMatrix() const;
Vector3 GetVector() const;
static Quaternion Cross(const Quaternion &a, const Quaternion &b);
static float Dot(const Quaternion &a, const Quaternion &b);
static float Length(const Quaternion &q);
static float LengthSquared(const Quaternion &q);
static Quaternion Normalize(const Quaternion &q);
static Quaternion Conjugate(const Quaternion &q);
static Quaternion Inverse(const Quaternion &q);
static Quaternion CreateFromEulerAngles(float x, float y, float z);
static Quaternion CreateFromAxisAngle(float angle, const Vector3 &axis);
static Quaternion CreateFromRotationMatrix(const Matrix4x4 &matrix);
static void ExtractAxisAngle(const Quaternion &q, float *angle, Vector3 *axis);
static Quaternion Lerp(const Quaternion &a, const Quaternion &b, float interpolation);
static Quaternion Slerp(const Quaternion &a, const Quaternion &b, float interpolation);
float w;
float x;
float y;
float z;
};
Quaternion operator+(const Quaternion &left, const Quaternion &right);
Quaternion &operator+=(Quaternion &left, const Quaternion &right);
Quaternion operator-(const Quaternion &left, const Quaternion &right);
Quaternion &operator-=(Quaternion &left, const Quaternion &right);
Quaternion operator*(const Quaternion &left, float right);
Quaternion &operator*=(Quaternion &left, float right);
Quaternion operator*(const Quaternion &left, const Quaternion &right);
Quaternion &operator*=(Quaternion &left, const Quaternion &right);
Quaternion operator/(const Quaternion &left, float right);
Quaternion &operator/=(Quaternion &left, float right);
Vector3 operator*(const Vector3 &left, const Quaternion &right);
#define IDENTITY_QUATERNION Quaternion(1.0f, 0.0f, 0.0f, 0.0f)
inline void Quaternion::Set(float w, float x, float y, float z)
{
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
/**
* Converts a quaternion to a rotation matrix
* @return Matrix4x4
*/
inline Matrix4x4 Quaternion::ToMatrix() const
{
Matrix4x4 output;
output.m[_11] = 1.0f - (2.0f * ((y * y) + (z * z)));
output.m[_21] = 2.0f * ((x * y) + (z * w));
output.m[_31] = 2.0f * ((z * x) - (y * w));
output.m[_41] = 0.0f;
output.m[_12] = 2.0f * ((x * y) - (z * w));
output.m[_22] = 1.0f - (2.0f * ((z * z) + (x * x)));
output.m[_32] = 2.0f * ((y * z) + (x * w));
output.m[_42] = 0.0f;
output.m[_13] = 2.0f * ((z * x) + (y * w));
output.m[_23] = 2.0f * ((y * z) - (x * w));
output.m[_33] = 1.0f - (2.0f * ((y * y) + (x * x)));
output.m[_43] = 0.0f;
output.m[_14] = 0.0f;
output.m[_24] = 0.0f;
output.m[_34] = 0.0f;
output.m[_44] = 1.0f;
return output;
}
/**
* @return Vector3 the vector component of the quaternion.
*/
inline Vector3 Quaternion::GetVector() const
{
return Vector3(x, y, z);
}
/**
* Computes the cross product of two quaternions
* @param a first quaternion
* @param b second quaternion
* @return Quaternion the cross product
*/
inline Quaternion Quaternion::Cross(const Quaternion &a, const Quaternion &b)
{
return a * b;
}
/**
* Computes the dot product of 2 quaternions.
* @param a first quaternion
* @param b second quaternion
* @return float the dot product
*/
inline float Quaternion::Dot(const Quaternion &a, const Quaternion &b)
{
return (a.w * b.w) + (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}
/**
* Computes the length (magnitude) of a quaternion.
* @param q quaternion to retrieve the length of
* @return float the length
*/
inline float Quaternion::Length(const Quaternion &q)
{
return sqrtf((q.w * q.w) + (q.x * q.x) + (q.y * q.y) + (q.z * q.z));
}
/**
* Computes the squared length of a quaternion (the length minus the
* sqrt call).
* @param q quaternion to retrieve the squared length of
* @return float the squared length
*/
inline float Quaternion::LengthSquared(const Quaternion &q)
{
return (q.w * q.w) + (q.x * q.x) + (q.y * q.y) + (q.z * q.z);
}
/**
* Normalizes a quaternion (only if necessary)
* @param q quaternion to be normalized
* @return Quaternion normalized quaternion
*/
inline Quaternion Quaternion::Normalize(const Quaternion &q)
{
float inverseLength = 1.0f / Length(q);
return Quaternion(
q.w * inverseLength,
q.x * inverseLength,
q.y * inverseLength,
q.z * inverseLength
);
}
/**
* Computes the conjugate of a quaternion. If the quaternion
* is unit length, this also returns the inverse.
* @param q quaternion to retrieve the conjugate of
* @return Quaternion conjugate
*/
inline Quaternion Quaternion::Conjugate(const Quaternion &q)
{
return Quaternion(q.w, -q.x, -q.y, -q.z);
}
/**
* Computes the inverse of a given quaternion
* @param q quaternion to retrieve the inverse of
* @return Quaternion inverse of the quaternion
*/
inline Quaternion Quaternion::Inverse(const Quaternion &q)
{
float inverseSquaredLength = 1.0f / LengthSquared(q);
return Quaternion(
q.w * inverseSquaredLength,
-q.x * inverseSquaredLength,
-q.y * inverseSquaredLength,
-q.z * inverseSquaredLength
);
}
/**
* Converts euler angles to a quaternion
* @param x x angle of rotation (specified in radians)
* @param y y angle of rotation (specified in radians)
* @param z z angle of rotation (specified in radians)
* @return Quaternion quaternion equivalent to the euler angle
* orientation
*/
inline Quaternion Quaternion::CreateFromEulerAngles(float x, float y, float z)
{
Quaternion qx(cosf(x / 2.0f), sinf(x / 2.0f), 0.0f, 0.0f);
Quaternion qy(cosf(y / 2.0f), 0.0f, sinf(y / 2.0f), 0.0f);
Quaternion qz(cosf(z / 2.0f), 0.0f, 0.0f, sinf(z / 2.0f));
return Normalize(qz * qy * qx);
}
/**
* Converts an axis angle to a quaternion
* @param angle the angle to rotate be (specified in radians)
* @param axis the axis being rotated about
* @return Quaternion quaternion equivalent to the axis angle
* orientation
*/
inline Quaternion Quaternion::CreateFromAxisAngle(float angle, const Vector3 &axis)
{
Quaternion result;
float c = cosf(angle / 2.0f);
float s = sinf(angle / 2.0f);
result.w = c;
result.x = axis.x * s;
result.y = axis.y * s;
result.z = axis.z * s;
return Normalize(result);
}
/**
* Converts a rotation matrix to a quaternion
* @param matrix matrix to be converted
* @return Quaternion quaternion equivalent of the rotation
* matrix
*/
inline Quaternion Quaternion::CreateFromRotationMatrix(const Matrix4x4 &matrix)
{
Quaternion result;
float n = matrix.m[_11] + matrix.m[_22] + matrix.m[_33];
if (n > 0.0f)
{
float a = sqrtf(n + 1.0f);
result.w = a / 2.0f;
a = 0.5f / a;
result.x = (matrix.m[_32] - matrix.m[_23]) * a;
result.y = (matrix.m[_13] - matrix.m[_31]) * a;
result.z = (matrix.m[_21] - matrix.m[_12]) * a;
}
else if ((matrix.m[_11] >= matrix.m[_22]) && (matrix.m[_11] >= matrix.m[_33]))
{
float a = sqrtf(1.0f + matrix.m[_11] - matrix.m[_22] - matrix.m[_33]);
float b = 0.5f / a;
result.x = 0.5f * a;
result.y = (matrix.m[_21] + matrix.m[_12]) * b;
result.z = (matrix.m[_31] + matrix.m[_13]) * b;
result.w = (matrix.m[_32] - matrix.m[_23]) * b;
}
else if (matrix.m[_22] > matrix.m[_33])
{
float a = sqrtf(1.0f + matrix.m[_22] - matrix.m[_11] - matrix.m[_33]);
float b = 0.5f / a;
result.x = (matrix.m[_12] + matrix.m[_21]) * b;
result.y = 0.5f * a;
result.z = (matrix.m[_23] + matrix.m[_32]) * b;
result.w = (matrix.m[_13] - matrix.m[_31]) * b;
}
else
{
float a = sqrtf(1.0f + matrix.m[_33] - matrix.m[_11] - matrix.m[_22]);
float b = 0.5f / a;
result.x = (matrix.m[_13] + matrix.m[_31]) * b;
result.y = (matrix.m[_23] + matrix.m[_32]) * b;
result.z = 0.5f * a;
result.w = (matrix.m[_21] - matrix.m[_12]) * b;
}
return Normalize(result);
}
/**
* Converts a quaternion to an axis-angle representation.
* @param q the normalized quaternion to convert
* @param angle the angle (in radians)
* @param axis a vector that will contain the axis
*/
inline void Quaternion::ExtractAxisAngle(const Quaternion &q, float *angle, Vector3 *axis)
{
*angle = 2.0f * acosf(q.w);
float n = sqrtf(1.0f - (q.w * q.w));
if (n > 0.0001f)
*axis = q.GetVector() / n;
else
*axis = X_AXIS;
}
/**
* Linearly interpolates between two quaternions.
* @param a the first quaternion
* @param b the second quaternion
* @param interpolation the amount to interpolate
* @return Quaternion the interpolated quaternion
*/
inline Quaternion Quaternion::Lerp(const Quaternion &a, const Quaternion &b, float interpolation)
{
return (a * (1.0f - interpolation)) + (b * interpolation);
}
/**
* Interpolates between two quaternions using spherical
* interpolation.
* @param a the first quaternion
* @param b the second quaternion
* @param interpolation the amount to interpolate
* @return Quaternion the interpolated quaternion
*/
inline Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, float interpolation)
{
if (LengthSquared(a) == 0.0f)
{
if (LengthSquared(b) == 0.0f)
return IDENTITY_QUATERNION;
else
return b;
}
else if (LengthSquared(b) == 0.0f)
return a;
Quaternion q1 = a;
Quaternion q2 = b;
float cosHalfAngle = q1.w * q2.w + Vector3::Dot(q1.GetVector(), q2.GetVector());
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
return q1;
else if (cosHalfAngle < 0.0f)
{
q2.x = -q2.x;
q2.y = -q2.y;
q2.z = -q2.z;
q2.w = -q2.w;
cosHalfAngle = -cosHalfAngle;
}
float blendA;
float blendB;
if (cosHalfAngle < 0.99f)
{
float halfAngle = acosf(cosHalfAngle);
float sinHalfAngle = sinf(halfAngle);
float oneOverSinHalfAngle = 1.0f / sinHalfAngle;
blendA = sinf(halfAngle * (1.0f - interpolation)) * oneOverSinHalfAngle;
blendB = sinf(halfAngle * interpolation) * oneOverSinHalfAngle;
}
else
{
blendA = 1.0f - interpolation;
blendB = interpolation;
}
Quaternion result(q1.w * blendA + q2.w * blendB, q1.GetVector() * blendA + q2.GetVector() * blendB);
if (LengthSquared(result) > 0.0f)
return Normalize(result);
else
return IDENTITY_QUATERNION;
}
inline Quaternion operator+(const Quaternion &left, const Quaternion &right)
{
return Quaternion(
left.w + right.w,
left.x + right.x,
left.y + right.y,
left.z + right.z
);
}
inline Quaternion &operator+=(Quaternion &left, const Quaternion &right)
{
left = left + right;
return left;
}
inline Quaternion operator-(const Quaternion &left, const Quaternion &right)
{
return Quaternion(
left.w - right.w,
left.x - right.x,
left.y - right.y,
left.z - right.z
);
}
inline Quaternion &operator-=(Quaternion &left, const Quaternion &right)
{
left = left - right;
return left;
}
inline Quaternion operator*(const Quaternion &left, float right)
{
return Quaternion(
left.w * right,
left.x * right,
left.y * right,
left.z * right
);
}
inline Quaternion &operator*=(Quaternion &left, float right)
{
left = left * right;
return left;
}
inline Quaternion operator*(const Quaternion &left, const Quaternion &right)
{
return Quaternion(
(left.w * right.w) - (left.x * right.x) - (left.y * right.y) - (left.z * right.z),
(left.w * right.x) + (left.x * right.w) + (left.y * right.z) - (left.z * right.y),
(left.w * right.y) + (left.y * right.w) + (left.z * right.x) - (left.x * right.z),
(left.w * right.z) + (left.z * right.w) + (left.x * right.y) - (left.y * right.x)
);
}
inline Quaternion &operator*=(Quaternion &left, const Quaternion &right)
{
left = left * right;
return left;
}
inline Quaternion operator/(const Quaternion &left, float right)
{
return Quaternion(
left.w / right,
left.x / right,
left.y / right,
left.z / right
);
}
inline Quaternion &operator/=(Quaternion &left, float right)
{
left = left / right;
return left;
}
inline Vector3 operator*(const Vector3 &left, const Quaternion &right)
{
return Vector3(
((left.x * ((1.0f - (right.y * (right.y + right.y))) - (right.z * (right.z + right.z)))) + (left.y * ((right.x * (right.y + right.y)) - (right.w * (right.z + right.z))))) + (left.z * ((right.x * (right.z + right.z)) + (right.w * (right.y + right.y)))),
((left.x * ((right.x * (right.y + right.y)) + (right.w * (right.z + right.z)))) + (left.y * ((1.0f - (right.x * (right.x + right.x))) - (right.z * (right.z + right.z))))) + (left.z * ((right.y * (right.z + right.z)) - (right.w * (right.x + right.x)))),
((left.x * ((right.x * (right.z + right.z)) - (right.w * (right.y + right.y)))) + (left.y * ((right.y * (right.z + right.z)) + (right.w * (right.x + right.x))))) + (left.z * ((1.0f - (right.x * (right.x + right.x))) - (right.y * (right.y + right.y))))
);
}
#endif

View file

@ -1,11 +1,236 @@
#ifndef __VECTOR2_H_INCLUDED__
#define __VECTOR2_H_INCLUDED__
#ifndef __GEOMETRY_VECTOR2_H_INCLUDED__
#define __GEOMETRY_VECTOR2_H_INCLUDED__
#include <math.h>
/**
* Represents a 2D vector and provides common methods for vector math.
* <p>Referenced/based on code from:</p>
* <ul>
* <li>3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)</li>
* <li>http://www.dhpoware.com/source/mathlib.html</li>
* </ul>
* @author Gered
*/
class Vector2
{
public:
Vector2() {}
Vector2(float x, float y)
{
this->x = x;
this->y = y;
}
Vector2(const float *v)
{
x = v[0];
y = v[1];
}
~Vector2() {}
void Set(float x, float y);
static float Distance(const Vector2 &a, const Vector2 &b);
static float Dot(const Vector2 &a, const Vector2 &b);
static float Length(const Vector2 &v);
static float LengthSquared(const Vector2 &v);
static Vector2 Normalize(const Vector2 &v);
static Vector2 SetLength(const Vector2 &v, float length);
float x;
float y;
};
#endif
bool operator==(const Vector2 &left, const Vector2 &right);
Vector2 operator-(const Vector2 &left);
Vector2 operator+(const Vector2 &left, const Vector2 &right);
Vector2 &operator+=(Vector2 &left, const Vector2 &right);
Vector2 operator-(const Vector2 &left, const Vector2 &right);
Vector2 &operator-=(Vector2 &left, const Vector2 &right);
Vector2 operator*(const Vector2 &left, float right);
Vector2 &operator*=(Vector2 &left, float right);
Vector2 operator/(const Vector2 &left, float right);
Vector2 &operator/=(Vector2 &left, float right);
Vector2 operator*(const Vector2 &left, const Vector2 &right);
Vector2 &operator*=(Vector2 &left, const Vector2 &right);
Vector2 operator/(const Vector2 &left, const Vector2 &right);
Vector2 &operator/=(Vector2 &left, const Vector2 &right);
inline void Vector2::Set(float x, float y)
{
this->x = x;
this->y = y;
}
/**
* Calculates the distance between two points.
* @param a the first point
* @param b the second point
* @return the distance between both points
*/
inline float Vector2::Distance(const Vector2 &a, const Vector2 &b)
{
return sqrtf(
((b.x - a.x) * (b.x - a.x)) +
((b.y - a.y) * (b.y - a.y))
);
}
/**
* Computes the dot product of 2 vectors.
* @param a first vector
* @param b second vector
* @return the dot product
*/
inline float Vector2::Dot(const Vector2 &a, const Vector2 &b)
{
return
(a.x * b.y) +
(a.y * b.y);
}
/**
* Returns the length (magnitude) of a vector.
* @param v vector to calculate the length of
* @return the vector length
*/
inline float Vector2::Length(const Vector2 &v)
{
return sqrtf(
(v.x * v.x) +
(v.y * v.y)
);
}
/**
* Returns the squared length of a vector (the magnitude minus the sqrt
* call).
* @param v vector to calculate the squared length of
* @return squared length of the vector
*/
inline float Vector2::LengthSquared(const Vector2 &v)
{
return
(v.x * v.x) +
(v.y * v.y);
}
/**
* Normalizes a vector.
* @param v vector to normalize
* @return the normalized vector
*/
inline Vector2 Vector2::Normalize(const Vector2 &v)
{
float inverseLength = 1.0f / Length(v);
return Vector2(
v.x * inverseLength,
v.y * inverseLength
);
}
/**
* Adjusts a vector so that it's length is equal to the given length.
* @param v the original vector to be adjusted
* @param length desired vector length (magnitude)
* @return the resulting vector after it's length has been converted to the
* desired amount
*/
inline Vector2 Vector2::SetLength(const Vector2 &v, float length)
{
return v * (length / Length(v));
}
inline bool operator==(const Vector2 &left, const Vector2 &right)
{
return (left.x == right.x && left.y == right.y);
}
inline Vector2 operator-(const Vector2 &left)
{
return Vector2(-left.x, -left.y);
}
inline Vector2 operator+(const Vector2 &left, const Vector2 &right)
{
return Vector2(left.x + right.x, left.y + right.y);
}
inline Vector2 &operator+=(Vector2 &left, const Vector2 &right)
{
left.x += right.x;
left.y += right.y;
return left;
}
inline Vector2 operator-(const Vector2 &left, const Vector2 &right)
{
return Vector2(left.x - right.x, left.y - right.y);
}
inline Vector2 &operator-=(Vector2 &left, const Vector2 &right)
{
left.x -= right.x;
left.y -= right.y;
return left;
}
inline Vector2 operator*(const Vector2 &left, float right)
{
return Vector2(left.x * right, left.y * right);
}
inline Vector2 &operator*=(Vector2 &left, float right)
{
left.x *= right;
left.y *= right;
return left;
}
inline Vector2 operator/(const Vector2 &left, float right)
{
return Vector2(left.x / right, left.y / right);
}
inline Vector2 &operator/=(Vector2 &left, float right)
{
left.x /= right;
left.y /= right;
return left;
}
inline Vector2 operator*(const Vector2 &left, const Vector2 &right)
{
return Vector2(left.x * right.x, left.y * right.y);
}
inline Vector2 &operator*=(Vector2 &left, const Vector2 &right)
{
left.x *= right.x;
left.y *= right.y;
return left;
}
inline Vector2 operator/(const Vector2 &left, const Vector2 &right)
{
return Vector2(left.x / right.x, left.y / right.y);
}
inline Vector2 &operator/=(Vector2 &left, const Vector2 &right)
{
left.x /= right.x;
left.y /= right.y;
return left;
}
#endif

View file

@ -1,29 +1,52 @@
#ifndef __VECTOR3_H_INCLUDED__
#define __VECTOR3_H_INCLUDED__
#ifndef __GEOMETRY_VECTOR3_H_INCLUDED__
#define __GEOMETRY_VECTOR3_H_INCLUDED__
#include <math.h>
#include "../common.h"
/**
* Represents a 3D vector and provides common methods/operators
* for vector math
/**
* <p>Represents a 3D vector and provides common methods for vector math.</p>
* <p>Referenced/based on code from:</p>
* <ul>
* <li>3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)</li>
* <li>http://www.dhpoware.com/source/mathlib.html</li>
* <li>http://www.peroxide.dk/papers/collision/collision.pdf</li>
* </ul>
* @author Gered
*/
class Vector3
{
public:
Vector3() {}
Vector3(float vx, float vy, float vz) { x = vx; y = vy; z = vz; }
Vector3(const float *v) { x = v[0]; y = v[1]; z = v[2]; }
Vector3(float x, float y, float z)
{
this->x = x;
this->y = y;
this->z = z;
}
Vector3(const float *v)
{
x = v[0];
y = v[1];
z = v[2];
}
~Vector3() {}
void Set(float x, float y, float z);
static Vector3 Cross(const Vector3 &a, const Vector3 &b);
static float Dot(const Vector3 &a, const Vector3 &b);
static Vector3 Normalize(const Vector3 &a);
static Vector3 SurfaceNormal(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3);
static float Magnitude(const Vector3 &a);
static float SquaredLength(const Vector3 &a);
static Vector3 SetLength(const Vector3 &v, float length);
static float Distance(const Vector3 &a, const Vector3 &b);
static bool IsPointInTriangle(const Vector3 &point, const Vector3 &pa, const Vector3 &pb, const Vector3 &pc);
static float Dot(const Vector3 &a, const Vector3 &b);
static BOOL IsPointInTriangle(const Vector3 &point, const Vector3 &a, const Vector3 &b, const Vector3 &c);
static float Length(const Vector3 &v);
static float LengthSquared(const Vector3 &v);
static Vector3 Normalize(const Vector3 &v);
static Vector3 SetLength(const Vector3 &v, float length);
static Vector3 SurfaceNormal(const Vector3 &a, const Vector3 &b, const Vector3 &c);
static Vector3 Lerp(const Vector3 &a, const Vector3 &b, float interpolation);
float x;
float y;
@ -46,138 +69,43 @@ Vector3 operator/(const Vector3 &left, const Vector3 &right);
Vector3 &operator/=(Vector3 &left, const Vector3 &right);
#define ZERO_VECTOR Vector3(0.0f, 0.0f, 0.0f)
#define X_AXIS Vector3(1.0f, 0.0f, 0.0f)
#define Y_AXIS Vector3(0.0f, 1.0f, 0.0f)
#define Z_AXIS Vector3(0.0f, 0.0f, 1.0f)
#define UP Vector3(0.0f, 1.0f, 0.0f)
#define DOWN Vector3(0.0f, -1.0f, 0.0f)
#define FORWARD Vector3(0.0f, 0.0f, -1.0f)
#define BACKWARD Vector3(0.0f, 0.0f, 1.0f)
#define LEFT Vector3(-1.0f, 0.0f, 0.0f)
#define RIGHT Vector3(1.0f, 0.0f, 0.0f)
#define UP_VECTOR Vector3(0.0f, 1.0f, 0.0f)
inline void Vector3::Set(float x, float y, float z)
{
this->x = x;
this->y = y;
this->z = z;
}
/**
* Computes the cross product of 2 vectors.
* x = a.y * b.z - b.y * a.z
* y = a.z * b.x - b.z * a.x
* z = a.x * b.y - b.x * a.y
* @param a first vector
/**
* Computes the cross product of 2 vectors.
* @param a first vector
* @param b second vector
*
* @return Vector3 the cross product
* @return the cross product
*/
inline Vector3 Vector3::Cross(const Vector3 &a, const Vector3 &b)
{
return Vector3(
(a.y * b.z) - (b.y * a.z),
(a.z * b.x) - (b.z * a.x),
(a.x * b.y) - (b.x * a.y)
(a.y * b.z) - (a.z * b.y),
(a.z * b.x) - (a.x * b.z),
(a.x * b.y) - (a.y * b.x)
);
}
/**
* Computes the dot product of 2 vectors.
* dot = (a.x * b.x) + (a.y * b.y) + (a.z * b.z)
* @param a first vector
* @param b second vector
*
* @return float the dot product
*/
inline float Vector3::Dot(const Vector3 &a, const Vector3 &b)
{
return (a.x * b.x) +
(a.y * b.y) +
(a.z * b.z);
}
/**
* Normalizes a vector
* x = a.x / ||a||
* y = a.y / ||a||
* z = a.z / ||a||
* @param a vector to normalize
*
* @return Vector3 the normalized vector
*/
inline Vector3 Vector3::Normalize(const Vector3 &a)
{
float magnitudeSquared = (a.x * a.x) + (a.y * a.y) + (a.z * a.z);
if (magnitudeSquared > 0.0f)
{
float inverseMagnitude = 1.0f / sqrtf(magnitudeSquared);
return Vector3(
a.x * inverseMagnitude,
a.y * inverseMagnitude,
a.z * inverseMagnitude
);
}
else
return a;
}
/**
* Calculates a normal vector for the given 3 vectors making up
* a triangle (counter-clockwise order)
* @param v1 first vertex
* @param v2 second vertex
* @param v3 third vertex
*
* @return Vector3 normal vector for the triangle
*/
inline Vector3 Vector3::SurfaceNormal(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
{
return Vector3::Normalize(Vector3::Cross(v2 - v1, v3 - v1));
}
/**
* Returns magnitude of a vector.
* ||a|| = sqrt((a.x * a.x) + (a.y * a.y) + (a.z * a.z))
* @param a vector to calculate the magnitude of
*
* @return float vector magnitude
*/
inline float Vector3::Magnitude(const Vector3 &a)
{
return sqrtf(
(a.x * a.x) +
(a.y * a.y) +
(a.z * a.z)
);
}
/**
* Returns the squared length of a vector (the magnitude minus
* the sqrt call)
* @param a vector to calculate the squared length of
*
* @return float squared length of the vector
*/
inline float Vector3::SquaredLength(const Vector3 &a)
{
return
(a.x * a.x) +
(a.y * a.y) +
(a.z * a.z);
}
/**
* Adjusts a vector so that it's magnitude is equal to the given
* length
* @param v the original vector to be adjusted
* @param length desired vector magnitude
*
* @return Vector3 the resulting vector after it's length has
* been converted to the desired amount
*/
inline Vector3 Vector3::SetLength(const Vector3 &v, float length)
{
float magnitude = Vector3::Magnitude(v);
return v * (length / magnitude);
}
/**
* Calculates the distance between two points
* Calculates the distance between two points.
* @param a the first point
* @param b the second point
*
* @return float the distance between both points
* @return the distance between both points
*/
inline float Vector3::Distance(const Vector3 &a, const Vector3 &b)
{
@ -189,37 +117,131 @@ inline float Vector3::Distance(const Vector3 &a, const Vector3 &b)
}
/**
* Checks if a given point lies inside a triangle or not
* Computes the dot product of 2 vectors.
* @param a first vector
* @param b second vector
* @return the dot product
*/
inline float Vector3::Dot(const Vector3 &a, const Vector3 &b)
{
return
(a.x * b.x) +
(a.y * b.y) +
(a.z * b.z);
}
/**
* Checks if a given point lies inside a triangle or not.
* @param point point to test
* @param a first vector of the triangle
* @param b second vector of the triangle
* @param c third vector of the triangle
*
* @return BOOL TRUE if the point lies inside the triangle,
* FALSE if it doesn't
* @return TRUE if the point lies inside the triangle
*/
inline bool Vector3::IsPointInTriangle(const Vector3 &point, const Vector3 &pa, const Vector3 &pb, const Vector3 &pc)
inline BOOL Vector3::IsPointInTriangle(const Vector3 &point, const Vector3 &a, const Vector3 &b, const Vector3 &c)
{
Vector3 edge1 = pb - pa;
Vector3 edge2 = pc - pa;
float a = Vector3::Dot(edge1, edge1);
float b = Vector3::Dot(edge1, edge2);
float c = Vector3::Dot(edge2, edge2);
float ac_bb = (a * c) - (b * b);
Vector3 vp(point.x - pa.x, point.y - pa.y, point.z - pa.z);
float d = Vector3::Dot(vp, edge1);
float e = Vector3::Dot(vp, edge2);
float x = (d * c) - (e * b);
float y = (e * a) - (d * b);
float z = x + y - ac_bb;
int result = (( ((unsigned int&) z)& ~(((unsigned int&) x)|((unsigned int&) y)) ) & 0x80000000);
if (result == 0)
return false;
Vector3 v0 = c - a;
Vector3 v1 = b - a;
Vector3 v2 = point - a;
float dot00 = (v0.x * v0.x) + (v0.y * v0.y) + (v0.z * v0.z);
float dot01 = (v0.x * v1.x) + (v0.y * v1.y) + (v0.z * v1.z);
float dot02 = (v0.x * v2.x) + (v0.y * v2.y) + (v0.z * v2.z);
float dot11 = (v1.x * v1.x) + (v1.y * v1.y) + (v1.z * v1.z);
float dot12 = (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
float denom = dot00 * dot11 - dot01 * dot01;
if (denom == 0)
return FALSE;
float u = (dot11 * dot02 - dot01 * dot12) / denom;
float v = (dot00 * dot12 - dot01 * dot02) / denom;
if (u >= 0 && v >= 0 && u + v <= 1)
return TRUE;
else
return true;
return FALSE;
}
/**
* Returns the length (magnitude) of a vector.
* @param v vector to calculate the length of
* @return the vector length
*/
inline float Vector3::Length(const Vector3 &v)
{
return sqrtf(
(v.x * v.x) +
(v.y * v.y) +
(v.z * v.z)
);
}
/**
* Returns the squared length of a vector (the magnitude minus the sqrt
* call).
* @param v vector to calculate the squared length of
* @return squared length of the vector
*/
inline float Vector3::LengthSquared(const Vector3 &v)
{
return
(v.x * v.x) +
(v.y * v.y) +
(v.z * v.z);
}
/**
* Normalizes a vector.
* @param v vector to normalize
* @return the normalized vector
*/
inline Vector3 Vector3::Normalize(const Vector3 &v)
{
float inverseLength = 1.0f / Length(v);
return Vector3(
v.x * inverseLength,
v.y * inverseLength,
v.z * inverseLength
);
}
/**
* Adjusts a vector so that it's length is equal to the given
* length.
* @param v the original vector to be adjusted
* @param length desired vector length (magnitude)
* @return the resulting vector after it's length has been converted to the
* desired amount
*/
inline Vector3 Vector3::SetLength(const Vector3 &v, float length)
{
return v * (length / Length(v));
}
/**
* Calculates a normal vector for the given 3 vectors making up a
* triangle (counter clockwise order).
* @param a first vertex
* @param b second vertex
* @param c third vertex
* @return normal vector for the triangle
*/
inline Vector3 Vector3::SurfaceNormal(const Vector3 &a, const Vector3 &b, const Vector3 &c)
{
return Normalize(Cross((b - a), (c - a)));
}
/**
* Linearly interpolates between two vectors.
* @param a the first vector
* @param b the second vector
* @param interpolation the amount to interpolate
* @return Vector3 the interpolated vector
*/
inline Vector3 Vector3::Lerp(const Vector3 &a, const Vector3 &b, float interpolation)
{
return a + (b - a) * interpolation;
}
inline bool operator==(const Vector3 &left, const Vector3 &right)
@ -316,4 +338,4 @@ inline Vector3 &operator/=(Vector3 &left, const Vector3 &right)
return left;
}
#endif
#endif