/* ----------------------------------------------------------------------------- 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 tVector2 ::operator * (const Matrix3 &m) const { return tVector2 ( (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 tVector2 ::operator * (const Matrix3 &m) const { return tVector2 ( 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 ::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; } //------------------------------------------------------------------------------