gltf_viewer_lib/render/
math.rs

1use std::f32;
2
3use cgmath;
4pub use cgmath::prelude::*;
5pub use cgmath::{vec3, vec4};
6
7use num_traits::clamp;
8
9use collision;
10
11pub type Vector2 = cgmath::Vector2<f32>;
12pub type Vector3 = cgmath::Vector3<f32>;
13pub type Vector4 = cgmath::Vector4<f32>;
14
15pub type Point3 = cgmath::Point3<f32>;
16
17pub type Matrix4 = cgmath::Matrix4<f32>;
18pub type Quaternion = cgmath::Quaternion<f32>;
19
20pub type Aabb3 = collision::Aabb3<f32>;
21
22// A point's spherical coordinates, inspired by ThreeJS version
23pub struct Spherical {
24    pub radius: f32,
25    pub phi: f32,
26    pub theta: f32,
27}
28
29impl Default for Spherical {
30    fn default() -> Self {
31        Spherical { radius: 1.0, phi: 0.0, theta: 0.0 }
32    }
33}
34
35impl Spherical {
36    pub fn from_vec3(vec3: Vector3) -> Self {
37        let radius = vec3.magnitude();
38        let (theta, phi) = if radius == 0.0 {
39            (0.0, 0.0)
40        } else {
41            (
42                vec3.x.atan2(vec3.z), // equator angle around y-up axis
43                clamp(vec3.y / radius, -1.0, 1.0).acos() // polar angle
44            )
45        };
46        Self {
47            radius,
48            theta,
49            phi
50        }
51    }
52
53    pub fn to_vec3(&self) -> Vector3 {
54        let sin_phi_radius = self.phi.sin() * self.radius;
55        let x = sin_phi_radius * self.theta.sin();
56        let y = self.phi.cos() * self.radius;
57        let z = sin_phi_radius * self.theta.cos();
58        vec3(x, y, z)
59    }
60}
61
62use std::num::ParseFloatError;
63pub fn parse_vec3(s: &str) -> Result<Vector3, ParseFloatError> {
64    let coords: Vec<&str> = s.split(',').collect();
65    assert!(coords.len() == 3, "Failed to parse Vector3 ({})", s);
66    let x = coords[0].parse::<f32>()?;
67    let y = coords[1].parse::<f32>()?;
68    let z = coords[2].parse::<f32>()?;
69
70    Ok(vec3(x, y, z))
71}