Skip to content

Commit 1ebfe2b

Browse files
infusiontoji
authored andcommitted
Optimized quaternion rotation routine
1 parent d03371d commit 1ebfe2b

File tree

3 files changed

+51
-44
lines changed

3 files changed

+51
-44
lines changed

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV.
1+
Copyright (c) 2015-2024, Brandon Jones, Colin MacKenzie IV.
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal

src/vec3.js

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -538,40 +538,38 @@ export function transformMat3(out, a, m) {
538538
*
539539
* @param {vec3} out the receiving vector
540540
* @param {ReadonlyVec3} a the vector to transform
541-
* @param {ReadonlyQuat} q quaternion to transform with
541+
* @param {ReadonlyQuat} q normalized quaternion to transform with
542542
* @returns {vec3} out
543543
*/
544544
export function transformQuat(out, a, q) {
545-
// benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
546-
let qx = q[0],
545+
546+
// Fast Vector Rotation using Quaternions by Robert Eisele
547+
// https://raw.org/proof/vector-rotation-using-quaternions/
548+
549+
const qx = q[0],
547550
qy = q[1],
548551
qz = q[2],
549552
qw = q[3];
550-
let x = a[0],
551-
y = a[1],
552-
z = a[2];
553-
// var qvec = [qx, qy, qz];
554-
// var uv = vec3.cross([], qvec, a);
555-
let uvx = qy * z - qz * y,
556-
uvy = qz * x - qx * z,
557-
uvz = qx * y - qy * x;
558-
// var uuv = vec3.cross([], qvec, uv);
559-
let uuvx = qy * uvz - qz * uvy,
560-
uuvy = qz * uvx - qx * uvz,
561-
uuvz = qx * uvy - qy * uvx;
562-
// vec3.scale(uv, uv, 2 * w);
563-
let w2 = qw * 2;
564-
uvx *= w2;
565-
uvy *= w2;
566-
uvz *= w2;
567-
// vec3.scale(uuv, uuv, 2);
568-
uuvx *= 2;
569-
uuvy *= 2;
570-
uuvz *= 2;
571-
// return vec3.add(out, a, vec3.add(out, uv, uuv));
572-
out[0] = x + uvx + uuvx;
573-
out[1] = y + uvy + uuvy;
574-
out[2] = z + uvz + uuvz;
553+
554+
const vx = a[0],
555+
vy = a[1],
556+
vz = a[2];
557+
558+
// t = q x v
559+
let tx = qy * vz - qz * vy;
560+
let ty = qz * vx - qx * vz;
561+
let tz = qx * vy - qy * vx;
562+
563+
// t = 2t
564+
tx = tx + tx;
565+
ty = ty + ty;
566+
tz = tz + tz;
567+
568+
// v + w t + q x t
569+
out[0] = vx + qw * tx + qy * tz - qz * ty;
570+
out[1] = vy + qw * ty + qz * tx - qx * tz;
571+
out[2] = vz + qw * tz + qx * ty - qy * tx;
572+
575573
return out;
576574
}
577575

src/vec4.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ export function random(out, scale) {
449449
var v1, v2, v3, v4;
450450
var s1, s2;
451451
var rand;
452-
452+
453453
rand = glMatrix.RANDOM();
454454
v1 = rand * 2 - 1;
455455
v2 = (4 * glMatrix.RANDOM() - 2) * Math.sqrt(rand * -rand + rand);
@@ -493,28 +493,37 @@ export function transformMat4(out, a, m) {
493493
*
494494
* @param {vec4} out the receiving vector
495495
* @param {ReadonlyVec4} a the vector to transform
496-
* @param {ReadonlyQuat} q quaternion to transform with
496+
* @param {ReadonlyQuat} q normalized quaternion to transform with
497497
* @returns {vec4} out
498498
*/
499499
export function transformQuat(out, a, q) {
500-
let x = a[0],
501-
y = a[1],
502-
z = a[2];
503-
let qx = q[0],
500+
501+
// Fast Vector Rotation using Quaternions by Robert Eisele
502+
// https://raw.org/proof/vector-rotation-using-quaternions/
503+
504+
const qx = q[0],
504505
qy = q[1],
505506
qz = q[2],
506507
qw = q[3];
507508

508-
// calculate quat * vec
509-
let ix = qw * x + qy * z - qz * y;
510-
let iy = qw * y + qz * x - qx * z;
511-
let iz = qw * z + qx * y - qy * x;
512-
let iw = -qx * x - qy * y - qz * z;
509+
const vx = a[0],
510+
vy = a[1],
511+
vz = a[2];
512+
513+
// t = q x v
514+
let tx = qy * vz - qz * vy;
515+
let ty = qz * vx - qx * vz;
516+
let tz = qx * vy - qy * vx;
517+
518+
// t = 2t
519+
tx = tx + tx;
520+
ty = ty + ty;
521+
tz = tz + tz;
513522

514-
// calculate result * inverse quat
515-
out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
516-
out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
517-
out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
523+
// v + w t + q x t
524+
out[0] = vx + qw * tx + qy * tz - qz * ty;
525+
out[1] = vy + qw * ty + qz * tx - qx * tz;
526+
out[2] = vz + qw * tz + qx * ty - qy * tx;
518527
out[3] = a[3];
519528
return out;
520529
}

0 commit comments

Comments
 (0)