diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index c6bec188b..84d7b64b4 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -58,10 +58,10 @@ extern const vec_t *const quat_origin; } while (0) #define QuatConj(a,b) \ do { \ - (b)[0] = (a)[0]; \ + (b)[0] = -(a)[0]; \ (b)[1] = -(a)[1]; \ (b)[2] = -(a)[2]; \ - (b)[3] = -(a)[3]; \ + (b)[3] = (a)[3]; \ } while (0) #define QuatAdd(a,b,c) \ do { \ diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index 05c93af59..e328ff2fc 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -76,8 +76,8 @@ typedef vec_t quat_t[4]; ///< A quaternion. typedef vec_t vec5_t[5]; typedef union { struct { - vec_t s; vec3_t v; + vec_t s; } sv; quat_t q; } Quat_t; diff --git a/libs/models/iqm/model_iqm.c b/libs/models/iqm/model_iqm.c index 6eabf7117..6d6e8de0b 100644 --- a/libs/models/iqm/model_iqm.c +++ b/libs/models/iqm/model_iqm.c @@ -118,7 +118,6 @@ get_joints (const iqmheader *hdr, byte *buffer) { iqmjoint *joint; uint32_t i, j; - float t; if (hdr->ofs_joints + hdr->num_joints * sizeof (iqmjoint) > hdr->filesize) return 0; @@ -135,10 +134,6 @@ get_joints (const iqmheader *hdr, byte *buffer) joint[i].translate[j] = LittleFloat (joint[i].translate[j]); for (j = 0; j < 4; j++) joint[i].rotate[j] = LittleFloat (joint[i].rotate[j]); - // iqm quaternions use xyzw but QF quaternions use wxyz - t = joint[i].rotate[3]; - memmove (&joint[i].rotate[1], &joint[i].rotate[0], 3 * sizeof (float)); - joint[i].rotate[0] = t; for (j = 0; j < 3; j++) joint[i].scale[j] = LittleFloat (joint[i].scale[j]); } @@ -442,19 +437,18 @@ load_iqm_anims (model_t *mod, const iqmheader *hdr, byte *buffer) if (p->mask & 0x004) translation[2] += *framedata++ * p->channelscale[2]; - // QF's quaternions are wxyz while IQM's quaternions are xyzw - rotation[1] = p->channeloffset[3]; + rotation[0] = p->channeloffset[3]; if (p->mask & 0x008) - rotation[1] += *framedata++ * p->channelscale[3]; - rotation[2] = p->channeloffset[4]; + rotation[0] += *framedata++ * p->channelscale[3]; + rotation[1] = p->channeloffset[4]; if (p->mask & 0x010) - rotation[2] += *framedata++ * p->channelscale[4]; - rotation[3] = p->channeloffset[5]; + rotation[1] += *framedata++ * p->channelscale[4]; + rotation[2] = p->channeloffset[5]; if (p->mask & 0x020) - rotation[3] += *framedata++ * p->channelscale[5]; - rotation[0] = p->channeloffset[6]; + rotation[2] += *framedata++ * p->channelscale[5]; + rotation[3] = p->channeloffset[6]; if (p->mask & 0x040) - rotation[0] += *framedata++ * p->channelscale[6]; + rotation[3] += *framedata++ * p->channelscale[6]; scale[0] = p->channeloffset[7]; if (p->mask & 0x080) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 9f1053025..a1e11f48b 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -248,11 +248,11 @@ QuatMult (const quat_t q1, const quat_t q2, quat_t out) vec_t s; vec3_t v; - s = q1[0] * q2[0] - DotProduct (q1 + 1, q2 + 1); - CrossProduct (q1 + 1, q2 + 1, v); - VectorMultAdd (v, q1[0], q2 + 1, v); - VectorMultAdd (v, q2[0], q1 + 1, out + 1); - out[0] = s; + s = q1[3] * q2[3] - DotProduct (q1, q2); + CrossProduct (q1, q2, v); + VectorMultAdd (v, q1[3], q2, v); + VectorMultAdd (v, q2[3], q1, out); + out[3] = s; } VISIBLE void @@ -261,12 +261,12 @@ QuatMultVec (const quat_t q, const vec3_t v, vec3_t out) vec_t s; vec3_t tv; - s = -DotProduct (q + 1, v); - CrossProduct (q + 1, v, tv); - VectorMultAdd (tv, q[0], v, tv); - CrossProduct (q + 1, tv, out); - VectorMultSub (out, s, q + 1, out); - VectorMultAdd (out, q[0], tv, out); + s = -DotProduct (q, v); + CrossProduct (q, v, tv); + VectorMultAdd (tv, q[3], v, tv); + CrossProduct (q, tv, out); + VectorMultSub (out, s, q, out); + VectorMultAdd (out, q[3], tv, out); } VISIBLE void @@ -288,19 +288,19 @@ QuatExp (const quat_t a, quat_t b) vec_t r; vec_t c, s; - VectorCopy (a + 1, n); + VectorCopy (a, n); th = VectorNormalize (n); - r = expf (a[0]); + r = expf (a[3]); c = cosf (th); s = sinf (th); - VectorScale (n, r * s, b + 1); - b[0] = r * c; + VectorScale (n, r * s, b); + b[3] = r * c; } VISIBLE void QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical) { - vec_t aa, ab, ac, ad, bb, bc, bd, cc, cd, dd; + vec_t xx, xy, xz, xw, yy, yz, yw, zz, zw, ww; vec_t *_m[4] = { m + (homogenous ? 0 : 0), m + (homogenous ? 4 : 3), @@ -308,28 +308,28 @@ QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical) m + (homogenous ? 12 : 9), }; - aa = q[0] * q[0]; - ab = q[0] * q[1]; - ac = q[0] * q[2]; - ad = q[0] * q[3]; + xx = q[0] * q[0]; + xy = q[0] * q[1]; + xz = q[0] * q[2]; + xw = q[0] * q[3]; - bb = q[1] * q[1]; - bc = q[1] * q[2]; - bd = q[1] * q[3]; + yy = q[1] * q[1]; + yz = q[1] * q[2]; + yw = q[1] * q[3]; - cc = q[2] * q[2]; - cd = q[2] * q[3]; + zz = q[2] * q[2]; + zw = q[2] * q[3]; - dd = q[3] * q[3]; + ww = q[3] * q[3]; if (vertical) { - VectorSet (aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac), _m[0]); - VectorSet (2 * (bc - ad), aa - bb + cc - dd, 2 * (cd + ab), _m[1]); - VectorSet (2 * (bd + ac), 2 * (cd - ab), aa - bb - cc + dd, _m[2]); + VectorSet (ww + xx - yy - zz, 2 * (xy + zw), 2 * (xz - yw), _m[0]); + VectorSet (2 * (xy - zw), ww - xx + yy - zz, 2 * (yz + xw), _m[1]); + VectorSet (2 * (xz + yw), 2 * (yz - xw), ww - xx - yy + zz, _m[2]); } else { - VectorSet (aa + bb - cc - dd, 2 * (bc - ad), 2 * (bd + ac), _m[0]); - VectorSet (2 * (bc + ad), aa - bb + cc - dd, 2 * (cd - ab), _m[1]); - VectorSet (2 * (bd - ac), 2 * (cd + ab), aa - bb - cc + dd, _m[2]); + VectorSet (ww + xx - yy - zz, 2 * (xy - zw), 2 * (xz + yw), _m[0]); + VectorSet (2 * (xy + zw), ww - xx + yy - zz, 2 * (yz - xw), _m[1]); + VectorSet (2 * (xz - yw), 2 * (yz + xw), ww - xx - yy + zz, _m[2]); } if (homogenous) { _m[0][3] = 0; @@ -555,10 +555,10 @@ AngleQuat (const vec3_t angles, quat_t q) sr = sin (alpha); cr = cos (alpha); - QuatSet (cy * cp * cr + sy * sp * sr, - cy * cp * sr - sy * sp * cr, - cy * sp * cr + sy * cp * sr, - sy * cp * cr - cy * sp * sr, + QuatSet (cy * cp * sr - sy * sp * cr, // x + cy * sp * cr + sy * cp * sr, // y + sy * cp * cr - cy * sp * sr, // z + cy * cp * cr + sy * sp * sr, // w q); } @@ -1112,29 +1112,29 @@ Mat3Decompose (const mat3_t mat, quat_t rot, vec3_t shear, vec3_t scale) t = 1 + row[0][0] + row[1][1] + row[2][2]; if (t >= 1e-5) { vec_t s = sqrt (t) * 2; - rot[0] = s / 4; - rot[1] = (row[2][1] - row[1][2]) / s; - rot[2] = (row[0][2] - row[2][0]) / s; - rot[3] = (row[1][0] - row[0][1]) / s; + rot[0] = (row[2][1] - row[1][2]) / s; + rot[1] = (row[0][2] - row[2][0]) / s; + rot[2] = (row[1][0] - row[0][1]) / s; + rot[3] = s / 4; } else { if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { vec_t s = sqrt (1 + row[0][0] - row[1][1] - row[2][2]) * 2; - rot[0] = (row[2][1] - row[1][2]) / s; - rot[1] = s / 4; - rot[2] = (row[1][0] + row[0][1]) / s; - rot[3] = (row[0][2] + row[2][0]) / s; + rot[0] = s / 4; + rot[1] = (row[1][0] + row[0][1]) / s; + rot[2] = (row[0][2] + row[2][0]) / s; + rot[3] = (row[2][1] - row[1][2]) / s; } else if (row[1][1] > row[2][2]) { vec_t s = sqrt (1 + row[1][1] - row[0][0] - row[2][2]) * 2; - rot[0] = (row[0][2] - row[2][0]) / s; - rot[1] = (row[1][0] + row[0][1]) / s; - rot[2] = s / 4; - rot[3] = (row[2][1] + row[1][2]) / s; + rot[0] = (row[1][0] + row[0][1]) / s; + rot[1] = s / 4; + rot[2] = (row[2][1] + row[1][2]) / s; + rot[3] = (row[0][2] - row[2][0]) / s; } else { vec_t s = sqrt (1 + row[2][2] - row[0][0] - row[1][1]) * 2; - rot[0] = (row[1][0] - row[0][1]) / s; - rot[1] = (row[0][2] + row[2][0]) / s; - rot[2] = (row[2][1] + row[1][2]) / s; - rot[3] = s / 4; + rot[0] = (row[0][2] + row[2][0]) / s; + rot[1] = (row[2][1] + row[1][2]) / s; + rot[2] = s / 4; + rot[3] = (row[1][0] - row[0][1]) / s; } } return 1; diff --git a/libs/util/test/test-mat3.c b/libs/util/test/test-mat3.c index 385200750..f852d281a 100644 --- a/libs/util/test/test-mat3.c +++ b/libs/util/test/test-mat3.c @@ -80,7 +80,8 @@ negate: return 1; fail: - printf ("\n\n(%g %g %g)\n", VectorExpand (angles)); + printf ("\ntest_angle\n"); + printf ("(%g %g %g)\n", VectorExpand (angles)); printf (" [%g %g %g %g]\n", QuatExpand (rotation)); printf (" [%g %g %g %g] [%g %g %g] [%g %g %g]\n", QuatExpand (r), VectorExpand (scale), VectorExpand (shear)); @@ -110,7 +111,8 @@ test_transform (const vec3_t angles, const vec3_t scale) return 1; fail: - printf ("\n\n(%g %g %g) (%g %g %g)\n", VectorExpand (angles), + printf ("\ntest_transform\n"); + printf ("(%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale)); printf (" (%g %g %g)\n", VectorExpand (x)); printf (" (%g %g %g)\n", VectorExpand (y)); @@ -146,7 +148,8 @@ test_transform2 (const vec3_t angles, const vec3_t scale) return 1; fail: - printf ("\n\n(%g %g %g) (%g %g %g) (%g %g %g)\n", + printf ("\ntest_transform2\n"); + printf ("(%g %g %g) (%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale), VectorExpand (v)); printf (" (%g %g %g)\n", VectorExpand (x)); printf (" (%g %g %g)\n", VectorExpand (y)); @@ -173,7 +176,8 @@ test_inverse (const vec3_t angles, const vec3_t scale) return 1; fail: - printf ("\n\n(%g %g %g) (%g %g %g)\n", + printf ("\ntest_inverse\n"); + printf ("(%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale)); printf (" [%g %g %g]\n [%g %g %g]\n [%g %g %g]\n\n", Mat3Expand (mat)); printf (" [%g %g %g]\n [%g %g %g]\n [%g %g %g]\n\n", Mat3Expand (inv)); diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index ce679771c..47539d144 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -9,7 +9,7 @@ static struct { quat_t q2; quat_t expect; } quat_mult_tests[] = { - {{4, 1, 2, 3}, {8, 5, 6, 7}, {-6, 24, 48, 48}}, + {{1, 2, 3, 4}, {5, 6, 7, 8}, {24, 48, 48, -6}}, }; #define num_quat_mult_tests (sizeof (quat_mult_tests) / sizeof (quat_mult_tests[0])) @@ -50,10 +50,10 @@ test_quat_mult(const quat_t q1, const quat_t q2, const quat_t expect) goto fail; return 1; fail: - printf ("%g %g %g %g\n", QuatExpand (q1)); - printf ("%g %g %g %g\n", QuatExpand (q2)); - printf ("%g %g %g %g\n", QuatExpand (r)); - printf ("%g %g %g %g\n", QuatExpand (expect)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q1)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q2)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (r)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (expect)); return 0; } @@ -64,12 +64,12 @@ rotate_vec (const quat_t r, const vec3_t v, vec3_t out) quat_t qv = {0, 0, 0, 0}; quat_t t; - VectorCopy (v, qv + 1); + VectorCopy (v, qv); QuatConj (r, t); QuatMult (qv, t, t); QuatMult (r, t, t); - VectorCopy (t + 1, out); + VectorCopy (t, out); } static int @@ -78,54 +78,55 @@ test_rotation (const vec3_t angles) int i; vec3_t forward, right, up; - quat_t quat, f, r, u, t; - quat_t qf = {0, 1, 0, 0}; - quat_t qr = {0, 0, -1, 0}; - quat_t qu = {0, 0, 0, 1}; + quat_t quat, conj, f, r, u, t; + quat_t qf = {1, 0, 0, 0}; + quat_t qr = {0, -1, 0, 0}; + quat_t qu = {0, 0, 1, 0}; AngleVectors (angles, forward, right, up); AngleQuat (angles, quat); + QuatConj (quat, conj); // rotate forward vector - QuatConj (quat, t); - QuatMult (qf, t, t); + QuatMult (qf, conj, t); QuatMult (quat, t, f); // rotate right vector - QuatConj (quat, t); - QuatMult (qr, t, t); + QuatMult (qr, conj, t); QuatMult (quat, t, r); // rotate up vector - QuatConj (quat, t); - QuatMult (qu, t, t); + QuatMult (qu, conj, t); QuatMult (quat, t, u); - if (!compare (f[0], 0)) + if (!compare (f[3], 0)) goto fail; for (i = 0; i < 3; i++) - if (!compare (forward[i], f[i + 1])) + if (!compare (forward[i], f[i])) goto fail; - if (!compare (r[0], 0)) + if (!compare (r[3], 0)) goto fail; for (i = 0; i < 3; i++) - if (!compare (right[i], r[i + 1])) + if (!compare (right[i], r[i])) goto fail; - if (!compare (u[0], 0)) + if (!compare (u[3], 0)) goto fail; for (i = 0; i < 3; i++) - if (!compare (up[i], u[i + 1])) + if (!compare (up[i], u[i])) goto fail; return 1; fail: - printf ("\n\n%g %g %g\n\n", angles[0], angles[1], angles[2]); - printf ("%g %g %g\n", forward[0], forward[1], forward[2]); - printf ("%g %g %g\n", right[0], right[1], right[2]); - printf ("%g %g %g\n\n", up[0], up[1], up[2]); + printf ("\ntest_rotation\n"); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand (angles)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (quat)); + printf ("%11.9g %11.9g %11.9g %11.9g\n\n", QuatExpand (conj)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand (forward)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand (right)); + printf ("%11.9g %11.9g %11.9g\n\n", VectorExpand (up)); - printf ("%g %g %g %g\n", f[0], f[1], f[2], f[3]); - printf ("%g %g %g %g\n", r[0], r[1], r[2], r[3]); - printf ("%g %g %g %g\n", u[0], u[1], u[2], u[3]); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (f)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (r)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (u)); return 0; } @@ -164,14 +165,15 @@ test_rotation2 (const vec3_t angles) goto fail; return 1; fail: - printf ("\n\n%g %g %g\n\n", angles[0], angles[1], angles[2]); - printf ("%g %g %g\n", forward[0], forward[1], forward[2]); - printf ("%g %g %g\n", right[0], right[1], right[2]); - printf ("%g %g %g\n\n", up[0], up[1], up[2]); + printf ("\ntest_rotation2\n"); + printf ("\n\n%11.9g %11.9g %11.9g\n\n", angles[0], angles[1], angles[2]); + printf ("%11.9g %11.9g %11.9g\n", forward[0], forward[1], forward[2]); + printf ("%11.9g %11.9g %11.9g\n", right[0], right[1], right[2]); + printf ("%11.9g %11.9g %11.9g\n\n", up[0], up[1], up[2]); - printf ("%g %g %g\n", f[0], f[1], f[2]); - printf ("%g %g %g\n", r[0], r[1], r[2]); - printf ("%g %g %g\n", u[0], u[1], u[2]); + printf ("%11.9g %11.9g %11.9g\n", f[0], f[1], f[2]); + printf ("%11.9g %11.9g %11.9g\n", r[0], r[1], r[2]); + printf ("%11.9g %11.9g %11.9g\n", u[0], u[1], u[2]); return 0; } @@ -192,8 +194,9 @@ test_rotation3 (const vec3_t angles) goto fail; return 1; fail: - printf ("%g %g %g\n", VectorExpand(a)); - printf ("%g %g %g\n", VectorExpand(b)); + printf ("\ntest_rotation3\n"); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(a)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(b)); return 0; } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index f212cbe7a..682ffb628 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -543,8 +543,8 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) msurface_t *surf; dstring_t *vertices; - QuatSet (sqrt(0.5), 0, 0, sqrt(0.5), sky_fix); // proper skies - QuatSet (1, 0, 0, 0, sky_rotation[0]); + QuatSet (0, 0, sqrt(0.5), sqrt(0.5), sky_fix); // proper skies + QuatSet (0, 0, 0, 1, sky_rotation[0]); QuatCopy (sky_rotation[0], sky_rotation[1]); QuatSet (0, 0, 0, 0, sky_velocity); QuatExp (sky_velocity, sky_velocity); diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index e346b31af..2a912fcb0 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -464,8 +464,8 @@ main (void) m += bonemats[int (vbones.z)] * vweights.z; m += bonemats[int (vbones.w)] * vweights.w; #if 0 - q0 = m[0].yzwx; //swizzle for conversion betwen QF and GL - qe = m[1].yzwx; //swizzle for conversion betwen QF and GL + q0 = m[0]; + qe = m[1]; sh = m[2].xyz; sc = m[3].xyz; diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index 4fa961228..224182a79 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -99,7 +99,7 @@ R_IQMBlendFrames (const iqm_t *iqm, int frame1, int frame2, float blend, } else { #if 0 for (i = 0; i < iqm->num_joints; i++) { - QuatSet (1, 0, 0, 0, frame[i].rt.q0.q); + QuatSet (0, 0, 0, 1, frame[i].rt.q0.q); QuatSet (0, 0, 0, 0, frame[i].rt.qe.q); QuatSet (0, 0, 0, 0, frame[i].shear); QuatSet (1, 1, 1, 0, frame[i].scale); diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 33c156cca..ee754f587 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -593,11 +593,11 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) return e; if (is_float_val (e1)) { - float_quat[0] = expr_float (e1); + QuatSet (0, 0, 0, expr_float (e1), float_quat); q2 = float_quat; q1 = expr_quaternion (e2); } else if (is_float_val (e2)) { - float_quat[0] = expr_float (e2); + QuatSet (0, 0, 0, expr_float (e2), float_quat); q2 = float_quat; q1 = expr_quaternion (e1); } else { @@ -627,7 +627,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) if (get_type (e2) == &type_quaternion) { QuatMult (q1, q2, q); } else { - QuatScale (q1, q2[0], q); + QuatScale (q1, q2[3], q); } e = new_quaternion_expr (q); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0270ff58f..c8aebc5e0 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -163,35 +163,42 @@ convert_vector (expr_t *e) if (e->e.vector.type == &type_quaternion) { // guaranteed to have two or four elements if (e->e.vector.list->next->next) { - // four vals: w, x, y, z - expr_t *w = e->e.vector.list; - expr_t *x = w->next; + // four vals: x, y, z, w + expr_t *x = e->e.vector.list; expr_t *y = x->next; expr_t *z = y->next; - w = fold_constants (cast_expr (&type_float, w)); + expr_t *w = z->next; x = fold_constants (cast_expr (&type_float, x)); y = fold_constants (cast_expr (&type_float, y)); z = fold_constants (cast_expr (&type_float, z)); - if (is_constant (w) && is_constant (x) && is_constant (y) - && is_constant (z)) { - val[0] = expr_float(w); - val[1] = expr_float(x); - val[2] = expr_float(y); - val[3] = expr_float(z); + w = fold_constants (cast_expr (&type_float, w)); + if (is_constant (x) && is_constant (y) && is_constant (z) + && is_constant (w)) { + val[0] = expr_float(x); + val[1] = expr_float(y); + val[2] = expr_float(z); + val[3] = expr_float(w); return new_quaternion_expr (val); } } else { - // s, v - expr_t *s = e->e.vector.list; - expr_t *v = s->next; + // v, s + expr_t *v = e->e.vector.list; + expr_t *s = v->next; - s = fold_constants (cast_expr (&type_float, s)); v = convert_vector (v); - if (is_constant (s) && is_constant (v)) { - val[0] = expr_float (s); - memcpy (val + 1, expr_vector (v), 3 * sizeof (float)); + s = fold_constants (cast_expr (&type_float, s)); + if (is_constant (v) && is_constant (s)) { + memcpy (val, expr_vector (v), 3 * sizeof (float)); + val[3] = expr_float (s); return new_quaternion_expr (val); } + // Either v or is is not constant, so can't convert to a quaternion + // constant. + // Rebuild the list in case v or s is a new expression + s->next = 0; + v->next = s; + e->e.vector.list = v; + return e; } } internal_error (e, "bogus vector expression"); @@ -645,13 +652,23 @@ new_vector_list (expr_t *e) vec->e.vector.list = e; break; case 2: - // quaternion. first expression must be compatible with a float, - // the other must be a vector - if (!type_assignable (&type_float, get_type (e)) - || !type_assignable (&type_vector, get_type(e->next))) { + // quaternion. either float-ish, vector or vector, float-ish + if (type_assignable (&type_float, get_type (e)) + && type_assignable (&type_vector, get_type(e->next))) { + // float-ish, vector + // swap expressions + t = e; + e = e->next; + e->next = t; + t->next = 0; + } else if (type_assignable (&type_vector, get_type (e)) + && type_assignable (&type_float, get_type(e->next))) { + // vector, float-ish + // do nothing + } else { return error (t, "invalid types for vector elements"); } - // s, v + // v, s vec = new_expr (); vec->type = ex_vector; vec->e.vector.type = &type_quaternion; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index cdd18f991..1ebd97f4b 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -193,8 +193,11 @@ qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) space->type = qfos_string; space->num_defs = 0; space->defs = 0; - space->d.strings = malloc (size); - memcpy (space->d.strings, strings->strings, size); + space->d.strings = 0; + if (strings->strings) { + space->d.strings = malloc (size); + memcpy (space->d.strings, strings->strings, size); + } space->data_size = strings->size; space->id = qfo_strings_space; } @@ -207,8 +210,11 @@ qfo_init_code_space (qfo_t *qfo, qfo_mspace_t *space, codespace_t *code) space->type = qfos_code; space->num_defs = 0; space->defs = 0; - space->d.code = malloc (size); - memcpy (space->d.code, code->code, size); + space->d.code = 0; + if (code->code) { + space->d.code = malloc (size); + memcpy (space->d.code, code->code, size); + } space->data_size = code->size; space->id = qfo_code_space; } @@ -222,8 +228,11 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_data; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } space->data_size = data->size; } @@ -249,8 +258,11 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_type; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } space->data_size = data->size; space->id = qfo_type_space; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index bb1e3d7c2..c81222db0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -843,8 +843,8 @@ init_types (void) {0, 0} }; static struct_def_t quaternion_struct[] = { - {"s", &type_float}, {"v", &type_vector}, + {"s", &type_float}, {0, 0} }; static struct_def_t type_encoding_struct[] = { @@ -882,16 +882,16 @@ init_types (void) type_quaternion.meta = ty_none; { symbol_t *sym; - sym = new_symbol_type ("w", &type_float); + sym = new_symbol_type ("x", &type_float); sym->s.offset = 0; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("x", &type_float); + sym = new_symbol_type ("y", &type_float); sym->s.offset = 1; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("y", &type_float); + sym = new_symbol_type ("z", &type_float); sym->s.offset = 2; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("z", &type_float); + sym = new_symbol_type ("w", &type_float); sym->s.offset = 3; symtab_addsymbol (type_quaternion.t.symtab, sym); } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index ad84f25ae..f530f3b3a 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -316,9 +316,7 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) return !memcmp (&imm1->i.pointer, &imm2->i.pointer, sizeof (imm1->i.pointer)); } else if (tab == &quaternion_imm_defs) { - return (VectorCompare (imm1->i.quaternion_val, - imm2->i.quaternion_val) - && imm1->i.quaternion_val[3] == imm2->i.quaternion_val[3]); + return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); } else if (tab == &integer_imm_defs) { return imm1->i.integer_val == imm2->i.integer_val; } else { diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index b1a199fff..1ecb95fb4 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -37,6 +37,7 @@ test_progs_dat=\ infloop.dat \ modulo.dat \ paramret.dat \ + quaternion.dat \ return-ivar.dat \ sendv.dat \ state.dat \ @@ -130,6 +131,14 @@ paramret.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ include ./$(DEPDIR)/paramret.Qo +quaternion_dat_SOURCES=quaternion.r +quaternion_obj=$(quaternion_dat_SOURCES:.r=.qfo) +quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) +quaternion.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/quaternion.Qo + return_ivar_dat_SOURCES=return-ivar.r return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/quaternion.r b/tools/qfcc/test/quaternion.r new file mode 100644 index 000000000..f5f2c889a --- /dev/null +++ b/tools/qfcc/test/quaternion.r @@ -0,0 +1,73 @@ +void printf (string fmt, ...) = #0; + +int +test_format () +{ + int fail = 0; + quaternion q = '1 2 3 4'; + vector v = '-1 -2 -3'; + float s = -4; + + if (q.x != 1 || q.y != 2 || q.z != 3 || q.w != 4) { + printf ("q = '1 2 3 4' -> %q\n", q); + fail = 1; + } + if (q.v != '1 2 3' || q.s != 4) { + printf ("q = '1 2 3 4' -> %v, %g\n", q.v, q.s); + fail = 1; + } + q = nil; + if (q.x != 0 || q.y != 0 || q.z != 0 || q.w != 0) { + printf ("q = nil -> %q\n", q); + fail = 1; + } + if (q.v != '0 0 0' || q.s != 0) { + printf ("q = nil -> %v, %g\n", q.v, q.s); + fail = 1; + } + q = [1, [2, 3, 4]]; + if (q.x != 2 || q.y != 3 || q.z != 4 || q.w != 1) { + printf ("q = [1, [2, 3, 4]] -> %q\n", q); + fail = 1; + } + if (q.v != '2 3 4' || q.s != 1) { + printf ("q = [1, [2, 3, 4]] -> %v, %g\n", q.v, q.s); + fail = 1; + } + q = [[5, 6, 7], 8]; + if (q.x != 5 || q.y != 6 || q.z != 7 || q.w != 8) { + printf ("q = [[5, 6, 7], 8] -> %q\n", q); + fail = 1; + } + if (q.v != '5 6 7' || q.s != 8) { + printf ("q = [[5, 6, 7], 8] -> %v, %g\n", q.v, q.s); + fail = 1; + } +/* q = [s, v]; + if (q.x != v.x || q.y != v.y || q.z != v.z || q.w != s) { + printf ("q = [s, v] -> %q (%v)\n", q, v); + fail = 1; + } + if (q.v != v || q.s != s) { + printf ("q = [s, v] -> %v, %g (%v)\n", q.v, q.s, v); + fail = 1; + } + q = [v, s]; + if (q.x != v.x || q.y != v.y || q.z != v.z || q.w != s) { + printf ("q = [v, s] -> %q (%v %s)\n", q, v, s); + fail = 1; + } + if (q.v != v || q.s != s) { + printf ("q = [v, s] -> %v, %g (%v %s)\n", q.v, q.s, v, s); + fail = 1; + }*/ + return fail; +} + +int +main () +{ + int fail = 0; + fail |= test_format (); + return fail; +} diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index b364a7f0c..dcb251037 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -165,7 +165,10 @@ load_progs (const char *name) return 0; } pr.progs_name = name; - PR_LoadProgsFile (&pr, file, size, 16, 1024 * 1024); + pr.max_edicts = 16; + pr.zone_size = 1024 * 1024; + pr.stack_size = 64 * 1024; + PR_LoadProgsFile (&pr, file, size); Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name);