Skip to content

Commit 33a65b3

Browse files
committed
Quaternions support
1 parent f33ffc2 commit 33a65b3

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

src/math/matrix_operators.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,30 @@ export function invert_mat4(A: mat4): mat4 | null {
195195
);
196196
}
197197

198+
export function scalar_mult_vec3(u:vec3, n:number){
199+
return vec3(u[0]*n,u[1]*n,u[2]*n);
200+
}
201+
202+
export function scalar_mult(u:ArrayType, n:number){
203+
let out:ArrayType = new ArrayType(u.length);
204+
for(let i = 0; i < u.length; ++i){
205+
out[i] = u[i] * n;
206+
}
207+
return out;
208+
}
209+
210+
export function add_vec3(u:vec3, v:vec3): vec3{
211+
return vec3(u[0]+v[0],u[1]+v[1],u[2]+v[2]);
212+
}
213+
214+
export function add_mat(u:ArrayType, v:ArrayType):ArrayType{
215+
const out:ArrayType = new ArrayType(u.length);
216+
for(let i = 0; i < u.length; ++i){
217+
out[i] = u[i] + v[i];
218+
}
219+
return out;
220+
}
221+
198222

199223
export function length(v: ArrayType): number {
200224
return Math.sqrt(dot(v,v));

src/math/quaternions.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { add_vec3, cross, normalize, scalar_mult_vec3 } from "./matrix_operators";
2+
import { mat4, vec3, vec4 } from "./types";
3+
4+
5+
const EPSILON:number = 1e-7;
6+
7+
export function identity_quat():vec4{
8+
return vec4(0,0,0,1);
9+
}
10+
11+
export function quat_from_axis_angle(axis:vec3, angle:number):vec4{
12+
const half_angle = angle * 0.5;
13+
const prod:vec3 = scalar_mult_vec3(axis,Math.sin(half_angle));
14+
15+
return vec4(prod[0],prod[1],prod[2],Math.cos(half_angle));
16+
}
17+
18+
export function mul_quat(a:vec4, b:vec4):vec4{
19+
const ax = a[0], ay = a[1], az = a[2], aw = a[3];
20+
const bx = b[0], by = b[1], bz = b[2], bw = b[3];
21+
22+
return vec4(
23+
ax * bw + aw * bx + ay * bz - az * by,
24+
ay * bw + aw * by + az * bx - ax * bz,
25+
az * bw + aw * bz + ax * by - ay * bx,
26+
aw * bw - ax * bx - ay * by - az * bz
27+
);
28+
}
29+
30+
31+
/**
32+
* Rotates a vec3 with a quaternion
33+
* @param v
34+
* @param q A rotation quaternion
35+
*/
36+
export function rotate_vec3(v:vec3, q:vec4):vec3 {
37+
const quat_components = vec3(q[0],q[1],q[2]);
38+
39+
const t = scalar_mult_vec3(cross(quat_components,v),2.0);
40+
const prod_term = scalar_mult_vec3(t,q[3]);
41+
const first_term = add_vec3(v,prod_term);
42+
43+
return add_vec3(first_term,cross(quat_components,t));
44+
}
45+
46+
export function mat4_from_quat(q: vec4): mat4 {
47+
const x = q[0], y = q[1], z = q[2], w = q[3];
48+
49+
const x2 = x + x, y2 = y + y, z2 = z + z;
50+
const xx = x * x2, xy = x * y2, xz = x * z2;
51+
const yy = y * y2, yz = y * z2, zz = z * z2;
52+
const wx = w * x2, wy = w * y2, wz = w * z2;
53+
54+
return mat4(
55+
1 - (yy + zz), xy + wz, xz - wy, 0,
56+
xy - wz, 1 - (xx + zz), yz + wx, 0,
57+
xz + wy, yz - wx, 1 - (xx + yy), 0,
58+
0, 0, 0, 1
59+
);
60+
}
61+
62+
63+
export function slerp(start: vec4, end: vec4, t: number): vec4 {
64+
let x1 = start[0], y1 = start[1], z1 = start[2], w1 = start[3];
65+
let x2 = end[0], y2 = end[1], z2 = end[2], w2 = end[3];
66+
67+
let omega, cosom, sinom, scale0, scale1;
68+
cosom = x1 * x2 + y1 * y2 + z1 * z2 + w1 * w2;
69+
if (cosom < 0.0) {
70+
cosom = -cosom;
71+
x2 = -x2;
72+
y2 = -y2;
73+
z2 = -z2;
74+
w2 = -w2;
75+
}
76+
if ((1.0 - cosom) > EPSILON) {
77+
omega = Math.acos(cosom);
78+
sinom = Math.sin(omega);
79+
scale0 = Math.sin((1.0 - t) * omega) / sinom;
80+
scale1 = Math.sin(t * omega) / sinom;
81+
} else {
82+
scale0 = 1.0 - t;
83+
scale1 = t;
84+
}
85+
const res = vec4(
86+
scale0 * x1 + scale1 * x2,
87+
scale0 * y1 + scale1 * y2,
88+
scale0 * z1 + scale1 * z2,
89+
scale0 * w1 + scale1 * w2
90+
);
91+
92+
normalize(res);
93+
return res;
94+
}

0 commit comments

Comments
 (0)