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