#include "pch.h"
const Orientation Orientation::s_orientIdentity;
Orientation::Orientation()
{
Reset();
}
Orientation::Orientation(const float m[3][3])
{
for (int i = 0; (i < 3); i++)
for (int j = 0; (j < 3); j++)
m_r[i][j] = m[i][j];
}
Orientation::Orientation(const Orientation& o)
{
for (int i = 0; (i < 3); i++)
for (int j = 0; (j < 3); j++)
m_r[i][j] = o.m_r[i][j];
}
Orientation::Orientation(const Vector& forwardAxis)
{
Set(forwardAxis);
}
Orientation::Orientation(const Vector& forwardAxis, const Vector& upAxis)
{
Set(forwardAxis, upAxis);
}
Orientation::Orientation(const Vector& axis, float theta)
{
Matrix mat;
mat.SetRotate(axis, theta);
for (int i = 0; (i < 3); i++) {
for (int j = 0; (j < 3); j++) {
m_r[i][j] = mat[j][i];
}
}
}
Orientation::~Orientation()
{
}
Orientation& Orientation::operator=(const Orientation& o)
{
for (int i = 0; (i < 3); i++)
for (int j = 0; (j < 3); j++)
m_r[i][j] = o.m_r[i][j];
return *this;
}
Orientation& Orientation::operator=(const float r[3][3])
{
for (int i = 0; (i < 3); i++)
for (int j = 0; (j < 3); j++)
m_r[i][j] = r[i][j];
return *this;
}
Orientation Orientation::operator*(const Orientation &o) const
{
Orientation r;
r.m_r[0][0] = m_r[0][0] * o.m_r[0][0] +
m_r[0][1] * o.m_r[1][0] +
m_r[0][2] * o.m_r[2][0];
r.m_r[0][1] = m_r[0][0] * o.m_r[0][1] +
m_r[0][1] * o.m_r[1][1] +
m_r[0][2] * o.m_r[2][1];
r.m_r[0][2] = m_r[0][0] * o.m_r[0][2] +
m_r[0][1] * o.m_r[1][2] +
m_r[0][2] * o.m_r[2][2];
r.m_r[1][0] = m_r[1][0] * o.m_r[0][0] +
m_r[1][1] * o.m_r[1][0] +
m_r[1][2] * o.m_r[2][0];
r.m_r[1][1] = m_r[1][0] * o.m_r[0][1] +
m_r[1][1] * o.m_r[1][1] +
m_r[1][2] * o.m_r[2][1];
r.m_r[1][2] = m_r[1][0] * o.m_r[0][2] +
m_r[1][1] * o.m_r[1][2] +
m_r[1][2] * o.m_r[2][2];
r.m_r[2][0] = m_r[2][0] * o.m_r[0][0] +
m_r[2][1] * o.m_r[1][0] +
m_r[2][2] * o.m_r[2][0];
r.m_r[2][1] = m_r[2][0] * o.m_r[0][1] +
m_r[2][1] * o.m_r[1][1] +
m_r[2][2] * o.m_r[2][1];
r.m_r[2][2] = m_r[2][0] * o.m_r[0][2] +
m_r[2][1] * o.m_r[1][2] +
m_r[2][2] * o.m_r[2][2];
return r;
}
Orientation& Orientation::operator*=(const Orientation &o)
{
Orientation r(*this);
m_r[0][0] = r.m_r[0][0] * o.m_r[0][0] +
r.m_r[0][1] * o.m_r[1][0] +
r.m_r[0][2] * o.m_r[2][0];
m_r[0][1] = r.m_r[0][0] * o.m_r[0][1] +
r.m_r[0][1] * o.m_r[1][1] +
r.m_r[0][2] * o.m_r[2][1];
m_r[0][2] = r.m_r[0][0] * o.m_r[0][2] +
r.m_r[0][1] * o.m_r[1][2] +
r.m_r[0][2] * o.m_r[2][2];
m_r[1][0] = r.m_r[1][0] * o.m_r[0][0] +
r.m_r[1][1] * o.m_r[1][0] +
r.m_r[1][2] * o.m_r[2][0];
m_r[1][1] = r.m_r[1][0] * o.m_r[0][1] +
r.m_r[1][1] * o.m_r[1][1] +
r.m_r[1][2] * o.m_r[2][1];
m_r[1][2] = r.m_r[1][0] * o.m_r[0][2] +
r.m_r[1][1] * o.m_r[1][2] +
r.m_r[1][2] * o.m_r[2][2];
m_r[2][0] = r.m_r[2][0] * o.m_r[0][0] +
r.m_r[2][1] * o.m_r[1][0] +
r.m_r[2][2] * o.m_r[2][0];
m_r[2][1] = r.m_r[2][0] * o.m_r[0][1] +
r.m_r[2][1] * o.m_r[1][1] +
r.m_r[2][2] * o.m_r[2][1];
m_r[2][2] = r.m_r[2][0] * o.m_r[0][2] +
r.m_r[2][1] * o.m_r[1][2] +
r.m_r[2][2] * o.m_r[2][2];
return *this;
}
bool Orientation::operator==(const Orientation &o) const
{
return ((CosUp2(o.GetUp()) > 0.999) && (CosRight2(o.GetRight()) > 0.999));
}
Orientation& Orientation::Invert()
{
float t;
t = m_r[0][1];
m_r[0][1] = m_r[1][0];
m_r[1][0] = t;
t = m_r[0][2];
m_r[0][2] = m_r[2][0];
m_r[2][0] = t;
t = m_r[2][1];
m_r[2][1] = m_r[1][2];
m_r[1][2] = t;
return *this;
}
Vector Orientation::TimesInverse(const Vector& xyz) const
{
return
Vector(
xyz.x * m_r[0][0] + xyz.y * m_r[0][1] + xyz.z * m_r[0][2],
xyz.x * m_r[1][0] + xyz.y * m_r[1][1] + xyz.z * m_r[1][2],
xyz.x * m_r[2][0] + xyz.y * m_r[2][1] + xyz.z * m_r[2][2]
);
}
Orientation Orientation::TimesInverse(const Orientation& o) const
{
Orientation r;
r.m_r[0][0] = m_r[0][0] * o.m_r[0][0] +
m_r[0][1] * o.m_r[0][1] +
m_r[0][2] * o.m_r[0][2];
r.m_r[0][1] = m_r[0][0] * o.m_r[1][0] +
m_r[0][1] * o.m_r[1][1] +
m_r[0][2] * o.m_r[1][2];
r.m_r[0][2] = m_r[0][0] * o.m_r[2][0] +
m_r[0][1] * o.m_r[2][1] +
m_r[0][2] * o.m_r[2][2];
r.m_r[1][0] = m_r[1][0] * o.m_r[0][0] +
m_r[1][1] * o.m_r[0][1] +
m_r[1][2] * o.m_r[0][2];
r.m_r[1][1] = m_r[1][0] * o.m_r[1][0] +
m_r[1][1] * o.m_r[1][1] +
m_r[1][2] * o.m_r[1][2];
r.m_r[1][2] = m_r[1][0] * o.m_r[2][0] +
m_r[1][1] * o.m_r[2][1] +
m_r[1][2] * o.m_r[2][2];
r.m_r[2][0] = m_r[2][0] * o.m_r[0][0] +
m_r[2][1] * o.m_r[0][1] +
m_r[2][2] * o.m_r[0][2];
r.m_r[2][1] = m_r[2][0] * o.m_r[1][0] +
m_r[2][1] * o.m_r[1][1] +
m_r[2][2] * o.m_r[1][2];
r.m_r[2][2] = m_r[2][0] * o.m_r[2][0] +
m_r[2][1] * o.m_r[2][1] +
m_r[2][2] * o.m_r[2][2];
return r;
}
void Orientation::TurnTo(const Vector& target)
{
float dot = CosUp2(target);
Vector up = (dot < -0.99f)
? GetForward()
: ((dot > 0.99f)
? -GetForward()
: GetUp());
Set(target, up);
}
float Orientation::TurnTo(const Vector& target,
float maxTurn)
{
float remaining;
float cosTurn2 = CosForward2(target);
if (cosTurn2 < 0.96f)
{
double dcos = (cosTurn2 < 0.0f)
? double(-sqrt(-cosTurn2))
: double(sqrt(cosTurn2));
float angle = (dcos <= -1.0)
? pi
: ((dcos >= 1.0)
? 0.0f
: (float)acos(dcos));
if (angle <= maxTurn)
{
TurnTo(target);
return 0.0f;
}
remaining = angle - maxTurn;
if (dcos < -0.999)
{
Yaw(maxTurn);
}
else
{
Vector twist = -CrossProduct(GetBackward(), target);
PostRotate(twist, maxTurn);
}
}
else
{
float yaw = acos(CosRight(target)) - 0.5f * pi;
float pitch = 0.5f * pi - acos(CosUp(target));
float angle = (float)sqrt(yaw * yaw + pitch * pitch);
if (angle <= maxTurn)
{
TurnTo(target);
return 0.0f;
}
remaining = angle - maxTurn;
float f = maxTurn / angle;
Yaw(yaw * f);
Pitch(pitch * f);
}
Renormalize();
return remaining;
}
void Orientation::Reset()
{
m_r[0][1] = m_r[0][2] = m_r[1][0] = m_r[1][2] = m_r[2][0] = m_r[2][1] = 0.0f; m_r[0][0] = m_r[1][1] = m_r[2][2] = 1.0f; }
bool Orientation::Set(const Vector& forwardAxis)
{
bool rc = true;
float forwardLength2 = forwardAxis.LengthSquared();
if (forwardLength2 != 0.0f) {
static const Vector xAxis(-1.0, 0.0, 0.0);
static const Vector yAxis( 0.0, -1.0, 0.0);
Vector upAxis = CrossProduct(xAxis, forwardAxis);
if (upAxis.LengthSquared() < forwardLength2 * 0.01F)
{
upAxis = CrossProduct(yAxis, forwardAxis);
}
Set(forwardAxis, upAxis);
}
else
{
Reset();
rc = false;
}
return rc;
}
bool Orientation::Set(const Vector& forwardAxis,
const Vector& upAxis)
{
Vector rightAxis = CrossProduct(forwardAxis, upAxis); float lRight = rightAxis.Length();
float lForward = forwardAxis.Length();
SetUp(CrossProduct(rightAxis, forwardAxis));
float lUp = GetUp().Length();
bool rc = true;
if ((lRight != 0.0f) && (lUp != 0.0f) && (lForward != 0.0f))
{
SetForward(forwardAxis / lForward);
SetUp(GetUp() / lUp);
SetRight(rightAxis / lRight);
}
else
{
Reset();
rc = false;
}
return rc;
}
static float cosX(const Vector& axis,
const Vector& xyz)
{
float dot = axis * xyz;
float l2 = xyz.LengthSquared();
if (l2 != 0.0f)
return dot / (float)sqrt(l2);
else
return 0.0f; }
static float cosX2(const Vector& axis,
const Vector& xyz)
{
float dot = axis * xyz;
float l2 = xyz.LengthSquared();
if (l2)
return dot >= 0.0f ? (dot*dot/l2) : (-dot*dot/l2); else
return 0.0f; }
float Orientation::CosUp(const Vector& xyz) const
{
return cosX(GetUp(), xyz);
}
float Orientation::CosRight(const Vector& xyz) const
{
return cosX(GetRight(), xyz);
}
float Orientation::CosForward(const Vector& xyz) const
{
return -cosX(*((Vector*)&m_r[2][0]), xyz);
}
float Orientation::CosUp2(const Vector& xyz) const
{
return cosX2(GetUp(), xyz);
}
float Orientation::CosRight2(const Vector& xyz) const
{
return cosX2(GetRight(), xyz);
}
float Orientation::CosForward2(const Vector& xyz) const
{
return -cosX2(*((Vector*)&m_r[2][0]), xyz);
}
Orientation& Orientation::PostPitch(float theta)
{
float c = (float)cos(theta);
float s = (float)sin(theta);
float r[3][3] =
{
{ m_r[0][0], c * m_r[0][1] - s * m_r[0][2], s * m_r[0][1] + c * m_r[0][2]},
{ m_r[1][0], c * m_r[1][1] - s * m_r[1][2], s * m_r[1][1] + c * m_r[1][2]},
{ m_r[2][0], c * m_r[2][1] - s * m_r[2][2], s * m_r[2][1] + c * m_r[2][2]}
};
*this = r;
return *this;
}
Orientation& Orientation::PostYaw(float theta)
{
float c = (float)cos(theta);
float s = (float)sin(theta);
float r[3][3] =
{
{c * m_r[0][0] + s * m_r[0][2], m_r[0][1], c * m_r[0][2] - s * m_r[0][0]},
{c * m_r[1][0] + s * m_r[1][2], m_r[1][1], c * m_r[1][2] - s * m_r[1][0]},
{c * m_r[2][0] + s * m_r[2][2], m_r[2][1], c * m_r[2][2] - s * m_r[2][0]}
};
*this = r;
return *this;
}
Orientation& Orientation::PostRoll(float theta)
{
float c = (float)cos(theta);
float s = (float)sin(theta);
float r[3][3] =
{
{c * m_r[0][0] - s * m_r[0][1], s * m_r[0][0] + c * m_r[0][1], m_r[0][2]},
{c * m_r[1][0] - s * m_r[1][1], s * m_r[1][0] + c * m_r[1][1], m_r[1][2]},
{c * m_r[2][0] - s * m_r[2][1], s * m_r[2][0] + c * m_r[2][1], m_r[2][2]}
};
*this = r;
return *this;
}
Orientation& Orientation::Pitch(float theta)
{
float c = (float)cos(theta);
float s = (float)sin(theta);
float r[3][3] =
{
{ m_r[0][0], m_r[0][1], m_r[0][2]},
{c * m_r[1][0] + s * m_r[2][0], c * m_r[1][1] + s * m_r[2][1], c * m_r[1][2] + s * m_r[2][2]},
{c * m_r[2][0] - s * m_r[1][0], c * m_r[2][1] - s * m_r[1][1], c * m_r[2][2] - s * m_r[1][2]},
};
*this = r;
return *this;
}
Orientation& Orientation::Yaw(float theta)
{
float c = (float)cos(theta);
float s = (float)sin(theta);
float r[3][3] =
{
{c * m_r[0][0] - s * m_r[2][0], c * m_r[0][1] - s * m_r[2][1], c * m_r[0][2] - s * m_r[2][2]},
{ m_r[1][0], m_r[1][1], m_r[1][2]},
{c * m_r[2][0] + s * m_r[0][0], c * m_r[2][1] + s * m_r[0][1], c * m_r[2][2] + s * m_r[0][2]},
};
*this = r;
return *this;
}
Orientation& Orientation::Roll(float theta)
{
float c = (float)cos(theta);
float s = (float)sin(theta);
float r[3][3] =
{
{c * m_r[0][0] + s * m_r[1][0], c * m_r[0][1] + s * m_r[1][1], c * m_r[0][2] + s * m_r[1][2]},
{c * m_r[1][0] - s * m_r[0][0], c * m_r[1][1] - s * m_r[0][1], c * m_r[1][2] - s * m_r[0][2]},
{ m_r[2][0], m_r[2][1], m_r[2][2]}
};
*this = r;
return *this;
}
Orientation& Orientation::PreRotate(const Vector& axis, float theta)
{
Orientation o(axis, theta);
*this = o * *this;
return *this;
}
Orientation& Orientation::PostRotate(const Vector& axis,
float theta)
{
Orientation o(axis, theta);
*this *= o;
return *this;
}