add basic shape generation
This commit is contained in:
parent
4b138deb34
commit
77cab94a6e
|
|
@ -15,6 +15,7 @@ use crate::{
|
||||||
mod camera;
|
mod camera;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod render;
|
mod render;
|
||||||
|
mod shape;
|
||||||
mod trace;
|
mod trace;
|
||||||
|
|
||||||
const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb;
|
const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb;
|
||||||
|
|
|
||||||
140
src/shape.rs
Normal file
140
src/shape.rs
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
use glam::{Vec3, vec3};
|
||||||
|
|
||||||
|
pub type Face = [u16; 3];
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Mesh {
|
||||||
|
pub vertices: Vec<Vec3>,
|
||||||
|
pub indices: Vec<Face>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sphere(subdiv: usize) -> Mesh {
|
||||||
|
assert!(subdiv >= 2);
|
||||||
|
assert!(2 * subdiv * (subdiv - 1) + 2 <= 1 << 16);
|
||||||
|
|
||||||
|
let mut vertices = Vec::new();
|
||||||
|
vertices.push(Vec3::Z);
|
||||||
|
for j in 1..subdiv {
|
||||||
|
let v = j as f32 / subdiv as f32;
|
||||||
|
let theta = PI * v;
|
||||||
|
let (xy, z) = theta.sin_cos();
|
||||||
|
for i in 0..2 * subdiv {
|
||||||
|
let u = i as f32 / (2 * subdiv) as f32;
|
||||||
|
let phi = 2. * PI * u;
|
||||||
|
let (y, x) = phi.sin_cos();
|
||||||
|
vertices.push(vec3(xy * x, xy * y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vertices.push(-Vec3::Z);
|
||||||
|
assert_eq!(vertices.len(), 2 * subdiv * (subdiv - 1) + 2);
|
||||||
|
|
||||||
|
let mut indices = Vec::new();
|
||||||
|
let subdiv = subdiv as u16;
|
||||||
|
for i in 0..2 * subdiv - 1 {
|
||||||
|
indices.push([0, i + 1, i + 2]);
|
||||||
|
}
|
||||||
|
indices.push([0, 2 * subdiv, 1]);
|
||||||
|
for j in 0..subdiv - 2 {
|
||||||
|
let k1 = j * 2 * subdiv + 1;
|
||||||
|
let k2 = k1 + 2 * subdiv;
|
||||||
|
for i in 0..2 * subdiv - 1 {
|
||||||
|
let a = k1 + i;
|
||||||
|
let b = k2 + i;
|
||||||
|
indices.push([a, b, b + 1]);
|
||||||
|
indices.push([a, b + 1, a + 1]);
|
||||||
|
}
|
||||||
|
let a = k1 + 2 * subdiv - 1;
|
||||||
|
let b = k2 + 2 * subdiv - 1;
|
||||||
|
indices.push([a, b, k2]);
|
||||||
|
indices.push([a, k2, k1]);
|
||||||
|
}
|
||||||
|
let k1 = 2 * subdiv * (subdiv - 2) + 1;
|
||||||
|
let k2 = 2 * subdiv * (subdiv - 1) + 1;
|
||||||
|
for i in 0..2 * subdiv - 1 {
|
||||||
|
indices.push([k1 + i, k2, k1 + i + 1]);
|
||||||
|
}
|
||||||
|
indices.push([k1 + 2 * subdiv - 1, k2, k1]);
|
||||||
|
|
||||||
|
Mesh { vertices, indices }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use approx::abs_diff_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sphere_2_topology() {
|
||||||
|
assert_eq!(
|
||||||
|
sphere(2).indices,
|
||||||
|
vec![
|
||||||
|
[0, 1, 2],
|
||||||
|
[0, 2, 3],
|
||||||
|
[0, 3, 4],
|
||||||
|
[0, 4, 1],
|
||||||
|
[1, 5, 2],
|
||||||
|
[2, 5, 3],
|
||||||
|
[3, 5, 4],
|
||||||
|
[4, 5, 1],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn are_equal_eps(left: &[Vec3], right: &[Vec3], eps: f32) -> bool {
|
||||||
|
if left.len() != right.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
left.iter()
|
||||||
|
.zip(right.iter())
|
||||||
|
.all(|(a, b)| abs_diff_eq!(a, b, epsilon = eps))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sphere_2_geometry() {
|
||||||
|
let left = sphere(2).vertices;
|
||||||
|
let right = [Vec3::Z, Vec3::X, Vec3::Y, -Vec3::X, -Vec3::Y, -Vec3::Z];
|
||||||
|
assert!(
|
||||||
|
are_equal_eps(&left, &right, 1e-6),
|
||||||
|
"assertion `left == right` failed\n left: {left:?}\n right: {right:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sphere_3_topology() {
|
||||||
|
assert_eq!(
|
||||||
|
sphere(3).indices,
|
||||||
|
vec![
|
||||||
|
// top
|
||||||
|
[0, 1, 2],
|
||||||
|
[0, 2, 3],
|
||||||
|
[0, 3, 4],
|
||||||
|
[0, 4, 5],
|
||||||
|
[0, 5, 6],
|
||||||
|
[0, 6, 1],
|
||||||
|
// belt
|
||||||
|
[1, 7, 8],
|
||||||
|
[1, 8, 2],
|
||||||
|
[2, 8, 9],
|
||||||
|
[2, 9, 3],
|
||||||
|
[3, 9, 10],
|
||||||
|
[3, 10, 4],
|
||||||
|
[4, 10, 11],
|
||||||
|
[4, 11, 5],
|
||||||
|
[5, 11, 12],
|
||||||
|
[5, 12, 6],
|
||||||
|
[6, 12, 7],
|
||||||
|
[6, 7, 1],
|
||||||
|
// bottom
|
||||||
|
[7, 13, 8],
|
||||||
|
[8, 13, 9],
|
||||||
|
[9, 13, 10],
|
||||||
|
[10, 13, 11],
|
||||||
|
[11, 13, 12],
|
||||||
|
[12, 13, 7],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user