Commit 75d8343a authored by Richard Gustavsen's avatar Richard Gustavsen

runtimerender: export QSSGEulerAngleConverter, and move related API inside it

Many of the functions found in QQuick3DNode belongs better in
QSSGEulerAngleConverter. By refactoring them inside that class, we
can also use them from other places, and in particular from
QQuick3DNode where we need to calculate the global matrix.
parent 8168dff3
Pipeline #4736 failed with stage
in 3 minutes and 51 seconds
......@@ -124,119 +124,19 @@ bool QSSGRenderNode::calculateGlobalVariables()
return retval && flags.testFlag(Flag::Active);
}
// Create some mapping of euler angles to their axis mapping.
#define ITERATE_POSSIBLE_EULER_ANGLES \
HANDLE_EULER_ANGLE(EulOrdXYZs, X, Y, Z) \
HANDLE_EULER_ANGLE(EulOrdXYXs, X, Y, X) \
HANDLE_EULER_ANGLE(EulOrdXZYs, X, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdXZXs, X, Z, X) \
HANDLE_EULER_ANGLE(EulOrdYZXs, Y, Z, X) \
HANDLE_EULER_ANGLE(EulOrdYZYs, Y, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdYXZs, Y, X, Z) \
HANDLE_EULER_ANGLE(EulOrdYXYs, Y, X, Y) \
HANDLE_EULER_ANGLE(EulOrdZXYs, Z, X, Y) \
HANDLE_EULER_ANGLE(EulOrdZXZs, Z, X, Z) \
HANDLE_EULER_ANGLE(EulOrdZYXs, Z, Y, X) \
HANDLE_EULER_ANGLE(EulOrdZYZs, Z, Y, Z) \
HANDLE_EULER_ANGLE(EulOrdZYXr, Z, Y, X) \
HANDLE_EULER_ANGLE(EulOrdXYXr, X, Y, X) \
HANDLE_EULER_ANGLE(EulOrdYZXr, Y, Z, X) \
HANDLE_EULER_ANGLE(EulOrdXZXr, X, Z, X) \
HANDLE_EULER_ANGLE(EulOrdXZYr, X, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdYZYr, Y, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdZXYr, Z, X, Y) \
HANDLE_EULER_ANGLE(EulOrdYXYr, Y, X, Y) \
HANDLE_EULER_ANGLE(EulOrdYXZr, Y, X, Z) \
HANDLE_EULER_ANGLE(EulOrdZXZr, Z, X, Z) \
HANDLE_EULER_ANGLE(EulOrdXYZr, X, Y, Z) \
HANDLE_EULER_ANGLE(EulOrdZYZr, Z, Y, Z)
inline EulerAngles rotationAndOrderToShoemake(QVector3D inRotation, quint32 inOrder)
{
EulerAngles retval;
retval.w = float(inOrder);
int X = 0;
int Y = 1;
int Z = 2;
switch (inOrder) {
#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \
case order: \
retval.x = -inRotation[xIdx]; \
retval.y = -inRotation[yIdx]; \
retval.z = -inRotation[zIdx]; \
break;
ITERATE_POSSIBLE_EULER_ANGLES
#undef HANDLE_EULER_ANGLE
default:
Q_ASSERT(false);
retval.x = inRotation[X];
retval.y = inRotation[Y];
retval.z = inRotation[Z];
break;
}
return retval;
}
QVector3D QSSGRenderNode::getRotationVectorFromRotationMatrix(const QMatrix3x3 &inMatrix) const
{
QMatrix4x4 theConvertMatrix = { inMatrix(0, 0),
inMatrix(0, 1),
inMatrix(0, 2),
0.0f,
inMatrix(1, 0),
inMatrix(1, 1),
inMatrix(1, 2),
0.0f,
inMatrix(2, 0),
inMatrix(2, 1),
inMatrix(2, 2),
0.0f,
0.0f,
0.0f,
0.0f,
1.0f };
if (flags.testFlag(Flag::LeftHanded))
QSSGRenderNode::flipCoordinateSystem(theConvertMatrix);
QSSGEulerAngleConverter theConverter;
HMatrix *theHMatrix = reinterpret_cast<HMatrix *>(theConvertMatrix.data());
EulerAngles theAngles = theConverter.eulerFromHMatrix(*theHMatrix, rotationOrder);
return getRotationVectorFromEulerAngles(theAngles);
return QSSGEulerAngleConverter::calculateRotationVector(inMatrix, flags.testFlag(Flag::LeftHanded), rotationOrder);
}
QVector3D QSSGRenderNode::getRotationVectorFromEulerAngles(const EulerAngles &inAngles)
{
QVector3D retval(0, 0, 0);
int X = 0;
int Y = 1;
int Z = 2;
switch (int(inAngles.w)) {
#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \
case order: \
retval[xIdx] = -inAngles.x; \
retval[yIdx] = -inAngles.y; \
retval[zIdx] = -inAngles.z; \
break;
ITERATE_POSSIBLE_EULER_ANGLES
#undef HANDLE_EULER_ANGLE
default:
Q_ASSERT(false);
retval.setX(inAngles.x);
retval.setY(inAngles.y);
retval.setZ(inAngles.z);
break;
}
return retval;
return QSSGEulerAngleConverter::calculateRotationVector(inAngles);
}
void QSSGRenderNode::calculateRotationMatrix(QMatrix4x4 &outMatrix) const
{
QSSGEulerAngleConverter theConverter;
EulerAngles theAngles(rotationAndOrderToShoemake(rotation, int(rotationOrder)));
HMatrix *theMatrix = reinterpret_cast<HMatrix *>(&outMatrix);
theConverter.eulerToHMatrix(theAngles, *theMatrix);
outMatrix = QSSGEulerAngleConverter::createRotationMatrix(rotation, rotationOrder);
}
void QSSGRenderNode::calculateLocalTransform()
......
......@@ -38,6 +38,8 @@
#include <cstring>
#include <cstdio>
#include <QtQuick3DUtils/private/qssgutils_p.h>
#ifdef _MSC_VER
#pragma warning(disable : 4365) // warnings on conversion from unsigned int to int
#endif
......@@ -312,6 +314,125 @@ EulerAngles QSSGEulerAngleConverter::eulerFromQuat(Quat theQuaternion, int theOr
return eulerFromHMatrix(theMatrix, theOrder);
}
//==============================================================================
// Create some mapping of euler angles to their axis mapping.
#define ITERATE_POSSIBLE_EULER_ANGLES \
HANDLE_EULER_ANGLE(EulOrdXYZs, X, Y, Z) \
HANDLE_EULER_ANGLE(EulOrdXYXs, X, Y, X) \
HANDLE_EULER_ANGLE(EulOrdXZYs, X, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdXZXs, X, Z, X) \
HANDLE_EULER_ANGLE(EulOrdYZXs, Y, Z, X) \
HANDLE_EULER_ANGLE(EulOrdYZYs, Y, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdYXZs, Y, X, Z) \
HANDLE_EULER_ANGLE(EulOrdYXYs, Y, X, Y) \
HANDLE_EULER_ANGLE(EulOrdZXYs, Z, X, Y) \
HANDLE_EULER_ANGLE(EulOrdZXZs, Z, X, Z) \
HANDLE_EULER_ANGLE(EulOrdZYXs, Z, Y, X) \
HANDLE_EULER_ANGLE(EulOrdZYZs, Z, Y, Z) \
HANDLE_EULER_ANGLE(EulOrdZYXr, Z, Y, X) \
HANDLE_EULER_ANGLE(EulOrdXYXr, X, Y, X) \
HANDLE_EULER_ANGLE(EulOrdYZXr, Y, Z, X) \
HANDLE_EULER_ANGLE(EulOrdXZXr, X, Z, X) \
HANDLE_EULER_ANGLE(EulOrdXZYr, X, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdYZYr, Y, Z, Y) \
HANDLE_EULER_ANGLE(EulOrdZXYr, Z, X, Y) \
HANDLE_EULER_ANGLE(EulOrdYXYr, Y, X, Y) \
HANDLE_EULER_ANGLE(EulOrdYXZr, Y, X, Z) \
HANDLE_EULER_ANGLE(EulOrdZXZr, Z, X, Z) \
HANDLE_EULER_ANGLE(EulOrdXYZr, X, Y, Z) \
HANDLE_EULER_ANGLE(EulOrdZYZr, Z, Y, Z)
EulerAngles QSSGEulerAngleConverter::calculateEulerAngles(const QVector3D &rotation, quint32 order)
{
EulerAngles retval;
retval.w = float(order);
int X = 0;
int Y = 1;
int Z = 2;
switch (order) {
#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \
case order: \
retval.x = -rotation[xIdx]; \
retval.y = -rotation[yIdx]; \
retval.z = -rotation[zIdx]; \
break;
ITERATE_POSSIBLE_EULER_ANGLES
#undef HANDLE_EULER_ANGLE
default:
Q_ASSERT(false);
retval.x = rotation[X];
retval.y = rotation[Y];
retval.z = rotation[Z];
break;
}
return retval;
}
QVector3D QSSGEulerAngleConverter::calculateRotationVector(const EulerAngles &angles)
{
QVector3D retval(0, 0, 0);
int X = 0;
int Y = 1;
int Z = 2;
switch (int(angles.w)) {
#define HANDLE_EULER_ANGLE(order, xIdx, yIdx, zIdx) \
case order: \
retval[xIdx] = -angles.x; \
retval[yIdx] = -angles.y; \
retval[zIdx] = -angles.z; \
break;
ITERATE_POSSIBLE_EULER_ANGLES
#undef HANDLE_EULER_ANGLE
default:
Q_ASSERT(false);
retval.setX(angles.x);
retval.setY(angles.y);
retval.setZ(angles.z);
break;
}
return retval;
}
QMatrix4x4 QSSGEulerAngleConverter::createRotationMatrix(const QVector3D &rotationAsRadians, quint32 order)
{
QMatrix4x4 matrix;
const EulerAngles theAngles = QSSGEulerAngleConverter::calculateEulerAngles(rotationAsRadians, order);
QSSGEulerAngleConverter theConverter;
theConverter.eulerToHMatrix(theAngles, *reinterpret_cast<HMatrix *>(&matrix));
return matrix;
}
QVector3D QSSGEulerAngleConverter::calculateRotationVector(const QMatrix3x3 &rotationMatrix, bool matrixIsLeftHanded, quint32 order)
{
QMatrix4x4 theConvertMatrix = { rotationMatrix(0, 0),
rotationMatrix(0, 1),
rotationMatrix(0, 2),
0.0f,
rotationMatrix(1, 0),
rotationMatrix(1, 1),
rotationMatrix(1, 2),
0.0f,
rotationMatrix(2, 0),
rotationMatrix(2, 1),
rotationMatrix(2, 2),
0.0f,
0.0f,
0.0f,
0.0f,
1.0f };
if (matrixIsLeftHanded)
mat44::flip(theConvertMatrix);
QSSGEulerAngleConverter theConverter;
HMatrix *theHMatrix = reinterpret_cast<HMatrix *>(theConvertMatrix.data());
EulerAngles theAngles = theConverter.eulerFromHMatrix(*theHMatrix, int(order));
return calculateRotationVector(theAngles);
}
//==============================================================================
/**
* Dump the Order information
......
......@@ -43,6 +43,7 @@
//
#include <qmath.h>
#include <QtQuick3DRuntimeRender/private/qtquick3druntimerenderglobal_p.h>
QT_BEGIN_NAMESPACE
//==============================================================================
......@@ -130,7 +131,7 @@ typedef Quat EulerAngles; /* (x,y,z)=ang 1,2,3, w=order code */
#define TODEG(x) x = (float)(x * 180 / M_PI);
#define TORAD(x) x = (float)(x / 180 * M_PI);
class QSSGEulerAngleConverter
class Q_QUICK3DRUNTIMERENDER_EXPORT QSSGEulerAngleConverter
{
private:
char m_orderInfoBuffer[1024];
......@@ -146,6 +147,11 @@ public:
EulerAngles eulerFromHMatrix(HMatrix M, int order);
EulerAngles eulerFromQuat(Quat q, int order);
static EulerAngles calculateEulerAngles(const QVector3D &rotation, quint32 order);
static QVector3D calculateRotationVector(const EulerAngles &angles);
static QVector3D calculateRotationVector(const QMatrix3x3 &rotationMatrix, bool matrixIsLeftHanded, quint32 order);
static QMatrix4x4 createRotationMatrix(const QVector3D &rotationAsRadians, quint32 order);
// Debug Stuff
const char *dumpOrderInfo();
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment