diff --git a/LICENSE.md b/LICENSE.md index 3a96fca4..7cba1934 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV. +Copyright (c) 2015-2024, Brandon Jones, Colin MacKenzie IV. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/vec3.js b/src/vec3.js index 650eafab..c54c5fab 100644 --- a/src/vec3.js +++ b/src/vec3.js @@ -538,40 +538,38 @@ export function transformMat3(out, a, m) { * * @param {vec3} out the receiving vector * @param {ReadonlyVec3} a the vector to transform - * @param {ReadonlyQuat} q quaternion to transform with + * @param {ReadonlyQuat} q normalized quaternion to transform with * @returns {vec3} out */ export function transformQuat(out, a, q) { - // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed - let qx = q[0], + + // Fast Vector Rotation using Quaternions by Robert Eisele + // https://raw.org/proof/vector-rotation-using-quaternions/ + + const qx = q[0], qy = q[1], qz = q[2], qw = q[3]; - let x = a[0], - y = a[1], - z = a[2]; - // var qvec = [qx, qy, qz]; - // var uv = vec3.cross([], qvec, a); - let uvx = qy * z - qz * y, - uvy = qz * x - qx * z, - uvz = qx * y - qy * x; - // var uuv = vec3.cross([], qvec, uv); - let uuvx = qy * uvz - qz * uvy, - uuvy = qz * uvx - qx * uvz, - uuvz = qx * uvy - qy * uvx; - // vec3.scale(uv, uv, 2 * w); - let w2 = qw * 2; - uvx *= w2; - uvy *= w2; - uvz *= w2; - // vec3.scale(uuv, uuv, 2); - uuvx *= 2; - uuvy *= 2; - uuvz *= 2; - // return vec3.add(out, a, vec3.add(out, uv, uuv)); - out[0] = x + uvx + uuvx; - out[1] = y + uvy + uuvy; - out[2] = z + uvz + uuvz; + + const vx = a[0], + vy = a[1], + vz = a[2]; + + // t = q x v + let tx = qy * vz - qz * vy; + let ty = qz * vx - qx * vz; + let tz = qx * vy - qy * vx; + + // t = 2t + tx = tx + tx; + ty = ty + ty; + tz = tz + tz; + + // v + w t + q x t + out[0] = vx + qw * tx + qy * tz - qz * ty; + out[1] = vy + qw * ty + qz * tx - qx * tz; + out[2] = vz + qw * tz + qx * ty - qy * tx; + return out; } diff --git a/src/vec4.js b/src/vec4.js index d1b96beb..6044df0a 100644 --- a/src/vec4.js +++ b/src/vec4.js @@ -449,7 +449,7 @@ export function random(out, scale) { var v1, v2, v3, v4; var s1, s2; var rand; - + rand = glMatrix.RANDOM(); v1 = rand * 2 - 1; v2 = (4 * glMatrix.RANDOM() - 2) * Math.sqrt(rand * -rand + rand); @@ -493,28 +493,37 @@ export function transformMat4(out, a, m) { * * @param {vec4} out the receiving vector * @param {ReadonlyVec4} a the vector to transform - * @param {ReadonlyQuat} q quaternion to transform with + * @param {ReadonlyQuat} q normalized quaternion to transform with * @returns {vec4} out */ export function transformQuat(out, a, q) { - let x = a[0], - y = a[1], - z = a[2]; - let qx = q[0], + + // Fast Vector Rotation using Quaternions by Robert Eisele + // https://raw.org/proof/vector-rotation-using-quaternions/ + + const qx = q[0], qy = q[1], qz = q[2], qw = q[3]; - // calculate quat * vec - let ix = qw * x + qy * z - qz * y; - let iy = qw * y + qz * x - qx * z; - let iz = qw * z + qx * y - qy * x; - let iw = -qx * x - qy * y - qz * z; + const vx = a[0], + vy = a[1], + vz = a[2]; + + // t = q x v + let tx = qy * vz - qz * vy; + let ty = qz * vx - qx * vz; + let tz = qx * vy - qy * vx; + + // t = 2t + tx = tx + tx; + ty = ty + ty; + tz = tz + tz; - // calculate result * inverse quat - out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; - out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; - out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; + // v + w t + q x t + out[0] = vx + qw * tx + qy * tz - qz * ty; + out[1] = vy + qw * ty + qz * tx - qx * tz; + out[2] = vz + qw * tz + qx * ty - qy * tx; out[3] = a[3]; return out; }