use genmesh::{EmitTriangles, Triangulate, Vertex as GenVertex};
use genmesh::generators::{self, IndexedPolygon, SharedVertex};
use mint;
#[derive(Clone, Debug, Default)]
pub struct Geometry {
pub base: Shape,
pub tex_coords: Vec<mint::Point2<f32>>,
pub faces: Vec<[u32; 3]>,
pub joints: Joints,
pub shapes: Vec<Shape>,
}
#[derive(Clone, Debug, Default)]
pub struct Shape {
pub vertices: Vec<mint::Point3<f32>>,
pub normals: Vec<mint::Vector3<f32>>,
pub tangents: Vec<mint::Vector4<f32>>,
}
#[derive(Clone, Debug, Default)]
pub struct Joints {
pub indices: Vec<[i32; 4]>,
pub weights: Vec<[f32; 4]>,
}
impl Geometry {
pub fn with_vertices(vertices: Vec<mint::Point3<f32>>) -> Self {
Geometry {
base: Shape {
vertices,
.. Shape::default()
},
.. Geometry::default()
}
}
fn generate<P, G, Fpos, Fnor>(
gen: G,
fpos: Fpos,
fnor: Fnor,
) -> Self
where
P: EmitTriangles<Vertex = usize>,
G: IndexedPolygon<P> + SharedVertex<GenVertex>,
Fpos: Fn(GenVertex) -> mint::Point3<f32>,
Fnor: Fn(GenVertex) -> mint::Vector3<f32>,
{
Geometry {
base: Shape {
vertices: gen.shared_vertex_iter().map(fpos).collect(),
normals: gen.shared_vertex_iter().map(fnor).collect(),
.. Shape::default()
},
faces: gen.indexed_polygon_iter()
.triangulate()
.map(|t| [t.x as u32, t.y as u32, t.z as u32])
.collect(),
.. Geometry::default()
}
}
pub fn plane(
width: f32,
height: f32,
) -> Self {
Self::generate(
generators::Plane::new(),
|GenVertex { pos, .. }| [pos.x * 0.5 * width, pos.y * 0.5 * height, 0.0].into(),
|v| v.normal.into(),
)
}
pub fn cuboid(
width: f32,
height: f32,
depth: f32,
) -> Self {
Self::generate(
generators::Cube::new(),
|GenVertex { pos, .. }| {
[
pos.x * 0.5 * width,
pos.y * 0.5 * height,
pos.z * 0.5 * depth,
].into()
},
|v| v.normal.into(),
)
}
pub fn cylinder(
radius_top: f32,
radius_bottom: f32,
height: f32,
radius_segments: usize,
) -> Self {
Self::generate(
generators::Cylinder::new(radius_segments),
|GenVertex { pos, .. }| {
let scale = (pos.z + 1.0) * 0.5 * radius_top + (1.0 - pos.z) * 0.5 * radius_bottom;
[pos.y * scale, pos.z * 0.5 * height, pos.x * scale].into()
},
|GenVertex { normal, .. }| [normal.y, normal.z, normal.x].into(),
)
}
pub fn uv_sphere(
radius: f32,
equatorial_segments: usize,
meridional_segments: usize,
) -> Self {
Self::generate(
generators::SphereUv::new(equatorial_segments, meridional_segments),
|GenVertex { pos, .. }| [pos.x * radius, pos.y * radius, pos.z * radius].into(),
|v| v.normal.into(),
)
}
}