fix quat::get_hpr(), set_hpr() in non-standard coordinate systems

This commit is contained in:
David Rose 2005-03-04 21:29:33 +00:00
parent 59fbee7ece
commit 0c519fbc4f
2 changed files with 64 additions and 46 deletions

View File

@ -86,22 +86,22 @@ extract_to_matrix(FLOATNAME(LMatrix4) &m) const {
// (from Real-time Rendering, p.49) // (from Real-time Rendering, p.49)
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void FLOATNAME(LQuaternion):: void FLOATNAME(LQuaternion)::
set_hpr(const FLOATNAME(LVecBase3) &hpr) { set_hpr(const FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs) {
FLOATNAME(LQuaternion) quat_h, quat_p, quat_r; FLOATNAME(LQuaternion) quat_h, quat_p, quat_r;
FLOATNAME(LVector3) v; FLOATNAME(LVector3) v;
FLOATTYPE a, s, c; FLOATTYPE a, s, c;
v = FLOATNAME(LVector3)::up(); v = FLOATNAME(LVector3)::up(cs);
a = deg_2_rad(hpr[0] * 0.5f); a = deg_2_rad(hpr[0] * 0.5f);
csincos(a, &s, &c); csincos(a, &s, &c);
quat_h.set(c, v[0] * s, v[1] * s, v[2] * s); quat_h.set(c, v[0] * s, v[1] * s, v[2] * s);
v = FLOATNAME(LVector3)::right(); v = FLOATNAME(LVector3)::right(cs);
a = deg_2_rad(hpr[1] * 0.5f); a = deg_2_rad(hpr[1] * 0.5f);
csincos(a, &s, &c); csincos(a, &s, &c);
s = csin(a); s = csin(a);
quat_p.set(c, v[0] * s, v[1] * s, v[2] * s); quat_p.set(c, v[0] * s, v[1] * s, v[2] * s);
v = FLOATNAME(LVector3)::forward(); v = FLOATNAME(LVector3)::forward(cs);
a = deg_2_rad(hpr[2] * 0.5f); a = deg_2_rad(hpr[2] * 0.5f);
csincos(a, &s, &c); csincos(a, &s, &c);
quat_r.set(c, v[0] * s, v[1] * s, v[2] * s); quat_r.set(c, v[0] * s, v[1] * s, v[2] * s);
@ -136,7 +136,7 @@ set_hpr(const FLOATNAME(LVecBase3) &hpr) {
// quaternion. // quaternion.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
FLOATNAME(LVecBase3) FLOATNAME(LQuaternion):: FLOATNAME(LVecBase3) FLOATNAME(LQuaternion)::
get_hpr() const { get_hpr(CoordinateSystem cs) const {
if (!temp_hpr_fix) { if (!temp_hpr_fix) {
// With the old, broken hpr code in place, just go through the // With the old, broken hpr code in place, just go through the
// existing matrix decomposition code. Not particularly speedy, // existing matrix decomposition code. Not particularly speedy,
@ -146,11 +146,17 @@ get_hpr() const {
FLOATNAME(LMatrix3) mat; FLOATNAME(LMatrix3) mat;
extract_to_matrix(mat); extract_to_matrix(mat);
FLOATNAME(LVecBase3) scale, hpr; FLOATNAME(LVecBase3) scale, hpr;
decompose_matrix(mat, scale, hpr); decompose_matrix(mat, scale, hpr, cs);
return hpr; return hpr;
} }
if (cs == CS_default) {
cs = get_default_coordinate_system();
}
FLOATNAME(LVecBase3) hpr; FLOATNAME(LVecBase3) hpr;
if (cs == CS_zup_right) {
FLOATTYPE N = (_v.data[0] * _v.data[0]) + (_v.data[1] * _v.data[1]) + (_v.data[2] * _v.data[2]) + (_v.data[3] * _v.data[3]); FLOATTYPE N = (_v.data[0] * _v.data[0]) + (_v.data[1] * _v.data[1]) + (_v.data[2] * _v.data[2]) + (_v.data[3] * _v.data[3]);
FLOATTYPE s = (N == 0.0f) ? 0.0f : (2.0f / N); FLOATTYPE s = (N == 0.0f) ? 0.0f : (2.0f / N);
FLOATTYPE xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, c1, c2, c3, c4; FLOATTYPE xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, c1, c2, c3, c4;
@ -190,6 +196,18 @@ get_hpr() const {
hpr[0] = rad_2_deg(catan2(sh, ch)); hpr[0] = rad_2_deg(catan2(sh, ch));
hpr[1] = rad_2_deg(catan2(sp, cp)); hpr[1] = rad_2_deg(catan2(sp, cp));
} else {
// The code above implements quat-to-hpr for CS_zup_right only.
// For other coordinate systems, someone is welcome to extend the
// implementation; I'm going to choose the lazy path till then.
FLOATNAME(LMatrix3) mat;
extract_to_matrix(mat);
FLOATNAME(LVecBase3) scale;
decompose_matrix(mat, scale, hpr, cs);
return hpr;
}
#ifndef NDEBUG #ifndef NDEBUG
if (paranoid_hpr_quat) { if (paranoid_hpr_quat) {
FLOATNAME(LMatrix3) mat; FLOATNAME(LMatrix3) mat;

View File

@ -67,8 +67,8 @@ PUBLISHED:
void set_from_matrix(const FLOATNAME(LMatrix3) &m); void set_from_matrix(const FLOATNAME(LMatrix3) &m);
INLINE_LINMATH void set_from_matrix(const FLOATNAME(LMatrix4) &m); INLINE_LINMATH void set_from_matrix(const FLOATNAME(LMatrix4) &m);
void set_hpr(const FLOATNAME(LVecBase3) &hpr); void set_hpr(const FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs = CS_default);
FLOATNAME(LVecBase3) get_hpr() const; FLOATNAME(LVecBase3) get_hpr(CoordinateSystem cs = CS_default) const;
INLINE_LINMATH FLOATNAME(LVector3) get_axis() const; INLINE_LINMATH FLOATNAME(LVector3) get_axis() const;
INLINE_LINMATH FLOATTYPE get_angle() const; INLINE_LINMATH FLOATTYPE get_angle() const;