Add Icospheres.

Additionally documents the shapes module.
This commit is contained in:
OptimisticPeach 2020-08-13 00:13:56 -04:00
parent 19d2f9c2cd
commit 86c20eb6df
3 changed files with 82 additions and 1 deletions

View file

@ -38,6 +38,7 @@ once_cell = "1.4.0"
downcast-rs = "1.1.1" downcast-rs = "1.1.1"
thiserror = "1.0" thiserror = "1.0"
anyhow = "1.0" anyhow = "1.0"
hexasphere = "0.1.5"
[features] [features]
png = ["image/png"] png = ["image/png"]

View file

@ -165,12 +165,16 @@ impl Mesh {
} }
} }
/// Generation for some primitive shape meshes.
pub mod shape { pub mod shape {
use super::{Mesh, VertexAttribute}; use super::{Mesh, VertexAttribute};
use crate::pipeline::PrimitiveTopology; use crate::pipeline::PrimitiveTopology;
use bevy_math::*; use bevy_math::*;
use hexasphere::Hexasphere;
/// A cube.
pub struct Cube { pub struct Cube {
/// Half the side length of the cube.
pub size: f32, pub size: f32,
} }
@ -246,8 +250,11 @@ pub mod shape {
} }
} }
/// A rectangle on the XY plane.
pub struct Quad { pub struct Quad {
/// Full width and height of the rectangle.
pub size: Vec2, pub size: Vec2,
/// Flips the texture coords of the resulting vertices.
pub flip: bool, pub flip: bool,
} }
@ -341,7 +348,9 @@ pub mod shape {
} }
} }
/// A square on the XZ plane.
pub struct Plane { pub struct Plane {
/// The total side length of the square.
pub size: f32, pub size: f32,
} }
@ -378,6 +387,70 @@ pub mod shape {
} }
} }
} }
/// A sphere made from a subdivided Icosahedron.
pub struct Icosphere {
/// The radius of the sphere.
pub radius: f32,
/// The number of subdivisions applied.
pub subdivisions: usize,
}
impl Default for Icosphere {
fn default() -> Self {
Self {
radius: 1.0,
subdivisions: 5,
}
}
}
impl From<Icosphere> for Mesh {
fn from(sphere: Icosphere) -> Self {
let hexasphere = Hexasphere::new(sphere.subdivisions, |point| {
let inclination = point.z().acos();
let azumith = point.y().atan2(point.x());
let norm_inclination = 1.0 - (inclination / std::f32::consts::PI);
let norm_azumith = (azumith / std::f32::consts::PI) * 0.5;
[norm_inclination, norm_azumith]
});
let raw_points = hexasphere.raw_points();
let points = raw_points
.iter()
.map(|&p| {
(p * sphere.radius).into()
})
.collect::<Vec<[f32; 3]>>();
let normals = raw_points
.iter()
.copied()
.map(Into::into)
.collect::<Vec<[f32; 3]>>();
let uvs = hexasphere.raw_data().to_owned();
let mut indices = Vec::with_capacity(hexasphere.indices_per_main_triangle() * 20);
for i in 0..20 {
hexasphere.get_indices(i, &mut indices);
}
Mesh {
primitive_topology: PrimitiveTopology::TriangleList,
attributes: vec![
VertexAttribute::position(points),
VertexAttribute::normal(normals),
VertexAttribute::uv(uvs),
],
indices: Some(indices)
}
}
}
} }
fn remove_current_mesh_resources( fn remove_current_mesh_resources(

View file

@ -29,6 +29,13 @@ fn setup(
translation: Translation::new(0.0, 1.0, 0.0), translation: Translation::new(0.0, 1.0, 0.0),
..Default::default() ..Default::default()
}) })
// sphere
.spawn(PbrComponents {
mesh: meshes.add(Mesh::from(shape::Icosphere { subdivisions: 4, radius: 0.5 })),
material: materials.add(Color::rgb(0.1, 0.4, 0.8).into()),
translation: Translation::new(1.5, 1.5, 1.5),
..Default::default()
})
// light // light
.spawn(LightComponents { .spawn(LightComponents {
translation: Translation::new(4.0, 8.0, 4.0), translation: Translation::new(4.0, 8.0, 4.0),