Interactive WebGL Goldberg polyhedron viewer and painter with PBR shading, adjustable environment lighting, paint tools (pen, brush, circle, fill, line, pick), undo/redo, colour palettes, and mesh relaxation. Added to the standalone experiments index. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
46 lines
1.4 KiB
JavaScript
46 lines
1.4 KiB
JavaScript
import { quat_from_axis_angle, quat_mul } from './math.mjs';
|
|
|
|
export class Spin_State {
|
|
constructor() {
|
|
this.active = false;
|
|
this.axis = [0, 1, 0];
|
|
this.target = [0, 1, 0];
|
|
this.speed = 0.00035; // radians per millisecond
|
|
this.last_t = null;
|
|
}
|
|
|
|
_random_unit() {
|
|
let x, y, z, r;
|
|
do {
|
|
x = Math.random()*2-1; y = Math.random()*2-1; z = Math.random()*2-1;
|
|
r = Math.sqrt(x*x+y*y+z*z);
|
|
} while (r < 0.001 || r > 1);
|
|
return [x/r, y/r, z/r];
|
|
}
|
|
|
|
_new_target() { this.target = this._random_unit(); }
|
|
|
|
// Advance spin by dt ms. Returns updated rot_quat (unchanged if not active).
|
|
tick(dt, rot_quat) {
|
|
if (!this.active) { return rot_quat; }
|
|
if (this.last_t === null) { this._new_target(); return rot_quat; }
|
|
|
|
const drift = Math.min(1, dt * 0.0003);
|
|
const [ax,ay,az] = this.axis;
|
|
const [tx,ty,tz] = this.target;
|
|
let mx = ax + (tx-ax)*drift, my = ay + (ty-ay)*drift, mz = az + (tz-az)*drift;
|
|
const mr = Math.sqrt(mx*mx+my*my+mz*mz);
|
|
this.axis = [mx/mr, my/mr, mz/mr];
|
|
|
|
const dot = this.axis[0]*this.target[0] + this.axis[1]*this.target[1] + this.axis[2]*this.target[2];
|
|
if (dot > 0.999) { this._new_target(); }
|
|
|
|
const angle = this.speed * dt;
|
|
const [rx,ry,rz] = this.axis;
|
|
return quat_mul(quat_from_axis_angle(rx, ry, rz, angle), rot_quat);
|
|
}
|
|
|
|
start() { this.active = true; this.last_t = null; }
|
|
stop() { this.active = false; this.last_t = null; }
|
|
}
|