Vector rotation and conversion of the four-tuple group

zhaozj2021-02-16  101

// Copyright (C) Liang Yi, 2004 // Last modified: 2004.8. Hangzhou

#ifndef rotation_header

#define rotation_header

#include "matrix.h"

Const Double delta_ROT = 1.0e-10;

Template

Class quaternion;

Template

Class Rotation;

Template

Quaternion

RotationToquaternion

Const rotation

& r)

// r

Be normalized

{

T cosvalue, sinvalue, theta;

Theta = R.angle / 180.0F * m_pi;

Cosvalue = T (COS (Theta / 2.0F));

SINVALUE = T (SIN (Theta / 2.0F));

Return quaternion

(SINVALUE * R.AXIS.X,

SINVALUE * R.AXIS.Y,

SINVALUE * R.AXIS.Z,

CosValue);

}

Template

Rotation

QuaternionTorotation

Const quaternion

& q)

// q

Be normalized

{

IF ((Q.W> 1-Delta_ROT) && (Q.W <1 Delta_ROT) ||

((q.w> -1-delta_rot) && (q.w <-1 delta_rot)))))))

{

Return Rotation

();

}

T sinvalue, haldheta;

HALFTHETA = T (ACOS (Q.W));

SINVALUE = T (Halftheta);

IF (sinvalue

{

Return Rotation

();

}

Return Rotation

(Q.X / SINVALUE,

Q.Y / SINVALUE, Q.Z / SINVALUE,

Halftheta * 2.0F * 180.0F / 3.14159F);

}

Template

Void QuaternionTomatrix (T M [16], Const Quaternion

& q)

// q

Be normalized

{

T M [4] [4];

T WX, WY, WZ, XX, YY, YZ, XY, XZ, ZZ, X2, Y2, Z2;

// Calculate Coefficients

X2 = Q.X * 2.0F;

Y2 = Q.Y * 2.0F;

Z2 = q.z * 2.0F;

XX = q.x * x2; xy = q.x * y2; xz = q.x * z2;

YY = q.y * y2; yz = q.y * z2; zz = q.z * z2;

WX = q.w * x2; wy = q.w * y2; wz = q.w * z2;

M [0] [0] = 1.0F - (YY ZZ);

M [0] [1] = XY WZ;

M [0] [2] = xz - wy;

M [0] [3] = 0.0F;

M [1] [0] = XY - WZ;

M [1] [1] = 1.0F - (XX ZZ);

M [1] [2] = YZ WX;

M [1] [3] = 0.0F; M [2] [0] = XZ WY;

M [2] [1] = yz - wx;

M [2] [2] = 1.0F - (xx yy);

M [2] [3] = 0.0F;

M [3] [0] = 0;

M [3] [1] = 0;

M [3] [2] = 0;

M [3] [3] = 1;

For (SIZE_T I = 0; i <4; i )

For (SIZE_T J = 0; J <4; J )

M [i * 4 j] = m [i] [j];

}

Template

Void QuaternionTomatrix_opengl (T M [16], Const Quaternion

& q)

{

T M [4] [4]; // Column Major Format (OpenGL Format)

T WX, WY, WZ, XX, YY, YZ, XY, XZ, ZZ, X2, Y2, Z2;

// Calculate Coefficients

X2 = Q.X * 2.0F;

Y2 = Q.Y * 2.0F;

Z2 = q.z * 2.0F;

XX = q.x * x2; xy = q.x * y2; xz = q.x * z2;

YY = q.y * y2; yz = q.y * z2; zz = q.z * z2;

WX = q.w * x2; wy = q.w * y2; wz = q.w * z2;

M [0] [0] = 1.0F - (YY ZZ);

M [0] [1] = xy - wz;

M [0] [2] = XZ WY;

M [0] [3] = 0.0F;

M [1] [0] = XY WZ;

M [1] [1] = 1.0F - (XX ZZ);

M [1] [2] = yz - wx;

M [1] [3] = 0.0F;

M [2] [0] = xz - wy;

M [2] [1] = YZ WX;

M [2] [2] = 1.0F - (xx yy);

M [2] [3] = 0.0F;

M [3] [0] = 0;

M [3] [1] = 0;

M [3] [2] = 0;

M [3] [3] = 1;

For (int i = 0; i <4; i )

For (int J = 0; j <4; j )

M [i * 4 j] = m [i] [j]; // column major format (OpenGL Format)

}

Template

Quaternion

Vectortoquaternion

Const Vector3D

& v)

{

Return quaternion

(V.x, v.y, v.z, 0);

}

Template

Vector3D

QuaternionTovector

Const quaternion

Q)

{

Return Vector3D

(Q.X, Q.Y, Q.Z);

}

// v After the Q transform is V ', the function returns V'

Template

Vector3D

Vectortransform

Const Vector3D

& V,

Const quaternion

& Q)

{

IF ((Q.W> 1-Delta_ROT) && (Q.W <1 Delta_ROT)) || (Q.W> -1-Delta_ROT) && (Q.W <-1 Delta_ROT)) Return V;

Quaternion

A, B, C;

A = vectortoquaternion (v);

B = q;

B.INVERSE ()

C = q * a * b;

Return QuaternionTovector (C);

}

Template

Class Rotation

{

PUBLIC:

Vector3D

Axis;

TANGLE;

PUBLIC:

Rotation (T x = 0, T y = 0, T z = 1.0, t_angle = 0)

{

Axis.x = x;

Axis.y = y;

Axis.z = z;

Angle = _angle;

}

Rotation (Vector3D)

& v, t_angle = 0)

{

AXIS = V;

Angle = _angle;

}

}

Template

Class quaternion

{

PUBLIC:

T x, y, z, w;

PUBLIC:

Quaternion (t _x = 0, t _y = 0, t_z = 1, t_w = 0)

{

X = _x;

Y = _y;

z = _z;

W = _w;

}

T MAGNITUDE ()

{

RETURN SQRT (x * x y * y z * z w * w);

}

Void Normalize (Quaternion

& OUT

{

T mgnitude ();

IF (m> 0)

{

Out.x = x / m;

Out.y = y / m;

OUT.Z = z / m;

Out.w = w / m;

}

}

void normalize ()

{

Normalize (* this);

}

Void Inverse (Quaternion

& OUT

{

T mgnitude ();

IF (m> 0)

{

Out.x = -x / m;

Out.y = -y / m;

OUT.Z = -Z / m;

Out.w = -w / m;

}

}

Void inVerse ()

{

INVERSE (* THIS);

}

Void Conjugate (Quaternion

& OUT

{

Out.x = -x;

Out.y = -y;

Out.z = -z;

}

Void conjugate ()

{

CONJUGATE (* this);

}

Quaternion

Operator (Quaternion

& q)

{

Return quaternion

(x Q.X, Y Q.Y, Z Q.Z, W Q.W);

}

Quaternion

Operator - Quaternion

& q)

{

Return quaternion

(x-q.x, y-q.y, z-q.z, w-q.w);

}

Quaternion

Operator * (

Const quaternion

& q)

{

Return quaternion

(w * q.x x * q.w y * q.z - z * q.y,

w * q.y y * q.w z * q.x - x * q.z,

W * q.z z * q.w x * q.y - y * q.x, w * q.w - x * q.x - y * q.y - z * q.z);

}

Quaternion

Operator * (t s)

{

Return quaternion

(x * s, y * s, z * s, w * s);

}

// Nick Bobick write

// Purpose: Spherical Linear Interpolation Between Two Quaternions

// Arguments: Two quaternions, blend factor

Quaternion

Slerp

Const quaternion

& from,

Const quaternion

& to, t t)

{

T TO1 [4];

T Omega, Cosom, Sinom, Scale0, Scale1;

// Calc Cosine

Cosom = from.x * to.x from.y * to.y from.z * to.z

from.w * to.w;

// Adjust Signs (if Necessary)

IF (cosom <0.0) {cosom = -cosom; TO1 [0] = - to.x;

TO1 [1] = - to.y;

TO1 [2] = - to.z;

TO1 [3] = - to.w;

} else {

TO1 [0] = TO.X;

TO1 [1] = to.y;

TO1 [2] = to.z;

TO1 [3] = to.w;

}

// Calculate Coefficients

IF ((1.0 - Cosom)> Delta_ROT) {

// Standard Case (Slerp)

Omega = T (ACOS (Cosom));

Sinom = T (Sin (OMEGA));

Scale0 = T (SIN ((1.0 - t) * omega) / sinom);

Scale1 = T (SIN (T * Omega) / Sinom);

} else {

// "from" and "to" quaternions are very close close

// ... SO We can do a linear interpolation

Scale0 = 1.0F - t;

Scale1 = T;

}

// Calculate Final Values

Return (scale0 * from.x scale1 * to1 [0],

Scale0 * from.y scale1 * to1 [1],

Scale0 * from.z scale1 * TO1 [2],

Scale0 * from.w scale1 * to1 [3]);

}

}

#ENDIF

转载请注明原文地址:https://www.9cbs.com/read-11409.html

New Post(0)