138 lines
4.8 KiB
C++
Executable File
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__
|