use std::ops::{Index,IndexMut};
use std::borrow::{Borrow,BorrowMut};
use std::slice;
use std::vec;
use std::iter::{FromIterator, IntoIterator};
use std::io::BufRead;
use super::vertex::*;
use rin_math::{vec3, vec2, zero};
use color::{ToRgba, rgba};
use std::path::Path;
use std::io;
use std::fs::File;
use std::mem;
use std::iter;
#[cfg(feature="serialize")]
use serde_derive::{Serialize, Deserialize};
#[cfg(not(target_os="android"))]
pub type IndexT = u32;
#[cfg(target_os="android")]
pub type IndexT = u16;
#[derive(Debug,Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct Mesh<T>{
vertices: Vec<T>,
indices: Vec<IndexT>,
primitive_type: PrimitiveType,
}
impl<T> Default for Mesh<T>{
fn default() -> Mesh<T>{
Mesh{
vertices: vec![],
indices: vec![],
primitive_type: PrimitiveType::Triangles,
}
}
}
pub fn mesh<T>(vertices: Vec<T>, ty: PrimitiveType) ->Mesh<T>{
Mesh::from_vertices_and_type(vertices,ty)
}
impl<T> Mesh<T>{
pub fn new(vertices: Vec<T>, indices: Vec<IndexT>, primitive_type: PrimitiveType) -> Mesh<T>{
Mesh{vertices, indices, primitive_type}
}
pub fn from_vertices(vertices: Vec<T>) -> Mesh<T>{
Mesh{vertices: vertices, indices: Vec::new(), primitive_type: PrimitiveType::Triangles}
}
pub fn from_vertices_and_type(vertices: Vec<T>, ty: PrimitiveType) -> Mesh<T>{
Mesh{vertices: vertices, indices: Vec::new(), primitive_type: ty}
}
pub fn from_iter_and_type<I: Iterator<Item=T>>(vertices: I, ty: PrimitiveType) -> Mesh<T>{
Mesh{vertices: vertices.collect(), indices: Vec::new(), primitive_type: ty}
}
pub fn from_vertices_indices(vertices: Vec<T>, indices: Vec<IndexT>) -> Mesh<T>{
Mesh{vertices: vertices, indices: indices, primitive_type: PrimitiveType::Triangles}
}
pub fn with_type(ty: PrimitiveType) -> Mesh<T>{
Mesh{vertices: Vec::new(), indices: Vec::new(), primitive_type: ty}
}
pub fn set_vertices(&mut self, vertices: Vec<T>){
self.vertices = vertices;
}
pub fn set_indices(&mut self, indices: Vec<IndexT>){
self.indices = indices;
}
pub fn indices(&self) -> &Vec<IndexT>{
&self.indices
}
pub fn indices_mut(&mut self) -> &mut Vec<IndexT>{
&mut self.indices
}
pub fn vertices(&self) -> &[T]{
&self.vertices
}
pub fn vertices_mut(&mut self) -> &mut Vec<T>{
&mut self.vertices
}
pub fn vertices_indices_mut(&mut self) -> (&mut Vec<T>, &mut Vec<IndexT>){
(&mut self.vertices, &mut self.indices)
}
pub fn iter(&self) -> slice::Iter<T>{
self.vertices.iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut< T>{
self.vertices.iter_mut()
}
pub fn into_iter(self) -> vec::IntoIter<T>{
self.vertices.into_iter()
}
pub fn pop(&mut self) -> Option<T>{
self.vertices.pop()
}
pub fn push(&mut self, value: T){
self.vertices.push(value);
}
pub fn extend<I: IntoIterator<Item=T>>(&mut self, other: I){
self.vertices.extend(other);
}
pub fn insert(&mut self, index: usize, element: T){
self.vertices.insert(index, element);
}
pub fn get_mut(&mut self, index: usize) -> &mut T{
self.vertices.get_mut(index).unwrap()
}
pub fn reserve(&mut self, capacity: usize){
self.vertices.reserve(capacity);
}
pub unsafe fn set_len(&mut self, len: usize){
self.vertices.set_len(len);
}
pub fn truncate(&mut self, len: usize){
self.vertices.truncate(len);
}
pub fn last(&self) -> Option<&T>{
self.vertices.last()
}
pub fn last_mut(&mut self) -> Option<&mut T>{
self.vertices.last_mut()
}
pub fn primitive_type(&self) -> PrimitiveType{
self.primitive_type
}
pub fn set_primitive_type(&mut self, ty: PrimitiveType){
self.primitive_type = ty;
}
pub fn add_face(&mut self, i0: IndexT, i1: IndexT, i2: IndexT){
self.indices.push(i0);
self.indices.push(i1);
self.indices.push(i2);
}
pub fn clear(&mut self){
self.vertices.clear();
self.indices.clear();
}
pub fn clear_vertices(&mut self){
self.vertices.clear();
}
pub fn clear_indices(&mut self){
self.indices.clear();
}
pub fn len(&self) -> usize{
self.vertices.len()
}
pub fn is_empty(&self) -> bool{
self.vertices.is_empty()
}
pub fn as_slice(&self) -> MeshSlice<T> {
MeshSlice::new(&self.vertices, &self.indices, self.primitive_type)
}
pub fn faces(&self) -> Box<dyn Iterator<Item = [&T; 3]> + '_>{
match self.primitive_type() {
PrimitiveType::Triangles => {
if self.indices.is_empty(){
Box::new(self.vertices.chunks_exact(3).map(|tri| [
&tri[0],
&tri[1],
&tri[2],
]))
}else{
Box::new(self.indices.chunks_exact(3).map(move |tri| [
&self.vertices[tri[0] as usize],
&self.vertices[tri[1] as usize],
&self.vertices[tri[2] as usize],
]))
}
}
PrimitiveType::TriangleStrip => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
Box::new(
iter::once([
&self.vertices[0],
&self.vertices[1],
&self.vertices[2],
]).chain(self.vertices[1..].windows(3).map(|v|[
&v[1],
&v[0],
&v[2]
]))
)
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
Box::new(
iter::once([
&self.vertices[self.indices[0] as usize],
&self.vertices[self.indices[1] as usize],
&self.vertices[self.indices[2] as usize],
]).chain(self.indices[1..].windows(3).map(move |i| [
&self.vertices[i[1] as usize],
&self.vertices[i[0] as usize],
&self.vertices[i[2] as usize],
]))
)
}
}
PrimitiveType::TriangleFan => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
Box::new(
iter::once([
&self.vertices[0],
&self.vertices[1],
&self.vertices[2],
]).chain(self.vertices.windows(4).map(move |v| [
&v[0],
&v[2],
&v[3]
]))
)
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
Box::new(
iter::once([
&self.vertices[self.indices[0] as usize],
&self.vertices[self.indices[1] as usize],
&self.vertices[self.indices[2] as usize],
]).chain(self.indices.windows(4).map(move |i| [
&self.vertices[i[0] as usize],
&self.vertices[i[2] as usize],
&self.vertices[i[3] as usize],
]))
)
}
}
_ => unimplemented!("Only Triangles, TrianglesStrip and TriangleFan PrimitiveType supported")
}
}
pub fn faces_mut(&mut self) -> Box<dyn Iterator<Item = [&mut T; 3]> + '_>{
match self.primitive_type() {
PrimitiveType::Triangles => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
Box::new(self.vertices.chunks_exact_mut(3).map(|tri| [
unsafe{ mem::transmute(&mut tri[0]) },
unsafe{ mem::transmute(&mut tri[1]) },
unsafe{ mem::transmute(&mut tri[2]) },
]))
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
let indices = &self.indices;
let vertices: &mut Vec<T> = unsafe{ mem::transmute(&mut self.vertices) };
Box::new(indices.chunks_exact(3).map(move |tri| [
unsafe{ mem::transmute(&mut vertices[tri[0] as usize]) },
unsafe{ mem::transmute(&mut vertices[tri[1] as usize]) },
unsafe{ mem::transmute(&mut vertices[tri[2] as usize]) },
]))
}
}
PrimitiveType::TriangleStrip => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
let vertices: &mut Vec<T> = unsafe{ mem::transmute(&mut self.vertices) };
Box::new(
iter::once([
unsafe{ mem::transmute(&mut vertices[0]) },
unsafe{ mem::transmute(&mut vertices[1]) },
unsafe{ mem::transmute(&mut vertices[2]) },
]).chain((0..vertices.len()-3).map(move |i| [
unsafe{ mem::transmute(&mut vertices[i+2]) },
unsafe{ mem::transmute(&mut vertices[i+1]) },
unsafe{ mem::transmute(&mut vertices[i+3]) },
]))
)
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
let indices = &self.indices;
let vertices: &mut Vec<T> = unsafe{ mem::transmute(&mut self.vertices) };
Box::new(
iter::once([
unsafe{ mem::transmute(&mut vertices[indices[0] as usize]) },
unsafe{ mem::transmute(&mut vertices[indices[1] as usize]) },
unsafe{ mem::transmute(&mut vertices[indices[2] as usize]) },
]).chain(indices[1..indices.len()].windows(3).map(move |i| [
unsafe{ mem::transmute(&mut vertices[i[1] as usize]) },
unsafe{ mem::transmute(&mut vertices[i[0] as usize]) },
unsafe{ mem::transmute(&mut vertices[i[2] as usize]) },
]))
)
}
}
PrimitiveType::TriangleFan => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
let vertices: &mut Vec<T> = unsafe{ mem::transmute(&mut self.vertices) };
Box::new(
iter::once([
unsafe{ mem::transmute(&mut vertices[0]) },
unsafe{ mem::transmute(&mut vertices[1]) },
unsafe{ mem::transmute(&mut vertices[2]) },
]).chain((0..vertices.len()-3).map(move |i| [
unsafe{ mem::transmute(&mut vertices[i]) },
unsafe{ mem::transmute(&mut vertices[i+2]) },
unsafe{ mem::transmute(&mut vertices[i+3]) },
]))
)
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
let indices = &self.indices;
let vertices: &mut Vec<T> = unsafe{ mem::transmute(&mut self.vertices) };
Box::new(
iter::once([
unsafe{ mem::transmute(&mut vertices[indices[0] as usize]) },
unsafe{ mem::transmute(&mut vertices[indices[1] as usize]) },
unsafe{ mem::transmute(&mut vertices[indices[2] as usize]) },
]).chain(indices.windows(4).map(move |i| [
unsafe{ mem::transmute(&mut vertices[i[0] as usize]) },
unsafe{ mem::transmute(&mut vertices[i[2] as usize]) },
unsafe{ mem::transmute(&mut vertices[i[3] as usize]) },
]))
)
}
}
_ => unimplemented!("Only Triangles, TrianglesStrip and TriangleFan PrimitiveType supported")
}
}
}
impl<T: Clone> Mesh<T>{
pub fn into_faces(self) -> Box<dyn Iterator<Item = [T; 3]>>
where T: 'static
{
match self.primitive_type() {
PrimitiveType::Triangles => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
let vertices = self.vertices;
Box::new((0..vertices.len()).step_by(3).map(move |i| [
vertices[i+0].clone(),
vertices[i+1].clone(),
vertices[i+2].clone(),
]))
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
let indices = self.indices;
let vertices = self.vertices;
Box::new((0..indices.len()).step_by(3).map(move |i| [
vertices[indices[i+0] as usize].clone(),
vertices[indices[i+1] as usize].clone(),
vertices[indices[i+2] as usize].clone(),
]))
}
}
PrimitiveType::TriangleStrip => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
let vertices = self.vertices;
Box::new(
iter::once([
vertices[0].clone(),
vertices[1].clone(),
vertices[2].clone(),
]).chain((0..vertices.len()-3).map(move |i| [
vertices[i+2].clone(),
vertices[i+1].clone(),
vertices[i+3].clone(),
]))
)
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
let indices = self.indices;
let vertices = self.vertices;
Box::new(
iter::once([
vertices[indices[0] as usize].clone(),
vertices[indices[1] as usize].clone(),
vertices[indices[2] as usize].clone(),
]).chain((0..indices.len()-3).map(move |i| [
vertices[indices[i+2] as usize].clone(),
vertices[indices[i+1] as usize].clone(),
vertices[indices[i+3] as usize].clone(),
]))
)
}
}
PrimitiveType::TriangleFan => {
if self.indices.is_empty(){
if self.vertices.len() < 3 {
return Box::new(iter::empty())
}
let vertices = self.vertices;
Box::new(
iter::once([
vertices[0].clone(),
vertices[1].clone(),
vertices[2].clone(),
]).chain((0..vertices.len()-3).map(move |i| [
vertices[i].clone(),
vertices[i+2].clone(),
vertices[i+3].clone(),
]))
)
}else{
if self.indices.len() < 3 {
return Box::new(iter::empty())
}
let indices = self.indices;
let vertices = self.vertices;
Box::new(
iter::once([
vertices[indices[0] as usize].clone(),
vertices[indices[1] as usize].clone(),
vertices[indices[2] as usize].clone(),
]).chain((0..indices.len()-3).map(move |i| [
vertices[indices[i] as usize].clone(),
vertices[indices[i+2] as usize].clone(),
vertices[indices[i+3] as usize].clone(),
]))
)
}
}
_ => unimplemented!("Only Triangles, TrianglesStrip and TriangleFan PrimitiveType supported")
}
}
}
impl<T: Clone> Mesh<T>{
pub fn extend_from_mesh(&mut self, other: &Mesh<T>){
let offset = self.vertices.len() as u32;
self.vertices.extend_from_slice(other.vertices());
self.indices.extend(other.indices().iter().map(|i| i + offset));
}
pub fn extend_from_slice(&mut self, other: &[T]){
self.vertices.extend_from_slice(other);
}
}
impl<T> Index<usize> for Mesh<T>{
type Output = T;
fn index(&self, index: usize) -> &T{
self.vertices.index(index)
}
}
impl<T> IndexMut<usize> for Mesh<T>{
fn index_mut(&mut self, index: usize) -> &mut T{
self.vertices.index_mut(index)
}
}
impl<T> AsRef<[T]> for Mesh<T>{
fn as_ref(&self) -> &[T]{
self.vertices.as_ref()
}
}
impl<T> AsMut<[T]> for Mesh<T>{
fn as_mut(&mut self) -> &mut [T]{
self.vertices.as_mut()
}
}
impl<T> Into<Vec<T>> for Mesh<T>{
fn into(self) -> Vec<T>{
self.vertices
}
}
impl<T> Into<(Vec<T>, Vec<IndexT>)> for Mesh<T>{
fn into(self) -> (Vec<T>, Vec<IndexT>){
(self.vertices, self.indices)
}
}
impl<T> Borrow<[T]> for Mesh<T>{
fn borrow(&self) -> &[T]{
self.vertices.borrow()
}
}
impl<T> BorrowMut<[T]> for Mesh<T>{
fn borrow_mut(&mut self) -> &mut [T]{
self.vertices.borrow_mut()
}
}
impl<T> FromIterator<T> for Mesh<T>{
fn from_iter<I>(iter: I) -> Mesh<T> where I: IntoIterator<Item=T>{
Mesh{
vertices: iter.into_iter().collect(),
indices: vec![],
primitive_type: PrimitiveType::Triangles
}
}
}
#[derive(Clone,Copy,Debug,Eq,PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum PrimitiveType{
Triangles,
TriangleStrip,
TriangleFan,
Lines,
LineStrip,
LineLoop,
LinesAdjacency,
LineStripAdjacency,
Points,
Patches
}
impl Default for PrimitiveType{
fn default() -> PrimitiveType {
PrimitiveType::Triangles
}
}
pub fn load_ply<C: ToRgba, P: AsRef<Path>>(path: P, default_color: C) -> Result<Mesh<Vertex3DTexColor>,String>{
let file = File::open(path.as_ref())
.map_err(|err| format!("Couldn't open {}: {:?}", path.as_ref().display(), err))?;
let reader = io::BufReader::new(file);
let mut mesh: Mesh<Vertex3DTexColor> = Mesh::default();
let mut first_line = true;
let mut vertex_dim = 0;
let mut texcoord_dim = 0;
let mut color_dim = 0;
let mut state = "init".to_string();
let mut idx = 0;
for line in reader.lines() {
let line = line.unwrap().trim_end_matches([' ','\n'].as_ref()).to_string();
if first_line && line!="ply"{
return Err("couldn't read file, ply not found on first line".to_string());
}
first_line = false;
if line.starts_with("format"){
if line != "format ascii 1.0"{
return Err(format!("{}, not supported",line));
}
continue;
}
if line.starts_with("element"){
let element_ty_len: Vec<&str> = line.split(' ').collect();
let ty = element_ty_len[1];
let len = element_ty_len[2];
if ty == "vertex"{
unsafe{
let new_len = len.parse().unwrap();
mesh.reserve(new_len);
mesh.set_len(new_len);
}
}
state = ty.to_string();
println!("state: {}",state);
continue;
}
if line.starts_with("property"){
println!("state on property: {}",state);
match state.as_ref(){
"vertex" => vertex_dim+=1,
"texcoord" => texcoord_dim+=1,
"color" => color_dim+=1,
_ => {}
}
continue;
}
if line == "end_header"{
state = "vertices".to_string();
continue;
}
if state == "vertices"{
let components: Vec<&str> = line.split(' ').collect();
let mut next_pos = 0;
if idx<mesh.vertices.len(){
if vertex_dim == 2{
let pos = vec3(components[next_pos].parse().unwrap(),components[next_pos+1].parse().unwrap(),0.0);
mesh[idx].position = pos;
next_pos = 3;
}else if vertex_dim >= 3{
let pos = vec3(components[next_pos].parse().unwrap(),components[next_pos+1].parse().unwrap(),components[next_pos+2].parse().unwrap());
mesh[idx].position = pos;
next_pos = vertex_dim+1;
}
if texcoord_dim >= 2{
let texcoord = vec2(components[next_pos].parse().unwrap(),components[next_pos+1].parse().unwrap());
mesh[idx].texcoord = texcoord;
next_pos += texcoord_dim;
}else{
mesh[idx].texcoord = zero();
}
if color_dim >= 3{
let r = components[next_pos].parse().unwrap();
let g = components[next_pos+1].parse().unwrap();
let b = components[next_pos+2].parse().unwrap();
if color_dim == 3{
let color = rgba!(r,g,b,1.0f32);
mesh[idx].color = color;
}else if color_dim >= 4{
let a = components[next_pos+3].parse().unwrap();
let color = rgba!(r,g,b,a);
mesh[idx].color = color;
}
}else{
mesh[idx].color = default_color.to_rgba().to_standard();
}
idx += 1;
}else{
state = "faces".to_string();
idx = 0;
}
}
if state == "faces"{
let components: Vec<&str> = line.split(' ').collect();
let num_components: usize = components[0].parse().unwrap();
if num_components == 3 {
mesh.add_face(components[1].parse().unwrap(), components[2].parse().unwrap(), components[3].parse().unwrap());
}else if num_components == 4{
mesh.add_face(components[1].parse().unwrap(), components[2].parse().unwrap(), components[3].parse().unwrap());
mesh.add_face(components[3].parse().unwrap(), components[4].parse().unwrap(), components[1].parse().unwrap());
}
idx += 1;
}
}
Ok(mesh)
}
use crate::{MeshSlice, projection};
#[cfg(feature="gl")]
use crate::PrimitiveTypeToGl;
#[cfg(feature="gl")]
impl<'a,T: Clone> Into<glin::simple_vao::Data<'a,T>> for &'a Mesh<T>{
fn into(self) -> glin::simple_vao::Data<'a,T>{
glin::simple_vao::Data{
vertices: self,
indices: self.indices(),
mode: self.primitive_type().to_gl()
}
}
}