diff --git a/.gitignore b/.gitignore index 4b4b284..b1b2783 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ !*.gif !*.html +!*.js !*.md !*.woff2 diff --git a/cube.js b/cube.js new file mode 100644 index 0000000..0184837 --- /dev/null +++ b/cube.js @@ -0,0 +1,142 @@ +"use strict"; + +const __cube = document.querySelector(".cube"); + +class Vec3 { + static up = new Vec3(0, 1, 0); + static right = new Vec3(1, 0, 0); + + constructor(x, y, z) { + this.x = x; + this.y = y; + this.z = z; + } + + length() { + return Math.sqrt(this.x ** 2 + this.y ** 2 + this.z ** 2); + } + + normalize() { + const length = this.length(); + + if (length != 0) { + this.x /= length; + this.y /= length; + this.z /= length; + } + } + + static sub(v, t) { + return new Vec3( + v.x - t.x, + v.y - t.y, + v.z - t.z, + ) + } +} + +class Vec2 extends Vec3 { + constructor(x, y) { + super(x, y, 0) + } +} + +class Quat { + constructor(x, y, z, w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + static fromAngleAxis(angle, axis) { + axis.normalize(); + + const half = angle / 2; + + const sinHalf = Math.sin(half); + const cosHalf = Math.cos(half); + + const x = axis.x * sinHalf; + const y = axis.y * sinHalf; + const z = axis.z * sinHalf; + const w = cosHalf; + + return new Quat(x, y, z, w); + } + + static mul(q, r) { + return new Quat( + q.w * r.x + q.x * r.w + q.y * r.z - q.z * r.y, + q.w * r.y - q.x * r.z + q.y * r.w + q.z * r.x, + q.w * r.z + q.x * r.y - q.y * r.x + q.z * r.w, + q.w * r.w - q.x * r.x - q.y * r.y - q.z * r.z, + ); + } + + apply() { + __cube.style.transform = `rotate3d(${this.x}, ${this.y}, ${this.z}, ${this.w}rad)`; + } +} + +let friction = 0.01; +let sensitivity = 0.01; +let velocity = 0; + +const orientation = { + __value: new Quat(0, 0, 0, 1), + + set(value) { + this.__value = value; + this.__value.apply(); + }, + + get() { + return this.__value; + }, +}; + +(() => { + const mouse = { + down: false, + lastMove: window.performance.now(), + previous: new Vec2(0, 0), + }; + + document.addEventListener("mouseleave", () => { + mouse.down = false; + }); + + document.addEventListener("mouseup", () => { + mouse.down = false; + }); + + document.addEventListener("mousedown", (event) => { + // Disables link dragging that occurs when spinning. + event.preventDefault(); + mouse.down = true; + }); + + document.addEventListener("mousemove", (event) => { + if (!mouse.down) return; + + const newMouse = new Vec2(event.clientX, event.clientY); + + if (window.performance.now() - mouse.lastMove > 100) { + // This is a fresh scroll. + mouse.previous = newMouse; + } + + const delta = Vec2.sub(newMouse, mouse.previous); + + mouse.previous = newMouse; + mouse.lastMove = window.performance.now(); + + const rotation = Quat.mul( + Quat.fromAngleAxis(delta.x * sensitivity, Vec3.up), + Quat.fromAngleAxis(delta.y * sensitivity, Vec3.right), + ); + + orientation.set(Quat.mul(orientation.get(), rotation)); + }); +})(); diff --git a/index.html b/index.html index d5b022e..4822efd 100644 --- a/index.html +++ b/index.html @@ -223,150 +223,7 @@ - + - \ No newline at end of file +