248 lines
4.8 KiB
C
248 lines
4.8 KiB
C
/*
|
|
* Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved.
|
|
*
|
|
* $Id: angles.c 1.1 1997/12/10 16:41:20 jon Exp $
|
|
* $Locker: $
|
|
*
|
|
* Euler angle manipulation - loosely based on -
|
|
* "Euler Angle Conversion" Ken Shoemake, Graphics Gems IV pp. 222
|
|
*
|
|
*/
|
|
#include "brender.h"
|
|
#include "brassert.h"
|
|
#include "shortcut.h"
|
|
|
|
BR_RCS_ID("$Id: angles.c 1.1 1997/12/10 16:41:20 jon Exp $")
|
|
|
|
/*
|
|
* Table of axes for each order
|
|
*/
|
|
static struct order_info {
|
|
br_uint_8 a0;
|
|
br_uint_8 a1;
|
|
br_uint_8 a2;
|
|
br_uint_8 _pad[1];
|
|
} OrderAxes[] = {
|
|
{0,1,2},
|
|
{1,2,0},
|
|
{2,0,1},
|
|
{0},
|
|
{0,2,1},
|
|
{1,0,2},
|
|
{2,1,0},
|
|
{0},
|
|
{0,1,2},
|
|
{1,2,0},
|
|
{2,0,1},
|
|
{0},
|
|
{0,2,1},
|
|
{1,0,2},
|
|
{2,1,0},
|
|
{0},
|
|
{0,1,2},
|
|
{1,2,0},
|
|
{2,0,1},
|
|
{0},
|
|
{0,2,1},
|
|
{1,0,2},
|
|
{2,1,0},
|
|
{0},
|
|
{0,1,2},
|
|
{1,2,0},
|
|
{2,0,1},
|
|
{0},
|
|
{0,2,1},
|
|
{1,0,2},
|
|
{2,1,0},
|
|
{0},
|
|
};
|
|
|
|
br_matrix34 * BR_PUBLIC_ENTRY BrEulerToMatrix34(br_matrix34 *mat, br_euler *euler)
|
|
{
|
|
br_uint_8 o = eO;
|
|
br_angle ti,tj,th;
|
|
br_scalar ci,cj,ch,si,sj,sh,cc,cs,sc,ss;
|
|
int a0,a1,a2;
|
|
|
|
UASSERT(mat != NULL);
|
|
UASSERT(euler != NULL);
|
|
UASSERT(euler->order < BR_ASIZE(OrderAxes));
|
|
|
|
if(o & BR_EULER_FRAME)
|
|
ti = eZ, tj = eY, th = eX;
|
|
else
|
|
ti = eX, tj = eY, th = eZ;
|
|
|
|
if(o & BR_EULER_PARITY)
|
|
ti = -ti, tj = -tj, th = -th;
|
|
|
|
ci = BR_COS(ti); cj = BR_COS(tj); ch = BR_COS(th);
|
|
si = BR_SIN(ti); sj = BR_SIN(tj); sh = BR_SIN(th);
|
|
cc = BR_MUL(ci,ch); cs = BR_MUL(ci,sh);
|
|
sc = BR_MUL(si,ch); ss = BR_MUL(si,sh);
|
|
|
|
a0 = OrderAxes[o].a0;
|
|
a1 = OrderAxes[o].a1;
|
|
a2 = OrderAxes[o].a2;
|
|
|
|
if(o & BR_EULER_REPEAT) {
|
|
M(a0,a0)= cj; M(a1,a0)= BR_MUL(sj,si); M(a2,a0)= BR_MUL(sj,ci);
|
|
M(a0,a1)= BR_MUL(sj,sh); M(a1,a1)= -BR_MUL(cj,ss)+cc; M(a2,a1)= -BR_MUL(cj,cs)-sc;
|
|
M(a0,a2)= -BR_MUL(sj,ch); M(a1,a2)= BR_MUL(cj,sc)+cs; M(a2,a2)= BR_MUL(cj,cc)-ss;
|
|
} else {
|
|
M(a0,a0)= BR_MUL(cj,ch); M(a1,a0)= BR_MUL(sj,sc)-cs; M(a2,a0)= BR_MUL(sj,cc)+ss;
|
|
M(a0,a1)= BR_MUL(cj,sh); M(a1,a1)= BR_MUL(sj,ss)+cc; M(a2,a1)= BR_MUL(sj,cs)-sc;
|
|
M(a0,a2)= -sj; M(a1,a2)= BR_MUL(cj,si); M(a2,a2)= BR_MUL(cj,ci);
|
|
}
|
|
|
|
M(3,0) = M(3,1) = M(3,2) = S0;
|
|
|
|
return mat;
|
|
}
|
|
|
|
br_euler * BR_PUBLIC_ENTRY BrMatrix34ToEuler(br_euler *euler, br_matrix34 *mat)
|
|
{
|
|
br_uint_8 o = eO;
|
|
int a0,a1,a2;
|
|
|
|
UASSERT(mat != NULL);
|
|
UASSERT(euler != NULL);
|
|
UASSERT(euler->order < BR_ASIZE(OrderAxes));
|
|
|
|
a0 = OrderAxes[o].a0;
|
|
a1 = OrderAxes[o].a1;
|
|
a2 = OrderAxes[o].a2;
|
|
|
|
if(o & BR_EULER_REPEAT) {
|
|
br_scalar sy;
|
|
|
|
sy = BR_LENGTH2(M(a1,a0),M(a2,a0));
|
|
|
|
if(sy > BR_MUL(16,BR_SCALAR_EPSILON)) {
|
|
eX = BR_ATAN2( M(a1,a0), M(a2,a0));
|
|
eY = BR_ATAN2( sy, M(a0,a0));
|
|
eZ = BR_ATAN2( M(a0,a1),-M(a0,a2));
|
|
} else {
|
|
eX = BR_ATAN2(-M(a2,a1), M(a1,a1));
|
|
eY = BR_ATAN2( sy, M(a0,a0));
|
|
eZ = 0;
|
|
}
|
|
} else {
|
|
br_scalar cy;
|
|
|
|
cy = BR_LENGTH2(M(a0,a0),M(a0,a1));
|
|
|
|
if(cy > BR_MUL(16,BR_SCALAR_EPSILON)) {
|
|
eX = BR_ATAN2( M(a1,a2), M(a2,a2));
|
|
eY = BR_ATAN2(-M(a0,a2), cy);
|
|
eZ = BR_ATAN2( M(a0,a1), M(a0,a0));
|
|
} else {
|
|
eX = BR_ATAN2(-M(a2,a1), M(a1,a1));
|
|
eY = BR_ATAN2(-M(a0,a2), cy);
|
|
eZ = 0;
|
|
}
|
|
}
|
|
|
|
if(o & BR_EULER_PARITY) {
|
|
eX = -eX;
|
|
eY = -eY;
|
|
eZ = -eZ;
|
|
}
|
|
|
|
if(o & BR_EULER_FRAME) {
|
|
br_angle t;
|
|
|
|
t = eX;
|
|
eX = eZ;
|
|
eZ = t;
|
|
}
|
|
|
|
return euler;
|
|
}
|
|
|
|
br_matrix4 * BR_PUBLIC_ENTRY BrEulerToMatrix4(br_matrix4 *mat, br_euler *euler)
|
|
{
|
|
br_matrix34 tmp;
|
|
|
|
UASSERT(mat != NULL);
|
|
|
|
BrEulerToMatrix34(&tmp,euler);
|
|
|
|
BrMatrix4Copy34(mat,&tmp);
|
|
|
|
return mat;
|
|
}
|
|
|
|
br_euler * BR_PUBLIC_ENTRY BrMatrix4ToEuler(br_euler *dest, br_matrix4 *mat)
|
|
{
|
|
br_matrix34 tmp;
|
|
|
|
UASSERT(mat != NULL);
|
|
|
|
BrMatrix34Copy4(&tmp,mat);
|
|
|
|
return BrMatrix34ToEuler(dest,&tmp);
|
|
}
|
|
|
|
br_quat * BR_PUBLIC_ENTRY BrEulerToQuat(br_quat *q, br_euler *euler)
|
|
{
|
|
br_uint_8 o = eO;
|
|
br_angle ti,tj,th;
|
|
br_scalar ci,cj,ch,si,sj,sh,cc,cs,sc,ss;
|
|
int a0,a1,a2;
|
|
|
|
UASSERT(q != NULL);
|
|
UASSERT(euler != NULL);
|
|
UASSERT(euler->order < BR_ASIZE(OrderAxes));
|
|
|
|
if(o & BR_EULER_FRAME)
|
|
ti = eZ/2, tj = eY/2, th = eX/2;
|
|
else
|
|
ti = eX/2, tj = eY/2, th = eZ/2;
|
|
|
|
if(o & BR_EULER_PARITY)
|
|
tj = -tj;
|
|
|
|
ci = BR_COS(ti); cj = BR_COS(tj); ch = BR_COS(th);
|
|
si = BR_SIN(ti); sj = BR_SIN(tj); sh = BR_SIN(th);
|
|
cc = BR_MUL(ci,ch); cs = BR_MUL(ci,sh);
|
|
sc = BR_MUL(si,ch); ss = BR_MUL(si,sh);
|
|
|
|
a0 = OrderAxes[o].a0;
|
|
a1 = OrderAxes[o].a1;
|
|
a2 = OrderAxes[o].a2;
|
|
|
|
if(o & BR_EULER_REPEAT) {
|
|
qi(a0) = BR_MUL(cj,(cs+sc));
|
|
qi(a1) = BR_MUL(sj,(cc+ss));
|
|
qi(a2) = BR_MUL(sj,(cs-sc));
|
|
qi( 3) = BR_MUL(cj,(cc-ss));
|
|
} else {
|
|
qi(a0) = BR_MUL(cj,sc) - BR_MUL(sj,cs);
|
|
qi(a1) = BR_MUL(cj,ss) + BR_MUL(sj,cc);
|
|
qi(a2) = BR_MUL(cj,cs) - BR_MUL(sj,sc);
|
|
qi( 3) = BR_MUL(cj,cc) + BR_MUL(sj,ss);
|
|
}
|
|
|
|
if(o & BR_EULER_PARITY)
|
|
qi(a1) = -qi(a1);
|
|
|
|
return q;
|
|
}
|
|
|
|
br_euler * BR_PUBLIC_ENTRY BrQuatToEuler(br_euler *euler,
|
|
br_quat *q)
|
|
{
|
|
br_matrix34 mat;
|
|
|
|
/*
|
|
* Convert quat to matrix
|
|
*/
|
|
BrQuatToMatrix34(&mat,q);
|
|
|
|
/*
|
|
* Generate a matrix from the quat
|
|
*/
|
|
return BrMatrix34ToEuler(euler,&mat);
|
|
}
|
|
|