commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View 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;
}
//------------------------------------------------------------------------------

View 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;
}

View 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;
}
//------------------------------------------------------------------------------

View 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;
}
//------------------------------------------------------------------------------