rust_webvr_api/
utils.rs

1#[cfg(feature = "utils")]
2
3use std::mem;
4use std::sync::atomic::AtomicUsize;
5use std::sync::atomic::Ordering::SeqCst;
6use time;
7
8static DEVICE_ID_COUNTER: AtomicUsize  = AtomicUsize::new(0);
9
10// Generates a unique identifier for any VRDisplay
11#[allow(dead_code)]
12pub fn new_id() -> u32 {
13    DEVICE_ID_COUNTER.fetch_add(1, SeqCst) as u32
14}
15
16// Returns the current time in milliseconds
17#[allow(dead_code)]
18pub fn timestamp() -> f64 {
19    let timespec = time::get_time();
20    timespec.sec as f64 * 1000.0 + (timespec.nsec as f64 * 1e-6)
21}
22
23// Multiply 4x4 matrices
24#[allow(dead_code)]
25pub fn multiply_matrix(a: &[f32; 16], b: &[f32; 16], out: &mut [f32; 16]) {
26    let mut tmp: [f32; 16] = [0.; 16];
27
28    tmp[0] = b[0] * a[0] + b[1] * a[4] + b[2] * a[8] + b[3] * a[12];
29    tmp[1] = b[0] * a[1] + b[1] * a[5] + b[2] * a[9] + b[3] * a[13];
30    tmp[2] = b[0] * a[2] + b[1] * a[6] + b[2] * a[10] + b[3] * a[14];
31    tmp[3] = b[0] * a[3] + b[1] * a[7] + b[2] * a[11] + b[3] * a[15];
32    
33    tmp[4] = b[4] * a[0] + b[5] * a[4] + b[6] * a[8] + b[7] * a[12];
34    tmp[5] = b[4] * a[1] + b[5] * a[5] + b[6] * a[9] + b[7] * a[13];
35    tmp[6] = b[4] * a[2] + b[5] * a[6] + b[6] * a[10] + b[7] * a[14];
36    tmp[7] = b[4] * a[3] + b[5] * a[7] + b[6] * a[11] + b[7] * a[15];
37    
38    tmp[8] = b[8] * a[0] + b[9] * a[4] + b[10] * a[8] + b[11] * a[12];
39    tmp[9] = b[8] * a[1] + b[9] * a[5] + b[10] * a[9] + b[11] * a[13];
40    tmp[10] = b[8] * a[2] + b[9] * a[6] + b[10] * a[10] + b[11] * a[14];
41    tmp[11] = b[8] * a[3] + b[9] * a[7] + b[10] * a[11] + b[11] * a[15];
42    
43    tmp[12] = b[12] * a[0] + b[13] * a[4] + b[14] * a[8] + b[15] * a[12];
44    tmp[13] = b[12] * a[1] + b[13] * a[5] + b[14] * a[9] + b[15] * a[13];
45    tmp[14] = b[12] * a[2] + b[13] * a[6] + b[14] * a[10] + b[15] * a[14];
46    tmp[15] = b[12] * a[3] + b[13] * a[7] + b[14] * a[11] + b[15] * a[15];
47
48    *out = tmp;
49}
50
51#[allow(dead_code)]
52pub fn inverse_matrix(m: &[f32; 16], out: &mut [f32; 16]) -> bool {
53    adjoint_matrix(&m, out);
54
55    let det = determinant4x4(m);
56    if det == 0f32 {
57        return false;
58    }
59
60    for i in 0..16 {
61        out[i] = out[i] / det;
62    }
63    true
64}
65
66#[allow(dead_code)]
67pub fn adjoint_matrix(m: &[f32; 16], out: &mut [f32; 16]) {
68    let mut tmp: [f32; 16] = [0.; 16];
69
70    tmp[0]  =   determinant3x3(m[5], m[9], m[13], m[6], m[10], m[14], m[7], m[11], m[15]);
71    tmp[4]  = - determinant3x3(m[4], m[8], m[12], m[6], m[10], m[14], m[7], m[11], m[15]);
72    tmp[8]  =   determinant3x3(m[4], m[8], m[12], m[5], m[9], m[13], m[7], m[11], m[15]);
73    tmp[12] = - determinant3x3(m[4], m[8], m[12], m[5], m[9], m[13], m[6], m[10], m[14]);
74
75    tmp[1]  = - determinant3x3(m[1], m[9], m[13], m[2], m[10], m[14], m[3], m[11], m[15]);
76    tmp[5]  =   determinant3x3(m[0], m[8], m[12], m[2], m[10], m[14], m[3], m[11], m[15]);
77    tmp[9]  = - determinant3x3(m[0], m[8], m[12], m[1], m[9], m[13], m[3], m[11], m[15]);
78    tmp[13] =   determinant3x3(m[0], m[8], m[12], m[1], m[9], m[13], m[2], m[10], m[14]);
79
80    tmp[2]  =   determinant3x3(m[1], m[5], m[13], m[2], m[6], m[14], m[3], m[7], m[15]);
81    tmp[6]  = - determinant3x3(m[0], m[4], m[12], m[2], m[6], m[14], m[3], m[7], m[15]);
82    tmp[10] =   determinant3x3(m[0], m[4], m[12], m[1], m[5], m[13], m[3], m[7], m[15]);
83    tmp[14] = - determinant3x3(m[0], m[4], m[12], m[1], m[5], m[13], m[2], m[6], m[14]);
84
85    tmp[3]  = - determinant3x3(m[1], m[5], m[9], m[2], m[6], m[10], m[3], m[7], m[11]);
86    tmp[7]  =   determinant3x3(m[0], m[4], m[8], m[2], m[6], m[10], m[3], m[7], m[11]);
87    tmp[11] = - determinant3x3(m[0], m[4], m[8], m[1], m[5], m[9], m[3], m[7], m[11]);
88    tmp[15] =   determinant3x3(m[0], m[4], m[8], m[1], m[5], m[9], m[2], m[6], m[10]);
89    
90    *out = tmp;
91}
92
93#[allow(dead_code)]
94pub fn determinant4x4(m: &[f32; 16]) -> f32 {
95    m[0] * determinant3x3(m[5], m[9], m[13], m[6], m[10], m[14], m[7], m[11], m[15])
96    - m[1] * determinant3x3(m[4], m[8], m[12], m[6], m[10], m[14], m[7], m[11], m[15])
97    + m[2] * determinant3x3(m[4], m[8], m[12], m[5], m[9], m[13], m[7], m[11], m[15])
98    - m[3] * determinant3x3(m[4], m[8], m[12], m[5], m[9], m[13], m[6], m[10], m[14])
99}
100
101#[allow(dead_code)]
102fn determinant3x3(a1: f32, a2: f32, a3: f32, b1: f32, b2: f32, b3: f32, c1: f32, c2: f32, c3: f32) -> f32 {
103    a1 * determinant2x2(b2, b3, c2, c3)
104    - b1 * determinant2x2(a2, a3, c2, c3)
105    + c1 * determinant2x2(a2, a3, b2, b3)
106}
107
108#[allow(dead_code)]
109#[inline]
110fn determinant2x2(a: f32, b: f32, c: f32, d: f32) -> f32 {
111    a * d - b * c
112}
113
114// Adapted from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
115#[allow(dead_code)]
116#[inline]
117pub fn matrix_to_quat(matrix: &[f32; 16]) -> [f32; 4] {
118    let m: &[[f32; 4]; 4] = unsafe { mem::transmute(matrix) };
119    let w = f32::max(0.0, 1.0 + m[0][0] + m[1][1] + m[2][2]).sqrt() * 0.5;
120    let mut x = f32::max(0.0, 1.0 + m[0][0] - m[1][1] - m[2][2]).sqrt() * 0.5;
121    let mut y = f32::max(0.0, 1.0 - m[0][0] + m[1][1] - m[2][2]).sqrt() * 0.5;
122    let mut z = f32::max(0.0, 1.0 - m[0][0] - m[1][1] + m[2][2]).sqrt() * 0.5;
123
124    x = copysign(x, m[2][1] - m[1][2]);
125    y = copysign(y, m[0][2] - m[2][0]);
126    z = copysign(z, m[1][0] - m[0][1]);
127
128    [x, y, z, w]
129}
130
131#[allow(dead_code)]
132#[inline]
133pub fn copysign(a: f32, b: f32) -> f32 {
134    if b == 0.0 {
135        0.0
136    } else {
137        a.abs() * b.signum()
138    }
139}