use std::path::Path;
use bytemuck;
use derive_more::{From, TryInto};
use gltf;
use strum;
use crate::{math, math::geometry, util, vertex};
pub mod capsule;
pub mod cylinder;
pub mod grid;
pub mod hemisphere;
pub mod sphere;
#[derive(Clone, Debug, PartialEq, From, TryInto)]
pub enum Mesh {
Lines3d (Lines3d)
}
#[derive(Clone, Debug, PartialEq, From)]
pub struct Lines3d {
pub vertices : Vec <vertex::Vert3dInstanced>,
pub indices : Vec <u32>
}
impl Mesh {
pub fn load_gltf <P : AsRef <Path>> (path : P) -> Self {
let (document, buffers, _images) = gltf::import (path).unwrap();
let mut meshes = document.meshes();
let mesh = meshes.next().unwrap();
debug_assert!(meshes.next().is_none());
let mut primitives = mesh.primitives();
let primitive = primitives.next().unwrap();
debug_assert!(primitives.next().is_none());
let reader = primitive.reader (|buffer| Some (&buffers[buffer.index()]));
let vertices = reader.read_positions().unwrap()
.map (|inst_position| vertex::Vert3dInstanced { inst_position }).collect();
let indices = reader.read_indices().unwrap().into_u32().collect();
Lines3d { vertices, indices }.into()
}
pub fn write_gltf <P : AsRef <Path>> (&self, path : P) {
fn bounding_coords (points: &[vertex::Vert3dInstanced])
-> ([f32; 3], [f32; 3])
{
let mut min = [f32::MAX, f32::MAX, f32::MAX];
let mut max = [f32::MIN, f32::MIN, f32::MIN];
for point in points {
let p = point.inst_position;
for i in 0..3 {
min[i] = f32::min (min[i], p[i]);
max[i] = f32::max (max[i], p[i]);
}
}
(min, max)
}
let (vertices, indices) = match self {
Mesh::Lines3d (Lines3d { vertices, indices }) => (vertices, indices)
};
let (min, max) = bounding_coords (&vertices[..]);
let vertices_bytes = bytemuck::cast_slice (vertices);
let indices_bytes = bytemuck::cast_slice (indices);
let (buffer, views) =
util::gltf::json_buffer_views (0, &[vertices_bytes, indices_bytes]);
let position_accessor = util::gltf::json_accessor (0, vertices.len() as u32,
gltf::json::accessor::Type::Vec3,
gltf::json::accessor::ComponentType::F32, Some ([min, max]));
let index_accessor = util::gltf::json_accessor (1, indices.len() as u32,
gltf::json::accessor::Type::Scalar,
gltf::json::accessor::ComponentType::U32, None);
let lines_primitive = util::gltf::json_primitive (
gltf::json::mesh::Semantic::Positions, gltf::json::mesh::Mode::Lines, 1);
let mesh = util::gltf::json_mesh (vec![lines_primitive]);
let node = util::gltf::json_node (0);
let root = util::gltf::json_root (
vec![node], vec![mesh], vec![buffer], views,
vec![position_accessor, index_accessor]);
let writer = std::fs::File::create (path).unwrap();
gltf::json::serialize::to_writer_pretty (writer, &root).unwrap();
}
}
impl Lines3d {
pub fn empty() -> Self {
Lines3d { vertices: vec![], indices: vec![] }
}
}
impl From <geometry::Aabb3 <f32>> for Lines3d {
fn from (aabb : geometry::Aabb3 <f32>) -> Self {
use strum::IntoEnumIterator;
let vertices = math::Octant::iter().map (|octant| vertex::Vert3dInstanced {
inst_position: aabb.corner (octant).0.into_array()
}).collect();
let indices = vec![
0, 1, 0, 2, 0, 4,
7, 6, 7, 5, 7, 3,
1, 3, 1, 5,
2, 3, 2, 6,
4, 5, 4, 6
];
Lines3d { vertices, indices }
}
}