use libc::{c_uint, c_float};
use std::fmt;
use types::{Vector3D, Color4D, Matrix4x4, AiString};
use util::{ptr_ptr_to_slice, ptr_to_slice};
use mesh::PrimitiveType::{Point, Line, Triangle, Polygon};
pub const MAX_FACE_INDICES : usize = 0x7fff;
pub const MAX_BONE_WEIGHTS : usize = 0x7fffffff;
pub const MAX_VERTICES : usize = 0x7fffffff;
pub const MAX_FACES : usize = 0x7fffffff;
pub const MAX_NUMBER_OF_COLOR_SETS : usize = 0x8;
pub const MAX_NUMBER_OF_TEXTURECOORDS : usize = 0x8;
#[repr(C)]
pub struct Face {
pub num_indices: c_uint,
indices: *mut c_uint,
}
impl Face {
pub fn get_indices(&self) -> &[u32] {
unsafe { ptr_to_slice(self.indices, self.num_indices as usize) }
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C)]
pub struct VertexWeight {
pub vertex_id: c_uint,
pub weight: c_float,
}
#[repr(C)]
pub struct Bone {
pub name: AiString,
pub num_weights: c_uint,
weights: *mut VertexWeight,
pub offset_matrix: Matrix4x4,
}
impl Bone {
pub fn get_weights(&self) -> &[VertexWeight] {
unsafe { ptr_to_slice(self.weights, self.num_weights as usize) }
}
}
#[allow(unused_qualifications)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(C)]
pub enum PrimitiveType {
Point = 0x1,
Line = 0x2,
Triangle = 0x4,
Polygon = 0x8,
}
impl PrimitiveType {
pub fn get_primitive_type(n: u32) -> PrimitiveType {
match n {
0 => panic!("0 is an invalid number for vertices in a face"),
1 => Point,
2 => Line,
3 => Triangle,
_ => Polygon,
}
}
}
#[repr(C)]
pub struct AnimMesh {
vertices: *mut Vector3D,
normals: *mut Vector3D,
tangents: *mut Vector3D,
bitangents: *mut Vector3D,
colors: [*mut Color4D; MAX_NUMBER_OF_COLOR_SETS],
texture_coords: [*mut Vector3D; MAX_NUMBER_OF_TEXTURECOORDS],
pub num_vertices: c_uint,
}
impl AnimMesh {
pub fn get_vertices(&self) -> &[Vector3D] {
unsafe { ptr_to_slice(self.vertices, self.num_vertices as usize) }
}
pub fn get_normals(&self) -> &[Vector3D] {
let len = match self.normals.is_null() {
true => 0,
false => self.num_vertices as usize,
};
unsafe { ptr_to_slice(self.normals, len) }
}
pub fn get_tangents(&self) -> &[Vector3D] {
let len = match self.tangents.is_null() {
true => 0,
false => self.num_vertices as usize,
};
unsafe { ptr_to_slice(self.tangents, len) }
}
pub fn get_bitangents(&self) -> &[Vector3D] {
let len = match self.bitangents.is_null() {
true => 0,
false => self.num_vertices as usize,
};
unsafe { ptr_to_slice(self.bitangents, len) }
}
pub fn get_colors(&self) -> Vec<&[Color4D]> {
let mut list = Vec::with_capacity(MAX_NUMBER_OF_COLOR_SETS);
for colors in self.colors.iter() {
if colors.is_null() { break; }
unsafe {
list.push(ptr_to_slice(*colors, self.num_vertices as usize));
}
}
list
}
pub fn get_texture_coords(&self) -> Vec<&[Vector3D]> {
let mut list = Vec::with_capacity(MAX_NUMBER_OF_TEXTURECOORDS);
for tex_coords in self.texture_coords.iter() {
if tex_coords.is_null() { break; }
unsafe {
list.push(ptr_to_slice(*tex_coords, self.num_vertices as usize));
}
}
list
}
}
#[repr(C)]
pub struct Mesh {
pub primitive_types: c_uint,
pub num_vertices: c_uint,
pub num_faces: c_uint,
vertices: *mut Vector3D,
normals: *mut Vector3D,
tangents: *mut Vector3D,
bitangents : *mut Vector3D,
colors: [*mut Color4D; MAX_NUMBER_OF_COLOR_SETS],
texture_coords: [*mut Vector3D; MAX_NUMBER_OF_TEXTURECOORDS],
pub num_uv_components: [c_uint; MAX_NUMBER_OF_TEXTURECOORDS],
faces: *mut Face,
pub num_bones: c_uint,
bones: *mut*mut Bone,
pub material_index: c_uint,
pub name: AiString,
pub num_anim_meshes: c_uint,
anim_meshes: *mut*mut AnimMesh,
}
impl Mesh {
pub fn has_primitive(&self, prim: PrimitiveType) -> bool {
(self.primitive_types & prim as u32) != 0
}
pub fn get_vertices(&self) -> &[Vector3D] {
unsafe { ptr_to_slice(self.vertices, self.num_vertices as usize) }
}
pub fn get_normals(&self) -> &[Vector3D] {
let len = match self.normals.is_null() {
true => 0,
false => self.num_vertices as usize,
};
unsafe { ptr_to_slice(self.normals, len) }
}
pub fn get_tangents(&self) -> &[Vector3D] {
let len = match self.tangents.is_null() {
true => 0,
false => self.num_vertices as usize,
};
unsafe { ptr_to_slice(self.tangents, len) }
}
pub fn get_bitangents(&self) -> &[Vector3D] {
let len = match self.bitangents.is_null() {
true => 0,
false => self.num_vertices as usize,
};
unsafe { ptr_to_slice(self.bitangents, len) }
}
pub fn get_colors(&self) -> Vec<&[Color4D]> {
let mut list = Vec::with_capacity(MAX_NUMBER_OF_COLOR_SETS);
for colors in self.colors.iter() {
if colors.is_null() { break; }
unsafe {
list.push(ptr_to_slice(*colors, self.num_vertices as usize));
}
}
list
}
pub fn get_texture_coords(&self) -> Vec<&[Vector3D]> {
let mut list = Vec::with_capacity(MAX_NUMBER_OF_COLOR_SETS);
for tex_coords in self.texture_coords.iter() {
if tex_coords.is_null() { break; }
unsafe {
list.push(ptr_to_slice(*tex_coords, self.num_vertices as usize));
}
}
list
}
pub fn get_faces(&self) -> &[Face] {
unsafe { ptr_to_slice(self.faces, self.num_faces as usize) }
}
pub fn get_bones(&self) -> &[&Bone] {
unsafe { ptr_ptr_to_slice(self.bones, self.num_bones as usize) }
}
}
impl fmt::Display for Mesh {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "Mesh {{ name: {}, primitive_types:", self.name,));
if self.has_primitive(Point) { try!(write!(f, " Point")) }
if self.has_primitive(Line) { try!(write!(f, " Line")) }
if self.has_primitive(Triangle) { try!(write!(f, " Triangle")) }
if self.has_primitive(Polygon) { try!(write!(f, " Polygon")) }
write!(f, ", num_vertices: {}, num_faces: {}, num_bones: {}, material_index: {} }}",
self.num_vertices,
self.num_faces,
self.num_bones,
self.material_index)
}
}