zeus/include/CVector3f.hpp

401 lines
10 KiB
C++
Raw Normal View History

2015-04-19 20:39:16 +00:00
#ifndef CVECTOR3F_HPP
#define CVECTOR3F_HPP
#include "Global.hpp"
2015-10-25 19:31:41 +00:00
#include "Math.hpp"
#include "CVector2f.hpp"
#include "TVectorUnion.hpp"
#if ZE_ATHENA_TYPES
2015-04-19 20:39:16 +00:00
#include <Athena/IStreamReader.hpp>
#endif
2015-04-19 20:39:16 +00:00
#include <math.h>
2015-04-19 23:15:32 +00:00
#include <assert.h>
2015-04-19 20:39:16 +00:00
namespace Zeus
{
2015-10-25 19:31:41 +00:00
class alignas(16) CVector3f
2015-04-19 20:39:16 +00:00
{
#if __atdna__
float clangVec __attribute__((__vector_size__(12)));
#endif
2015-04-19 20:39:16 +00:00
public:
ZE_DECLARE_ALIGNED_ALLOCATOR();
union
{
struct { float x, y, z; };
float v[4];
#if __SSE__
__m128 mVec128;
#elif __GEKKO_PS__
ps128_t mVec128;
#endif
};
2015-04-19 23:15:32 +00:00
inline CVector3f() {zeroOut();}
2015-10-25 19:31:41 +00:00
#if __SSE__ || __GEKKO_PS__
2015-04-19 20:39:16 +00:00
CVector3f(const __m128& mVec128) : mVec128(mVec128) {v[3] = 0.0f;}
2015-07-29 21:59:03 +00:00
#endif
2015-07-29 21:59:03 +00:00
#if ZE_ATHENA_TYPES
CVector3f(const atVec3f& vec)
2015-10-25 19:31:41 +00:00
#if __SSE__ || __GEKKO_PS__
2015-07-29 21:59:03 +00:00
: mVec128(vec.mVec128){}
#else
{
x = vec.vec[0], y = vec.vec[1], z = vec.vec[2], v[3] = 0.0f;
}
#endif
operator atVec3f()
{
atVec3f ret;
#if __SSE__
ret.mVec128 = mVec128;
#else
ret.vec = v;
2015-04-19 20:39:16 +00:00
#endif
return ret;
}
operator atVec3f() const
{
atVec3f ret;
#if __SSE__
ret.mVec128 = mVec128;
#else
ret.vec = v;
#endif
return ret;
}
2015-11-26 00:23:29 +00:00
void read(Athena::io::IStreamReader& input)
2015-04-19 20:39:16 +00:00
{
x = input.readFloat();
y = input.readFloat();
z = input.readFloat();
v[3] = 0.0f;
}
2015-11-26 00:23:29 +00:00
CVector3f(Athena::io::IStreamReader& input) {read(input);}
#endif
CVector3f(float xyz) {splat(xyz);}
void assign(float x, float y, float z) {v[0] = x; v[1] = y; v[2] = z; v[3] = 0.0;}
CVector3f(float x, float y, float z) {assign(x, y, z);}
CVector3f(const CVector2f& other)
{
x = other.x;
y = other.y;
z = 0.0;
v[3] = 0.0f;
}
2015-04-19 20:39:16 +00:00
inline bool operator ==(const CVector3f& rhs) const
{return (x == rhs.x && y == rhs.y && z == rhs.z);}
inline bool operator !=(const CVector3f& rhs) const
{return !(*this == rhs);}
2015-04-19 20:39:16 +00:00
inline CVector3f operator+(const CVector3f& rhs) const
{
#if __SSE__
return CVector3f(_mm_add_ps(mVec128, rhs.mVec128));
2015-10-25 19:31:41 +00:00
#elif __GEKKO_PS__
return CVector3f(__mm_gekko_add_ps(mVec128, rhs.mVec128));
2015-04-19 20:39:16 +00:00
#else
return CVector3f(x + rhs.x, y + rhs.y, z + rhs.z);
#endif
}
inline CVector3f operator-(const CVector3f& rhs) const
{
#if __SSE__
return CVector3f(_mm_sub_ps(mVec128, rhs.mVec128));
#else
return CVector3f(x - rhs.x, y - rhs.y, z - rhs.z);
#endif
}
inline CVector3f operator-() const
{
#if __SSE__
return CVector3f(_mm_sub_ps(_mm_xor_ps(mVec128, mVec128), mVec128));
2015-10-25 19:31:41 +00:00
#elif __GEKKO_PS__
return CVector3f(_mm_gekko_neg_ps(mVec128));
2015-04-19 20:39:16 +00:00
#else
return CVector3f(-x, -y, -z);
#endif
}
inline CVector3f operator*(const CVector3f& rhs) const
{
#if __SSE__
return CVector3f(_mm_mul_ps(mVec128, rhs.mVec128));
#else
return CVector3f(x * rhs.x, y * rhs.y, z * rhs.z);
#endif
}
inline CVector3f operator/(const CVector3f& rhs) const
{
#if __SSE__
return CVector3f(_mm_div_ps(mVec128, rhs.mVec128));
#else
return CVector3f(x / rhs.x, y / rhs.y, z / rhs.z);
#endif
}
inline CVector3f operator+(float val) const
{
#if __SSE__
TVectorUnion splat = {{val, val, val, 0.0}};
return CVector3f(_mm_add_ps(mVec128, splat.mVec128));
#else
return CVector3f(x + val, y + val, z + val);
#endif
}
inline CVector3f operator-(float val) const
{
2015-10-25 19:31:41 +00:00
#if __SSE__ || __GEKKO_PS__
2015-04-19 20:39:16 +00:00
TVectorUnion splat = {{val, val, val, 0.0}};
2015-10-25 19:31:41 +00:00
#endif
#if __SSE__
2015-04-19 20:39:16 +00:00
return CVector3f(_mm_sub_ps(mVec128, splat.mVec128));
2015-10-25 19:31:41 +00:00
#elif __GEKKO_PS__
return CVector3f(_mm_gekko_sub_ps(mVec128, splat.mVec128));
2015-04-19 20:39:16 +00:00
#else
return CVector3f(x - val, y - val, z - val);
#endif
}
inline CVector3f operator*(float val) const
{
2015-10-25 19:31:41 +00:00
#if __SSE__ || __GEKKO_PS__
2015-04-19 20:39:16 +00:00
TVectorUnion splat = {{val, val, val, 0.0}};
2015-10-25 19:31:41 +00:00
#endif
#if __SSE__
2015-04-19 20:39:16 +00:00
return CVector3f(_mm_mul_ps(mVec128, splat.mVec128));
2015-10-25 19:31:41 +00:00
#elif __GEKKO_PS__
return CVector3f(_mm_gekko_mul_ps(mVec128, splat.mVec128));
2015-04-19 20:39:16 +00:00
#else
return CVector3f(x * val, y * val, z * val);
#endif
}
inline CVector3f operator/(float val) const
{
2015-10-25 19:31:41 +00:00
#if __SSE__ || __GEKKO_PS__
2015-04-19 20:39:16 +00:00
TVectorUnion splat = {{val, val, val, 0.0}};
2015-10-25 19:31:41 +00:00
#endif
#if __SSE__
2015-04-19 20:39:16 +00:00
return CVector3f(_mm_div_ps(mVec128, splat.mVec128));
2015-10-25 19:31:41 +00:00
#elif __GEKKO_PS__
return CVector3f(_mm_gekko_div_ps(mVec128, splat.mVec128));
2015-04-19 20:39:16 +00:00
#else
return CVector3f(x / val, y / val, z / val);
#endif
}
inline const CVector3f& operator +=(const CVector3f& rhs)
{
#if __SSE__
mVec128 = _mm_add_ps(mVec128, rhs.mVec128);
2015-10-25 19:31:41 +00:00
#elif __GEKKO_PS__
mVec128 = _mm_gekko_add_ps(mVec128, rhs.mVec128);
2015-04-19 20:39:16 +00:00
#else
x += rhs.x; y += rhs.y; z += rhs.z;
#endif
return *this;
}
inline const CVector3f& operator -=(const CVector3f& rhs)
{
#if __SSE__
mVec128 = _mm_sub_ps(mVec128, rhs.mVec128);
#else
x -= rhs.x; y -= rhs.y; z -= rhs.z;
#endif
return *this;
}
inline const CVector3f& operator *=(const CVector3f& rhs)
{
#if __SSE__
mVec128 = _mm_mul_ps(mVec128, rhs.mVec128);
#else
x *= rhs.x; y *= rhs.y; z *= rhs.z;
#endif
return *this;
}
inline const CVector3f& operator /=(const CVector3f& rhs)
{
#if __SSE__
mVec128 = _mm_div_ps(mVec128, rhs.mVec128);
#else
x /= rhs.x; y /= rhs.y; z /= rhs.z;
#endif
return *this;
}
2015-04-19 23:15:32 +00:00
inline void normalize()
{
float mag = magnitude();
2015-10-25 19:31:41 +00:00
mag = 1.0 / mag;
*this *= mag;
2015-04-19 23:15:32 +00:00
}
inline CVector3f normalized() const
{
float mag = magnitude();
2015-10-25 19:31:41 +00:00
mag = 1.0 / mag;
return *this * mag;
2015-04-19 23:15:32 +00:00
}
2015-04-19 20:39:16 +00:00
inline CVector3f cross(const CVector3f& rhs) const
{ return CVector3f(y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x); }
2015-08-25 22:04:15 +00:00
inline float dot(const CVector3f& rhs) const
2015-04-19 20:39:16 +00:00
{
2015-11-02 18:44:46 +00:00
#if __SSE__
2015-04-19 20:39:16 +00:00
TVectorUnion result;
2015-11-02 18:44:46 +00:00
#if __SSE4_1__ || __SSE4_2__
if (cpuFeatures().SSE41 || cpuFeatures().SSE42)
{
result.mVec128 = _mm_dp_ps(mVec128, rhs.mVec128, 0xF1);
return result.v[0];
}
#endif
2015-04-19 20:39:16 +00:00
result.mVec128 = _mm_mul_ps(mVec128, rhs.mVec128);
return result.v[0] + result.v[1] + result.v[2];
#else
return (x * rhs.x) + (y * rhs.y) + (z * rhs.z);
#endif
}
inline float magSquared() const
2015-04-19 20:39:16 +00:00
{
2015-11-02 18:44:46 +00:00
#if __SSE__
2015-04-19 20:39:16 +00:00
TVectorUnion result;
2015-11-02 18:44:46 +00:00
#if __SSE4_1__ || __SSE4_2__
if (cpuFeatures().SSE41 || cpuFeatures().SSE42)
{
result.mVec128 = _mm_dp_ps(mVec128, mVec128, 0x71);
return result.v[0];
}
#endif
2015-04-19 20:39:16 +00:00
result.mVec128 = _mm_mul_ps(mVec128, mVec128);
return result.v[0] + result.v[1] + result.v[2];
#else
return x*x + y*y + z*z;
#endif
}
inline float magnitude() const
2015-10-25 19:31:41 +00:00
{ return Math::sqrtF(magSquared()); }
2015-04-19 20:39:16 +00:00
inline void zeroOut()
{
#if __SSE__
mVec128 = _mm_xor_ps(mVec128, mVec128);
#else
v[0] = 0.0; v[1] = 0.0; v[2] = 0.0; v[3] = 0.0;
#endif
}
inline void splat(float xyz)
{
#if __SSE__
TVectorUnion splat = {{xyz, xyz, xyz, 0.0f}};
mVec128 = splat.mVec128;
#else
v[0] = xyz; v[1] = xyz; v[2] = xyz; v[3] = 0.0f;
#endif
}
static float getAngleDiff(const CVector3f& a, const CVector3f& b);
static inline CVector3f lerp(const CVector3f& a, const CVector3f& b, float t)
{ return (a + (b - a) * t); }
2015-04-19 20:39:16 +00:00
static inline CVector3f nlerp(const CVector3f& a, const CVector3f& b, float t)
{ return lerp(a, b, t).normalized(); }
2015-04-19 20:39:16 +00:00
static CVector3f slerp(const CVector3f& a, const CVector3f& b, float t);
2015-08-25 22:04:15 +00:00
//static CVector3f slerp(const CVector3f& a, const CVector3f& b, const CRelAngle& angle);
2015-10-25 19:31:41 +00:00
inline bool canBeNormalized() const
{
const float epsilon = 1.1920929e-7f;
if (fabs(x) >= epsilon || fabs(y) >= epsilon || fabs(z) >= epsilon)
return true;
return false;
}
2015-08-25 22:04:15 +00:00
2015-10-25 19:31:41 +00:00
inline bool isNormalized() const
{ return !canBeNormalized(); }
2015-08-25 22:04:15 +00:00
2015-08-29 04:49:19 +00:00
inline bool isZero() const
2015-10-25 19:31:41 +00:00
{ return magSquared() <= 1.1920929e-7f; }
2015-08-29 04:49:19 +00:00
2015-08-25 22:04:15 +00:00
inline void scaleToLength(float newLength)
{
float length = magSquared();
2015-10-25 19:31:41 +00:00
if (length < 1.1920929e-7f)
2015-08-25 22:04:15 +00:00
{
x = newLength, y = 0.f, z = 0.f;
return;
}
length = sqrt(length);
float scalar = newLength / length;
*this *= scalar;
}
2015-04-19 20:39:16 +00:00
2015-08-25 22:04:15 +00:00
inline CVector3f scaledToLength(float newLength) const
{
2015-08-25 22:04:15 +00:00
CVector3f v = *this;
v.scaleToLength(newLength);
return v;
}
2015-04-19 20:39:16 +00:00
2015-10-25 19:31:41 +00:00
inline bool isEqu(const CVector3f& other, float epsilon=1.1920929e-7f)
2015-08-29 04:49:19 +00:00
{
CVector3f diffVec = other - *this;
return (diffVec.x <= epsilon && diffVec.y <= epsilon && diffVec.z <= epsilon);
}
2015-04-19 20:39:16 +00:00
inline float& operator[](size_t idx) {return (&x)[idx];}
inline const float& operator[](size_t idx) const {return (&x)[idx];}
static const CVector3f skOne;
2015-04-19 23:15:32 +00:00
static const CVector3f skNegOne;
2015-04-19 20:39:16 +00:00
static const CVector3f skZero;
};
static inline CVector3f operator+(float lhs, const CVector3f& rhs)
{
#if __SSE__
TVectorUnion splat = {{lhs, lhs, lhs, 0.0}};
return CVector3f(_mm_add_ps(splat.mVec128, rhs.mVec128));
#else
return CVector3f(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z);
#endif
}
static inline CVector3f operator-(float lhs, const CVector3f& rhs)
{
#if __SSE__
TVectorUnion splat = {{lhs, lhs, lhs, 0.0}};
return CVector3f(_mm_sub_ps(splat.mVec128, rhs.mVec128));
#else
return CVector3f(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z);
#endif
}
static inline CVector3f operator*(float lhs, const CVector3f& rhs)
{
#if __SSE__
TVectorUnion splat = {{lhs, lhs, lhs, 0.0}};
return CVector3f(_mm_mul_ps(splat.mVec128, rhs.mVec128));
#else
return CVector3f(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
#endif
}
static inline CVector3f operator/(float lhs, const CVector3f& rhs)
{
#if __SSE__
TVectorUnion splat = {{lhs, lhs, lhs, 0.0}};
return CVector3f(_mm_div_ps(splat.mVec128, rhs.mVec128));
#else
return CVector3f(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
#endif
}
}
2015-04-19 20:39:16 +00:00
#endif // CVECTOR3F_HPP