commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
319
include/framework/math/matrix3.cpp
Normal file
319
include/framework/math/matrix3.cpp
Normal file
@ -0,0 +1,319 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <cmath>
|
||||
#include "math/matrix3.h"
|
||||
#include "math/matrix4.h"
|
||||
#include "metafile/nml.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Math;
|
||||
|
||||
Matrix3 Matrix3::static_identity;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Matrix3::Inverse(Matrix3 &i) const
|
||||
{
|
||||
// Covariants.
|
||||
i.m[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
|
||||
i.m[0][1] = m[0][2] * m[2][1] - m[0][1] * m[2][2];
|
||||
i.m[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
|
||||
i.m[1][0] = m[1][2] * m[2][0] - m[1][0] * m[2][2];
|
||||
i.m[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
|
||||
i.m[1][2] = m[0][2] * m[1][0] - m[0][0] * m[1][2];
|
||||
i.m[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
|
||||
i.m[2][1] = m[0][1] * m[2][0] - m[0][0] * m[2][1];
|
||||
i.m[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
|
||||
|
||||
float k = m[0][0] * i.m[0][0] + m[0][1] * i.m[1][0] + m[0][2] * i.m[2][0];
|
||||
if (!k)
|
||||
return false;
|
||||
|
||||
k = 1.f / k;
|
||||
i.m[0][0] *= k; i.m[0][1] *= k; i.m[0][2] *= k;
|
||||
i.m[1][0] *= k; i.m[1][1] *= k; i.m[1][2] *= k;
|
||||
i.m[2][0] *= k; i.m[2][1] *= k; i.m[2][2] *= k;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Matrix3::VectorMatrix(const Vector4 &v)
|
||||
{ return Matrix3(v.x, 0, 0, v.y, 0, 0, v.z, 0, 0); }
|
||||
Matrix3 Matrix3::CrossProductMatrix(const Vector4 &v)
|
||||
{ return Matrix3(0, -v.z, v.y, v.z, 0, -v.x, -v.y, v.x, 0); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Matrix3::Normalized() const
|
||||
{
|
||||
Vector4 x(GetRow(0)), y(GetRow(1)), z(GetRow(2));
|
||||
|
||||
Matrix3 m;
|
||||
m.SetRow(0, x.Normalized());
|
||||
m.SetRow(1, y.Normalized());
|
||||
m.SetRow(2, z.Normalized());
|
||||
return m;
|
||||
}
|
||||
Matrix3 Matrix3::AsOrthonormalBase() const
|
||||
{
|
||||
Vector4 x(GetRow(0)), y(GetRow(1));
|
||||
|
||||
Matrix3 m;
|
||||
x = x.Normalized();
|
||||
m.SetRow(0, x);
|
||||
Vector4 z(x.Cross(y).Normalized());
|
||||
m.SetRow(2, z);
|
||||
y = z.Cross(x).Normalized();
|
||||
m.SetRow(1, y);
|
||||
return m;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Vector4 Matrix3::AsEuler(rOrder rorder) const
|
||||
{
|
||||
Vector4 euler(0, 0, 0);
|
||||
|
||||
switch (rorder)
|
||||
{
|
||||
case rOrder_ZYX:
|
||||
euler.y = ASin(-m[2][0]);
|
||||
euler.z = atan2(m[1][0], m[0][0]);
|
||||
euler.x = atan2(m[2][1], m[2][2]);
|
||||
break;
|
||||
|
||||
case rOrder_XZY:
|
||||
euler.z = ASin(-m[0][1]);
|
||||
euler.x = atan2(m[2][1], m[1][1]);
|
||||
euler.y = atan2(m[0][2], m[0][0]);
|
||||
break;
|
||||
|
||||
case rOrder_XYZ:
|
||||
euler.y = ASin(m[0][2]);
|
||||
euler.x = atan2(-m[1][2], m[2][2]);
|
||||
euler.z = atan2(-m[0][1], m[0][0]);
|
||||
break;
|
||||
|
||||
case rOrder_YZX:
|
||||
euler.z = ASin(m[1][0]);
|
||||
euler.x = atan2(-m[1][2], m[1][1]);
|
||||
euler.y = atan2(-m[2][0], m[0][0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
case rOrder_YXZ: // Engine default.
|
||||
euler.x = ASin(-m[1][2]);
|
||||
euler.y = atan2(m[0][2], m[2][2]);
|
||||
euler.z = atan2(m[1][0], m[1][1]);
|
||||
break;
|
||||
|
||||
case rOrder_ZXY: // MAX default.
|
||||
euler.x = ASin(m[2][1]);
|
||||
euler.y = atan2(-m[2][0], m[2][2]);
|
||||
euler.z = atan2(-m[0][1], m[1][1]);
|
||||
break;
|
||||
|
||||
case rOrder_XY:
|
||||
euler.y = ACos(m[0][0]);
|
||||
euler.x = ACos(m[1][1]);
|
||||
euler.z = 0;
|
||||
break;
|
||||
}
|
||||
return euler;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Matrix3::FromEuler(const Vector4 &euler, rOrder rorder)
|
||||
{ return Matrix3::FromEuler(euler.x, euler.y, euler.z, rorder); }
|
||||
Matrix3 Matrix3::FromEuler(float x, float y, float z, rOrder rorder)
|
||||
{
|
||||
float cx = Cos(x), cy = Cos(y), cz = Cos(z),
|
||||
sx = Sin(x), sy = Sin(y), sz = Sin(z);
|
||||
|
||||
switch (rorder)
|
||||
{
|
||||
case rOrder_XZY:
|
||||
return Matrix3 ( cy * cz, sx * sy + cx * cy * sz, -cx * sy + cy * sx * sz,
|
||||
-sz, cx * cz, cz * sx,
|
||||
cz * sy, -cy * sx + cx * sy * sz, cx * cy + sx * sy * sz );
|
||||
|
||||
case rOrder_ZYX:
|
||||
return Matrix3 ( cy * cz, cy * sz, -sy,
|
||||
cz * sx * sy - cx * sz, cx * cz + sx * sy * sz, cy * sx,
|
||||
cx *cz * sy + sx * sz, -cz * sx + cx * sy * sz, cx * cy );
|
||||
|
||||
case rOrder_XYZ:
|
||||
return Matrix3 ( cy * cz, cz * sx * sy + cx * sz, -cx * cz * sy + sx * sz,
|
||||
-cy * sz, cx * cz - sx * sy * sz, cz * sx + cx * sy * sz,
|
||||
sy, -cy * sx, cx * cy );
|
||||
|
||||
case rOrder_ZXY:
|
||||
return Matrix3 ( cy * cz - sx * sy * sz, cz * sx * sy + cy * sz, -cx * sy,
|
||||
-cx * sz, cx * cz, sx,
|
||||
cz * sy + cy * sx * sz, -cy * cz * sx + sy * sz, cx * cy );
|
||||
|
||||
case rOrder_YZX:
|
||||
return Matrix3 ( cy * cz, sz, -cz * sy,
|
||||
sx * sy - cx * cy * sz, cx * cz, cy * sx + cx * sy * sz,
|
||||
cx * sy + cy * sx * sz, -cz * sx, cx * cy - sx * sy * sz );
|
||||
|
||||
case rOrder_YXZ:
|
||||
return Matrix3 ( cy * cz + sx * sy * sz, cx * sz, -cz * sy + cy * sx * sz,
|
||||
cz * sx * sy - cy * sz, cx * cz, cy * cz * sx + sy * sz,
|
||||
cx * sy, -sx, cx * cy );
|
||||
|
||||
case rOrder_XY:
|
||||
return Matrix3 ( cy, sx * sy, -cx * sy,
|
||||
0, cx, sx,
|
||||
sy, -cy * sx, cx * cy );
|
||||
}
|
||||
return Matrix3::IdentityMatrix();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Matrix3::TranslationMatrix(const Vector4 &t)
|
||||
{ return Matrix3(1, 0, 0, 0, 1, 0, t.x, t.y, 1); }
|
||||
Matrix3 Matrix3::TranslationMatrix(const Vector2 &t)
|
||||
{ return Matrix3(1, 0, 0, 0, 1, 0, t.x, t.y, 1); }
|
||||
Matrix3 Matrix3::ScaleMatrix(const Vector4 &s)
|
||||
{ return Matrix3(s.x, 0, 0, 0, s.y, 0, 0, 0, s.z); }
|
||||
Matrix3 Matrix3::ScaleMatrix(const Vector2 &s)
|
||||
{ return Matrix3(s.x, 0, 0, 0, s.y, 0, 0, 0, 1); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Matrix3::RotationMatrixXAxis(float a)
|
||||
{ return Matrix3(1, 0, 0, 0, Cos(a), Sin(a), 0, -Sin(a), Cos(a)); }
|
||||
Matrix3 Matrix3::RotationMatrixYAxis(float a)
|
||||
{ return Matrix3(Cos(a), 0, -Sin(a), 0, 1, 0, Sin(a), 0, Cos(a)); }
|
||||
Matrix3 Matrix3::RotationMatrixZAxis(float a)
|
||||
{ return Matrix3(Cos(a), Sin(a), 0, -Sin(a), Cos(a), 0, 0, 0, 1); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Matrix3::SetRow(uint n, const Vector4 &row)
|
||||
{ m[0][n] = row.x; m[1][n] = row.y; m[2][n] = row.z; }
|
||||
void Matrix3::SetColumn(uint n, const Vector4 &col)
|
||||
{ m[n][0] = col.x; m[n][1] = col.y; m[n][2] = col.z; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Matrix3::FromOrthonormalBasis(const Vector4 &w, const Vector4 *v)
|
||||
{
|
||||
Matrix3 mtx;
|
||||
|
||||
float l = w.Len();
|
||||
if (!l)
|
||||
return Matrix3::IdentityMatrix();
|
||||
|
||||
Vector4 wn = w / l, u;
|
||||
|
||||
if (!v)
|
||||
{
|
||||
if (!EqualZero(wn.x) || !EqualZero(wn.z))
|
||||
{
|
||||
u.Set(wn.z, 0, -wn.x); // Cross with up = {0,1,0}.
|
||||
u = u.Normalized();
|
||||
}
|
||||
else
|
||||
u.Set(-1, 0, 0);
|
||||
|
||||
Vector4 c(wn.Cross(u));
|
||||
mtx.SetRow(1, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector4 vn(v->Normalized());
|
||||
mtx.SetRow(1, vn);
|
||||
u = vn.Cross(wn);
|
||||
}
|
||||
|
||||
mtx.SetRow(0, u);
|
||||
mtx.SetRow(2, wn);
|
||||
return mtx;
|
||||
}
|
||||
Matrix3 Matrix3::FromMatrix4(const Matrix4 &mtx)
|
||||
{
|
||||
return Matrix3(
|
||||
mtx.m[0][0], mtx.m[1][0], mtx.m[2][0],
|
||||
mtx.m[0][1], mtx.m[1][1], mtx.m[2][1],
|
||||
mtx.m[0][2], mtx.m[1][2], mtx.m[2][2]
|
||||
);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Matrix3::Apply(Vector4 *o, const Vector4 *v, uint n) const
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
for (uint c = 0; c < n; c++)
|
||||
{
|
||||
float x = v->x, y = v->y, z = v->z;
|
||||
o->x = x * m[0][0] + y * m[0][1] + z * m[0][2];
|
||||
o->y = x * m[1][0] + y * m[1][1] + z * m[1][2];
|
||||
o->z = x * m[2][0] + y * m[2][1] + z * m[2][2];
|
||||
o->w = 1;
|
||||
o++; v++;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Matrix3::Set
|
||||
(
|
||||
float m00, float m10, float m20,
|
||||
float m01, float m11, float m21,
|
||||
float m02, float m12, float m22
|
||||
)
|
||||
{
|
||||
m[0][0] = m00; m[1][0] = m10; m[2][0] = m20;
|
||||
m[0][1] = m01; m[1][1] = m11; m[2][1] = m21;
|
||||
m[0][2] = m02; m[1][2] = m12; m[2][2] = m22;
|
||||
}
|
||||
void Matrix3::Set(const Vector4 &u, const Vector4 &v, const Vector4 &w)
|
||||
{
|
||||
m[0][0] = u.x; m[1][0] = u.y; m[2][0] = u.z;
|
||||
m[0][1] = v.x; m[1][1] = v.y; m[2][1] = v.z;
|
||||
m[0][2] = w.x; m[1][2] = w.y; m[2][2] = w.z;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NML::Tag *Matrix3::AsMetaTag(const char *id) const
|
||||
{
|
||||
NML::Tag *root = new NML::Tag(id ? id : "Mtx3");
|
||||
root->AddChild(GetRow(0).AsMetaTag("R0"));
|
||||
root->AddChild(GetRow(1).AsMetaTag("R1"));
|
||||
root->AddChild(GetRow(2).AsMetaTag("R2"));
|
||||
return root;
|
||||
}
|
||||
bool Matrix3::FromMetaTag(NML::Tag &tag)
|
||||
{
|
||||
NML::Tag *t;
|
||||
Vector4 R;
|
||||
|
||||
List <NML::Tag *> ::Iterator i(tag.GetTags().GetRoot());
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(0, R);
|
||||
++i;
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(1, R);
|
||||
++i;
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(2, R);
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
277
include/framework/math/matrix4.cpp
Normal file
277
include/framework/math/matrix4.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "math/matrix4.h"
|
||||
#include "math/matrix3.h"
|
||||
#include "math/quaternion.h"
|
||||
#include "metafile/nml.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
Matrix4 Matrix4::static_identity(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Matrix4::FromMatrix3(const Matrix3 &m)
|
||||
{
|
||||
return Matrix4(
|
||||
m.m[0][0], m.m[1][0], m.m[2][0], 0,
|
||||
m.m[0][1], m.m[1][1], m.m[2][1], 0,
|
||||
m.m[0][2], m.m[1][2], m.m[2][2], 0,
|
||||
0, 0, 0, 1
|
||||
);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const Matrix4 &Matrix4WithInverse::Get() const
|
||||
{ return matrix; }
|
||||
const Matrix4 &Matrix4WithInverse::GetInverse() const
|
||||
{ return imatrix; }
|
||||
void Matrix4WithInverse::Commit()
|
||||
{ imatrix = matrix.InversedFast(); }
|
||||
void Matrix4WithInverse::Set(const Matrix4 &m)
|
||||
{
|
||||
matrix = m;
|
||||
Commit();
|
||||
}
|
||||
Vector4 Matrix4WithInverse::GetRow(uint n, bool w_1) const
|
||||
{ return matrix.GetRow(n, w_1); }
|
||||
Vector4 Matrix4WithInverse::GetColumn(uint n, bool w_1) const
|
||||
{ return matrix.GetColumn(n, w_1); }
|
||||
void Matrix4WithInverse::SetRow(uint n, const Vector4 &row, bool w_1)
|
||||
{
|
||||
matrix.SetRow(n, row, w_1);
|
||||
Commit();
|
||||
}
|
||||
void Matrix4WithInverse::SetColumn(uint n, const Vector4 &col, bool w_1)
|
||||
{
|
||||
matrix.SetColumn(n, col, w_1);
|
||||
Commit();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NML::Tag *Matrix4WithInverse::AsMetaTag(const char *id) const
|
||||
{ return matrix.AsMetaTag(id); }
|
||||
bool Matrix4WithInverse::FromMetaTag(NML::Tag &tag)
|
||||
{
|
||||
if (!matrix.FromMetaTag(tag))
|
||||
return false;
|
||||
Commit();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Matrix4::TransformationMatrix(const Vector4 &p, const Matrix3 &r, const Vector4 &s, const Vector4 *o)
|
||||
{
|
||||
Matrix4 m =
|
||||
Matrix4::TranslationMatrix(p) *
|
||||
Matrix4::FromMatrix3(r) *
|
||||
Matrix4::ScaleMatrix(s);
|
||||
return o ? m * Matrix4::TranslationMatrix(*o) : m;
|
||||
}
|
||||
Matrix4 Matrix4::TransformationMatrix(const Vector4 &p, const Vector4 &r, const Vector4 &s, const Vector4 *o)
|
||||
{
|
||||
Matrix4 m =
|
||||
Matrix4::TranslationMatrix(p) *
|
||||
Matrix4::FromMatrix3(Matrix3::FromEuler(r.x, r.y, r.z)) *
|
||||
Matrix4::ScaleMatrix(s);
|
||||
return o ? m * Matrix4::TranslationMatrix(*o) : m;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Matrix4::LerpAsOrthonormalBase(const Matrix4 &a, const Matrix4 &b, float k, bool fast)
|
||||
{
|
||||
if (fast)
|
||||
{
|
||||
Matrix4 o;
|
||||
for (int m = 0; m < 4; ++m)
|
||||
for (int n = 0; n < 4; ++n)
|
||||
o.m[m][n] = (b.m[m][n] - a.m[m][n]) * k + a.m[m][n];
|
||||
return o;
|
||||
}
|
||||
|
||||
Matrix3 a_matrix3, b_matrix3;
|
||||
Vector4 a_position, b_position, a_scale, b_scale;
|
||||
|
||||
a.Decompose(&a_position, &a_scale, &a_matrix3);
|
||||
b.Decompose(&b_position, &b_scale, &b_matrix3);
|
||||
|
||||
Quaternion a_orientation(Quaternion::FromMatrix3(a_matrix3));
|
||||
Quaternion b_orientation(Quaternion::FromMatrix3(b_matrix3));
|
||||
|
||||
return Matrix4::TranslationMatrix((b_position - a_position) * k + a_position) *
|
||||
Matrix4::FromMatrix3(Quaternion::Slerp(k, a_orientation, b_orientation).AsMatrix3()) *
|
||||
Matrix4::ScaleMatrix((b_scale - a_scale) * k + a_scale);
|
||||
}
|
||||
void Matrix4::Decompose(Vector4 *position, Vector4 *scale, Vector4 *rotation, Math::rOrder order) const
|
||||
{
|
||||
Matrix3 m3;
|
||||
Decompose(position, scale, &m3);
|
||||
if (rotation)
|
||||
*rotation = m3.AsEuler(order);
|
||||
}
|
||||
void Matrix4::Decompose(Vector4 *position, Vector4 *scale, Matrix3 *rotation) const
|
||||
{
|
||||
// Extract position.
|
||||
if (position)
|
||||
*position = GetRow(3);
|
||||
|
||||
// Extract scale.
|
||||
Vector4 scl;
|
||||
scl.Set(GetRow(0).Len(), GetRow(1).Len(), GetRow(2).Len());
|
||||
|
||||
// Handle negative scale (permute X to preserve left-handedness).
|
||||
Vector4 left = GetRow(1).Cross(GetRow(2));
|
||||
if (left.Dot(GetRow(0)) < 0)
|
||||
scl.x = -scl.x;
|
||||
if (scale)
|
||||
*scale = scl;
|
||||
|
||||
// Rotation 3x3 (renormalized).
|
||||
if (rotation)
|
||||
{
|
||||
if (scl.x)
|
||||
{
|
||||
scl.x = 1 / scl.x;
|
||||
rotation->SetRow(0, Vector4(m[0][0] * scl.x, m[1][0] * scl.x, m[2][0] * scl.x));
|
||||
}
|
||||
else rotation->SetRow(0, Vector4(1, 0, 0));
|
||||
|
||||
if (scl.y)
|
||||
{
|
||||
scl.y = 1 / scl.y;
|
||||
rotation->SetRow(1, Vector4(m[0][1] * scl.y, m[1][1] * scl.y, m[2][1] * scl.y));
|
||||
}
|
||||
else rotation->SetRow(1, Vector4(0, 1, 0));
|
||||
|
||||
if (scl.z)
|
||||
{
|
||||
scl.z = 1 / scl.z;
|
||||
rotation->SetRow(2, Vector4(m[0][2] * scl.z, m[1][2] * scl.z, m[2][2] * scl.z));
|
||||
}
|
||||
else rotation->SetRow(2, Vector4(0, 0, 1));
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Matrix4::InversedFast() const
|
||||
{
|
||||
// Extract inverse scale.
|
||||
Vector4 scl(1.f / GetRow(0).Len(), 1.f / GetRow(1).Len(), 1.f / GetRow(2).Len());
|
||||
|
||||
// Inverse rotation 3x3 (renormalized).
|
||||
Matrix3 irt (
|
||||
m[0][0] * scl.x, m[0][1] * scl.y, m[0][2] * scl.z,
|
||||
m[1][0] * scl.x, m[1][1] * scl.y, m[1][2] * scl.z,
|
||||
m[2][0] * scl.x, m[2][1] * scl.y, m[2][2] * scl.z
|
||||
);
|
||||
|
||||
// Recompose as inverse matrix.
|
||||
return Matrix4::ScaleMatrix(scl) * (Matrix4::FromMatrix3(irt) * Matrix4::TranslationMatrix(GetRow(3).Reversed()));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Matrix4::AsOrthonormalBase() const
|
||||
{
|
||||
Matrix3 rcp (
|
||||
m[0][0], m[1][0], m[2][0],
|
||||
m[0][1], m[1][1], m[2][1],
|
||||
m[0][2], m[1][2], m[2][2]
|
||||
);
|
||||
rcp = rcp.AsOrthonormalBase();
|
||||
|
||||
Matrix4 otb(*this);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
otb.m[i][j] = rcp.m[i][j];
|
||||
return otb;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix4 Matrix4::TranslationMatrix(const Vector4 &t)
|
||||
{ return Matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, t.x, t.y, t.z, 1); }
|
||||
Matrix4 Matrix4::ScaleMatrix(const Vector4 &s)
|
||||
{ return Matrix4(s.x, 0, 0, 0, 0, s.y, 0, 0, 0, 0, s.z, 0, 0, 0, 0, 1); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NML::Tag *Matrix4::AsMetaTag(const char *id) const
|
||||
{
|
||||
NML::Tag *root = new NML::Tag(id ? id : "Mtx4");
|
||||
root->AddChild(GetRow(0, false).AsMetaTag("R0", true));
|
||||
root->AddChild(GetRow(1, false).AsMetaTag("R1", true));
|
||||
root->AddChild(GetRow(2, false).AsMetaTag("R2", true));
|
||||
root->AddChild(GetRow(3, false).AsMetaTag("R3", true));
|
||||
return root;
|
||||
}
|
||||
bool Matrix4::FromMetaTag(NML::Tag &tag)
|
||||
{
|
||||
NML::Tag *t;
|
||||
Vector4 R;
|
||||
|
||||
List <NML::Tag *> ::Iterator i(tag.GetTags().GetRoot());
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(0, R, false);
|
||||
++i;
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(1, R, false);
|
||||
++i;
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(2, R, false);
|
||||
++i;
|
||||
|
||||
t = i.ObjectPtr();
|
||||
if (!t) return false;
|
||||
R.FromMetaTag(*t); SetRow(3, R, false);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool Matrix4::Inverse(Matrix4 &out) const
|
||||
{
|
||||
float inv[16], det;
|
||||
|
||||
inv[0] = m[1][1] * m[2][2] * m[3][3] - m[1][1] * m[2][3] * m[3][2] - m[2][1] * m[1][2] * m[3][3] + m[2][1] * m[1][3] * m[3][2] + m[3][1] * m[1][2] * m[2][3] - m[3][1] * m[1][3] * m[2][2];
|
||||
inv[4] = -m[1][0] * m[2][2] * m[3][3] + m[1][0] * m[2][3] * m[3][2] + m[2][0] * m[1][2] * m[3][3] - m[2][0] * m[1][3] * m[3][2] - m[3][0] * m[1][2] * m[2][3] + m[3][0] * m[1][3] * m[2][2];
|
||||
inv[8] = m[1][0] * m[2][1] * m[3][3] - m[1][0] * m[2][3] * m[3][1] - m[2][0] * m[1][1] * m[3][3] + m[2][0] * m[1][3] * m[3][1] + m[3][0] * m[1][1] * m[2][3] - m[3][0] * m[1][3] * m[2][1];
|
||||
inv[12] = -m[1][0] * m[2][1] * m[3][2] + m[1][0] * m[2][2] * m[3][1] + m[2][0] * m[1][1] * m[3][2] - m[2][0] * m[1][2] * m[3][1] - m[3][0] * m[1][1] * m[2][2] + m[3][0] * m[1][2] * m[2][1];
|
||||
inv[1] = -m[0][1] * m[2][2] * m[3][3] + m[0][1] * m[2][3] * m[3][2] + m[2][1] * m[0][2] * m[3][3] - m[2][1] * m[0][3] * m[3][2] - m[3][1] * m[0][2] * m[2][3] + m[3][1] * m[0][3] * m[2][2];
|
||||
inv[5] = m[0][0] * m[2][2] * m[3][3] - m[0][0] * m[2][3] * m[3][2] - m[2][0] * m[0][2] * m[3][3] + m[2][0] * m[0][3] * m[3][2] + m[3][0] * m[0][2] * m[2][3] - m[3][0] * m[0][3] * m[2][2];
|
||||
inv[9] = -m[0][0] * m[2][1] * m[3][3] + m[0][0] * m[2][3] * m[3][1] + m[2][0] * m[0][1] * m[3][3] - m[2][0] * m[0][3] * m[3][1] - m[3][0] * m[0][1] * m[2][3] + m[3][0] * m[0][3] * m[2][1];
|
||||
inv[13] = m[0][0] * m[2][1] * m[3][2] - m[0][0] * m[2][2] * m[3][1] - m[2][0] * m[0][1] * m[3][2] + m[2][0] * m[0][2] * m[3][1] + m[3][0] * m[0][1] * m[2][2] - m[3][0] * m[0][2] * m[2][1];
|
||||
inv[2] = m[0][1] * m[1][2] * m[3][3] - m[0][1] * m[1][3] * m[3][2] - m[1][1] * m[0][2] * m[3][3] + m[1][1] * m[0][3] * m[3][2] + m[3][1] * m[0][2] * m[1][3] - m[3][1] * m[0][3] * m[1][2];
|
||||
inv[6] = -m[0][0] * m[1][2] * m[3][3] + m[0][0] * m[1][3] * m[3][2] + m[1][0] * m[0][2] * m[3][3] - m[1][0] * m[0][3] * m[3][2] - m[3][0] * m[0][2] * m[1][3] + m[3][0] * m[0][3] * m[1][2];
|
||||
inv[10] = m[0][0] * m[1][1] * m[3][3] - m[0][0] * m[1][3] * m[3][1] - m[1][0] * m[0][1] * m[3][3] + m[1][0] * m[0][3] * m[3][1] + m[3][0] * m[0][1] * m[1][3] - m[3][0] * m[0][3] * m[1][1];
|
||||
inv[14] = -m[0][0] * m[1][1] * m[3][2] + m[0][0] * m[1][2] * m[3][1] + m[1][0] * m[0][1] * m[3][2] - m[1][0] * m[0][2] * m[3][1] - m[3][0] * m[0][1] * m[1][2] + m[3][0] * m[0][2] * m[1][1];
|
||||
inv[3] = -m[0][1] * m[1][2] * m[2][3] + m[0][1] * m[1][3] * m[2][2] + m[1][1] * m[0][2] * m[2][3] - m[1][1] * m[0][3] * m[2][2] - m[2][1] * m[0][2] * m[1][3] + m[2][1] * m[0][3] * m[1][2];
|
||||
inv[7] = m[0][0] * m[1][2] * m[2][3] - m[0][0] * m[1][3] * m[2][2] - m[1][0] * m[0][2] * m[2][3] + m[1][0] * m[0][3] * m[2][2] + m[2][0] * m[0][2] * m[1][3] - m[2][0] * m[0][3] * m[1][2];
|
||||
inv[11] = -m[0][0] * m[1][1] * m[2][3] + m[0][0] * m[1][3] * m[2][1] + m[1][0] * m[0][1] * m[2][3] - m[1][0] * m[0][3] * m[2][1] - m[2][0] * m[0][1] * m[1][3] + m[2][0] * m[0][3] * m[1][1];
|
||||
inv[15] = m[0][0] * m[1][1] * m[2][2] - m[0][0] * m[1][2] * m[2][1] - m[1][0] * m[0][1] * m[2][2] + m[1][0] * m[0][2] * m[2][1] + m[2][0] * m[0][1] * m[1][2] - m[2][0] * m[0][2] * m[1][1];
|
||||
det = m[0][0] * inv[0] + m[0][1] * inv[4] + m[0][2] * inv[8] + m[0][3] * inv[12];
|
||||
|
||||
if (det == 0)
|
||||
return false;
|
||||
|
||||
det = 1.f / det;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
((float *)out.m)[i] = inv[i] * det;
|
||||
|
||||
return true;
|
||||
}
|
||||
218
include/framework/math/quaternion.cpp
Normal file
218
include/framework/math/quaternion.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "math/quaternion.h"
|
||||
#include "math/matrix3.h"
|
||||
#include "metafile/nml.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Quaternion Quaternion::Slerp(float t, const Quaternion &a, const Quaternion &b)
|
||||
{
|
||||
float norm = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
|
||||
bool bFlip = false;
|
||||
|
||||
if (norm < 0.0f)
|
||||
{
|
||||
norm = -norm;
|
||||
bFlip = true;
|
||||
}
|
||||
|
||||
float inv_d;
|
||||
if (1.0f - norm < 0.000001f)
|
||||
inv_d = 1.0f - t;
|
||||
|
||||
else
|
||||
{
|
||||
float theta = Math::ACos(norm);
|
||||
float s = 1.f / Math::Sin(theta);
|
||||
|
||||
inv_d = Math::Sin((1.0f - t) * theta) * s;
|
||||
t = Math::Sin(t * theta) * s;
|
||||
}
|
||||
|
||||
if (bFlip)
|
||||
t = -t;
|
||||
|
||||
return Quaternion(inv_d * a.x + t * b.x, inv_d * a.y + t * b.y, inv_d * a.z + t * b.z, inv_d * a.w + t * b.w);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
float Quaternion::Distance(const Quaternion &a, const Quaternion &b)
|
||||
{
|
||||
const float dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z, dw = a.w - b.w;
|
||||
return Math::Sqrt((dx * dx) + (dy * dy) + (dz * dz) + (dw * dw));
|
||||
}
|
||||
Quaternion Quaternion::Inverse() const
|
||||
{
|
||||
const float norm = w * w + x * x + y * y + z * z;
|
||||
if (norm > 0)
|
||||
{
|
||||
const float inorm = 1.f / norm;
|
||||
return Quaternion(x * -inorm, y * -inorm, z * -inorm, w * inorm);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Quaternion Quaternion::Normalize() const
|
||||
{
|
||||
float d = Math::Sqrt(x * x + y * y + z * z + w * w);
|
||||
if (!d)
|
||||
return Quaternion(1, 1, 1, 1);
|
||||
|
||||
float k = 1.f / d;
|
||||
return Quaternion(x * k, y * k, z * k, w * k);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Quaternion Quaternion::LookAt(const Vector4 &at)
|
||||
{ return Quaternion::FromMatrix3(Matrix3::FromOrthonormalBasis(at)); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Quaternion Quaternion::FromMatrix3(const Matrix3 &m)
|
||||
{
|
||||
// From "Quaternion Calculus and Fast Animation".
|
||||
float x, y, z, w;
|
||||
float trace = m.m[0][0] + m.m[1][1] + m.m[2][2];
|
||||
|
||||
if (trace > 0.0)
|
||||
{
|
||||
// |w| > 1/2, may as well choose w > 1/2
|
||||
float root = Math::Sqrt(trace + 1.0f); // 2w
|
||||
w = 0.5f * root;
|
||||
root = 0.5f / root; // 1/(4w)
|
||||
x = (m.m[2][1] - m.m[1][2]) * root;
|
||||
y = (m.m[0][2] - m.m[2][0]) * root;
|
||||
z = (m.m[1][0] - m.m[0][1]) * root;
|
||||
}
|
||||
else
|
||||
{
|
||||
// |w| <= 1/2
|
||||
static size_t inext[3] = { 1, 2, 0 };
|
||||
size_t i = 0;
|
||||
if (m.m[1][1] > m.m[0][0])
|
||||
i = 1;
|
||||
if (m.m[2][2] > m.m[i][i])
|
||||
i = 2;
|
||||
size_t j = inext[i];
|
||||
size_t k = inext[j];
|
||||
|
||||
float root = Math::Sqrt(m.m[i][i] - m.m[j][j] - m.m[k][k] + 1.0f);
|
||||
float *quat[3] = { &x, &y, &z };
|
||||
*quat[i] = 0.5f * root;
|
||||
root = 0.5f / root;
|
||||
w = (m.m[k][j] - m.m[j][k]) * root;
|
||||
*quat[j] = (m.m[j][i] + m.m[i][j]) * root;
|
||||
*quat[k] = (m.m[k][i] + m.m[i][k]) * root;
|
||||
}
|
||||
return Quaternion(x, y, z, w);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Quaternion Quaternion::FromAxisAngle(float a, float _x, float _y, float _z)
|
||||
{
|
||||
float sn = Math::Sin(a * 0.5f), cs = Math::Cos(a * 0.5f);
|
||||
return Quaternion(_x * sn, _y * sn, _z * sn, cs).Normalize();
|
||||
}
|
||||
Quaternion Quaternion::FromEuler(float _x, float _y, float _z, Math::rOrder rorder)
|
||||
{
|
||||
Quaternion qx(Quaternion::FromAxisAngle(_x, 1, 0, 0)),
|
||||
qy(Quaternion::FromAxisAngle(_y, 0, 1, 0)),
|
||||
qz(Quaternion::FromAxisAngle(_z, 0, 0, 1)),
|
||||
q;
|
||||
|
||||
switch (rorder)
|
||||
{
|
||||
case Math::rOrder_ZYX: q = qz * qy * qx; break;
|
||||
case Math::rOrder_YZX: q = qy * qz * qx; break;
|
||||
case Math::rOrder_ZXY: q = qz * qx * qy; break;
|
||||
case Math::rOrder_XZY: q = qx * qz * qy; break;
|
||||
default:
|
||||
case Math::rOrder_YXZ: q = qy * qx * qz; break;
|
||||
case Math::rOrder_XYZ: q = qx * qy * qz; break;
|
||||
case Math::rOrder_XY: q = qx * qy; break;
|
||||
}
|
||||
return q.Normalize();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Matrix3 Quaternion::AsMatrix3() const
|
||||
{
|
||||
float sqw = w * w, sqx = x * x, sqy = y * y, sqz = z * z;
|
||||
|
||||
Matrix3 m;
|
||||
|
||||
float invs = 1.f / (sqx + sqy + sqz + sqw);
|
||||
m.m[0][0] = ( sqx - sqy - sqz + sqw) * invs; // Since sqw + sqx + sqy + sqz = 1 / invs * invs.
|
||||
m.m[1][1] = (-sqx + sqy - sqz + sqw) * invs;
|
||||
m.m[2][2] = (-sqx - sqy + sqz + sqw) * invs;
|
||||
|
||||
float tmp1 = x * y;
|
||||
float tmp2 = z * w;
|
||||
m.m[1][0] = 2.f * (tmp1 + tmp2) * invs;
|
||||
m.m[0][1] = 2.f * (tmp1 - tmp2) * invs;
|
||||
|
||||
tmp1 = x * z;
|
||||
tmp2 = y * w;
|
||||
m.m[2][0] = 2.f * (tmp1 - tmp2) * invs;
|
||||
m.m[0][2] = 2.f * (tmp1 + tmp2) * invs;
|
||||
tmp1 = y * z;
|
||||
tmp2 = x * w;
|
||||
m.m[2][1] = 2.f * (tmp1 + tmp2) * invs;
|
||||
m.m[1][2] = 2.f * (tmp1 - tmp2) * invs;
|
||||
|
||||
return m;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NML::Tag *Quaternion::AsMetaTag(const char *id) const
|
||||
{
|
||||
NML::Tag *root = new NML::Tag(id ? id : "Quaternion");
|
||||
|
||||
if (root)
|
||||
{
|
||||
root->AddChild("X", x);
|
||||
root->AddChild("Y", y);
|
||||
root->AddChild("Z", z);
|
||||
root->AddChild("W", w);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
bool Quaternion::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) return false;
|
||||
w = t->GetReal();
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
207
include/framework/math/vector.cpp
Normal file
207
include/framework/math/vector.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user