1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-19 19:59:09 +00:00

Change all CRLF-text files to LF-text files

to match H'uru for patching
This commit is contained in:
rarified
2021-01-28 12:08:00 -07:00
parent 6ae3df25f5
commit a553708b5b
3385 changed files with 1112046 additions and 1112046 deletions

View File

@ -1,442 +1,442 @@
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsAffineParts.h"
#include "../plInterp/hsInterp.h"
#include "hsStream.h"
#include "plProfile.h"
#define PL_OPTIMIZE_COMPOSE
inline void QuatTo3Vectors(const hsQuat& q, hsVector3* const v)
{
v[0][0] = 1.0f - 2.0f*q.fY*q.fY - 2.0f*q.fZ*q.fZ;
v[0][1] = 2.0f*q.fX*q.fY - 2.0f*q.fW*q.fZ;
v[0][2] = 2.0f*q.fX*q.fZ + 2.0f*q.fW*q.fY;
v[1][0] = 2.0f*q.fX*q.fY + 2.0f*q.fW*q.fZ;
v[1][1] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fZ*q.fZ;
v[1][2] = 2.0f*q.fY*q.fZ - 2.0f*q.fW*q.fX;
v[2][0] = 2.0f*q.fX*q.fZ - 2.0f*q.fW*q.fY;
v[2][1] = 2.0f*q.fY*q.fZ + 2.0f*q.fW*q.fX;
v[2][2] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fY*q.fY;
}
inline void QuatTo3VectorsTranspose(const hsQuat& q, hsVector3* const v)
{
v[0][0] = 1.0f - 2.0f*q.fY*q.fY - 2.0f*q.fZ*q.fZ;
v[1][0] = 2.0f*q.fX*q.fY - 2.0f*q.fW*q.fZ;
v[2][0] = 2.0f*q.fX*q.fZ + 2.0f*q.fW*q.fY;
v[0][1] = 2.0f*q.fX*q.fY + 2.0f*q.fW*q.fZ;
v[1][1] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fZ*q.fZ;
v[2][1] = 2.0f*q.fY*q.fZ - 2.0f*q.fW*q.fX;
v[0][2] = 2.0f*q.fX*q.fZ - 2.0f*q.fW*q.fY;
v[1][2] = 2.0f*q.fY*q.fZ + 2.0f*q.fW*q.fX;
v[2][2] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fY*q.fY;
}
//
// Constructors
// Convert from Gems struct for now
//
hsAffineParts::hsAffineParts(gemAffineParts *ap)
{
AP_SET((*this), (*ap));
}
//
//
//
hsAffineParts::hsAffineParts()
{
}
//
//
//
void hsAffineParts::Reset()
{
fT.Set(0,0,0);
fQ.Identity();
fU.Identity();
fK.Set(1,1,1);
fF = 1.0;
}
plProfile_CreateTimer("Compose", "Affine", Compose);
plProfile_CreateTimer("ComposeInv", "Affine", ComposeInv);
//
// Create an affine matrix from the various parts
//
// AffineParts:
// Vector t; /* Translation components */
// Quat q; /* Essential rotation */
// Quat u; /* Stretch rotation */
// Vector k; /* Stretch factors */
// float f; /* Sign of determinant */
//
// A matrix M is decomposed by : M = T F R U K Utranspose.
// T is the translate mat.
// F is +-Identity (to flip the rotation or not).
// R is the rot matrix.
// U is the stretch matrix.
// K is the scale factor matrix.
//
void hsAffineParts::ComposeMatrix(hsMatrix44 *out) const
{
plProfile_BeginTiming(Compose);
#ifndef PL_OPTIMIZE_COMPOSE
// Built U matrix
hsMatrix44 U;
fU.MakeMatrix(&U);
// Build scale factor matrix
hsMatrix44 K;
K.MakeScaleMat(&fK);
// Build Utranspose matrix
hsMatrix44 Utp;
U.GetTranspose(&Utp);
// Build R matrix
hsMatrix44 R;
fQ.MakeMatrix(&R);
// Build flip matrix
// hsAssert(fF == 1.0 || fF == -1.0, "Invalid flip portion of affine parts");
hsMatrix44 F;
if (fF==-1.0)
{
hsVector3 s;
s.Set(-1,-1,-1);
F.MakeScaleMat(&s);
}
else
F.Reset();
// Build translate matrix
hsMatrix44 T;
T.MakeTranslateMat(&fT);
//
// Concat mats
//
*out = K * Utp;
*out = U * (*out);
*out = R * (*out); // Q
*out = F * (*out);
*out = T * (*out); // Translate happens last
#else // PL_OPTIMIZE_COMPOSE
// M = T F R U K Ut,
// but these are mostly very sparse matrices. So rather
// than construct the full 6 matrices and concatenate them,
// we'll work out by hand what the non-zero results will be.
// T = |1 0 0 Tx|
// |0 1 0 Ty|
// |0 0 1 Tz|
// F = |f 0 0 0|
// |0 f 0 0|
// |0 0 f 0|, where f is either 1 or -1
// R = |R00 R01 R02 0|
// |R10 R11 R12 0|
// |R20 R21 R22 0|
// U = |U00 U01 U02 0|
// |U10 U11 U12 0|
// |U20 U21 U22 0|
// K = |Sx 0 0 0|
// |0 Sy 0 0|
// |0 0 Sz 0|
// Ut = |U00 U10 U20 0|
// |U01 U11 U21 0|
// |U02 U12 U22 0|, where Uij is from matrix U
//
// So, K * Ut =
// |Sx*U00 Sx*U10 Sx*U20 0|
// |Sy*U01 Sy*U11 Sy*U21 0|
// |Sz*U02 Sz*U12 Sz*U22 0|
//
// U * (K * Ut) =
// | U0 dot S*U0 U0 dot S*U1 U0 dot S*U2 0|
// | U1 dot S*U0 U1 dot S*U1 U1 dot S*U2 0|
// | U2 dot S*U0 U2 dot S*U1 U2 dot S*U2 0|
//
// Let's call that matrix UK
//
// Now R * U * K * Ut = R * UK =
// | R0 dot UKc0 R0 dot UKc1 R0 dot UKc2 0|
// | R1 dot UKc0 R1 dot UKc1 R1 dot UKc2 0|
// | R2 dot UKc0 R2 dot UKc1 R2 dot UKc2 0|, where UKci is column i from UK
//
// if f is -1, we negate the matrix we have so far, else we don't. We can
// accomplish this cleanly by just negating the scale vector S if f == -1.
//
// Since the translate is last, we can just stuff it into the 4th column.
//
// Since we only ever use UK as column vectors, we'll just construct it
// into 3 vectors representing the columns.
//
// The quat MakeMatrix function is pretty efficient, but it does a little more work
// than it has to filling out the whole matrix when we only need the 3x3 rotation,
// and we'd rather have it in the form of vectors anyway, so we'll use our own
// quat to 3 vectors function here.
hsVector3 U[3];
QuatTo3Vectors(fU, U);
int i, j;
hsVector3 UKt[3];
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
// SU[j] = (fK.fX * U[j].fX, fK.fY * U[j].fY, fK.fZ * U[j].fZ)
UKt[j][i] = U[i].fX * fK.fX * U[j].fX
+ U[i].fY * fK.fY * U[j].fY
+ U[i].fZ * fK.fZ * U[j].fZ;
}
}
hsVector3 R[3];
QuatTo3Vectors(fQ, R);
hsScalar f = fF < 0 ? -1.f : 1.f;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
out->fMap[i][j] = R[i].InnerProduct(UKt[j]) * f;
}
out->fMap[i][3] = fT[i];
}
out->fMap[3][0] = out->fMap[3][1] = out->fMap[3][2] = 0.f;
out->fMap[3][3] = 1.f;
out->NotIdentity();
#endif // PL_OPTIMIZE_COMPOSE
plProfile_EndTiming(Compose);
}
void hsAffineParts::ComposeInverseMatrix(hsMatrix44 *out) const
{
plProfile_BeginTiming(Compose);
#ifndef PL_OPTIMIZE_COMPOSE
// Built U matrix
hsMatrix44 U;
fU.Conjugate().MakeMatrix(&U);
// Build scale factor matrix
hsMatrix44 K;
hsVector3 invK;
invK.Set(hsScalarInvert(fK.fX),hsScalarInvert(fK.fY),hsScalarInvert(fK.fZ));
K.MakeScaleMat(&invK);
// Build Utranspose matrix
hsMatrix44 Utp;
U.GetTranspose(&Utp);
// Build R matrix
hsMatrix44 R;
fQ.Conjugate().MakeMatrix(&R);
// Build flip matrix
// hsAssert(fF == 1.0 || fF == -1.0, "Invalid flip portion of affine parts");
hsMatrix44 F;
if (fF==-1.0)
{
hsVector3 s;
s.Set(-1,-1,-1);
F.MakeScaleMat(&s);
}
else
F.Reset();
// Build translate matrix
hsMatrix44 T;
T.MakeTranslateMat(&-fT);
//
// Concat mats
//
*out = Utp * K;
*out = (*out) * U;
*out = (*out) * R;
*out = (*out) * F;
*out = (*out) * T;
#else // PL_OPTIMIZE_COMPOSE
// Same kind of thing here, except now M = Ut K U R F T
// and again
// T = |1 0 0 Tx|
// |0 1 0 Ty|
// |0 0 1 Tz|
// F = |f 0 0 0|
// |0 f 0 0|
// |0 0 f 0|, where f is either 1 or -1
// R = |R00 R01 R02 0|
// |R10 R11 R12 0|
// |R20 R21 R22 0|
// U = |U00 U01 U02 0|
// |U10 U11 U12 0|
// |U20 U21 U22 0|
// K = |Sx 0 0 0|
// |0 Sy 0 0|
// |0 0 Sz 0|
// Ut = |U00 U10 U20 0|
// |U01 U11 U21 0|
// |U02 U12 U22 0|, where Uij is from matrix U
//
// So, Ut * K =
// |U00*Sx U10*Sy U20*Sz 0|
// |U01*Sx U11*Sy U21*Sz 0|
// |U02*Sx U12*Sy U22*Sz 0|
//
// (Ut * K) * U = UK =
// |Ut0*S dot Ut0 Ut0*S dot Ut1 Ut0*S dot Ut2 0|
// |Ut1*S dot Ut0 Ut1*S dot Ut1 Ut1*S dot Ut2 0|
// |Ut2*S dot Ut0 Ut2*S dot Ut1 Ut2*S dot Ut2 0|
//
// (((Ut * K) * U) * R)[i][j] = UK[i] dot Rc[j]
//
// Again we'll stuff the flip into the scale.
//
// Now, because the T is on the other end of the concat (closest
// to the vertex), we can't just stuff it in. If Mr is the
// rotation part of the final matrix (Ut * K * U * R * F), then
// the translation components M[i][3] = Mr[i] dot T.
//
//
hsVector3 Ut[3];
QuatTo3VectorsTranspose(fU.Conjugate(), Ut);
int i, j;
hsVector3 invK;
invK.Set(hsScalarInvert(fK.fX),hsScalarInvert(fK.fY),hsScalarInvert(fK.fZ));
hsVector3 UK[3];
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
// SUt[i] = (Ut[i].fX * invK.fX, Ut[i].fY * invK.fY, Ut[i].fZ * invK.fZ)
// So SUt[i].InnerProduct(Ut[j]) ==
// Ut[i].fX * invK.fX * Ut[j].fX
// + Ut[i].fY * invK.fY * Ut[j].fY
// + Ut[i].fZ * invK.fZ * Ut[j].fZ
UK[i][j] = Ut[i].fX * invK.fX * Ut[j].fX
+ Ut[i].fY * invK.fY * Ut[j].fY
+ Ut[i].fZ * invK.fZ * Ut[j].fZ;
}
}
hsVector3 Rt[3];
QuatTo3VectorsTranspose(fQ.Conjugate(), Rt);
hsScalar f = fF < 0 ? -1.f : 1.f;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
out->fMap[i][j] = UK[i].InnerProduct(Rt[j]) * f;
}
out->fMap[i][3] = -(fT.InnerProduct((hsPoint3*)(&out->fMap[i])));
}
out->fMap[3][0] = out->fMap[3][1] = out->fMap[3][2] = 0.f;
out->fMap[3][3] = 1.f;
out->NotIdentity();
#endif // PL_OPTIMIZE_COMPOSE
plProfile_EndTiming(Compose);
}
//
// Given 2 affineparts structs and a p value (between 0-1),
// compute a new affine parts.
//
void hsAffineParts::SetFromInterp(const hsAffineParts &ap1, const hsAffineParts &ap2, float p)
{
hsAssert(p>=0.0 && p<=1.0, "Interpolate param must be 0-1");
#if 0
// Debug
float rad1,rad2, rad3;
hsVector3 axis1, axis2, axis3;
k1->fQ.GetAngleAxis(&rad1, &axis1);
k2->fQ.GetAngleAxis(&rad2, &axis2);
fQ.GetAngleAxis(&rad3, &axis3);
#endif
hsInterp::LinInterp(&ap1, &ap2, p, this);
}
//
// Read
//
void hsAffineParts::Read(hsStream *stream)
{
fT.Read(stream);
fQ.Read(stream);
fU.Read(stream);
fK.Read(stream);
fF = stream->ReadSwapFloat();
}
//
// Write
//
void hsAffineParts::Write(hsStream *stream)
{
fT.Write(stream);
fQ.Write(stream);
fU.Write(stream);
fK.Write(stream);
stream->WriteSwapFloat(fF);
}
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsAffineParts.h"
#include "../plInterp/hsInterp.h"
#include "hsStream.h"
#include "plProfile.h"
#define PL_OPTIMIZE_COMPOSE
inline void QuatTo3Vectors(const hsQuat& q, hsVector3* const v)
{
v[0][0] = 1.0f - 2.0f*q.fY*q.fY - 2.0f*q.fZ*q.fZ;
v[0][1] = 2.0f*q.fX*q.fY - 2.0f*q.fW*q.fZ;
v[0][2] = 2.0f*q.fX*q.fZ + 2.0f*q.fW*q.fY;
v[1][0] = 2.0f*q.fX*q.fY + 2.0f*q.fW*q.fZ;
v[1][1] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fZ*q.fZ;
v[1][2] = 2.0f*q.fY*q.fZ - 2.0f*q.fW*q.fX;
v[2][0] = 2.0f*q.fX*q.fZ - 2.0f*q.fW*q.fY;
v[2][1] = 2.0f*q.fY*q.fZ + 2.0f*q.fW*q.fX;
v[2][2] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fY*q.fY;
}
inline void QuatTo3VectorsTranspose(const hsQuat& q, hsVector3* const v)
{
v[0][0] = 1.0f - 2.0f*q.fY*q.fY - 2.0f*q.fZ*q.fZ;
v[1][0] = 2.0f*q.fX*q.fY - 2.0f*q.fW*q.fZ;
v[2][0] = 2.0f*q.fX*q.fZ + 2.0f*q.fW*q.fY;
v[0][1] = 2.0f*q.fX*q.fY + 2.0f*q.fW*q.fZ;
v[1][1] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fZ*q.fZ;
v[2][1] = 2.0f*q.fY*q.fZ - 2.0f*q.fW*q.fX;
v[0][2] = 2.0f*q.fX*q.fZ - 2.0f*q.fW*q.fY;
v[1][2] = 2.0f*q.fY*q.fZ + 2.0f*q.fW*q.fX;
v[2][2] = 1.0f - 2.0f*q.fX*q.fX - 2.0f*q.fY*q.fY;
}
//
// Constructors
// Convert from Gems struct for now
//
hsAffineParts::hsAffineParts(gemAffineParts *ap)
{
AP_SET((*this), (*ap));
}
//
//
//
hsAffineParts::hsAffineParts()
{
}
//
//
//
void hsAffineParts::Reset()
{
fT.Set(0,0,0);
fQ.Identity();
fU.Identity();
fK.Set(1,1,1);
fF = 1.0;
}
plProfile_CreateTimer("Compose", "Affine", Compose);
plProfile_CreateTimer("ComposeInv", "Affine", ComposeInv);
//
// Create an affine matrix from the various parts
//
// AffineParts:
// Vector t; /* Translation components */
// Quat q; /* Essential rotation */
// Quat u; /* Stretch rotation */
// Vector k; /* Stretch factors */
// float f; /* Sign of determinant */
//
// A matrix M is decomposed by : M = T F R U K Utranspose.
// T is the translate mat.
// F is +-Identity (to flip the rotation or not).
// R is the rot matrix.
// U is the stretch matrix.
// K is the scale factor matrix.
//
void hsAffineParts::ComposeMatrix(hsMatrix44 *out) const
{
plProfile_BeginTiming(Compose);
#ifndef PL_OPTIMIZE_COMPOSE
// Built U matrix
hsMatrix44 U;
fU.MakeMatrix(&U);
// Build scale factor matrix
hsMatrix44 K;
K.MakeScaleMat(&fK);
// Build Utranspose matrix
hsMatrix44 Utp;
U.GetTranspose(&Utp);
// Build R matrix
hsMatrix44 R;
fQ.MakeMatrix(&R);
// Build flip matrix
// hsAssert(fF == 1.0 || fF == -1.0, "Invalid flip portion of affine parts");
hsMatrix44 F;
if (fF==-1.0)
{
hsVector3 s;
s.Set(-1,-1,-1);
F.MakeScaleMat(&s);
}
else
F.Reset();
// Build translate matrix
hsMatrix44 T;
T.MakeTranslateMat(&fT);
//
// Concat mats
//
*out = K * Utp;
*out = U * (*out);
*out = R * (*out); // Q
*out = F * (*out);
*out = T * (*out); // Translate happens last
#else // PL_OPTIMIZE_COMPOSE
// M = T F R U K Ut,
// but these are mostly very sparse matrices. So rather
// than construct the full 6 matrices and concatenate them,
// we'll work out by hand what the non-zero results will be.
// T = |1 0 0 Tx|
// |0 1 0 Ty|
// |0 0 1 Tz|
// F = |f 0 0 0|
// |0 f 0 0|
// |0 0 f 0|, where f is either 1 or -1
// R = |R00 R01 R02 0|
// |R10 R11 R12 0|
// |R20 R21 R22 0|
// U = |U00 U01 U02 0|
// |U10 U11 U12 0|
// |U20 U21 U22 0|
// K = |Sx 0 0 0|
// |0 Sy 0 0|
// |0 0 Sz 0|
// Ut = |U00 U10 U20 0|
// |U01 U11 U21 0|
// |U02 U12 U22 0|, where Uij is from matrix U
//
// So, K * Ut =
// |Sx*U00 Sx*U10 Sx*U20 0|
// |Sy*U01 Sy*U11 Sy*U21 0|
// |Sz*U02 Sz*U12 Sz*U22 0|
//
// U * (K * Ut) =
// | U0 dot S*U0 U0 dot S*U1 U0 dot S*U2 0|
// | U1 dot S*U0 U1 dot S*U1 U1 dot S*U2 0|
// | U2 dot S*U0 U2 dot S*U1 U2 dot S*U2 0|
//
// Let's call that matrix UK
//
// Now R * U * K * Ut = R * UK =
// | R0 dot UKc0 R0 dot UKc1 R0 dot UKc2 0|
// | R1 dot UKc0 R1 dot UKc1 R1 dot UKc2 0|
// | R2 dot UKc0 R2 dot UKc1 R2 dot UKc2 0|, where UKci is column i from UK
//
// if f is -1, we negate the matrix we have so far, else we don't. We can
// accomplish this cleanly by just negating the scale vector S if f == -1.
//
// Since the translate is last, we can just stuff it into the 4th column.
//
// Since we only ever use UK as column vectors, we'll just construct it
// into 3 vectors representing the columns.
//
// The quat MakeMatrix function is pretty efficient, but it does a little more work
// than it has to filling out the whole matrix when we only need the 3x3 rotation,
// and we'd rather have it in the form of vectors anyway, so we'll use our own
// quat to 3 vectors function here.
hsVector3 U[3];
QuatTo3Vectors(fU, U);
int i, j;
hsVector3 UKt[3];
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
// SU[j] = (fK.fX * U[j].fX, fK.fY * U[j].fY, fK.fZ * U[j].fZ)
UKt[j][i] = U[i].fX * fK.fX * U[j].fX
+ U[i].fY * fK.fY * U[j].fY
+ U[i].fZ * fK.fZ * U[j].fZ;
}
}
hsVector3 R[3];
QuatTo3Vectors(fQ, R);
hsScalar f = fF < 0 ? -1.f : 1.f;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
out->fMap[i][j] = R[i].InnerProduct(UKt[j]) * f;
}
out->fMap[i][3] = fT[i];
}
out->fMap[3][0] = out->fMap[3][1] = out->fMap[3][2] = 0.f;
out->fMap[3][3] = 1.f;
out->NotIdentity();
#endif // PL_OPTIMIZE_COMPOSE
plProfile_EndTiming(Compose);
}
void hsAffineParts::ComposeInverseMatrix(hsMatrix44 *out) const
{
plProfile_BeginTiming(Compose);
#ifndef PL_OPTIMIZE_COMPOSE
// Built U matrix
hsMatrix44 U;
fU.Conjugate().MakeMatrix(&U);
// Build scale factor matrix
hsMatrix44 K;
hsVector3 invK;
invK.Set(hsScalarInvert(fK.fX),hsScalarInvert(fK.fY),hsScalarInvert(fK.fZ));
K.MakeScaleMat(&invK);
// Build Utranspose matrix
hsMatrix44 Utp;
U.GetTranspose(&Utp);
// Build R matrix
hsMatrix44 R;
fQ.Conjugate().MakeMatrix(&R);
// Build flip matrix
// hsAssert(fF == 1.0 || fF == -1.0, "Invalid flip portion of affine parts");
hsMatrix44 F;
if (fF==-1.0)
{
hsVector3 s;
s.Set(-1,-1,-1);
F.MakeScaleMat(&s);
}
else
F.Reset();
// Build translate matrix
hsMatrix44 T;
T.MakeTranslateMat(&-fT);
//
// Concat mats
//
*out = Utp * K;
*out = (*out) * U;
*out = (*out) * R;
*out = (*out) * F;
*out = (*out) * T;
#else // PL_OPTIMIZE_COMPOSE
// Same kind of thing here, except now M = Ut K U R F T
// and again
// T = |1 0 0 Tx|
// |0 1 0 Ty|
// |0 0 1 Tz|
// F = |f 0 0 0|
// |0 f 0 0|
// |0 0 f 0|, where f is either 1 or -1
// R = |R00 R01 R02 0|
// |R10 R11 R12 0|
// |R20 R21 R22 0|
// U = |U00 U01 U02 0|
// |U10 U11 U12 0|
// |U20 U21 U22 0|
// K = |Sx 0 0 0|
// |0 Sy 0 0|
// |0 0 Sz 0|
// Ut = |U00 U10 U20 0|
// |U01 U11 U21 0|
// |U02 U12 U22 0|, where Uij is from matrix U
//
// So, Ut * K =
// |U00*Sx U10*Sy U20*Sz 0|
// |U01*Sx U11*Sy U21*Sz 0|
// |U02*Sx U12*Sy U22*Sz 0|
//
// (Ut * K) * U = UK =
// |Ut0*S dot Ut0 Ut0*S dot Ut1 Ut0*S dot Ut2 0|
// |Ut1*S dot Ut0 Ut1*S dot Ut1 Ut1*S dot Ut2 0|
// |Ut2*S dot Ut0 Ut2*S dot Ut1 Ut2*S dot Ut2 0|
//
// (((Ut * K) * U) * R)[i][j] = UK[i] dot Rc[j]
//
// Again we'll stuff the flip into the scale.
//
// Now, because the T is on the other end of the concat (closest
// to the vertex), we can't just stuff it in. If Mr is the
// rotation part of the final matrix (Ut * K * U * R * F), then
// the translation components M[i][3] = Mr[i] dot T.
//
//
hsVector3 Ut[3];
QuatTo3VectorsTranspose(fU.Conjugate(), Ut);
int i, j;
hsVector3 invK;
invK.Set(hsScalarInvert(fK.fX),hsScalarInvert(fK.fY),hsScalarInvert(fK.fZ));
hsVector3 UK[3];
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
// SUt[i] = (Ut[i].fX * invK.fX, Ut[i].fY * invK.fY, Ut[i].fZ * invK.fZ)
// So SUt[i].InnerProduct(Ut[j]) ==
// Ut[i].fX * invK.fX * Ut[j].fX
// + Ut[i].fY * invK.fY * Ut[j].fY
// + Ut[i].fZ * invK.fZ * Ut[j].fZ
UK[i][j] = Ut[i].fX * invK.fX * Ut[j].fX
+ Ut[i].fY * invK.fY * Ut[j].fY
+ Ut[i].fZ * invK.fZ * Ut[j].fZ;
}
}
hsVector3 Rt[3];
QuatTo3VectorsTranspose(fQ.Conjugate(), Rt);
hsScalar f = fF < 0 ? -1.f : 1.f;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
out->fMap[i][j] = UK[i].InnerProduct(Rt[j]) * f;
}
out->fMap[i][3] = -(fT.InnerProduct((hsPoint3*)(&out->fMap[i])));
}
out->fMap[3][0] = out->fMap[3][1] = out->fMap[3][2] = 0.f;
out->fMap[3][3] = 1.f;
out->NotIdentity();
#endif // PL_OPTIMIZE_COMPOSE
plProfile_EndTiming(Compose);
}
//
// Given 2 affineparts structs and a p value (between 0-1),
// compute a new affine parts.
//
void hsAffineParts::SetFromInterp(const hsAffineParts &ap1, const hsAffineParts &ap2, float p)
{
hsAssert(p>=0.0 && p<=1.0, "Interpolate param must be 0-1");
#if 0
// Debug
float rad1,rad2, rad3;
hsVector3 axis1, axis2, axis3;
k1->fQ.GetAngleAxis(&rad1, &axis1);
k2->fQ.GetAngleAxis(&rad2, &axis2);
fQ.GetAngleAxis(&rad3, &axis3);
#endif
hsInterp::LinInterp(&ap1, &ap2, p, this);
}
//
// Read
//
void hsAffineParts::Read(hsStream *stream)
{
fT.Read(stream);
fQ.Read(stream);
fU.Read(stream);
fK.Read(stream);
fF = stream->ReadSwapFloat();
}
//
// Write
//
void hsAffineParts::Write(hsStream *stream)
{
fT.Write(stream);
fQ.Write(stream);
fU.Write(stream);
fK.Write(stream);
stream->WriteSwapFloat(fF);
}

View File

@ -1,89 +1,89 @@
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HSAFFINEPARTS_inc
#define HSAFFINEPARTS_inc
#include "hsGeometry3.h"
#include "hsQuat.h"
#include "mat_decomp.h"
class hsAffineParts
{
public:
// Constructors
hsAffineParts(gemAffineParts *); // Convert from Gems struct for now
hsAffineParts();
void Reset();
hsVector3 fT; /* Translation components */
hsQuat fQ; /* Essential rotation */
hsQuat fU; /* Stretch rotation */
hsVector3 fK; /* Stretch factors */
float fF; /* Sign of determinant */
void ComposeMatrix(hsMatrix44 *out) const;
void ComposeInverseMatrix(hsMatrix44 *out) const;
void SetFromInterp(const hsAffineParts &ap1, const hsAffineParts &ap2, float t);
void Read(hsStream *);
void Write(hsStream *);
int operator==(const hsAffineParts& a) const
{ return (fT == a.fT && fQ == a.fQ && fU == a.fU && fK == a.fK && fF == a.fF); }
};
//
// General set macro can also be used for 3DSMax struct
//
#define AP_SET(dst, src) \
{ \
dst.fT.Set(src.t.x, src.t.y, src.t.z); \
dst.fQ.Set(src.q.x, src.q.y, src.q.z, src.q.w); \
dst.fU.Set(src.u.x, src.u.y, src.u.z, src.u.w); \
dst.fK.Set(src.k.x, src.k.y, src.k.z); \
dst.fF = src.f; \
}
#endif
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HSAFFINEPARTS_inc
#define HSAFFINEPARTS_inc
#include "hsGeometry3.h"
#include "hsQuat.h"
#include "mat_decomp.h"
class hsAffineParts
{
public:
// Constructors
hsAffineParts(gemAffineParts *); // Convert from Gems struct for now
hsAffineParts();
void Reset();
hsVector3 fT; /* Translation components */
hsQuat fQ; /* Essential rotation */
hsQuat fU; /* Stretch rotation */
hsVector3 fK; /* Stretch factors */
float fF; /* Sign of determinant */
void ComposeMatrix(hsMatrix44 *out) const;
void ComposeInverseMatrix(hsMatrix44 *out) const;
void SetFromInterp(const hsAffineParts &ap1, const hsAffineParts &ap2, float t);
void Read(hsStream *);
void Write(hsStream *);
int operator==(const hsAffineParts& a) const
{ return (fT == a.fT && fQ == a.fQ && fU == a.fU && fK == a.fK && fF == a.fF); }
};
//
// General set macro can also be used for 3DSMax struct
//
#define AP_SET(dst, src) \
{ \
dst.fT.Set(src.t.x, src.t.y, src.t.z); \
dst.fQ.Set(src.q.x, src.q.y, src.q.z, src.q.w); \
dst.fU.Set(src.u.x, src.u.y, src.u.z, src.u.w); \
dst.fK.Set(src.k.x, src.k.y, src.k.z); \
dst.fF = src.f; \
}
#endif

View File

@ -1,228 +1,228 @@
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//
//////////////////////////////////////////////////////////////////////////
// EULER STUFF
// See Gems IV, Ken Shoemake
//////////////////////////////////////////////////////////////////////////
//
#include <float.h> // for FLT_EPSILON
#include "hsEuler.h"
#include "hsQuat.h"
#include "hsMatrix44.h"
enum QuatPart
{
X, Y, Z, W
};
//
// Construct quaternion from Euler angles (in radians).
//
void hsEuler::GetQuat(hsQuat* qu)
{
double a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
int i,j,k,h,n,s,f;
hsEuler ea=*this; // copy
EulGetOrd(ea.fOrder,i,j,k,h,n,s,f);
if (f==EulFrmR)
{
hsScalar t = ea.fX; ea.fX = ea.fZ; ea.fZ = t;
}
if (n==EulParOdd)
ea.fY = -ea.fY;
ti = ea.fX*0.5; tj = ea.fY*0.5; th = ea.fZ*0.5;
ci = cos(ti); cj = cos(tj); ch = cos(th);
si = sin(ti); sj = sin(tj); sh = sin(th);
cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
if (s==EulRepYes)
{
a[i] = cj*(cs + sc); /* Could speed up with */
a[j] = sj*(cc + ss); /* trig identities. */
a[k] = sj*(cs - sc);
qu->fW = static_cast<float>(cj*(cc - ss));
}
else
{
a[i] = cj*sc - sj*cs;
a[j] = cj*ss + sj*cc;
a[k] = cj*cs - sj*sc;
qu->fW = static_cast<float>(cj*cc + sj*ss);
}
if (n==EulParOdd)
a[j] = -a[j];
qu->fX = static_cast<float>(a[X]);
qu->fY = static_cast<float>(a[Y]);
qu->fZ = static_cast<float>(a[Z]);
}
//
// Construct matrix from Euler angles (in radians).
//
void hsEuler::GetMatrix44(hsMatrix44* mat)
{
double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
int i,j,k,h,n,s,f;
hsEuler ea=*this; // copy
EulGetOrd(ea.fOrder,i,j,k,h,n,s,f);
if (f==EulFrmR)
{
hsScalar t = ea.fX; ea.fX = ea.fZ; ea.fZ = t;
}
if (n==EulParOdd)
{
ea.fX = -ea.fX; ea.fY = -ea.fY; ea.fZ = -ea.fZ;
}
ti = ea.fX; tj = ea.fY; th = ea.fZ;
ci = cos(ti); cj = cos(tj); ch = cos(th);
si = sin(ti); sj = sin(tj); sh = sin(th);
cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
if (s==EulRepYes)
{
mat->fMap[i][i] = static_cast<float>(cj);
mat->fMap[i][j] = static_cast<float>(sj*si);
mat->fMap[i][k] = static_cast<float>(sj*ci);
mat->fMap[j][i] = static_cast<float>(sj*sh);
mat->fMap[j][j] = static_cast<float>(-cj*ss+cc);
mat->fMap[j][k] = static_cast<float>(-cj*cs-sc);
mat->fMap[k][i] = static_cast<float>(-sj*ch);
mat->fMap[k][j] = static_cast<float>(cj*sc+cs);
mat->fMap[k][k] = static_cast<float>(cj*cc-ss);
}
else
{
mat->fMap[i][i] = static_cast<float>(cj*ch);
mat->fMap[i][j] = static_cast<float>(sj*sc-cs);
mat->fMap[i][k] = static_cast<float>(sj*cc+ss);
mat->fMap[j][i] = static_cast<float>(cj*sh);
mat->fMap[j][j] = static_cast<float>(sj*ss+cc);
mat->fMap[j][k] = static_cast<float>(sj*cs-sc);
mat->fMap[k][i] = static_cast<float>(-sj);
mat->fMap[k][j] = static_cast<float>(cj*si);
mat->fMap[k][k] = static_cast<float>(cj*ci);
}
mat->fMap[W][X]=mat->fMap[W][Y]=mat->fMap[W][Z]=mat->fMap[X][W]=mat->fMap[Y][W]=mat->fMap[Z][W]=0.0;
mat->fMap[W][W]=1.0;
}
//
// Convert matrix to Euler angles (in radians)
//
void hsEuler::SetFromMatrix44(const hsMatrix44* mat, UInt32 order)
{
int i,j,k,h,n,s,f;
EulGetOrd(order,i,j,k,h,n,s,f);
if (s==EulRepYes)
{
double sy = sqrt(mat->fMap[i][j]*mat->fMap[i][j] + mat->fMap[i][k]*mat->fMap[i][k]);
if (sy > 16*FLT_EPSILON)
{
fX = static_cast<float>(atan2(mat->fMap[i][j], mat->fMap[i][k]));
fY = static_cast<float>(atan2(sy, (double)mat->fMap[i][i]));
fZ = static_cast<float>(atan2(mat->fMap[j][i], -mat->fMap[k][i]));
} else
{
fX = static_cast<float>(atan2(-mat->fMap[j][k], mat->fMap[j][j]));
fY = static_cast<float>(atan2(sy, (double)mat->fMap[i][i]));
fZ = 0;
}
}
else
{
double cy = sqrt(mat->fMap[i][i]*mat->fMap[i][i] + mat->fMap[j][i]*mat->fMap[j][i]);
if (cy > 16*FLT_EPSILON)
{
fX = static_cast<float>(atan2(mat->fMap[k][j], mat->fMap[k][k]));
fY = static_cast<float>(atan2((double)(-mat->fMap[k][i]), cy));
fZ = static_cast<float>(atan2(mat->fMap[j][i], mat->fMap[i][i]));
}
else
{
fX = static_cast<float>(atan2(-mat->fMap[j][k], mat->fMap[j][j]));
fY = static_cast<float>(atan2((double)(-mat->fMap[k][i]), cy));
fZ = 0;
}
}
if (n==EulParOdd)
{
fX = -fX; fY = - fY; fZ = -fZ;
}
if (f==EulFrmR)
{
hsScalar t = fX; fX = fZ; fZ = t;
}
fOrder = order;
}
//
// Convert quaternion to Euler angles (in radians)
//
void hsEuler::SetFromQuat(const hsQuat* q, UInt32 order)
{
hsMatrix44 mat;
double Nq = q->fX*q->fX+q->fY*q->fY+q->fZ*q->fZ+q->fW*q->fW;
double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
double xs = q->fX*s, ys = q->fY*s, zs = q->fZ*s;
double wx = q->fW*xs, wy = q->fW*ys, wz = q->fW*zs;
double xx = q->fX*xs, xy = q->fX*ys, xz = q->fX*zs;
double yy = q->fY*ys, yz = q->fY*zs, zz = q->fZ*zs;
mat.fMap[X][X] = static_cast<float>(1.0 - (yy + zz));
mat.fMap[X][Y] = static_cast<float>(xy - wz);
mat.fMap[X][Z] = static_cast<float>(xz + wy);
mat.fMap[Y][X] = static_cast<float>(xy + wz);
mat.fMap[Y][Y] = static_cast<float>(1.0 - (xx + zz));
mat.fMap[Y][Z] = static_cast<float>(yz - wx);
mat.fMap[Z][X] = static_cast<float>(xz - wy);
mat.fMap[Z][Y] = static_cast<float>(yz + wx);
mat.fMap[Z][Z] = static_cast<float>(1.0 - (xx + yy));
mat.fMap[W][X] = mat.fMap[W][Y] = mat.fMap[W][Z] =
mat.fMap[X][W] = mat.fMap[Y][W] = mat.fMap[Z][W] = 0.0;
mat.fMap[W][W] = 1.0;
SetFromMatrix44(&mat, order);
}
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//
//////////////////////////////////////////////////////////////////////////
// EULER STUFF
// See Gems IV, Ken Shoemake
//////////////////////////////////////////////////////////////////////////
//
#include <float.h> // for FLT_EPSILON
#include "hsEuler.h"
#include "hsQuat.h"
#include "hsMatrix44.h"
enum QuatPart
{
X, Y, Z, W
};
//
// Construct quaternion from Euler angles (in radians).
//
void hsEuler::GetQuat(hsQuat* qu)
{
double a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
int i,j,k,h,n,s,f;
hsEuler ea=*this; // copy
EulGetOrd(ea.fOrder,i,j,k,h,n,s,f);
if (f==EulFrmR)
{
hsScalar t = ea.fX; ea.fX = ea.fZ; ea.fZ = t;
}
if (n==EulParOdd)
ea.fY = -ea.fY;
ti = ea.fX*0.5; tj = ea.fY*0.5; th = ea.fZ*0.5;
ci = cos(ti); cj = cos(tj); ch = cos(th);
si = sin(ti); sj = sin(tj); sh = sin(th);
cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
if (s==EulRepYes)
{
a[i] = cj*(cs + sc); /* Could speed up with */
a[j] = sj*(cc + ss); /* trig identities. */
a[k] = sj*(cs - sc);
qu->fW = static_cast<float>(cj*(cc - ss));
}
else
{
a[i] = cj*sc - sj*cs;
a[j] = cj*ss + sj*cc;
a[k] = cj*cs - sj*sc;
qu->fW = static_cast<float>(cj*cc + sj*ss);
}
if (n==EulParOdd)
a[j] = -a[j];
qu->fX = static_cast<float>(a[X]);
qu->fY = static_cast<float>(a[Y]);
qu->fZ = static_cast<float>(a[Z]);
}
//
// Construct matrix from Euler angles (in radians).
//
void hsEuler::GetMatrix44(hsMatrix44* mat)
{
double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
int i,j,k,h,n,s,f;
hsEuler ea=*this; // copy
EulGetOrd(ea.fOrder,i,j,k,h,n,s,f);
if (f==EulFrmR)
{
hsScalar t = ea.fX; ea.fX = ea.fZ; ea.fZ = t;
}
if (n==EulParOdd)
{
ea.fX = -ea.fX; ea.fY = -ea.fY; ea.fZ = -ea.fZ;
}
ti = ea.fX; tj = ea.fY; th = ea.fZ;
ci = cos(ti); cj = cos(tj); ch = cos(th);
si = sin(ti); sj = sin(tj); sh = sin(th);
cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
if (s==EulRepYes)
{
mat->fMap[i][i] = static_cast<float>(cj);
mat->fMap[i][j] = static_cast<float>(sj*si);
mat->fMap[i][k] = static_cast<float>(sj*ci);
mat->fMap[j][i] = static_cast<float>(sj*sh);
mat->fMap[j][j] = static_cast<float>(-cj*ss+cc);
mat->fMap[j][k] = static_cast<float>(-cj*cs-sc);
mat->fMap[k][i] = static_cast<float>(-sj*ch);
mat->fMap[k][j] = static_cast<float>(cj*sc+cs);
mat->fMap[k][k] = static_cast<float>(cj*cc-ss);
}
else
{
mat->fMap[i][i] = static_cast<float>(cj*ch);
mat->fMap[i][j] = static_cast<float>(sj*sc-cs);
mat->fMap[i][k] = static_cast<float>(sj*cc+ss);
mat->fMap[j][i] = static_cast<float>(cj*sh);
mat->fMap[j][j] = static_cast<float>(sj*ss+cc);
mat->fMap[j][k] = static_cast<float>(sj*cs-sc);
mat->fMap[k][i] = static_cast<float>(-sj);
mat->fMap[k][j] = static_cast<float>(cj*si);
mat->fMap[k][k] = static_cast<float>(cj*ci);
}
mat->fMap[W][X]=mat->fMap[W][Y]=mat->fMap[W][Z]=mat->fMap[X][W]=mat->fMap[Y][W]=mat->fMap[Z][W]=0.0;
mat->fMap[W][W]=1.0;
}
//
// Convert matrix to Euler angles (in radians)
//
void hsEuler::SetFromMatrix44(const hsMatrix44* mat, UInt32 order)
{
int i,j,k,h,n,s,f;
EulGetOrd(order,i,j,k,h,n,s,f);
if (s==EulRepYes)
{
double sy = sqrt(mat->fMap[i][j]*mat->fMap[i][j] + mat->fMap[i][k]*mat->fMap[i][k]);
if (sy > 16*FLT_EPSILON)
{
fX = static_cast<float>(atan2(mat->fMap[i][j], mat->fMap[i][k]));
fY = static_cast<float>(atan2(sy, (double)mat->fMap[i][i]));
fZ = static_cast<float>(atan2(mat->fMap[j][i], -mat->fMap[k][i]));
} else
{
fX = static_cast<float>(atan2(-mat->fMap[j][k], mat->fMap[j][j]));
fY = static_cast<float>(atan2(sy, (double)mat->fMap[i][i]));
fZ = 0;
}
}
else
{
double cy = sqrt(mat->fMap[i][i]*mat->fMap[i][i] + mat->fMap[j][i]*mat->fMap[j][i]);
if (cy > 16*FLT_EPSILON)
{
fX = static_cast<float>(atan2(mat->fMap[k][j], mat->fMap[k][k]));
fY = static_cast<float>(atan2((double)(-mat->fMap[k][i]), cy));
fZ = static_cast<float>(atan2(mat->fMap[j][i], mat->fMap[i][i]));
}
else
{
fX = static_cast<float>(atan2(-mat->fMap[j][k], mat->fMap[j][j]));
fY = static_cast<float>(atan2((double)(-mat->fMap[k][i]), cy));
fZ = 0;
}
}
if (n==EulParOdd)
{
fX = -fX; fY = - fY; fZ = -fZ;
}
if (f==EulFrmR)
{
hsScalar t = fX; fX = fZ; fZ = t;
}
fOrder = order;
}
//
// Convert quaternion to Euler angles (in radians)
//
void hsEuler::SetFromQuat(const hsQuat* q, UInt32 order)
{
hsMatrix44 mat;
double Nq = q->fX*q->fX+q->fY*q->fY+q->fZ*q->fZ+q->fW*q->fW;
double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
double xs = q->fX*s, ys = q->fY*s, zs = q->fZ*s;
double wx = q->fW*xs, wy = q->fW*ys, wz = q->fW*zs;
double xx = q->fX*xs, xy = q->fX*ys, xz = q->fX*zs;
double yy = q->fY*ys, yz = q->fY*zs, zz = q->fZ*zs;
mat.fMap[X][X] = static_cast<float>(1.0 - (yy + zz));
mat.fMap[X][Y] = static_cast<float>(xy - wz);
mat.fMap[X][Z] = static_cast<float>(xz + wy);
mat.fMap[Y][X] = static_cast<float>(xy + wz);
mat.fMap[Y][Y] = static_cast<float>(1.0 - (xx + zz));
mat.fMap[Y][Z] = static_cast<float>(yz - wx);
mat.fMap[Z][X] = static_cast<float>(xz - wy);
mat.fMap[Z][Y] = static_cast<float>(yz + wx);
mat.fMap[Z][Z] = static_cast<float>(1.0 - (xx + yy));
mat.fMap[W][X] = mat.fMap[W][Y] = mat.fMap[W][Z] =
mat.fMap[X][W] = mat.fMap[Y][W] = mat.fMap[Z][W] = 0.0;
mat.fMap[W][W] = 1.0;
SetFromMatrix44(&mat, order);
}

View File

@ -1,132 +1,132 @@
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HS_EULER_inc
#define HS_EULER_inc
#include "hsGeometry3.h"
//
//////////////////////////////////////////////////////////////////////////
// EULER STUFF
// See Gems IV, Ken Shoemake
//////////////////////////////////////////////////////////////////////////
//
/*** Order type constants, constructors, extractors ***/
/* There are 24 possible conventions, designated by: */
/* o EulAxI = axis used initially */
/* o EulPar = parity of axis permutation */
/* o EulRep = repetition of initial axis as last */
/* o EulFrm = frame from which axes are taken */
/* Axes I,J,K will be a permutation of X,Y,Z. */
/* Axis H will be either I or K, depending on EulRep. */
/* Frame S takes axes from initial static frame. */
/* If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then */
/* {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v */
/* rotates v around Z by c radians. */
#define EulFrmS 0
#define EulFrmR 1
#define EulFrm(ord) ((unsigned)(ord)&1)
#define EulRepNo 0
#define EulRepYes 1
#define EulRep(ord) (((unsigned)(ord)>>1)&1)
#define EulParEven 0
#define EulParOdd 1
#define EulPar(ord) (((unsigned)(ord)>>2)&1)
#define EulSafe "\000\001\002\000"
#define EulNext "\001\002\000\001"
#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord)>>3)&3)]))
#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)==EulParOdd)]))
#define EulAxK(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)!=EulParOdd)]))
#define EulAxH(ord) ((EulRep(ord)==EulRepNo)?EulAxK(ord):EulAxI(ord))
/* EulGetOrd unpacks all useful information about order simultaneously. */
#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}
/* EulOrd creates an order value between 0 and 23 from 4-tuple choices. */
#define EulOrd(i,p,r,f) (((((((i)<<1)+(p))<<1)+(r))<<1)+(f))
/* Static axes */
#define EulOrdXYZs EulOrd(X,EulParEven,EulRepNo,EulFrmS)
#define EulOrdXYXs EulOrd(X,EulParEven,EulRepYes,EulFrmS)
#define EulOrdXZYs EulOrd(X,EulParOdd,EulRepNo,EulFrmS)
#define EulOrdXZXs EulOrd(X,EulParOdd,EulRepYes,EulFrmS)
#define EulOrdYZXs EulOrd(Y,EulParEven,EulRepNo,EulFrmS)
#define EulOrdYZYs EulOrd(Y,EulParEven,EulRepYes,EulFrmS)
#define EulOrdYXZs EulOrd(Y,EulParOdd,EulRepNo,EulFrmS)
#define EulOrdYXYs EulOrd(Y,EulParOdd,EulRepYes,EulFrmS)
#define EulOrdZXYs EulOrd(Z,EulParEven,EulRepNo,EulFrmS)
#define EulOrdZXZs EulOrd(Z,EulParEven,EulRepYes,EulFrmS)
#define EulOrdZYXs EulOrd(Z,EulParOdd,EulRepNo,EulFrmS)
#define EulOrdZYZs EulOrd(Z,EulParOdd,EulRepYes,EulFrmS)
/* Rotating axes */
#define EulOrdZYXr EulOrd(X,EulParEven,EulRepNo,EulFrmR)
#define EulOrdXYXr EulOrd(X,EulParEven,EulRepYes,EulFrmR)
#define EulOrdYZXr EulOrd(X,EulParOdd,EulRepNo,EulFrmR)
#define EulOrdXZXr EulOrd(X,EulParOdd,EulRepYes,EulFrmR)
#define EulOrdXZYr EulOrd(Y,EulParEven,EulRepNo,EulFrmR)
#define EulOrdYZYr EulOrd(Y,EulParEven,EulRepYes,EulFrmR)
#define EulOrdZXYr EulOrd(Y,EulParOdd,EulRepNo,EulFrmR)
#define EulOrdYXYr EulOrd(Y,EulParOdd,EulRepYes,EulFrmR)
#define EulOrdYXZr EulOrd(Z,EulParEven,EulRepNo,EulFrmR)
#define EulOrdZXZr EulOrd(Z,EulParEven,EulRepYes,EulFrmR)
#define EulOrdXYZr EulOrd(Z,EulParOdd,EulRepNo,EulFrmR)
#define EulOrdZYZr EulOrd(Z,EulParOdd,EulRepYes,EulFrmR)
struct hsMatrix44;
class hsQuat;
class hsEuler
{
public:
hsScalar fX,fY,fZ;
UInt32 fOrder;
hsEuler(hsScalar ai, hsScalar aj, hsScalar ah, UInt32 order) : fX(ai),fY(aj),fZ(ah),fOrder(order) {}
// getters, converters
void GetQuat(hsQuat* res );
void GetMatrix44(hsMatrix44* M);
// setters, converters
void SetFromMatrix44(const hsMatrix44* M, UInt32 order);
void SetFromQuat(const hsQuat* q, UInt32 order);
};
#endif // HS_EULER_inc
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HS_EULER_inc
#define HS_EULER_inc
#include "hsGeometry3.h"
//
//////////////////////////////////////////////////////////////////////////
// EULER STUFF
// See Gems IV, Ken Shoemake
//////////////////////////////////////////////////////////////////////////
//
/*** Order type constants, constructors, extractors ***/
/* There are 24 possible conventions, designated by: */
/* o EulAxI = axis used initially */
/* o EulPar = parity of axis permutation */
/* o EulRep = repetition of initial axis as last */
/* o EulFrm = frame from which axes are taken */
/* Axes I,J,K will be a permutation of X,Y,Z. */
/* Axis H will be either I or K, depending on EulRep. */
/* Frame S takes axes from initial static frame. */
/* If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then */
/* {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v */
/* rotates v around Z by c radians. */
#define EulFrmS 0
#define EulFrmR 1
#define EulFrm(ord) ((unsigned)(ord)&1)
#define EulRepNo 0
#define EulRepYes 1
#define EulRep(ord) (((unsigned)(ord)>>1)&1)
#define EulParEven 0
#define EulParOdd 1
#define EulPar(ord) (((unsigned)(ord)>>2)&1)
#define EulSafe "\000\001\002\000"
#define EulNext "\001\002\000\001"
#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord)>>3)&3)]))
#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)==EulParOdd)]))
#define EulAxK(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)!=EulParOdd)]))
#define EulAxH(ord) ((EulRep(ord)==EulRepNo)?EulAxK(ord):EulAxI(ord))
/* EulGetOrd unpacks all useful information about order simultaneously. */
#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}
/* EulOrd creates an order value between 0 and 23 from 4-tuple choices. */
#define EulOrd(i,p,r,f) (((((((i)<<1)+(p))<<1)+(r))<<1)+(f))
/* Static axes */
#define EulOrdXYZs EulOrd(X,EulParEven,EulRepNo,EulFrmS)
#define EulOrdXYXs EulOrd(X,EulParEven,EulRepYes,EulFrmS)
#define EulOrdXZYs EulOrd(X,EulParOdd,EulRepNo,EulFrmS)
#define EulOrdXZXs EulOrd(X,EulParOdd,EulRepYes,EulFrmS)
#define EulOrdYZXs EulOrd(Y,EulParEven,EulRepNo,EulFrmS)
#define EulOrdYZYs EulOrd(Y,EulParEven,EulRepYes,EulFrmS)
#define EulOrdYXZs EulOrd(Y,EulParOdd,EulRepNo,EulFrmS)
#define EulOrdYXYs EulOrd(Y,EulParOdd,EulRepYes,EulFrmS)
#define EulOrdZXYs EulOrd(Z,EulParEven,EulRepNo,EulFrmS)
#define EulOrdZXZs EulOrd(Z,EulParEven,EulRepYes,EulFrmS)
#define EulOrdZYXs EulOrd(Z,EulParOdd,EulRepNo,EulFrmS)
#define EulOrdZYZs EulOrd(Z,EulParOdd,EulRepYes,EulFrmS)
/* Rotating axes */
#define EulOrdZYXr EulOrd(X,EulParEven,EulRepNo,EulFrmR)
#define EulOrdXYXr EulOrd(X,EulParEven,EulRepYes,EulFrmR)
#define EulOrdYZXr EulOrd(X,EulParOdd,EulRepNo,EulFrmR)
#define EulOrdXZXr EulOrd(X,EulParOdd,EulRepYes,EulFrmR)
#define EulOrdXZYr EulOrd(Y,EulParEven,EulRepNo,EulFrmR)
#define EulOrdYZYr EulOrd(Y,EulParEven,EulRepYes,EulFrmR)
#define EulOrdZXYr EulOrd(Y,EulParOdd,EulRepNo,EulFrmR)
#define EulOrdYXYr EulOrd(Y,EulParOdd,EulRepYes,EulFrmR)
#define EulOrdYXZr EulOrd(Z,EulParEven,EulRepNo,EulFrmR)
#define EulOrdZXZr EulOrd(Z,EulParEven,EulRepYes,EulFrmR)
#define EulOrdXYZr EulOrd(Z,EulParOdd,EulRepNo,EulFrmR)
#define EulOrdZYZr EulOrd(Z,EulParOdd,EulRepYes,EulFrmR)
struct hsMatrix44;
class hsQuat;
class hsEuler
{
public:
hsScalar fX,fY,fZ;
UInt32 fOrder;
hsEuler(hsScalar ai, hsScalar aj, hsScalar ah, UInt32 order) : fX(ai),fY(aj),fZ(ah),fOrder(order) {}
// getters, converters
void GetQuat(hsQuat* res );
void GetMatrix44(hsMatrix44* M);
// setters, converters
void SetFromMatrix44(const hsMatrix44* M, UInt32 order);
void SetFromQuat(const hsQuat* q, UInt32 order);
};
#endif // HS_EULER_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +1,73 @@
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef MATDECOMP_inc
#define MATDECOMP_inc
//
// Types
//
typedef struct {float x, y, z, w;} gemQuat; /* Quaternion */
enum QuatPart {X, Y, Z, W};
typedef gemQuat HVect; /* Homogeneous 3D vector */
typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
typedef struct {
HVect t; /* Translation components */
gemQuat q; /* Essential rotation */
gemQuat u; /* Stretch rotation */
HVect k; /* Stretch factors */
float f; /* Sign of determinant */
} gemAffineParts;
//
// Funcs
//
float polar_decomp(const HMatrix M, HMatrix Q, HMatrix S);
HVect spect_decomp(const HMatrix S, HMatrix U);
gemQuat snuggle(gemQuat q, HVect *k);
void decomp_affine(const HMatrix A, gemAffineParts *parts);
void invert_affine(gemAffineParts *parts, gemAffineParts *inverse);
#endif
/*==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, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef MATDECOMP_inc
#define MATDECOMP_inc
//
// Types
//
typedef struct {float x, y, z, w;} gemQuat; /* Quaternion */
enum QuatPart {X, Y, Z, W};
typedef gemQuat HVect; /* Homogeneous 3D vector */
typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
typedef struct {
HVect t; /* Translation components */
gemQuat q; /* Essential rotation */
gemQuat u; /* Stretch rotation */
HVect k; /* Stretch factors */
float f; /* Sign of determinant */
} gemAffineParts;
//
// Funcs
//
float polar_decomp(const HMatrix M, HMatrix Q, HMatrix S);
HVect spect_decomp(const HMatrix S, HMatrix U);
gemQuat snuggle(gemQuat q, HVect *k);
void decomp_affine(const HMatrix A, gemAffineParts *parts);
void invert_affine(gemAffineParts *parts, gemAffineParts *inverse);
#endif