Created
October 19, 2018 02:02
-
-
Save flekschas/4467a9ae8c0fd9f687ab76e91cb53da1 to your computer and use it in GitHub Desktop.
A small library for rigid body transformations for WebGL.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { quat, vec3 } from 'gl-matrix'; | |
import * as rbt from './rigid-body-transform.js'; | |
const myFancyRbt = rbt.create(); | |
// Rotate 45 degree around the x axis | |
const r = rbt.create({ r: quat.fromEuler(45, 0, 0) }); | |
myFancyRbt.multiply(r); | |
// Translate | |
const t = rbt.create({ t: vec3.fromValues(1, 2, 3) }); | |
myFancyRbt.multiply(t); | |
// Translate and rotate!1!! (I know, now we're going crazy!) | |
const rt = rbt.create({ t: vec3.fromValues(1, 2, 3), r: quat.fromEuler(1, 33, 7) }); | |
// And store this crazy transformation as a new RBT | |
const myCrazyRbt = rbt.multiply(rbt.create(), myFancyRbt, rt); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mat4, quat, vec3, vec4 } from "gl-matrix"; | |
const scratch0 = new Float32Array(4); | |
const scratch1 = new Float32Array(4); | |
const scratch2 = new Float32Array(4); | |
const quatMulVec3 = (q, v) => { | |
const newQ = quat.multiply( | |
quat.create(), | |
quat.multiply(scratch0, q, quat.fromValues(0, v[0], v[1], v[2])), | |
quat.invert(scratch1, q), | |
); | |
return vec3.fromValues(newQ[1], newQ[2], newQ[3]); | |
}; | |
const quatMulVec4 = (q, v) => { | |
const newQ = quat.multiply( | |
quat.create(), | |
quat.multiply(scratch0, q, quat.fromValues(0, v[0], v[1], v[2])), | |
quat.invert(scratch1, q), | |
); | |
return vec4.fromValues(newQ[0], newQ[1], newQ[2], newQ[3]); | |
}; | |
const multiplyWithVec4 = (out, a, b) => vec4.add( | |
quatMulVec4(a.r, b), | |
vec4.scale(scratch2, [...a.getTranslation, 0], b[3]), | |
); | |
const multiplyWithRigidBodyTransform = (out, a, b) => { | |
vec3.add( | |
out.t, | |
a.t, | |
quatMulVec3(a.r, b.t), | |
); | |
quat.multiply(out.r, a.r, b.r); | |
return out; | |
}; | |
const multiply = (out, a, b, log = false) => { | |
if (!a.isRigidBodyTransform) { | |
console.warn('Param `a` needs to be a rigid body transformation.'); | |
return null; | |
} | |
if (b.length && b.length === 4) return multiplyWithVec4(out, a, b, log); | |
if (b.isRigidBodyTransform) return multiplyWithRigidBodyTransform(out, a, b, log); | |
console.warn( | |
'Variable `b` is of unknown datatype. ' | |
+ 'Only vec4 and rigid body transformations are supported.', | |
); | |
return null; | |
}; | |
const invert = (out, tform) => { | |
const rInv = quat.invert(quat.create(), tform.r); | |
out.setTranslation(quatMulVec3(rInv, vec3.negate(scratch2, tform.t))); | |
out.setRotation(rInv); | |
return out; | |
}; | |
const toMatrix = tform => mat4.fromRotationTranslation( | |
mat4.create(), | |
tform.r, | |
tform.t, | |
); | |
const create = ({ | |
t = vec3.create(), | |
r = quat.create(), | |
} = {}) => { | |
// Used for identifying this data type; | |
const isRigidBodyTransform = true; | |
const getTranslation = () => t; | |
const getRotation = () => r; | |
const setTranslation = (newT) => { t = newT; }; | |
const setRotation = (newR) => { r = newR; }; | |
const invertThis = function () { invert(this, this); }; | |
const multiplyThis = function (a) { multiply(this, this, a); }; | |
const toMatrixThis = function () { return toMatrix(this); }; | |
return { | |
isRigidBodyTransform, | |
get t() { return t; }, | |
get translation() { return t; }, | |
getTranslation, | |
get r() { return r; }, | |
get rotation() { return r; }, | |
getRotation, | |
set t(v) { return setTranslation(v); }, | |
set translation(v) { return setTranslation(v); }, | |
setTranslation, | |
set r(v) { return setRotation(v); }, | |
set rotation(v) { return setRotation(v); }, | |
setRotation, | |
invert: invertThis, | |
multiply: multiplyThis, | |
toMatrix: toMatrixThis, | |
}; | |
}; | |
export default create; | |
export { | |
create, | |
invert, | |
multiply, | |
toMatrix, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment