208 lines
6.8 KiB
C++
208 lines
6.8 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "metafile/nml.h"
|
|
#include "math/matrix3.h"
|
|
#include "math/matrix4.h"
|
|
#include "rand/rand.h"
|
|
|
|
using namespace GS;
|
|
|
|
|
|
namespace GS {
|
|
|
|
//------------------------------------------------------------------------------
|
|
template <> tVector2 <int> tVector2 <int> ::operator * (const Matrix3 &m) const
|
|
{
|
|
return tVector2 <int> ( (float(x) * m.m[0][0] + float(y) * m.m[0][1] + m.m[0][2]),
|
|
int(float(x) * m.m[1][0] + float(y) * m.m[1][1] + m.m[1][2]) );
|
|
}
|
|
template <> tVector2 <float> tVector2 <float> ::operator * (const Matrix3 &m) const
|
|
{
|
|
return tVector2 <float> ( x * m.m[0][0] + y * m.m[0][1] + m.m[0][2],
|
|
x * m.m[1][0] + y * m.m[1][1] + m.m[1][2] );
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
Vector4 Vector4::Floor() const
|
|
{ return Vector4(Math::Floor(x), Math::Floor(y), Math::Floor(z), Math::Floor(w)); }
|
|
Vector4 Vector4::Ceil() const
|
|
{ return Vector4(Math::Ceil(x), Math::Ceil(y), Math::Ceil(z), Math::Ceil(w)); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Vector4 Vector4::Abs() const
|
|
{ return Vector4(Types::Abs(x), Types::Abs(y), Types::Abs(z)); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Vector4 Vector4::Clamped(float min, float max) const
|
|
{
|
|
float _x, _y, _z;
|
|
if (x < min) _x = min; else if (x > max) _x = max; else _x = x;
|
|
if (y < min) _y = min; else if (y > max) _y = max; else _y = y;
|
|
if (z < min) _z = min; else if (z > max) _z = max; else _z = z;
|
|
return Vector4(_x, _y, _z);
|
|
}
|
|
Vector4 Vector4::Clamped(const Vector4 &min, const Vector4 &max) const
|
|
{
|
|
float _x, _y, _z;
|
|
if (x < min.x) _x = min.x; else if (x > max.x) _x = max.x; else _x = x;
|
|
if (y < min.y) _y = min.y; else if (y > max.y) _y = max.y; else _y = y;
|
|
if (z < min.z) _z = min.z; else if (z > max.z) _z = max.z; else _z = z;
|
|
return Vector4(_x, _y, _z);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Vector4 Vector4::ClampedMagnitude(float min, float max) const
|
|
{
|
|
float l2 = Len2();
|
|
if ((l2 >= (min * min)) && (l2 <= (max * max)))
|
|
return Vector4(*this);
|
|
if (l2 < 0.000001)
|
|
return Vector4(*this);
|
|
float l = Math::Sqrt((float)l2);
|
|
return (*this) * Types::Clamp(l, min, max) / l;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Vector4::operator *= (const Matrix4 &m)
|
|
{
|
|
float _x = x, _y = y, _z = z;
|
|
x = _x * m.m[0][0] + _y * m.m[0][1] + _z * m.m[0][2] + m.m[0][3];
|
|
y = _x * m.m[1][0] + _y * m.m[1][1] + _z * m.m[1][2] + m.m[1][3];
|
|
z = _x * m.m[2][0] + _y * m.m[2][1] + _z * m.m[2][2] + m.m[2][3];
|
|
}
|
|
Vector4 Vector4::operator * (const Matrix4 &m) const
|
|
{
|
|
return Vector4( x * m.m[0][0] + y * m.m[0][1] + z * m.m[0][2] + m.m[0][3],
|
|
x * m.m[1][0] + y * m.m[1][1] + z * m.m[1][2] + m.m[1][3],
|
|
x * m.m[2][0] + y * m.m[2][1] + z * m.m[2][2] + m.m[2][3] );
|
|
}
|
|
void Vector4::operator *= (const Matrix3 &m)
|
|
{
|
|
float _x = x, _y = y, _z = z;
|
|
x = _x * m.m[0][0] + _y * m.m[0][1] + _z * m.m[0][2];
|
|
y = _x * m.m[1][0] + _y * m.m[1][1] + _z * m.m[1][2];
|
|
z = _x * m.m[2][0] + _y * m.m[2][1] + _z * m.m[2][2];
|
|
}
|
|
Vector4 Vector4::operator * (const Matrix3 &m) const
|
|
{
|
|
return Vector4( x * m.m[0][0] + y * m.m[0][1] + z * m.m[0][2],
|
|
x * m.m[1][0] + y * m.m[1][1] + z * m.m[1][2],
|
|
x * m.m[2][0] + y * m.m[2][1] + z * m.m[2][2] );
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Vector4 Vector4::FaceForward(Vector4 &dir)
|
|
{
|
|
if (Dot(dir) >= 0)
|
|
return Reversed();
|
|
return *this;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
int Vector4::Hash() const
|
|
{
|
|
int a = (int)(x * 10.f), b = (int)(y * 10.f), c = (int)(z * 10.f);
|
|
// From Christer Ericson's Realtime Collision Detection.
|
|
return a * 0x8da6b343 + b * 0xd8163841 + c * 0xcb1ab31f;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Vector4::BaseToEuler(Vector4 &euler, Vector4 &u, Vector4 *v)
|
|
{
|
|
float _v = Math::Sqrt(u.x * u.x + u.y * u.y + u.z * u.z);
|
|
euler.x = -Math::ASin(u.y / _v);
|
|
|
|
_v = Math::Sqrt(u.x * u.x + u.z * u.z);
|
|
if (_v > 0.00001f)
|
|
euler.y = Math::ASin(u.x / _v);
|
|
else euler.y = 0;
|
|
|
|
if (u.z < 0.f)
|
|
{
|
|
if (euler.y < 0.f)
|
|
euler.y = - (Math::Pi + euler.y);
|
|
else euler.y = Math::Pi - euler.y;
|
|
}
|
|
euler.z = 0;
|
|
|
|
if (v)
|
|
{
|
|
Matrix3 mx(Matrix3::RotationMatrixXAxis(Units::Rad(euler.x)));
|
|
Matrix3 my(Matrix3::RotationMatrixYAxis(Units::Rad(euler.y)));
|
|
Vector4 bv(Vector4(1,0,0) * my * mx), vn(v->Normalized());
|
|
const float vc = vn.Dot(bv);
|
|
|
|
if (vc >= 1.f)
|
|
euler.z = 0.f;
|
|
else if (vc <= -1.f)
|
|
euler.z = Math::Pi;
|
|
else euler.z = Math::ACos(vc);
|
|
|
|
if ((bv.Cross(vn)).Dot(u) <= 0.f)
|
|
euler.z = (Math::Pi + Math::Pi) - euler.z;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
Vector4 Vector4::Random(float min, float max)
|
|
{ return Vector4(Random::FRRand(min, max), Random::FRRand(min, max), Random::FRRand(min, max)); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
NML::Tag *Vector4::AsMetaTag(const char *id, bool fulldump) const
|
|
{
|
|
NML::Tag *root = new NML::Tag(id ? id : "Vector");
|
|
|
|
if (root)
|
|
{
|
|
root->AddChild("X", x);
|
|
root->AddChild("Y", y);
|
|
root->AddChild("Z", z);
|
|
if (fulldump)
|
|
root->AddChild("W", w);
|
|
}
|
|
return root;
|
|
}
|
|
bool Vector4::FromMetaTag(NML::Tag &tag)
|
|
{
|
|
NML::Tag *t;
|
|
List <NML::Tag *> ::Iterator i(tag.GetTags().GetRoot());
|
|
|
|
t = i.ObjectPtr();
|
|
if (!t) return false;
|
|
x = t->GetReal();
|
|
++i;
|
|
|
|
t = i.ObjectPtr();
|
|
if (!t) return false;
|
|
y = t->GetReal();
|
|
++i;
|
|
|
|
t = i.ObjectPtr();
|
|
if (!t) return false;
|
|
z = t->GetReal();
|
|
++i;
|
|
|
|
t = i.ObjectPtr();
|
|
if (t)
|
|
w = t->GetReal();
|
|
|
|
return true;
|
|
}
|
|
//------------------------------------------------------------------------------
|