2017-04-17 06:17:10 -06:00

138 lines
4.8 KiB
C++
Executable File

/*******************************************************************
*
* DESCRIPTION: euler.h
*
* AUTHOR: Converted from Ken Shoemake's Graphics Gems IV code by Dan Silva
*
* HISTORY: converted 11/21/96
*
* RB: This file provides only a subset of those
* found in the original Graphics Gems paper.
* All orderings are 'static axis'.
*
*******************************************************************/
#ifndef __EULER__
#define __EULER__
#include "matrix3.h"
#include "quat.h"
#define EULERTYPE_XYZ 0
#define EULERTYPE_XZY 1
#define EULERTYPE_YZX 2
#define EULERTYPE_YXZ 3
#define EULERTYPE_ZXY 4
#define EULERTYPE_ZYX 5
#define EULERTYPE_XYX 6
#define EULERTYPE_YZY 7
#define EULERTYPE_ZXZ 8
#define EULERTYPE_RF 16 // rotating frame (axes) --prs.
void DllExport QuatToEuler(const Quat &q, float *ang, int type, bool flag = false); // flag added 001101 --prs.
void DllExport EulerToQuat(float *ang, Quat &q,int type);
void DllExport MatrixToEuler(const Matrix3 &mat, float *ang, int type, bool flag = FALSE);
void DllExport EulerToMatrix(float *ang, Matrix3 &mat, int type);
float DllExport GetEulerQuatAngleRatio(Quat &quat1,Quat &quat2, float *euler1, float *euler2, int type = EULERTYPE_XYZ);
float DllExport GetEulerMatAngleRatio(Matrix3 &mat1,Matrix3 &mat2, float *euler1, float *euler2, int type = EULERTYPE_XYZ);
class RotationValue {
//
// There are two classes of Euler angle types, that of which rotation
// axes are not repeated, from kXYZ to kZYX, and one of which an axis is
// repeated, from kXYX to kZXZ. Repeated types starts from kReptd.
// For non-repetitive Euler angles, there are two well-defined methods
// to associate three ordered angles, to axes. First, we can associate
// them with x-, y-, and z-, axes in order. The first angle, for example,
// is always associated with the x-axis, no matter where it appears
// in the Euler type (x-axis appears at second place in kZXY, for example).
// Second, we can associate them by position: the first angle is always
// associated with the first axis in the Euler type. For examples,
// the first angle is applied to the x-axis for kXYZ and kXZY, to the
// y-axis for kYXZ and kYZX, etc.
// Let's call the first method by (axis) name, and the second method
// by order. We associate angles by name for non-repetitive Euler types.
// For repetitive types, by-name is not well-defined, because there is
// a missing axis. For repetitive types, we associate angles by-order.
// Example:
// Point3 a = Euler(RotationValue::kZYX);
// then, a.x, a.y, a.z, are the Euler angles for the x-axis, y-axis,
// and z-axis.
// Point3 a = Euler(RotationValue::kZXZ);
// then, a.x is angle applied to the first z-axis (from left), a.y is
// applied to the x-axis, and a.z is applied to the second z-axis.
//
public:
enum EulerType {
kXYZ = EULERTYPE_XYZ,
kXZY,
kYZX,
kYXZ,
kZXY,
kZYX,
kXYX,
kYZY,
kZXZ
};
enum {
kReptd = kXYX,
kQuat = 100
};
static bool IsEuler(int rep) { return (kXYZ <= rep && rep <= kZXZ); }
static bool IsRepetitive(int rep) {
// Pre-cond: IsEuler(rep)
return rep >= kReptd; }
static bool IsQuat(int rep) { return rep == kQuat; }
void Set(const Point3& a, EulerType et) {
mQ.x = a.x;
mQ.y = a.y;
mQ.z = a.z;
mRep = et; }
void Set(const Quat& q) {
mQ = q;
mRep = kQuat; }
RotationValue() : mQ(), mRep(kXYZ) {}
RotationValue(const Point3& a, EulerType et) { Set(a, et); }
RotationValue(const Quat& q) { Set(q); }
RotationValue(const RotationValue& src) : mQ(src.mQ), mRep(src.mRep) {}
Point3 Euler(EulerType et =kXYZ) const {
if (et == mRep) return Point3(mQ.x, mQ.y, mQ.z);
else return ToEulerAngles(et); }
operator Quat() const {
if (mRep == kQuat) return mQ;
else return ToQuat(); }
DllExport operator Matrix3() const;
DllExport void PreApplyTo(Matrix3& m) const; // m = *this * m
DllExport void PostApplyTo(Matrix3& m) const; // m = m * *this
// *this = *this * aa
// Post-condition: NativeRep() will be changed after RotateBy()
DllExport void PostRotate(const AngAxis& aa);
int NativeRep() const { return mRep; }
Quat GetNative() const { return mQ; }
// Suppose a and o are Point3's, which holds Euler angles by axis name
// and by order, respectively. That is, a[0] is applied to the x-axis and
// o[0] is applied to the first axis (from left in the Euler type).
// Let et be non-repetitive Euler type. Then,
// o[kAxisToOrdinal[et][i]] = a[i]
// and a[kOrdinalToAxis[et][i]] = o[i]
//
static const int kAxisToOrdinal[kReptd][3];
static const int kOrdinalToAxis[kZXZ+1][3];
protected:
Point3 DllExport ToEulerAngles(EulerType et) const;
Quat DllExport ToQuat() const;
private:
Quat mQ;
short mRep;
};
#endif // __EULER__