Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 5x 90x 90x 90x 90x 30x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 30x 15x 15x 15x | import {vectorLength,multiplyVector} from './vector'
export const Quaternion = class Quaternion {
constructor(x, y, z, w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
static fromVector(vector) {
// Convert vector to quaternion with w = 0
return new Quaternion(vector.x, vector.y, vector.z, 0);
}
toVector() {
// Convert quaternion back to vector, ignoring w
return {x:this.x, y:this.y, z:this.z};
}
static dot(q1, q2) {
return q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
}
static slerpFromVectors(u,v,t) {
const normU=vectorLength(u)
const normV=vectorLength(v)
const newNormW = normU+Math.pow(Math.sin(t*Math.PI/2),2)*(normV - normU)
const U=normU!=0?multiplyVector(1/normU,u):u
const V=normV!=0?multiplyVector(1/normV,v):V
const qU=Quaternion.fromVector(U)
const qV=Quaternion.fromVector(V)
const qW = Quaternion.slerp(qU,qV,t)
const W=qW.toVector()
const normW = vectorLength(W)
const w = normW!=0 ? multiplyVector(newNormW/normW,W) : W
return w
}
static slerp(q1, q2, t) {
let dot = Quaternion.dot(q1, q2)
// Clamp dot product to stay in the domain of acos()
dot = Math.max(-1, Math.min(1, dot))
const theta_0 = Math.acos(dot)
Iif(theta_0<0.01){
return q1
}
const theta = theta_0 * t
const thetaComp = theta_0 * (1-t)
const sinTheta = Math.sin(theta)
const sinThetaComp = Math.sin(thetaComp)
const sinTheta_0 = Math.sin(theta_0)
const s1 = sinThetaComp/sinTheta_0
const s2 = sinTheta/sinTheta_0
const q1Component = q1.multiply(s1)
const q2Component = q2.multiply(s2)
const result = q1Component.add(q2Component)
return result.normalize()
}
multiply(scalar) {
return new Quaternion(this.x * scalar, this.y * scalar, this.z * scalar, this.w * scalar);
}
add(q) {
return new Quaternion(this.x + q.x, this.y + q.y, this.z + q.z, this.w + q.w);
}
subtract(q) {
return new Quaternion(this.x - q.x, this.y - q.y, this.z - q.z, this.w - q.w);
}
normalize() {
const norm = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
return new Quaternion(this.x / norm, this.y / norm, this.z / norm, this.w / norm);
}
} |