use std::sync::Arc;
use std::marker::PhantomData;
use na::{Translate, Identity, Point2};
use partitioning::BVT;
use bounding_volume::{self, HasBoundingVolume, AABB};
use math::{Point, Vector};
pub trait BaseMeshElement<I, P> {
fn new_with_vertices_and_indices(&[P], &I) -> Self;
}
pub struct BaseMesh<P: Point, I, E> {
bvt: BVT<usize, AABB<P>>,
bvs: Vec<AABB<P>>,
vertices: Arc<Vec<P>>,
indices: Arc<Vec<I>>,
uvs: Option<Arc<Vec<Point2<<P::Vect as Vector>::Scalar>>>>,
normals: Option<Arc<Vec<P::Vect>>>,
elt: PhantomData<E>
}
impl<P, I, E> Clone for BaseMesh<P, I, E>
where P: Point {
fn clone(&self) -> BaseMesh<P, I, E> {
BaseMesh {
bvt: self.bvt.clone(),
bvs: self.bvs.clone(),
vertices: self.vertices.clone(),
indices: self.indices.clone(),
uvs: self.uvs.clone(),
normals: self.normals.clone(),
elt: PhantomData
}
}
}
impl<P, I, E> BaseMesh<P, I, E>
where P: Point,
P::Vect: Translate<P>,
E: BaseMeshElement<I, P> + HasBoundingVolume<Identity, AABB<P>> {
pub fn new(vertices: Arc<Vec<P>>,
indices: Arc<Vec<I>>,
uvs: Option<Arc<Vec<Point2<<P::Vect as Vector>::Scalar>>>>,
normals: Option<Arc<Vec<P::Vect>>>) -> BaseMesh<P, I, E> {
for uvs in uvs.iter() {
assert!(uvs.len() == vertices.len());
}
let mut leaves = Vec::new();
let mut bvs = Vec::new();
{
let vs = &*vertices;
let is = &*indices;
for (i, is) in is[..].iter().enumerate() {
let vs: &[P] = &vs[..];
let element: E = BaseMeshElement::new_with_vertices_and_indices(vs, is);
let bv = bounding_volume::aabb(&element, &Identity::new());
leaves.push((i, bv.clone()));
bvs.push(bv);
}
}
let bvt = BVT::new_balanced(leaves);
BaseMesh {
bvt: bvt,
bvs: bvs,
vertices: vertices,
indices: indices,
uvs: uvs,
normals: normals,
elt: PhantomData
}
}
}
impl<P, I, E> BaseMesh<P, I, E>
where P: Point {
#[inline]
pub fn vertices(&self) -> &Arc<Vec<P>> {
&self.vertices
}
#[inline]
pub fn len(&self) -> usize {
self.bvs.len()
}
#[inline]
pub fn bounding_volumes(&self) -> &[AABB<P>] {
&self.bvs[..]
}
#[inline]
pub fn indices(&self) -> &Arc<Vec<I>> {
&self.indices
}
#[inline]
pub fn uvs(&self) -> &Option<Arc<Vec<Point2<<P::Vect as Vector>::Scalar>>>> {
&self.uvs
}
#[inline]
pub fn normals(&self) -> &Option<Arc<Vec<P::Vect>>> {
&self.normals
}
#[inline]
pub fn bvt(&self) -> &BVT<usize, AABB<P>> {
&self.bvt
}
}
impl<P, I, E> BaseMesh<P, I, E>
where P: Point,
E: BaseMeshElement<I, P> {
#[inline(always)]
pub fn element_at(&self, i: usize) -> E {
let vs: &[P] = &self.vertices[..];
BaseMeshElement::new_with_vertices_and_indices(vs, &self.indices[i])
}
}