mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Fix line endings and tabs
This commit is contained in:
@ -1,21 +1,21 @@
|
||||
include_directories("../../CoreLib")
|
||||
include_directories("../../NucleusLib/inc")
|
||||
include_directories("../../NucleusLib")
|
||||
include_directories("../../PubUtilLib")
|
||||
|
||||
set(plTransform_SOURCES
|
||||
hsAffineParts.cpp
|
||||
hsEuler.cpp
|
||||
mat_decomp.cpp
|
||||
)
|
||||
|
||||
set(plTransform_HEADERS
|
||||
hsAffineParts.h
|
||||
hsEuler.h
|
||||
mat_decomp.h
|
||||
)
|
||||
|
||||
add_library(plTransform STATIC ${plTransform_SOURCES} ${plTransform_HEADERS})
|
||||
|
||||
source_group("Source Files" FILES ${plTransform_SOURCES})
|
||||
source_group("Header Files" FILES ${plTransform_HEADERS})
|
||||
include_directories("../../CoreLib")
|
||||
include_directories("../../NucleusLib/inc")
|
||||
include_directories("../../NucleusLib")
|
||||
include_directories("../../PubUtilLib")
|
||||
|
||||
set(plTransform_SOURCES
|
||||
hsAffineParts.cpp
|
||||
hsEuler.cpp
|
||||
mat_decomp.cpp
|
||||
)
|
||||
|
||||
set(plTransform_HEADERS
|
||||
hsAffineParts.h
|
||||
hsEuler.h
|
||||
mat_decomp.h
|
||||
)
|
||||
|
||||
add_library(plTransform STATIC ${plTransform_SOURCES} ${plTransform_HEADERS})
|
||||
|
||||
source_group("Source Files" FILES ${plTransform_SOURCES})
|
||||
source_group("Header Files" FILES ${plTransform_HEADERS})
|
||||
|
@ -1,426 +1,426 @@
|
||||
/*==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/>.
|
||||
|
||||
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/>.
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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/>.
|
||||
|
||||
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/>.
|
||||
|
||||
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
|
||||
|
@ -1,212 +1,212 @@
|
||||
/*==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/>.
|
||||
|
||||
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/>.
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1,116 +1,116 @@
|
||||
/*==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/>.
|
||||
|
||||
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/>.
|
||||
|
||||
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
@ -1,57 +1,57 @@
|
||||
/*==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/>.
|
||||
|
||||
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/>.
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user