Changed how NoiseTexture is created to allow noise function and parameters to be passed in as options. Allowed setting of noise source from URL parameters.
277 lines
5.4 KiB
Rust
277 lines
5.4 KiB
Rust
use std::convert::From;
|
|
use std::fmt;
|
|
use std::num::ParseFloatError;
|
|
use std::ops::Add;
|
|
use std::ops::Div;
|
|
use std::ops::Index;
|
|
use std::ops::Mul;
|
|
use std::ops::Neg;
|
|
use std::ops::Sub;
|
|
use std::str;
|
|
|
|
#[derive(Default, Debug, Deserialize, Serialize, PartialEq, Copy, Clone)]
|
|
pub struct Vec3 {
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub z: f32,
|
|
}
|
|
|
|
pub fn cross(v1: Vec3, v2: Vec3) -> Vec3 {
|
|
Vec3 {
|
|
x: v1.y * v2.z - v1.z * v2.y,
|
|
y: v1.z * v2.x - v1.x * v2.z,
|
|
z: v1.x * v2.y - v1.y * v2.x,
|
|
}
|
|
}
|
|
|
|
pub fn dot(v1: Vec3, v2: Vec3) -> f32 {
|
|
v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
|
|
}
|
|
|
|
impl Vec3 {
|
|
pub fn new(x: f32, y: f32, z: f32) -> Vec3 {
|
|
Vec3 { x, y, z }
|
|
}
|
|
|
|
pub fn min(self) -> f32 {
|
|
self.x.min(self.y).min(self.z)
|
|
}
|
|
|
|
pub fn max(self) -> f32 {
|
|
self.x.max(self.y).max(self.z)
|
|
}
|
|
|
|
pub fn length(self) -> f32 {
|
|
self.squared_length().sqrt()
|
|
}
|
|
|
|
pub fn squared_length(self) -> f32 {
|
|
self.x * self.x + self.y * self.y + self.z * self.z
|
|
}
|
|
|
|
pub fn unit_vector(self) -> Vec3 {
|
|
self / self.length()
|
|
}
|
|
|
|
pub fn make_unit_vector(&mut self) {
|
|
*self = self.unit_vector();
|
|
}
|
|
}
|
|
|
|
impl From<[f32; 3]> for Vec3 {
|
|
fn from(v: [f32; 3]) -> Self {
|
|
Vec3 {
|
|
x: v[0],
|
|
y: v[1],
|
|
z: v[2],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Vec3 {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "{} {} {}", self.x, self.y, self.z)
|
|
}
|
|
}
|
|
|
|
impl str::FromStr for Vec3 {
|
|
type Err = ParseFloatError;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let coords: Vec<&str> = s.split(' ').collect();
|
|
Ok(Vec3 {
|
|
x: coords[0].parse::<f32>()?,
|
|
y: coords[1].parse::<f32>()?,
|
|
z: coords[2].parse::<f32>()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Add<f32> for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn add(self, r: f32) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x + r,
|
|
y: self.y + r,
|
|
z: self.z + r,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Add for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn add(self, r: Vec3) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x + r.x,
|
|
y: self.y + r.y,
|
|
z: self.z + r.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Div<Vec3> for f32 {
|
|
type Output = Vec3;
|
|
|
|
fn div(self, r: Vec3) -> Vec3 {
|
|
Vec3 {
|
|
x: self / r.x,
|
|
y: self / r.y,
|
|
z: self / r.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Div<f32> for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn div(self, r: f32) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x / r,
|
|
y: self.y / r,
|
|
z: self.z / r,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Index<usize> for Vec3 {
|
|
type Output = f32;
|
|
fn index(&self, idx: usize) -> &f32 {
|
|
match idx {
|
|
0 => &self.x,
|
|
1 => &self.y,
|
|
2 => &self.z,
|
|
_ => panic!(format!("idx {} out of range for vec3", idx)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Mul for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn mul(self, r: Vec3) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x * r.x,
|
|
y: self.y * r.y,
|
|
z: self.z * r.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Mul<Vec3> for f32 {
|
|
type Output = Vec3;
|
|
|
|
fn mul(self, v: Vec3) -> Vec3 {
|
|
Vec3 {
|
|
x: v.x * self,
|
|
y: v.y * self,
|
|
z: v.z * self,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Mul<f32> for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn mul(self, r: f32) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x * r,
|
|
y: self.y * r,
|
|
z: self.z * r,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Neg for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn neg(self) -> Vec3 {
|
|
-1. * self
|
|
}
|
|
}
|
|
|
|
impl Sub for Vec3 {
|
|
type Output = Vec3;
|
|
|
|
fn sub(self, r: Vec3) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x - r.x,
|
|
y: self.y - r.y,
|
|
z: self.z - r.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::f32::consts::PI;
|
|
use std::str::FromStr;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn vec_add() {
|
|
let v0 = Vec3::new(1., 2., 3.);
|
|
let v1 = Vec3::new(1., 1., 1.);
|
|
assert_eq!(v0 + v1, Vec3::new(2., 3., 4.));
|
|
}
|
|
|
|
#[test]
|
|
fn vec_div() {
|
|
let v0 = Vec3::new(1., 2., 4.);
|
|
assert_eq!(v0 / 2., Vec3::new(0.5, 1., 2.));
|
|
}
|
|
|
|
#[test]
|
|
fn vec_mul() {
|
|
let v0 = Vec3::new(1., 2., 4.);
|
|
assert_eq!(v0 * 0.5, Vec3::new(0.5, 1., 2.));
|
|
assert_eq!(v0 * v0, Vec3::new(1., 4., 16.));
|
|
}
|
|
|
|
#[test]
|
|
fn vec_sub() {
|
|
let v0 = Vec3::new(1., 2., 3.);
|
|
let v1 = Vec3::new(1., 1., 1.);
|
|
assert_eq!(v0 - v1, Vec3::new(0., 1., 2.));
|
|
}
|
|
|
|
#[test]
|
|
fn vec_idx() {
|
|
let v0 = Vec3::new(1., 2., 3.);
|
|
assert_eq!(v0[2], 3.);
|
|
}
|
|
|
|
#[test]
|
|
fn vec_display() {
|
|
let v0 = Vec3::new(1., 2., 3.);
|
|
assert_eq!(format!("{}", v0), "1 2 3".to_owned());
|
|
}
|
|
|
|
#[test]
|
|
fn vec_from_str() {
|
|
assert_eq!(Vec3::from_str("1. 2. 3.").unwrap(), Vec3::new(1., 2., 3.));
|
|
}
|
|
|
|
#[test]
|
|
fn vec_str_roundtrip() {
|
|
let v = Vec3::from_str("1 2 3").unwrap();
|
|
let s = format!("{}", v);
|
|
assert_eq!(v, Vec3::from_str(&s).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn vec_dot() {
|
|
let v0 = Vec3::new(1., 0., 0.);
|
|
let v1 = Vec3::new(-1., 0., 0.);
|
|
assert_eq!(dot(v0, v1), v0.length() * v1.length() * PI.cos());
|
|
}
|
|
|
|
#[test]
|
|
fn vec_cross() {
|
|
let v0 = Vec3::new(1., 0., 0.);
|
|
let v1 = Vec3::new(0., 1., 0.);
|
|
assert_eq!(cross(v0, v1), Vec3::new(0., 0., 1.));
|
|
}
|
|
}
|