|
|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
|
work.
|
|
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
|
or by snail mail at:
|
|
|
|
|
Cyan Worlds, I
|
|
|
|
|
nc.
|
|
|
|
|
14617 N Newport Hwy
|
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include "HeadSpin.h"
|
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
|
|
#include "hsGeometry3.h"
|
|
|
|
|
#include "hsQuat.h"
|
|
|
|
|
#include "hsMatrix44.h"
|
|
|
|
|
#include "hsStream.h"
|
|
|
|
|
|
|
|
|
|
#ifdef HS_SIMD_INCLUDE
|
|
|
|
|
# include HS_SIMD_INCLUDE
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static hsMatrix44 myIdent = hsMatrix44().Reset();
|
|
|
|
|
const hsMatrix44& hsMatrix44::IdentityMatrix() { return myIdent; }
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
For the rotation:
|
|
|
|
|
<EFBFBD> 2 2 <EFBFBD>
|
|
|
|
|
<EFBFBD> 1 - (2Y + 2Z ) 2XY + 2ZW 2XZ - 2YW <EFBFBD>
|
|
|
|
|
<EFBFBD> <EFBFBD>
|
|
|
|
|
<EFBFBD> 2 2 <EFBFBD>
|
|
|
|
|
M = <EFBFBD> 2XY - 2ZW 1 - (2X + 2Z ) 2YZ + 2XW <EFBFBD>
|
|
|
|
|
<EFBFBD> <EFBFBD>
|
|
|
|
|
<EFBFBD> 2 2 <EFBFBD>
|
|
|
|
|
<EFBFBD> 2XZ + 2YW 2YZ - 2XW 1 - (2X + 2Y ) <EFBFBD>
|
|
|
|
|
<EFBFBD> <EFBFBD>
|
|
|
|
|
|
|
|
|
|
The translation is far too complex to discuss here. ;^)
|
|
|
|
|
*/
|
|
|
|
|
hsMatrix44::hsMatrix44(const hsScalarTriple &translate, const hsQuat &rotate)
|
|
|
|
|
{
|
|
|
|
|
float xx = rotate.fX * rotate.fX;
|
|
|
|
|
float xy = rotate.fX * rotate.fY;
|
|
|
|
|
float xz = rotate.fX * rotate.fZ;
|
|
|
|
|
float xw = rotate.fX * rotate.fW;
|
|
|
|
|
|
|
|
|
|
float yy = rotate.fY * rotate.fY;
|
|
|
|
|
float yz = rotate.fY * rotate.fZ;
|
|
|
|
|
float yw = rotate.fY * rotate.fW;
|
|
|
|
|
|
|
|
|
|
float zz = rotate.fZ * rotate.fZ;
|
|
|
|
|
float zw = rotate.fZ * rotate.fW;
|
|
|
|
|
|
|
|
|
|
fMap[0][0] = 1 - 2 * ( yy + zz ); fMap[0][1] = 2 * ( xy - zw ); fMap[0][2] = 2 * ( xz + yw ); fMap[0][3] = translate.fX;
|
|
|
|
|
fMap[1][0] = 2 * ( xy + zw ); fMap[1][1] = 1 - 2 * ( xx + zz ); fMap[1][2] = 2 * ( yz - xw ); fMap[1][3] = translate.fY;
|
|
|
|
|
fMap[2][0] = 2 * ( xz - yw ); fMap[2][1] = 2 * ( yz + xw ); fMap[2][2] = 1 - 2 * ( xx + yy ); fMap[2][3] = translate.fZ;
|
|
|
|
|
fMap[3][0] = fMap[3][1] = fMap[3][2] = 0.0f;
|
|
|
|
|
fMap[3][3] = 1.0f;
|
|
|
|
|
NotIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::DecompRigid(hsScalarTriple &translate, hsQuat &rotate) const
|
|
|
|
|
{
|
|
|
|
|
translate = GetTranslate();
|
|
|
|
|
rotate.QuatFromMatrix44(*this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static hsMatrix44 mat_mult_fpu(const hsMatrix44 &a, const hsMatrix44 &b)
|
|
|
|
|
{
|
|
|
|
|
hsMatrix44 c;
|
|
|
|
|
|
|
|
|
|
if( a.fFlags & b.fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
{
|
|
|
|
|
c.Reset();
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( a.fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
return b;
|
|
|
|
|
if( b.fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
return a;
|
|
|
|
|
|
|
|
|
|
c.fMap[0][0] = (a.fMap[0][0] * b.fMap[0][0]) + (a.fMap[0][1] * b.fMap[1][0]) + (a.fMap[0][2] * b.fMap[2][0]) + (a.fMap[0][3] * b.fMap[3][0]);
|
|
|
|
|
c.fMap[0][1] = (a.fMap[0][0] * b.fMap[0][1]) + (a.fMap[0][1] * b.fMap[1][1]) + (a.fMap[0][2] * b.fMap[2][1]) + (a.fMap[0][3] * b.fMap[3][1]);
|
|
|
|
|
c.fMap[0][2] = (a.fMap[0][0] * b.fMap[0][2]) + (a.fMap[0][1] * b.fMap[1][2]) + (a.fMap[0][2] * b.fMap[2][2]) + (a.fMap[0][3] * b.fMap[3][2]);
|
|
|
|
|
c.fMap[0][3] = (a.fMap[0][0] * b.fMap[0][3]) + (a.fMap[0][1] * b.fMap[1][3]) + (a.fMap[0][2] * b.fMap[2][3]) + (a.fMap[0][3] * b.fMap[3][3]);
|
|
|
|
|
|
|
|
|
|
c.fMap[1][0] = (a.fMap[1][0] * b.fMap[0][0]) + (a.fMap[1][1] * b.fMap[1][0]) + (a.fMap[1][2] * b.fMap[2][0]) + (a.fMap[1][3] * b.fMap[3][0]);
|
|
|
|
|
c.fMap[1][1] = (a.fMap[1][0] * b.fMap[0][1]) + (a.fMap[1][1] * b.fMap[1][1]) + (a.fMap[1][2] * b.fMap[2][1]) + (a.fMap[1][3] * b.fMap[3][1]);
|
|
|
|
|
c.fMap[1][2] = (a.fMap[1][0] * b.fMap[0][2]) + (a.fMap[1][1] * b.fMap[1][2]) + (a.fMap[1][2] * b.fMap[2][2]) + (a.fMap[1][3] * b.fMap[3][2]);
|
|
|
|
|
c.fMap[1][3] = (a.fMap[1][0] * b.fMap[0][3]) + (a.fMap[1][1] * b.fMap[1][3]) + (a.fMap[1][2] * b.fMap[2][3]) + (a.fMap[1][3] * b.fMap[3][3]);
|
|
|
|
|
|
|
|
|
|
c.fMap[2][0] = (a.fMap[2][0] * b.fMap[0][0]) + (a.fMap[2][1] * b.fMap[1][0]) + (a.fMap[2][2] * b.fMap[2][0]) + (a.fMap[2][3] * b.fMap[3][0]);
|
|
|
|
|
c.fMap[2][1] = (a.fMap[2][0] * b.fMap[0][1]) + (a.fMap[2][1] * b.fMap[1][1]) + (a.fMap[2][2] * b.fMap[2][1]) + (a.fMap[2][3] * b.fMap[3][1]);
|
|
|
|
|
c.fMap[2][2] = (a.fMap[2][0] * b.fMap[0][2]) + (a.fMap[2][1] * b.fMap[1][2]) + (a.fMap[2][2] * b.fMap[2][2]) + (a.fMap[2][3] * b.fMap[3][2]);
|
|
|
|
|
c.fMap[2][3] = (a.fMap[2][0] * b.fMap[0][3]) + (a.fMap[2][1] * b.fMap[1][3]) + (a.fMap[2][2] * b.fMap[2][3]) + (a.fMap[2][3] * b.fMap[3][3]);
|
|
|
|
|
|
|
|
|
|
c.fMap[3][0] = (a.fMap[3][0] * b.fMap[0][0]) + (a.fMap[3][1] * b.fMap[1][0]) + (a.fMap[3][2] * b.fMap[2][0]) + (a.fMap[3][3] * b.fMap[3][0]);
|
|
|
|
|
c.fMap[3][1] = (a.fMap[3][0] * b.fMap[0][1]) + (a.fMap[3][1] * b.fMap[1][1]) + (a.fMap[3][2] * b.fMap[2][1]) + (a.fMap[3][3] * b.fMap[3][1]);
|
|
|
|
|
c.fMap[3][2] = (a.fMap[3][0] * b.fMap[0][2]) + (a.fMap[3][1] * b.fMap[1][2]) + (a.fMap[3][2] * b.fMap[2][2]) + (a.fMap[3][3] * b.fMap[3][2]);
|
|
|
|
|
c.fMap[3][3] = (a.fMap[3][0] * b.fMap[0][3]) + (a.fMap[3][1] * b.fMap[1][3]) + (a.fMap[3][2] * b.fMap[2][3]) + (a.fMap[3][3] * b.fMap[3][3]);
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HS_SSE3
|
|
|
|
|
# define MULTBEGIN(i) \
|
|
|
|
|
xmm[0] = _mm_loadu_ps(a.fMap[i]);
|
|
|
|
|
# define MULTCELL(i, j) \
|
|
|
|
|
xmm[1] = _mm_set_ps(b.fMap[3][j], b.fMap[2][j], b.fMap[1][j], b.fMap[0][j]); \
|
|
|
|
|
xmm[j+2] = _mm_mul_ps(xmm[0], xmm[1]);
|
|
|
|
|
# define MULTFINISH(i) \
|
|
|
|
|
xmm[6] = _mm_hadd_ps(xmm[2], xmm[3]); \
|
|
|
|
|
xmm[7] = _mm_hadd_ps(xmm[4], xmm[5]); \
|
|
|
|
|
xmm[1] = _mm_hadd_ps(xmm[6], xmm[7]); \
|
|
|
|
|
_mm_storeu_ps(c.fMap[i], xmm[1]);
|
|
|
|
|
#endif // HS_SSE3
|
|
|
|
|
|
|
|
|
|
static hsMatrix44 mat_mult_sse3(const hsMatrix44 &a, const hsMatrix44 &b)
|
|
|
|
|
{
|
|
|
|
|
hsMatrix44 c;
|
|
|
|
|
#ifdef HS_SSE3
|
|
|
|
|
if( a.fFlags & b.fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
{
|
|
|
|
|
c.Reset();
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( a.fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
return b;
|
|
|
|
|
if( b.fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
return a;
|
|
|
|
|
|
|
|
|
|
__m128 xmm[8];
|
|
|
|
|
|
|
|
|
|
MULTBEGIN(0);
|
|
|
|
|
MULTCELL(0, 0);
|
|
|
|
|
MULTCELL(0, 1);
|
|
|
|
|
MULTCELL(0, 2);
|
|
|
|
|
MULTCELL(0, 3);
|
|
|
|
|
MULTFINISH(0);
|
|
|
|
|
|
|
|
|
|
MULTBEGIN(1);
|
|
|
|
|
MULTCELL(1, 0);
|
|
|
|
|
MULTCELL(1, 1);
|
|
|
|
|
MULTCELL(1, 2);
|
|
|
|
|
MULTCELL(1, 3);
|
|
|
|
|
MULTFINISH(1);
|
|
|
|
|
|
|
|
|
|
MULTBEGIN(2);
|
|
|
|
|
MULTCELL(2, 0);
|
|
|
|
|
MULTCELL(2, 1);
|
|
|
|
|
MULTCELL(2, 2);
|
|
|
|
|
MULTCELL(2, 3);
|
|
|
|
|
MULTFINISH(2);
|
|
|
|
|
|
|
|
|
|
MULTBEGIN(3);
|
|
|
|
|
MULTCELL(3, 0);
|
|
|
|
|
MULTCELL(3, 1);
|
|
|
|
|
MULTCELL(3, 2);
|
|
|
|
|
MULTCELL(3, 3);
|
|
|
|
|
MULTFINISH(3);
|
|
|
|
|
#endif // HS_SSE3
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CPU-optimized functions requiring dispatch
|
|
|
|
|
hsCpuFunctionDispatcher<hsMatrix44::mat_mult_ptr> hsMatrix44::mat_mult {
|
|
|
|
|
&mat_mult_fpu,
|
|
|
|
|
nullptr, // SSE1
|
|
|
|
|
nullptr, // SSE2
|
|
|
|
|
&mat_mult_sse3
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
hsPoint3 hsMatrix44::operator*(const hsPoint3& p) const
|
|
|
|
|
{
|
|
|
|
|
if (fFlags & hsMatrix44::kIsIdent)
|
|
|
|
|
return p;
|
|
|
|
|
|
|
|
|
|
hsPoint3 rVal;
|
|
|
|
|
rVal.fX = (p.fX * fMap[0][0]) + (p.fY * fMap[0][1]) + (p.fZ * fMap[0][2]) + fMap[0][3];
|
|
|
|
|
rVal.fY = (p.fX * fMap[1][0]) + (p.fY * fMap[1][1]) + (p.fZ * fMap[1][2]) + fMap[1][3];
|
|
|
|
|
rVal.fZ = (p.fX * fMap[2][0]) + (p.fY * fMap[2][1]) + (p.fZ * fMap[2][2]) + fMap[2][3];
|
|
|
|
|
return rVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsVector3 hsMatrix44::operator*(const hsVector3& p) const
|
|
|
|
|
{
|
|
|
|
|
if( fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
return p;
|
|
|
|
|
|
|
|
|
|
hsVector3 rVal;
|
|
|
|
|
|
|
|
|
|
rVal.fX = (p.fX * fMap[0][0]) + (p.fY * fMap[0][1]) + (p.fZ * fMap[0][2]);
|
|
|
|
|
rVal.fY = (p.fX * fMap[1][0]) + (p.fY * fMap[1][1]) + (p.fZ * fMap[1][2]);
|
|
|
|
|
rVal.fZ = (p.fX * fMap[2][0]) + (p.fY * fMap[2][1]) + (p.fZ * fMap[2][2]);
|
|
|
|
|
|
|
|
|
|
return rVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hsMatrix44::operator==(const hsMatrix44& ss) const
|
|
|
|
|
{
|
|
|
|
|
if( ss.fFlags & fFlags & hsMatrix44::kIsIdent )
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 4; i++)
|
|
|
|
|
{
|
|
|
|
|
for(int j = 0; j < 4; j++)
|
|
|
|
|
{
|
|
|
|
|
if (ss.fMap[i][j] != fMap[i][j])
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44& hsMatrix44::Scale(const hsVector3* scale)
|
|
|
|
|
{
|
|
|
|
|
fMap[0][0] *= scale->fX;
|
|
|
|
|
fMap[0][1] *= scale->fX;
|
|
|
|
|
fMap[0][2] *= scale->fX;
|
|
|
|
|
fMap[0][3] *= scale->fX;
|
|
|
|
|
|
|
|
|
|
fMap[1][0] *= scale->fY;
|
|
|
|
|
fMap[1][1] *= scale->fY;
|
|
|
|
|
fMap[1][2] *= scale->fY;
|
|
|
|
|
fMap[1][3] *= scale->fY;
|
|
|
|
|
|
|
|
|
|
fMap[2][0] *= scale->fZ;
|
|
|
|
|
fMap[2][1] *= scale->fZ;
|
|
|
|
|
fMap[2][2] *= scale->fZ;
|
|
|
|
|
fMap[2][3] *= scale->fZ;
|
|
|
|
|
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsVector3 hsMatrix44::RemoveScale()
|
|
|
|
|
{
|
|
|
|
|
hsVector3 xCol(fMap[0][0], fMap[0][1], fMap[0][2]);
|
|
|
|
|
float xLen = xCol.Magnitude();
|
|
|
|
|
hsVector3 yCol(fMap[1][0], fMap[1][1], fMap[1][2]);
|
|
|
|
|
float yLen = yCol.Magnitude();
|
|
|
|
|
hsVector3 zCol(fMap[2][0], fMap[2][1], fMap[2][2]);
|
|
|
|
|
float zLen = zCol.Magnitude();
|
|
|
|
|
|
|
|
|
|
fMap[0][0] /= xLen;
|
|
|
|
|
fMap[0][1] /= xLen;
|
|
|
|
|
fMap[0][2] /= xLen;
|
|
|
|
|
fMap[1][0] /= yLen;
|
|
|
|
|
fMap[1][1] /= yLen;
|
|
|
|
|
fMap[1][2] /= yLen;
|
|
|
|
|
fMap[2][0] /= zLen;
|
|
|
|
|
fMap[2][1] /= zLen;
|
|
|
|
|
fMap[2][2] /= zLen;
|
|
|
|
|
|
|
|
|
|
hsVector3 oldScale(xLen, yLen, zLen);
|
|
|
|
|
return oldScale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44& hsMatrix44::Translate(const hsVector3* pt)
|
|
|
|
|
{
|
|
|
|
|
for (int i =0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
fMap[i][3] += (*pt)[i];
|
|
|
|
|
}
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
hsMatrix44& hsMatrix44::SetTranslate(const hsScalarTriple* pt)
|
|
|
|
|
{
|
|
|
|
|
for (int i =0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
fMap[i][3] = (*pt)[i];
|
|
|
|
|
}
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
hsMatrix44& hsMatrix44::MakeRotateMat(int axis, float radians)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
SetRotate(axis, radians);
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44& hsMatrix44::Rotate(int axis, float radians)
|
|
|
|
|
{
|
|
|
|
|
hsMatrix44 rMat;
|
|
|
|
|
rMat.MakeRotateMat(axis, radians);
|
|
|
|
|
*this = rMat * *this;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44& hsMatrix44::SetRotate(int axis, float radians)
|
|
|
|
|
{
|
|
|
|
|
float s = sin(radians);
|
|
|
|
|
float c = cos(radians);
|
|
|
|
|
int c1,c2;
|
|
|
|
|
switch (axis)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
c1 = 1;
|
|
|
|
|
c2 = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
c1 = 0;
|
|
|
|
|
c2 = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
c1 = 0;
|
|
|
|
|
c2 = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
fMap[c1][c1] = c;
|
|
|
|
|
fMap[c2][c2] = c;
|
|
|
|
|
fMap[c1][c2] = s;
|
|
|
|
|
fMap[c2][c1] = -s;
|
|
|
|
|
|
|
|
|
|
NotIdentity();
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::MakeXRotation(float radians)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
float s = sin(radians);
|
|
|
|
|
float c = cos(radians);
|
|
|
|
|
|
|
|
|
|
fMap[1][1] = c;
|
|
|
|
|
fMap[2][2] = c;
|
|
|
|
|
fMap[1][2] = s;
|
|
|
|
|
fMap[2][1] = -s;
|
|
|
|
|
NotIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::MakeYRotation(float radians)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
float s = sin(radians);
|
|
|
|
|
float c = cos(radians);
|
|
|
|
|
fMap[0][0] = c;
|
|
|
|
|
fMap[2][2] = c;
|
|
|
|
|
fMap[0][2] = -s;
|
|
|
|
|
fMap[2][0] = s;
|
|
|
|
|
NotIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::MakeZRotation(float radians)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
float s = sin(radians);
|
|
|
|
|
float c = cos(radians);
|
|
|
|
|
fMap[0][0] = c;
|
|
|
|
|
fMap[1][1] = c;
|
|
|
|
|
fMap[0][1] = s;
|
|
|
|
|
fMap[1][0] = -s;
|
|
|
|
|
NotIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Not a camera matrix
|
|
|
|
|
//
|
|
|
|
|
hsMatrix44& hsMatrix44::Make(const hsPoint3* f, const hsPoint3* at, const hsVector3* up)
|
|
|
|
|
{
|
|
|
|
|
hsVector3 trans(f->fX, f->fY, f->fZ);
|
|
|
|
|
MakeTranslateMat(&trans);
|
|
|
|
|
|
|
|
|
|
hsVector3 back (f,at); // Z
|
|
|
|
|
back.Normalize();
|
|
|
|
|
|
|
|
|
|
hsVector3 leftEar = *up % back; // X, LHS
|
|
|
|
|
leftEar.Normalize();
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
// Ignore actual up vector
|
|
|
|
|
hsVector3 topHead = leftEar % back; // Y, RHS (should be flipped)
|
|
|
|
|
#else
|
|
|
|
|
hsVector3 topHead = *up;
|
|
|
|
|
#endif
|
|
|
|
|
topHead.Normalize();
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
fMap[i][0] = leftEar[i];
|
|
|
|
|
fMap[i][1] = back[i];
|
|
|
|
|
fMap[i][2] = topHead[i];
|
|
|
|
|
}
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Not a camera matrix
|
|
|
|
|
//
|
|
|
|
|
hsMatrix44& hsMatrix44::MakeUpPreserving(const hsPoint3* f, const hsPoint3* at, const hsVector3* up)
|
|
|
|
|
{
|
|
|
|
|
hsVector3 trans(f->fX, f->fY, f->fZ);
|
|
|
|
|
MakeTranslateMat(&trans);
|
|
|
|
|
|
|
|
|
|
hsVector3 topHead = *up;
|
|
|
|
|
topHead.Normalize();
|
|
|
|
|
|
|
|
|
|
hsVector3 back (f,at); // Z
|
|
|
|
|
back = -back; // really front
|
|
|
|
|
|
|
|
|
|
hsVector3 leftEar = *up % back; // X
|
|
|
|
|
leftEar.Normalize();
|
|
|
|
|
|
|
|
|
|
back = (topHead % leftEar);
|
|
|
|
|
back.Normalize();
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
fMap[i][0] = leftEar[i];
|
|
|
|
|
fMap[i][1] = back[i];
|
|
|
|
|
fMap[i][2] = topHead[i];
|
|
|
|
|
}
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Get info from a non-camera matrix. Vectors are normalized.
|
|
|
|
|
//
|
|
|
|
|
void hsMatrix44::GetAxis(hsVector3* view, hsVector3 *up, hsVector3* right)
|
|
|
|
|
{
|
|
|
|
|
if (view)
|
|
|
|
|
view->Set(-fMap[0][1],-fMap[1][1],-fMap[2][1]);
|
|
|
|
|
if (right)
|
|
|
|
|
right->Set(-fMap[0][0],-fMap[1][0],-fMap[2][0]);
|
|
|
|
|
if (up)
|
|
|
|
|
up->Set(fMap[0][2], fMap[1][2], fMap[2][2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const hsVector3 hsMatrix44::GetAxis(int i) const
|
|
|
|
|
{
|
|
|
|
|
hsVector3 ret;
|
|
|
|
|
switch(i)
|
|
|
|
|
{
|
|
|
|
|
case kView:
|
|
|
|
|
{
|
|
|
|
|
ret.Set(-fMap[0][1],-fMap[1][1],-fMap[2][1]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kUp:
|
|
|
|
|
{
|
|
|
|
|
ret.Set(fMap[0][2], fMap[1][2], fMap[2][2]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kRight:
|
|
|
|
|
{
|
|
|
|
|
ret.Set(-fMap[0][0],-fMap[1][0],-fMap[2][0]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Camera matrix
|
|
|
|
|
//
|
|
|
|
|
hsMatrix44& hsMatrix44::MakeCamera(const hsPoint3* from, const hsPoint3* at,
|
|
|
|
|
const hsVector3* up)
|
|
|
|
|
{
|
|
|
|
|
hsVector3 dirZ(at, from);
|
|
|
|
|
hsVector3 trans( -from->fX, -from->fY, -from->fZ );
|
|
|
|
|
hsVector3 dirY, dirX;
|
|
|
|
|
hsMatrix44 rmat;
|
|
|
|
|
|
|
|
|
|
dirX = (*up) % dirZ; // Stop passing in down!!! // mf_flip_up - mf
|
|
|
|
|
if (dirX.MagnitudeSquared())
|
|
|
|
|
dirX.Normalize();
|
|
|
|
|
|
|
|
|
|
if (dirZ.MagnitudeSquared())
|
|
|
|
|
dirZ.Normalize();
|
|
|
|
|
dirY = dirZ % dirX;
|
|
|
|
|
if (dirY.MagnitudeSquared())
|
|
|
|
|
dirY.Normalize();
|
|
|
|
|
|
|
|
|
|
this->Reset();
|
|
|
|
|
this->Translate(&trans);
|
|
|
|
|
rmat.Reset();
|
|
|
|
|
for(int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
rmat.fMap[0][i] = -dirX[i];
|
|
|
|
|
rmat.fMap[1][i] = dirY[i];
|
|
|
|
|
rmat.fMap[2][i] = dirZ[i];
|
|
|
|
|
}
|
|
|
|
|
rmat.NotIdentity();
|
|
|
|
|
*this = rmat * *this;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::MakeCameraMatrices(const hsPoint3& from, const hsPoint3& at, const hsVector3& up, hsMatrix44& worldToCamera, hsMatrix44& cameraToWorld)
|
|
|
|
|
{
|
|
|
|
|
hsVector3 dirZ(&at, &from);
|
|
|
|
|
|
|
|
|
|
hsVector3 dirX(dirZ % up);
|
|
|
|
|
dirX.Normalize();
|
|
|
|
|
|
|
|
|
|
hsVector3 dirY(dirX % dirZ);
|
|
|
|
|
dirY.Normalize();
|
|
|
|
|
|
|
|
|
|
worldToCamera.Reset(false);
|
|
|
|
|
cameraToWorld.Reset(false);
|
|
|
|
|
int i;
|
|
|
|
|
for( i = 0; i < 3; i++ )
|
|
|
|
|
{
|
|
|
|
|
worldToCamera.fMap[0][i] = dirX[i];
|
|
|
|
|
worldToCamera.fMap[1][i] = dirY[i];
|
|
|
|
|
worldToCamera.fMap[2][i] = dirZ[i];
|
|
|
|
|
|
|
|
|
|
cameraToWorld.fMap[i][0] = dirX[i];
|
|
|
|
|
cameraToWorld.fMap[i][1] = dirY[i];
|
|
|
|
|
cameraToWorld.fMap[i][2] = dirZ[i];
|
|
|
|
|
}
|
|
|
|
|
hsPoint3 trans = -from;
|
|
|
|
|
worldToCamera.fMap[0][3] = dirX.InnerProduct(trans);
|
|
|
|
|
worldToCamera.fMap[1][3] = dirY.InnerProduct(trans);
|
|
|
|
|
worldToCamera.fMap[2][3] = dirZ.InnerProduct(trans);
|
|
|
|
|
|
|
|
|
|
cameraToWorld.fMap[0][3] = from.fX;
|
|
|
|
|
cameraToWorld.fMap[1][3] = from.fY;
|
|
|
|
|
cameraToWorld.fMap[2][3] = from.fZ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::MakeEnvMapMatrices(const hsPoint3& pos, hsMatrix44* worldToCameras, hsMatrix44* cameraToWorlds)
|
|
|
|
|
{
|
|
|
|
|
MakeCameraMatrices(pos, hsPoint3(pos.fX - 1.f, pos.fY, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[0], cameraToWorlds[0]);
|
|
|
|
|
|
|
|
|
|
MakeCameraMatrices(pos, hsPoint3(pos.fX + 1.f, pos.fY, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[1], cameraToWorlds[1]);
|
|
|
|
|
|
|
|
|
|
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY + 1.f, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[2], cameraToWorlds[2]);
|
|
|
|
|
|
|
|
|
|
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY - 1.f, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[3], cameraToWorlds[3]);
|
|
|
|
|
|
|
|
|
|
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY, pos.fZ + 1.f), hsVector3(0, -1.f, 0), worldToCameras[4], cameraToWorlds[4]);
|
|
|
|
|
|
|
|
|
|
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY, pos.fZ - 1.f), hsVector3(0, 1.f, 0), worldToCameras[5], cameraToWorlds[5]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Vectors are normalized.
|
|
|
|
|
//
|
|
|
|
|
void hsMatrix44::GetAxisFromCamera(hsVector3* view, hsVector3 *up, hsVector3* right)
|
|
|
|
|
{
|
|
|
|
|
if (view)
|
|
|
|
|
view->Set(fMap[2][0],fMap[2][1],fMap[2][2]);
|
|
|
|
|
if (right)
|
|
|
|
|
right->Set(fMap[0][0],fMap[0][1],fMap[0][2]);
|
|
|
|
|
if (up)
|
|
|
|
|
up->Set(fMap[1][0], fMap[1][1], fMap[1][2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Camera matrix
|
|
|
|
|
//
|
|
|
|
|
hsMatrix44& hsMatrix44::MakeCameraUpPreserving(const hsPoint3* from, const hsPoint3* at,
|
|
|
|
|
const hsVector3* up)
|
|
|
|
|
{
|
|
|
|
|
hsVector3 dirZ(at, from);
|
|
|
|
|
hsVector3 trans( -from->fX, -from->fY, -from->fZ );
|
|
|
|
|
hsVector3 dirY( up->fX, up->fY, up->fZ );
|
|
|
|
|
hsVector3 dirX;
|
|
|
|
|
hsMatrix44 rmat;
|
|
|
|
|
|
|
|
|
|
dirX = dirY % dirZ;
|
|
|
|
|
dirX.Normalize();
|
|
|
|
|
|
|
|
|
|
dirY.Normalize();
|
|
|
|
|
dirZ = dirX % dirY;
|
|
|
|
|
dirZ.Normalize();
|
|
|
|
|
|
|
|
|
|
this->Reset();
|
|
|
|
|
this->Translate(&trans);
|
|
|
|
|
rmat.Reset();
|
|
|
|
|
for(int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
rmat.fMap[0][i] = -dirX[i];
|
|
|
|
|
rmat.fMap[1][i] = dirY[i];
|
|
|
|
|
rmat.fMap[2][i] = dirZ[i];
|
|
|
|
|
}
|
|
|
|
|
rmat.NotIdentity();
|
|
|
|
|
*this = rmat * *this;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static float GetDeterminant33(const hsMatrix44* mat)
|
|
|
|
|
{
|
|
|
|
|
return ((mat->fMap[0][0] * mat->fMap[1][1]) * mat->fMap[2][2]) +
|
|
|
|
|
((mat->fMap[0][1] * mat->fMap[1][2]) * mat->fMap[2][0]) +
|
|
|
|
|
((mat->fMap[0][2] * mat->fMap[1][0]) * mat->fMap[2][1]) -
|
|
|
|
|
((mat->fMap[0][2] * mat->fMap[1][1]) * mat->fMap[2][0]) -
|
|
|
|
|
((mat->fMap[0][1] * mat->fMap[1][0]) * mat->fMap[2][2]) -
|
|
|
|
|
((mat->fMap[0][0] * mat->fMap[1][2]) * mat->fMap[2][1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44* hsMatrix44::GetTranspose(hsMatrix44* transp) const
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0 ; i < 4; i++)
|
|
|
|
|
for(int j=0; j < 4; j++)
|
|
|
|
|
transp->fMap[i][j] = fMap[j][i];
|
|
|
|
|
return transp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline float Determinant2(float a, float b,float c, float d)
|
|
|
|
|
{
|
|
|
|
|
return (a * d) - (c * b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline float Determinant3(float a, float b, float c,
|
|
|
|
|
float d, float e, float f,
|
|
|
|
|
float g, float h, float i)
|
|
|
|
|
{
|
|
|
|
|
return (a * Determinant2(e, f, h, i))
|
|
|
|
|
- (b * Determinant2(d, f, g, i))
|
|
|
|
|
+ (c * Determinant2(d, e, g, h));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float hsMatrix44::GetDeterminant() const
|
|
|
|
|
{
|
|
|
|
|
return (fMap[0][0]*Determinant3(fMap[1][1], fMap[2][1], fMap[3][1],
|
|
|
|
|
fMap[1][2], fMap[2][2], fMap[3][2],
|
|
|
|
|
fMap[1][3], fMap[2][3], fMap[3][3]) -
|
|
|
|
|
fMap[1][0]*Determinant3(fMap[0][1], fMap[2][1], fMap[3][1],
|
|
|
|
|
fMap[0][2], fMap[2][2], fMap[3][2],
|
|
|
|
|
fMap[0][3], fMap[2][3], fMap[3][3]) +
|
|
|
|
|
fMap[2][0]*Determinant3(fMap[0][1], fMap[1][1], fMap[3][1],
|
|
|
|
|
fMap[0][2], fMap[1][2], fMap[3][2],
|
|
|
|
|
fMap[0][3], fMap[1][3], fMap[3][3]) -
|
|
|
|
|
fMap[3][0]*Determinant3(fMap[0][1], fMap[1][1], fMap[2][1],
|
|
|
|
|
fMap[0][2], fMap[1][2], fMap[2][2],
|
|
|
|
|
fMap[0][3], fMap[1][3], fMap[2][3]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsMatrix44 *hsMatrix44::GetAdjoint(hsMatrix44 *adj) const
|
|
|
|
|
{
|
|
|
|
|
float a1, a2, a3, a4, b1, b2, b3, b4;
|
|
|
|
|
float c1, c2, c3, c4, d1, d2, d3, d4;
|
|
|
|
|
/*
|
|
|
|
|
* calculate the adjoint of a 4x4 matrix
|
|
|
|
|
*
|
|
|
|
|
* Let a denote the minor determinant of matrix A obtained by
|
|
|
|
|
* ij
|
|
|
|
|
*
|
|
|
|
|
* deleting the ith row and jth column from A.
|
|
|
|
|
*
|
|
|
|
|
* i+j
|
|
|
|
|
* Let b = (-1) a
|
|
|
|
|
* ij ji
|
|
|
|
|
*
|
|
|
|
|
* The matrix B = (b ) is the adjoint of A
|
|
|
|
|
* ij
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* assign to individual variable names to aid */
|
|
|
|
|
/* selecting correct values */
|
|
|
|
|
|
|
|
|
|
a1 = fMap[0][0];
|
|
|
|
|
b1 = fMap[0][1];
|
|
|
|
|
c1 = fMap[0][2];
|
|
|
|
|
d1 = fMap[0][3];
|
|
|
|
|
|
|
|
|
|
a2 = fMap[1][0];
|
|
|
|
|
b2 = fMap[1][1];
|
|
|
|
|
c2 = fMap[1][2];
|
|
|
|
|
d2 = fMap[1][3];
|
|
|
|
|
|
|
|
|
|
a3 = fMap[2][0];
|
|
|
|
|
b3 = fMap[2][1];
|
|
|
|
|
c3 = fMap[2][2];
|
|
|
|
|
d3 = fMap[2][3];
|
|
|
|
|
|
|
|
|
|
a4 = fMap[3][0];
|
|
|
|
|
b4 = fMap[3][1];
|
|
|
|
|
c4 = fMap[3][2];
|
|
|
|
|
d4 = fMap[3][3];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* row column labeling reversed since we transpose rows & columns
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
adj->fMap[0][0] = Determinant3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
|
|
|
|
|
adj->fMap[1][0] = -Determinant3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
|
|
|
|
|
adj->fMap[2][0] = Determinant3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
|
|
|
|
|
adj->fMap[3][0] = -Determinant3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
|
|
|
|
|
|
|
|
|
adj->fMap[0][1] = -Determinant3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
|
|
|
|
|
adj->fMap[1][1] = Determinant3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
|
|
|
|
|
adj->fMap[2][1] = -Determinant3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
|
|
|
|
|
adj->fMap[3][1] = Determinant3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
|
|
|
|
|
|
|
|
|
|
adj->fMap[0][2] = Determinant3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
|
|
|
|
|
adj->fMap[1][2] = -Determinant3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
|
|
|
|
|
adj->fMap[2][2] = Determinant3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
|
|
|
|
|
adj->fMap[3][2] = -Determinant3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
|
|
|
|
|
|
|
|
|
|
adj->fMap[0][3] = -Determinant3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
|
|
|
|
|
adj->fMap[1][3] = Determinant3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
|
|
|
|
|
adj->fMap[2][3] = -Determinant3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
|
|
|
|
|
adj->fMap[3][3] = Determinant3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
|
|
|
|
|
|
|
|
|
|
adj->NotIdentity();
|
|
|
|
|
return adj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44* hsMatrix44::GetInverse(hsMatrix44* inverse) const
|
|
|
|
|
{
|
|
|
|
|
float det = GetDeterminant();
|
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
|
|
if (det == 0.0f)
|
|
|
|
|
{
|
|
|
|
|
inverse->Reset();
|
|
|
|
|
return inverse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
det = hsInvert(det);
|
|
|
|
|
GetAdjoint(inverse);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<4; i++)
|
|
|
|
|
for (j=0; j<4; j++)
|
|
|
|
|
inverse->fMap[i][j] *= det;
|
|
|
|
|
|
|
|
|
|
return inverse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44& hsMatrix44::SetScale(const hsVector3* pt)
|
|
|
|
|
{
|
|
|
|
|
for (int i =0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
fMap[i][i] = (*pt)[i];
|
|
|
|
|
}
|
|
|
|
|
NotIdentity();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44& hsMatrix44::MakeScaleMat(const hsVector3* pt)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
SetScale(pt);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsMatrix44 &hsMatrix44::MakeTranslateMat(const hsVector3 *trans)
|
|
|
|
|
{
|
|
|
|
|
Reset();
|
|
|
|
|
SetTranslate(trans);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsVector3* hsMatrix44::GetTranslate(hsVector3 *pt) const
|
|
|
|
|
{
|
|
|
|
|
for (int i =0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
(*pt)[i] = fMap[i][3];
|
|
|
|
|
}
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const hsPoint3 hsMatrix44::GetTranslate() const
|
|
|
|
|
{
|
|
|
|
|
hsPoint3 pt;
|
|
|
|
|
for (int i =0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
(pt)[i] = fMap[i][3];
|
|
|
|
|
}
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hsPoint3* hsMatrix44::MapPoints(long count, hsPoint3 points[]) const
|
|
|
|
|
{
|
|
|
|
|
if( !(fFlags & hsMatrix44::kIsIdent) )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for(i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
points[i] = *this * points[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return points;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hsMatrix44::IsIdentity(void)
|
|
|
|
|
{
|
|
|
|
|
bool retVal = true;
|
|
|
|
|
int i, j;
|
|
|
|
|
for( i = 0; i < 4; i++ )
|
|
|
|
|
{
|
|
|
|
|
for( j = 0; j < 4; j++ )
|
|
|
|
|
{
|
|
|
|
|
#if 0 // IDENTITY_CRISIS
|
|
|
|
|
if( i == j)
|
|
|
|
|
{
|
|
|
|
|
if (fMap[i][j] != 1.f)
|
|
|
|
|
{
|
|
|
|
|
NotIdentity();
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( fMap[i][j] != 0 )
|
|
|
|
|
{
|
|
|
|
|
NotIdentity();
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else // IDENTITY_CRISIS
|
|
|
|
|
const float kEPS = 1.e-5f;
|
|
|
|
|
if( i == j)
|
|
|
|
|
{
|
|
|
|
|
if( (fMap[i][j] < 1.f-kEPS) || (fMap[i][j] > 1.f+kEPS) )
|
|
|
|
|
{
|
|
|
|
|
NotIdentity();
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fMap[i][j] = 1.f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( (fMap[i][j] < -kEPS) || (fMap[i][j] > kEPS) )
|
|
|
|
|
{
|
|
|
|
|
NotIdentity();
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fMap[i][j] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // IDENTITY_CRISIS
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( retVal )
|
|
|
|
|
fFlags |= kIsIdent;
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hsMatrix44::GetParity() const
|
|
|
|
|
{
|
|
|
|
|
if( fFlags & kIsIdent )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
hsVector3* rows[3];
|
|
|
|
|
rows[0] = (hsVector3*)&fMap[0][0];
|
|
|
|
|
rows[1] = (hsVector3*)&fMap[1][0];
|
|
|
|
|
rows[2] = (hsVector3*)&fMap[2][0];
|
|
|
|
|
|
|
|
|
|
hsVector3 zeroXone = *rows[0] % *rows[1];
|
|
|
|
|
return zeroXone.InnerProduct(rows[2]) < 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::Read(hsStream *stream)
|
|
|
|
|
{
|
|
|
|
|
if (stream->ReadBool())
|
|
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
for(i=0; i<4; i++)
|
|
|
|
|
for(j=0; j<4; j++)
|
|
|
|
|
fMap[i][j] = stream->ReadLEFloat();
|
|
|
|
|
IsIdentity();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
Reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hsMatrix44::Write(hsStream *stream)
|
|
|
|
|
{
|
|
|
|
|
bool ident = IsIdentity();
|
|
|
|
|
stream->WriteBool(!ident);
|
|
|
|
|
if (!ident)
|
|
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
for(i=0; i<4; i++)
|
|
|
|
|
for(j=0; j<4; j++)
|
|
|
|
|
stream->WriteLEFloat(fMap[i][j]);
|
|
|
|
|
}
|
|
|
|
|
}
|