const bmw = new BMWalker();
document.oncontextmenu=()=> false;
this.elements = new Float32Array(16);
for (let i = 0; i < 16; i++) this.elements[i] = 0;
let radians = angle * PI / 180;
let len = sqrt(x * x + y * y + z * z);
let a00 = this.elements[0], a01 = this.elements[1], a02 = this.elements[2], a03 = this.elements[3],
a10 = this.elements[4], a11 = this.elements[5], a12 = this.elements[6], a13 = this.elements[7],
a20 = this.elements[8], a21 = this.elements[9], a22 = this.elements[10], a23 = this.elements[11];
let b00 = x * x * t + c, b01 = x * y * t - z * s, b02 = x * z * t + y * s,
b10 = y * x * t + z * s, b11 = y * y * t + c, b12 = y * z * t - x * s,
b20 = z * x * t - y * s, b21 = z * y * t + x * s, b22 = z * z * t + c;
this.elements[0] = a00 * b00 + a10 * b01 + a20 * b02;
this.elements[1] = a01 * b00 + a11 * b01 + a21 * b02;
this.elements[2] = a02 * b00 + a12 * b01 + a22 * b02;
this.elements[3] = a03 * b00 + a13 * b01 + a23 * b02;
this.elements[4] = a00 * b10 + a10 * b11 + a20 * b12;
this.elements[5] = a01 * b10 + a11 * b11 + a21 * b12;
this.elements[6] = a02 * b10 + a12 * b11 + a22 * b12;
this.elements[7] = a03 * b10 + a13 * b11 + a23 * b12;
this.elements[8] = a00 * b20 + a10 * b21 + a20 * b22;
this.elements[9] = a01 * b20 + a11 * b21 + a21 * b22;
this.elements[10] = a02 * b20 + a12 * b21 + a22 * b22;
this.elements[11] = a03 * b20 + a13 * b21 + a23 * b22;
function quaternionToEuler2(x,y,z,w) {
M.elements[0] = 1 - 2 * y * y - 2 * z * z;
M.elements[1] = 2 * x * y + 2 * z * w;
M.elements[2] = 2 * x * z - 2 * y * w;
M.elements[3] = 2 * x * y - 2 * z * w;
M.elements[4] = 1 - 2 * x * x - 2 * z * z;
M.elements[5] = 2 * y * z + 2 * x * w;
M.elements[6] = 2 * y * x + 2 * z * w;
M.elements[7] = 2 * y * z - 2 * x * w;
M.elements[8] = 2 * x * x + 1 - 2 * y * y;
M.elements[9] = 2 * y * z - 2 * x * w;
M.elements[10] = 2 * z * z + 1 - 2 * x * x;
let roll = Math.atan2(M.elements[5], M.elements[0]);
let pitch = Math.atan2(-M.elements[6], M.elements[8]);
let yaw = Math.atan2(M.elements[7], M.elements[9]);
function quaternionToEuler(x, y, z, w) {
const sinr_cosp = 2 * (w * x + y * z);
const cosr_cosp = 1 - 2 * (x * x + y * y);
const roll = Math.atan2(sinr_cosp, cosr_cosp);
const sinp = 2 * (w * y - z * x);
if (Math.abs(sinp) >= 1) {
pitch = Math.sign(sinp) * (Math.PI / 2);
const siny_cosp = 2 * (w * z + x * y);
const cosy_cosp = 1 - 2 * (y * y + z * z);
const yaw = Math.atan2(siny_cosp, cosy_cosp);
return { roll, pitch, yaw };
createCanvas(windowWidth,windowHeight, WEBGL);
bmw.setWalkerParam(0, 0, 0, 0);
map(mouseX, 0,width, -1.5,1.5),
noStroke();fill(0,127,127);
const lineMarkers = bmw.getLineMarkers(height*0.9);
lineMarkers.forEach((m) => {
lineEnd = createVector(m[0].x,m[0].y,0);
lineStart = createVector(m[1].x,m[1].y,0);
let lineDir = p5.Vector.sub(lineEnd, lineStart);
let axis = createVector(0, 1, 0).cross(lineDir);
let angle = -acos(createVector(0, 1, 0).dot(lineDir) / lineDir.mag()) * 180 / PI;
let rotationMatrix = new Matrix4();
rotationMatrix.rotate(angle, axis.x, axis.y, axis.z);
translate((lineEnd.x+lineStart.x)/2,(lineEnd.y+lineStart.y)/2,(lineEnd.z+lineStart.z)/2);
applyMatrix(rotationMatrix.elements);
cylinder(counter==7?40:10, lineDir.mag());
const markers = bmw.getMarkers(height*0.9);
markers.forEach((m, i) => {