use super::{Gradient, vertex::*, mesh::*, PrimitiveType};
use color::{ToRgba,ToRgb,Rgba};
use na::*;
use angle::*;
use std::{f32, f64};
use std::marker;
use alga;
use num_traits::{self, zero, NumCast, Float};
use std::ops::Neg;
#[derive(Debug,Clone)]
pub struct Line{
pub p1: Pnt2,
pub p2: Pnt2,
}
impl Line{
pub fn to_mesh(self) -> Mesh<Vec2>{
mesh(
vec![
self.p1.to_vec(),
self.p2.to_vec(),
],
PrimitiveType::Lines
)
}
pub fn to_color_mesh<C: ToRgba>(self, color: &C) -> Mesh<Vertex2DColor>{
mesh(
vec![
vertex2dcolor(self.p1.to_vec(), color),
vertex2dcolor(self.p2.to_vec(), color),
],
PrimitiveType::Lines
)
}
}
#[derive(Debug,Clone)]
pub struct Ellipse{
pub center: Pnt2,
pub width: f32,
pub height: f32,
}
impl Ellipse{
pub fn to_mesh(self, resolution: u32) -> Mesh<Vec2>{
let pos = self.center.to_vec();
let w = self.width * 0.5;
let h = self.height * 0.5;
let vertices = arc_iter(pos, w, h, zero(), Deg::two_pi(), resolution);
Mesh::from_iter_and_type(vertices, PrimitiveType::TriangleFan)
}
pub fn to_outline(self, resolution: u32) -> Mesh<Vec2>{
let pos = self.center.to_vec();
let w = self.width * 0.5;
let h = self.height * 0.5;
let vertices = arc_iter(pos, w, h, zero(), Deg::two_pi(), resolution);
Mesh::from_iter_and_type(vertices, PrimitiveType::LineLoop)
}
pub fn to_mesh_color<C:ToRgba>(self, color: &C, resolution: u32) -> Mesh<Vertex2DColor>{
let pos = self.center.to_vec();
let w = self.width * 0.5;
let h = self.height * 0.5;
let vertices = arc_iter(pos, w, h, zero(), Deg::two_pi(), resolution)
.map(|p| vertex2dcolor(p, color));
Mesh::from_iter_and_type(vertices, PrimitiveType::TriangleFan)
}
pub fn to_outline_color<C:ToRgba>(self, color: &C, resolution: u32) -> Mesh<Vertex2DColor>{
let pos = self.center.to_vec();
let w = self.width * 0.5;
let h = self.height * 0.5;
let vertices = arc_iter(pos, w, h, zero(), Deg::two_pi(), resolution)
.map(|p| vertex2dcolor(p, color));
Mesh::from_iter_and_type(vertices, PrimitiveType::LineLoop)
}
pub fn to_mesh_texcoords(self, resolution: u32) -> Mesh<Vertex2DTex>{
let pos = self.center.to_vec();
let w = self.width * 0.5;
let h = self.height * 0.5;
let size = vec2(self.width, self.height);
let vertices = arc_iter(pos, w, h, zero(), Deg::two_pi(), resolution)
.map(|p| {
let tex = p - pos;
let tex = vec2(tex.x / size.x, tex.y / size.y);
Vertex2DTex{ position: p, texcoord: tex }
});
Mesh::from_iter_and_type(vertices, PrimitiveType::TriangleFan)
}
}
#[derive(Debug,Clone)]
pub struct Circle{
pub center: Pnt2,
pub radius: f32,
}
impl Circle{
pub fn to_mesh(self, resolution: u32) -> Mesh<Vec2>{
Ellipse{
center: self.center,
width: self.radius * 2.,
height: self.radius * 2.,
}.to_mesh(resolution)
}
pub fn to_outline(self, resolution: u32) -> Mesh<Vec2>{
Ellipse{
center: self.center,
width: self.radius * 2.,
height: self.radius * 2.,
}.to_outline(resolution)
}
pub fn to_mesh_color<C:ToRgba>(self, color: &C, resolution: u32) -> Mesh<Vertex2DColor>{
Ellipse{
center: self.center,
width: self.radius * 2.,
height: self.radius * 2.,
}.to_mesh_color(color, resolution)
}
pub fn to_outline_color<C:ToRgba>(self, color: &C, resolution: u32) -> Mesh<Vertex2DColor>{
Ellipse{
center: self.center,
width: self.radius * 2.,
height: self.radius * 2.,
}.to_outline_color(color, resolution)
}
pub fn to_mesh_texcoords(self, resolution: u32) -> Mesh<Vertex2DTex>{
Ellipse{
center: self.center,
width: self.radius * 2.,
height: self.radius * 2.,
}.to_mesh_texcoords(resolution)
}
}
pub fn ellipse(x: f32, y: f32, w: f32, h:f32, resolution: u32) -> Mesh<Vec2>{
let vertices = arc_iter(vec2(x,y),w*0.5,h*0.5,zero(), Deg::two_pi(), resolution);
Mesh::from_iter_and_type(vertices, PrimitiveType::TriangleFan)
}
pub fn ellipse_texcoords(x: f32, y: f32, w: f32, h:f32, resolution: u32) -> Mesh<Vertex2DTex>{
let size = vec2(w,h);
let pos = vec2(x,y);
let vertices = arc_iter(vec2(x,y),w*0.5,h*0.5,zero(), Deg::two_pi(), resolution)
.map(|p| {
let tex = p - pos;
let tex = vec2(tex.x / size.x, tex.y / size.y);
Vertex2DTex{ position: p, texcoord: tex }
});
Mesh::from_iter_and_type(vertices, PrimitiveType::TriangleFan)
}
pub fn ellipse_color<C:ToRgba>(x: f32, y: f32, w: f32, h:f32, resolution: u32, color: &C) -> Mesh<Vertex2DColor>{
let vertices = arc_iter(vec2(x,y),w*0.5,h*0.5,zero(), Deg::two_pi(), resolution)
.map(|p| vertex2dcolor(p, color));
Mesh::from_iter_and_type(vertices, PrimitiveType::TriangleFan)
}
pub fn circle(x: f32, y: f32, r: f32, resolution: u32) -> Mesh<Vec2>{
ellipse(x,y,r*2.0,r*2.0,resolution)
}
pub fn circle_texcoords(x: f32, y: f32, r: f32, resolution: u32) -> Mesh<Vertex2DTex>{
ellipse_texcoords(x,y,r*2.0,r*2.0,resolution)
}
pub fn circle_color<C:ToRgba>(x: f32, y: f32, r: f32, resolution: u32, color: &C) -> Mesh<Vertex2DColor>{
ellipse_color(x,y,r*2.0,r*2.0,resolution,color)
}
pub fn line_color<C: ToRgba>(from: &Pnt2, to: &Pnt2, color: &C) -> Mesh<Vertex2DColor>{
mesh(
vec![
vertex2dcolor(vec2(from.x,from.y), color),
vertex2dcolor(vec2(to.x,to.y), color)
],
PrimitiveType::Lines
)
}
pub fn rectangle(x: f32, y: f32, w: f32, h: f32) -> Mesh<Vec2>{
mesh(
vec![
vec2(x,y),
vec2(x+w,y),
vec2(x+w,y+h),
vec2(x,y+h)
],
PrimitiveType::TriangleFan
)
}
pub fn rectangle_texcoords(x: f32, y: f32, w: f32, h: f32, s0: f32, t0: f32, s1: f32, t1:f32) -> Mesh<Vertex2DTex>{
mesh(
vec![
vertex2dtex(vec2(x,y), vec2(s0,t1)),
vertex2dtex(vec2(x+w,y), vec2(s1,t1)),
vertex2dtex(vec2(x+w,y+h), vec2(s1,t0)),
vertex2dtex(vec2(x,y+h), vec2(s0,t0)),
],
PrimitiveType::TriangleFan
)
}
pub fn rectangle_color<C: ToRgba>(x: f32, y: f32, w: f32, h: f32, color: &C) -> Mesh<Vertex2DColor>{
mesh(
vec![
vertex2dcolor(vec2(x,y), color),
vertex2dcolor(vec2(x+w,y), color),
vertex2dcolor(vec2(x+w,y+h), color),
vertex2dcolor(vec2(x,y+h), color),
],
PrimitiveType::TriangleFan
)
}
pub fn rectangle_gradient<C: ToRgba + ToRgb>(x: f32, y: f32, w: f32, h: f32, gradient: &Gradient<C>) -> Mesh<Vertex2DColor>{
match gradient{
&Gradient::Linear{..} => mesh(
vec![
vertex2dcolor::<Rgba<f32>>(vec2(x,y), &gradient.rgba_at(vec2(0.0,0.0))),
vertex2dcolor::<Rgba<f32>>(vec2(x+w,y), &gradient.rgba_at(vec2(1.0,0.0))),
vertex2dcolor::<Rgba<f32>>(vec2(x+w,y+h), &gradient.rgba_at(vec2(1.0,1.0))),
vertex2dcolor::<Rgba<f32>>(vec2(x,y+h), &gradient.rgba_at(vec2(0.0,1.0))),
],
PrimitiveType::TriangleFan
),
&Gradient::Circular{ref start_color, ref end_color} => {
let center = vec2(x, y) + vec2(w / 2., h / 2.);
let mut vertices = vec![ vertex2dcolor(center, start_color) ];
let resolution = 32;
let angle_bisector = Rad::two_pi() / (resolution as f32 * 2.);
let small_r = norm(&vec2(w / 2., h / 2.));
let big_r = small_r / angle_bisector.cos();
let two_pi: Rad<f32> = Rad::two_pi();
for i in 0..resolution+1 {
let theta:f32 = i as f32 * two_pi.value() / resolution as f32;
let pos = center + vec2(theta.sin(), theta.cos()) * big_r;
vertices.push(vertex2dcolor(pos, end_color));
}
mesh(vertices, PrimitiveType::TriangleFan)
}
}
}
pub fn sphere_texcoords(radius: f32, rings: u32, sectors: u32) -> Mesh<Vertex3DTexNormal>{
let inv_r = 1.0 / rings as f32;
let inv_s = 1.0 / sectors as f32;
let ring_vertices = rings + 1;
let sector_vertices = sectors + 1;
let mut mesh: Mesh<Vertex3DTexNormal> = Mesh::default();
mesh.reserve((ring_vertices*sector_vertices) as usize);
unsafe{
mesh.set_len((ring_vertices*sector_vertices) as usize);
}
mesh.indices_mut().reserve((ring_vertices * sector_vertices * 6) as usize);
unsafe{
mesh.indices_mut().set_len((ring_vertices * sector_vertices * 6) as usize);
}
let mut v = 0;
let mut i = 0;
sphere_vertices(rings,sectors,
|vertex,r,s|{
mesh[v].position = vertex * radius;
mesh[v].texcoord = vec2(s as f32 * inv_s, r as f32 * inv_r);
mesh[v].normal = vertex;
v+=1;
},
);
for r in 0 ..= rings {
for s in 0 .. sectors {
mesh.indices_mut()[i] = ((r+1) * sectors + (s+1)) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + (s+1)) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = ((r+1) * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = ((r+1) * sectors + (s+1)) as IndexT;
i += 1;
}
}
mesh
}
pub fn sphere_color<C:ToRgba>(radius: f32, rings: u32, sectors: u32, color: &C) -> Mesh<Vertex3DColorNormal>{
let ring_vertices = rings+1;
let sector_vertices = sectors+1;
let mut mesh: Mesh<Vertex3DColorNormal> = Mesh::default();
mesh.reserve((ring_vertices*sector_vertices) as usize);
unsafe{
mesh.set_len((ring_vertices*sector_vertices) as usize);
}
mesh.indices_mut().reserve((ring_vertices * sectors * 6) as usize);
unsafe{
mesh.indices_mut().set_len((ring_vertices * sectors * 6) as usize);
}
let mut v = 0;
let mut i = 0;
sphere_vertices(rings,sectors,
|vertex,_r,_s|{
mesh[v].position = vertex * radius;
mesh[v].color = color.to_rgba();
mesh[v].normal = vertex;
v+=1;
},
);
for r in 0 .. rings+1 {
for s in 0 .. sectors {
mesh.indices_mut()[i] = ((r+1) * sectors + (s+1)) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + (s+1)) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = ((r+1) * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = ((r+1) * sectors + (s+1)) as IndexT;
i += 1;
}
}
mesh
}
pub fn sphere(radius: f32, rings: u32, sectors: u32) -> Mesh<Vertex3DNormal>{
let ring_vertices = rings+1;
let sector_vertices = sectors+1;
let mut mesh: Mesh<Vertex3DNormal> = Mesh::default();
mesh.reserve((ring_vertices*sector_vertices) as usize);
unsafe{
mesh.set_len((ring_vertices*sector_vertices) as usize);
}
mesh.indices_mut().reserve((ring_vertices * sectors * 6) as usize);
unsafe{
mesh.indices_mut().set_len((ring_vertices * sectors * 6) as usize);
}
let mut v = 0;
let mut i = 0;
sphere_vertices(rings,sectors,
|vertex,_r,_s|{
mesh[v].position = vertex * radius;
mesh[v].normal = vertex;
v+=1;
},
);
for r in 0 .. rings+1 {
for s in 0 .. sectors {
mesh.indices_mut()[i] = ((r+1) * sectors + (s+1)) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + (s+1)) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = (r * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = ((r+1) * sectors + s) as IndexT;
i += 1;
mesh.indices_mut()[i] = ((r+1) * sectors + (s+1)) as IndexT;
i += 1;
}
}
mesh
}
pub fn cone(radius: f32, height: f32, segments: u32) -> Mesh<Vertex3DNormal>{
let mut mesh: Mesh<Vertex3DNormal> = Mesh::default();
const TWO_PI: f32 = 2.0 * f32::consts::PI;
let height_segments = 1;
let cap_segments = 1;
let radius_segments = segments;
let angle_step = -1. * TWO_PI / radius_segments as f32;
let height_step = 1. / height_segments as f32 * height;
let start = vec3!(0., height, 0.);
mesh.push(vertex3dnormal(start, Vec3::y()));
for iy in 1 .. height_segments + 1{
for ix in 1 .. radius_segments + 1{
let mut r = (iy as f32 / height_segments as f32) * radius;
let mut x = (ix as f32 * angle_step).cos() * r;
let mut y = height_step * (iy - 1) as f32;
let mut z = (ix as f32 * angle_step).sin() * r;
let pos = vec3!(x,y,z);
if iy == 0 {
r = 1.;
x = (ix as f32 * angle_step).cos() * r;
y = height_step * (iy - 1) as f32;
z = (ix as f32 * angle_step).sin() * r;
}
let new_pos = vec3!(x,y,z);
let diff = new_pos - start;
let crossed = (-Vec3::y()).cross(&new_pos);
let normal = crossed.cross(&diff);
mesh.push(vertex3dnormal(pos, normalize(&normal)));
}
}
mesh.push(vertex3dnormal(vec3!(0.), -Vec3::y()));
for ix in 1 .. radius_segments {
mesh.add_face(
0,
ix + 1,
ix,
);
}
mesh.add_face(
0,
1,
radius_segments,
);
for ix in 1 .. radius_segments {
mesh.add_face(
radius_segments + 1,
ix,
ix + 1,
);
}
mesh.add_face(
radius_segments + 1,
1,
radius_segments,
);
mesh
}
pub fn cube_wireframe(size: f32) -> Mesh<Vertex3D>{
let half = size * 0.5;
Mesh::new(
vec![
vertex3d(vec3( -half,-half,-half )),
vertex3d(vec3( -half, half,-half )),
vertex3d(vec3( half,-half,-half )),
vertex3d(vec3( half, half,-half )),
vertex3d(vec3( -half,-half, half )),
vertex3d(vec3( -half, half, half )),
vertex3d(vec3( half,-half, half )),
vertex3d(vec3( half, half, half )),
],
vec![
0,1, 1,3, 3,2, 2,0,
0,4, 1,5, 2,6, 3,7,
4,5, 5,7, 7,6, 6,4,
],
PrimitiveType::Lines
)
}
pub fn cube(side: f32) -> Mesh<Vertex3DNormal>{
let top = Vec3::y();
let bottom = -Vec3::y();
let left = -Vec3::x();
let right = Vec3::x();
let front = Vec3::z();
let back = -Vec3::z();
let vertices = vec![
vertex3dnormal(vec3(-0.5, -0.5, 0.5) * side, front),
vertex3dnormal(vec3( 0.5, -0.5, 0.5) * side, front),
vertex3dnormal(vec3( 0.5, 0.5, 0.5) * side, front),
vertex3dnormal(vec3(-0.5, 0.5, 0.5) * side, front),
vertex3dnormal(vec3(-0.5, -0.5, 0.5) * side, bottom),
vertex3dnormal(vec3( 0.5, -0.5, 0.5) * side, bottom),
vertex3dnormal(vec3( 0.5, -0.5, -0.5) * side, bottom),
vertex3dnormal(vec3(-0.5, -0.5, -0.5) * side, bottom),
vertex3dnormal(vec3(-0.5, -0.5, 0.5) * side, left),
vertex3dnormal(vec3(-0.5, -0.5, -0.5) * side, left),
vertex3dnormal(vec3(-0.5, 0.5, -0.5) * side, left),
vertex3dnormal(vec3(-0.5, 0.5, 0.5) * side, left),
vertex3dnormal(vec3( 0.5, -0.5, 0.5) * side, right),
vertex3dnormal(vec3( 0.5, -0.5, -0.5) * side, right),
vertex3dnormal(vec3( 0.5, 0.5, -0.5) * side, right),
vertex3dnormal(vec3( 0.5, 0.5, 0.5) * side, right),
vertex3dnormal(vec3(-0.5, 0.5, 0.5) * side, top),
vertex3dnormal(vec3(-0.5, 0.5, -0.5) * side, top),
vertex3dnormal(vec3( 0.5, 0.5, -0.5) * side, top),
vertex3dnormal(vec3( 0.5, 0.5, 0.5) * side, top),
vertex3dnormal(vec3(-0.5, -0.5, -0.5) * side, back),
vertex3dnormal(vec3( 0.5, -0.5, -0.5) * side, back),
vertex3dnormal(vec3( 0.5, 0.5, -0.5) * side, back),
vertex3dnormal(vec3(-0.5, 0.5, -0.5) * side, back),
];
let indices = vertices.iter()
.enumerate()
.collect::<Vec<_>>()
.chunks(4)
.flat_map(|v|{
vec![
v[0].0 as u32, v[1].0 as u32, v[2].0 as u32,
v[2].0 as u32, v[3].0 as u32, v[0].0 as u32
]
})
.collect::<Vec<_>>();
Mesh::from_vertices_indices(vertices, indices)
}
pub fn cube_color<C:ToRgba>(side: f32, color: &C) -> Mesh<Vertex3DColorNormal>{
let top = Vec3::y();
let bottom = -Vec3::y();
let left = -Vec3::x();
let right = Vec3::y();
let front = Vec3::z();
let back = -Vec3::z();
let vertices = vec![
vertex3dcolornormal(vec3(-0.5, -0.5, 0.5) * side, color, front),
vertex3dcolornormal(vec3( 0.5, -0.5, 0.5) * side, color, front),
vertex3dcolornormal(vec3( 0.5, 0.5, 0.5) * side, color, front),
vertex3dcolornormal(vec3(-0.5, 0.5, 0.5) * side, color, front),
vertex3dcolornormal(vec3(-0.5, -0.5, 0.5) * side, color, bottom),
vertex3dcolornormal(vec3( 0.5, -0.5, 0.5) * side, color, bottom),
vertex3dcolornormal(vec3( 0.5, -0.5, -0.5) * side, color, bottom),
vertex3dcolornormal(vec3(-0.5, -0.5, -0.5) * side, color, bottom),
vertex3dcolornormal(vec3(-0.5, -0.5, 0.5) * side, color, left),
vertex3dcolornormal(vec3(-0.5, -0.5, -0.5) * side, color, left),
vertex3dcolornormal(vec3(-0.5, 0.5, -0.5) * side, color, left),
vertex3dcolornormal(vec3(-0.5, 0.5, 0.5) * side, color, left),
vertex3dcolornormal(vec3( 0.5, -0.5, 0.5) * side, color, right),
vertex3dcolornormal(vec3( 0.5, -0.5, -0.5) * side, color, right),
vertex3dcolornormal(vec3( 0.5, 0.5, -0.5) * side, color, right),
vertex3dcolornormal(vec3( 0.5, 0.5, 0.5) * side, color, right),
vertex3dcolornormal(vec3(-0.5, 0.5, 0.5) * side, color, top),
vertex3dcolornormal(vec3(-0.5, 0.5, -0.5) * side, color, top),
vertex3dcolornormal(vec3( 0.5, 0.5, -0.5) * side, color, top),
vertex3dcolornormal(vec3( 0.5, 0.5, 0.5) * side, color, top),
vertex3dcolornormal(vec3(-0.5, -0.5, -0.5) * side, color, back),
vertex3dcolornormal(vec3( 0.5, -0.5, -0.5) * side, color, back),
vertex3dcolornormal(vec3( 0.5, 0.5, -0.5) * side, color, back),
vertex3dcolornormal(vec3(-0.5, 0.5, -0.5) * side, color, back),
];
let indices = vertices.iter()
.enumerate()
.collect::<Vec<_>>()
.chunks(4)
.flat_map(|v|{
vec![
v[0].0 as u32, v[1].0 as u32, v[2].0 as u32,
v[2].0 as u32, v[3].0 as u32, v[0].0 as u32
]
})
.collect::<Vec<_>>();
Mesh::from_vertices_indices(vertices, indices)
}
pub fn cuboid(extents: Vec3) -> Mesh<Vertex3DNormal>{
let top = Vec3::y();
let bottom = -Vec3::y();
let left = -Vec3::x();
let right = Vec3::y();
let front = Vec3::z();
let back = -Vec3::z();
let vertices = vec![
vertex3dnormal(vec3(-0.5, -0.5, 0.5).component_mul(&extents), front),
vertex3dnormal(vec3( 0.5, -0.5, 0.5).component_mul(&extents), front),
vertex3dnormal(vec3( 0.5, 0.5, 0.5).component_mul(&extents), front),
vertex3dnormal(vec3(-0.5, 0.5, 0.5).component_mul(&extents), front),
vertex3dnormal(vec3(-0.5, -0.5, 0.5).component_mul(&extents), bottom),
vertex3dnormal(vec3( 0.5, -0.5, 0.5).component_mul(&extents), bottom),
vertex3dnormal(vec3( 0.5, -0.5, -0.5).component_mul(&extents), bottom),
vertex3dnormal(vec3(-0.5, -0.5, -0.5).component_mul(&extents), bottom),
vertex3dnormal(vec3(-0.5, -0.5, 0.5).component_mul(&extents), left),
vertex3dnormal(vec3(-0.5, -0.5, -0.5).component_mul(&extents), left),
vertex3dnormal(vec3(-0.5, 0.5, -0.5).component_mul(&extents), left),
vertex3dnormal(vec3(-0.5, 0.5, 0.5).component_mul(&extents), left),
vertex3dnormal(vec3( 0.5, -0.5, 0.5).component_mul(&extents), right),
vertex3dnormal(vec3( 0.5, -0.5, -0.5).component_mul(&extents), right),
vertex3dnormal(vec3( 0.5, 0.5, -0.5).component_mul(&extents), right),
vertex3dnormal(vec3( 0.5, 0.5, 0.5).component_mul(&extents), right),
vertex3dnormal(vec3(-0.5, 0.5, 0.5).component_mul(&extents), top),
vertex3dnormal(vec3(-0.5, 0.5, -0.5).component_mul(&extents), top),
vertex3dnormal(vec3( 0.5, 0.5, -0.5).component_mul(&extents), top),
vertex3dnormal(vec3( 0.5, 0.5, 0.5).component_mul(&extents), top),
vertex3dnormal(vec3(-0.5, -0.5, -0.5).component_mul(&extents), back),
vertex3dnormal(vec3( 0.5, -0.5, -0.5).component_mul(&extents), back),
vertex3dnormal(vec3( 0.5, 0.5, -0.5).component_mul(&extents), back),
vertex3dnormal(vec3(-0.5, 0.5, -0.5).component_mul(&extents), back),
];
let indices = vertices.iter()
.enumerate()
.collect::<Vec<_>>()
.chunks(4)
.flat_map(|v|{
vec![
v[0].0 as u32, v[1].0 as u32, v[2].0 as u32,
v[2].0 as u32, v[3].0 as u32, v[0].0 as u32
]
})
.collect::<Vec<_>>();
Mesh::from_vertices_indices(vertices, indices)
}
pub fn cuboid_color<C:ToRgba>(extents: Vec3, color: &C) -> Mesh<Vertex3DColorNormal>{
let top = Vec3::y();
let bottom = -Vec3::y();
let left = -Vec3::x();
let right = Vec3::y();
let front = Vec3::z();
let back = -Vec3::z();
let vertices = vec![
vertex3dcolornormal(vec3(-0.5, -0.5, 0.5).component_mul(&extents), color, front),
vertex3dcolornormal(vec3( 0.5, -0.5, 0.5).component_mul(&extents), color, front),
vertex3dcolornormal(vec3( 0.5, 0.5, 0.5).component_mul(&extents), color, front),
vertex3dcolornormal(vec3(-0.5, 0.5, 0.5).component_mul(&extents), color, front),
vertex3dcolornormal(vec3(-0.5, -0.5, 0.5).component_mul(&extents), color, bottom),
vertex3dcolornormal(vec3( 0.5, -0.5, 0.5).component_mul(&extents), color, bottom),
vertex3dcolornormal(vec3( 0.5, -0.5, -0.5).component_mul(&extents), color, bottom),
vertex3dcolornormal(vec3(-0.5, -0.5, -0.5).component_mul(&extents), color, bottom),
vertex3dcolornormal(vec3(-0.5, -0.5, 0.5).component_mul(&extents), color, left),
vertex3dcolornormal(vec3(-0.5, -0.5, -0.5).component_mul(&extents), color, left),
vertex3dcolornormal(vec3(-0.5, 0.5, -0.5).component_mul(&extents), color, left),
vertex3dcolornormal(vec3(-0.5, 0.5, 0.5).component_mul(&extents), color, left),
vertex3dcolornormal(vec3( 0.5, -0.5, 0.5).component_mul(&extents), color, right),
vertex3dcolornormal(vec3( 0.5, -0.5, -0.5).component_mul(&extents), color, right),
vertex3dcolornormal(vec3( 0.5, 0.5, -0.5).component_mul(&extents), color, right),
vertex3dcolornormal(vec3( 0.5, 0.5, 0.5).component_mul(&extents), color, right),
vertex3dcolornormal(vec3(-0.5, 0.5, 0.5).component_mul(&extents), color, top),
vertex3dcolornormal(vec3(-0.5, 0.5, -0.5).component_mul(&extents), color, top),
vertex3dcolornormal(vec3( 0.5, 0.5, -0.5).component_mul(&extents), color, top),
vertex3dcolornormal(vec3( 0.5, 0.5, 0.5).component_mul(&extents), color, top),
vertex3dcolornormal(vec3(-0.5, -0.5, -0.5).component_mul(&extents), color, back),
vertex3dcolornormal(vec3( 0.5, -0.5, -0.5).component_mul(&extents), color, back),
vertex3dcolornormal(vec3( 0.5, 0.5, -0.5).component_mul(&extents), color, back),
vertex3dcolornormal(vec3(-0.5, 0.5, -0.5).component_mul(&extents), color, back),
];
let indices = vertices.iter()
.enumerate()
.collect::<Vec<_>>()
.chunks(4)
.flat_map(|v|{
vec![
v[0].0 as u32, v[1].0 as u32, v[2].0 as u32,
v[2].0 as u32, v[3].0 as u32, v[0].0 as u32
]
})
.collect::<Vec<_>>();
Mesh::from_vertices_indices(vertices, indices)
}
fn plane_indices(rows: IndexT, cols: IndexT) -> Vec<IndexT>{
(0..rows-1).flat_map(move |row|{
(0..cols-1).flat_map(move |col|{
vec![
row * cols + col,
(row + 1) * cols + col,
row * cols + col + 1,
row * cols + (col + 1),
(row + 1) * cols + col,
(row + 1) * cols + (col + 1),
]
})
}).collect()
}
pub fn plane(size: Vec2, rows: IndexT, cols: IndexT) -> Mesh<Vertex3DNormal>{
let half = size * 0.5;
let rows = rows + 1;
let cols = cols + 1;
let vertices = (0..rows).flat_map(move |row|{
(0..cols).map(move |col|{
let x = col as f32 / (cols - 1) as f32;
let y = row as f32 / (rows - 1) as f32;
let pos = vec2(x, y);
let pos = vec3!(pos.component_mul(&size) - half, 0.);
vertex3dnormal(pos, Vec3::z())
})
}).collect();
let indices = plane_indices(rows, cols);
Mesh::from_vertices_indices(vertices, indices)
}
pub fn plane_color<C: ToRgba>(size: Vec2, rows: IndexT, cols: IndexT, color: &C) -> Mesh<Vertex3DColorNormal>{
let half = size * 0.5;
let rows = rows + 1;
let cols = cols + 1;
let vertices = (0..rows).flat_map(move |row|{
(0..cols).map(move |col|{
let x = col as f32 / (cols - 1) as f32;
let y = row as f32 / (rows - 1) as f32;
let pos = vec2(x, y);
let pos = vec3!(pos.component_mul(&size) - half, 0.);
vertex3dcolornormal(pos, color, Vec3::z())
})
}).collect();
let indices = plane_indices(rows, cols);
Mesh::from_vertices_indices(vertices, indices)
}
pub fn plane_texcoords(size: Vec2, rows: IndexT, cols: IndexT) -> Mesh<Vertex3DTexNormal>{
let half = size * 0.5;
let rows = rows + 1;
let cols = cols + 1;
let vertices = (0..rows).flat_map(move |row|{
(0..cols).map(move |col|{
let x = col as f32 / (cols - 1) as f32;
let y = row as f32 / (rows - 1) as f32;
let texcoord = vec2(x,y);
let pos = vec3!(texcoord.component_mul(&size) - half, 0.);
vertex3dtexnormal(pos, texcoord, Vec3::z())
})
}).collect();
let indices = plane_indices(rows, cols);
Mesh::from_vertices_indices(vertices, indices)
}
pub fn plane_no_indices(size: Vec2, rows: IndexT, cols: IndexT) -> Mesh<Vertex3DNormal>{
let plane = plane(size, rows, cols);
plane.indices().iter().map(|i| plane[*i as usize]).collect()
}
pub fn plane_texcoords_no_indices(size: Vec2, rows: IndexT, cols: IndexT) -> Mesh<Vertex3DTexNormal>{
let plane = plane_texcoords(size, rows, cols);
plane.indices().iter().map(|i| plane[*i as usize]).collect()
}
pub fn plane_wireframe(size: Vec2, rows: IndexT, cols: IndexT) -> Mesh<Vertex3D>{
let half = size * 0.5;
let rows = rows + 1;
let cols = cols + 1;
let vertices = (0..rows).flat_map(move |row|{
(0..cols).map(move |col|{
let x = col as f32 / (cols - 1) as f32;
let y = row as f32 / (rows - 1) as f32;
let pos = vec2(x, y);
let pos = vec3!(pos.component_mul(&size) - half, 0.);
vertex3d(pos)
})
}).collect();
let indices = (0..rows-1).flat_map(move |row|{
(0..cols-1).flat_map(move |col|{
vec![
row * cols + col,
row * cols + col +1,
row * cols + col +1,
(row + 1) * cols + (col + 1),
(row + 1) * cols + (col + 1),
(row + 1) * cols + col,
(row + 1) * cols + col,
row * cols + col,
]
})
}).collect();
Mesh::new(vertices, indices, PrimitiveType::Lines)
}
pub fn bezier<T, U, F>(from: U, cp1: U, cp2: U, to: U, resolution: u32, mut f: F)
where T: alga::general::Real + NumCast,
U: FloatVec<T> + Copy,
F: FnMut(U){
let _3:T = num_traits::cast(3.0).unwrap();
let c:U = (cp1 - from) * _3;
let b:U = (cp2 - cp1) * _3 - c;
let a:U = to - from - c - b;
for i in 0 .. resolution+1{
let t: T = num_traits::cast(i as f32 / resolution as f32).unwrap();
let t2 = t*t;
let t3 = t2*t;
let p = a*t3 + b*t2 + c*t + from;
f(p);
}
}
pub struct BezierIter<U,T>{
i: u32, a: U, b: U, c: U, from: U, resolution: u32,
t: marker::PhantomData<T>,
}
impl<U,T> Iterator for BezierIter<U,T>
where T: alga::general::Real + NumCast,
U: FloatVec<T> + Copy{
type Item = U;
fn next(&mut self) -> Option<U>{
if self.i <= self.resolution{
let t: T = num_traits::cast(self.i as f64 / self.resolution as f64).unwrap();
let t2 = t*t;
let t3 = t2*t;
self.i += 1;
Some(self.a*t3 + self.b*t2 + self.c*t + self.from)
}else{
None
}
}
}
pub fn bezier_iter<T, U>(from: U, cp1: U, cp2: U, to: U, resolution: u32) -> BezierIter<U,T>
where T: alga::general::Real + NumCast,
U: FloatVec<T> + Copy{
let _3: T = num_traits::cast(3.0).unwrap();
let c:U = (cp1 - from) * _3;
let b:U = (cp2 - cp1) * _3 - c;
let a:U = to - from - c - b;
BezierIter{
i: 0,
c: c,
b: b,
a: a,
from: from,
resolution: resolution,
t: marker::PhantomData
}
}
pub fn quad_bezier<T, U, F>(from: U, cp1: U, to: U, resolution: u32, mut f: F)
where T: alga::general::Real + NumCast,
U: FloatVec<T> + Copy,
F: FnMut(U){
let _2:T = num_traits::cast(2.0).unwrap();
for i in 0 .. resolution+1{
let t: T = num_traits::cast(i as f32 / resolution as f32).unwrap();
let one_minus_t = one::<T>() - t;
let a = one_minus_t * one_minus_t;
let b = (_2 - t) * one_minus_t;
let c = t*t;
let p = from * a + cp1 * b + to * c;
f(p)
}
}
pub fn curve_vertices<T, U, F>(p0: U, p1: U, p2: U, p3: U, resolution: u32, mut f: F)
where T: alga::general::Real + NumCast,
U: FloatVec<T> + Copy + Neg<Output=U>,
F: FnMut(U){
let half: T = num_traits::cast(0.5).unwrap();
let _2: T = num_traits::cast(2.0).unwrap();
let _3: T = num_traits::cast(3.0).unwrap();
let _4: T = num_traits::cast(4.0).unwrap();
let _5: T = num_traits::cast(5.0).unwrap();
for i in 0 .. resolution+1{
let t:T = num_traits::cast(i as f32 / resolution as f32).unwrap();
let t2 = t*t;
let t3 = t2*t;
let p = ( ( p1 * _2 ) +
( -p0 + p2 ) * t +
( p0 * _2 - p1 * _5 + p2 * _4 - p3 ) * t2 +
( -p0 + p1 * _3 - p2 * _3 + p3 ) * t3 ) * half;
f(p);
}
}
pub fn star_vertices<T, U, F>(center: U, r: T, ri: T, points: u32, mut f: F)
where T: alga::general::Real + Float + NumCast,
u32: alga::general::SubsetOf<T>,
U: FloatVec<T> + Copy,
<U as alga::linear::InnerSpace>::Real: From<T>,
F: FnMut(U){
let alpha: Rad<T> = Rad::<T>::two_pi() / convert::<u32,T>(points*2);
let mut yr:U = zero();
yr[1] = From::from(r);
f(center + yr);
for i in (1 .. points*2).rev() {
let ra = if i % 2 == 1 {ri} else {r};
let float_i: T = num_traits::cast(i as f32).unwrap();
let omega = alpha * float_i;
let mut v: U = zero();
v[0] = From::from(ra * omega.sin());
v[1] = From::from(ra * omega.cos());
f(center + v);
}
}
pub struct ArcIter<U,T>{
i: u32,
resolution: u32,
center: U,
rx: T,
ry: T,
alpha: Rad<T>,
offset: Rad<T>,
}
impl<U,T> Iterator for ArcIter<U,T>
where T: alga::general::Real + Float,
U: FloatVec<T> + Copy,
<U as alga::linear::InnerSpace>::Real: From<T>{
type Item = U;
fn next(&mut self) -> Option<U>{
if self.i <= self.resolution {
let float_i: T = num_traits::cast(self.i).unwrap();
let omega = self.offset + self.alpha * float_i;
let mut v: U = zero();
v[0] = From::from(self.rx * omega.sin());
v[1] = From::from(self.ry * omega.cos());
self.i += 1;
Some(self.center + v)
}else{
None
}
}
}
pub fn arc_iter<T, U>(center: U, rx: T, ry: T, init_angle: Deg<T>, angle: Deg<T>, resolution: u32) -> ArcIter<U,T>
where T: alga::general::Real + Float,
U: FloatVec<T> + Copy{
let resolution = resolution;
let float_resolution: T = num_traits::cast(resolution).unwrap();
let alpha = angle.to_rad() / float_resolution;
let offset = init_angle.to_rad() + Rad::half_pi();
ArcIter{
i: 0,
resolution: resolution,
center: center,
rx: rx,
ry: ry,
alpha: alpha,
offset: offset,
}
}
pub fn arc_vertices<T, U, F> (center: U, rx: T, ry: T, init_angle: Deg<T>, angle: Deg<T>, resolution: u32, mut f: F)
where T: alga::general::Real + Float,
U: FloatVec<T> + Copy,
F: FnMut(U),
<U as alga::linear::InnerSpace>::Real: From<T> {
let resolution = resolution + 1;
let float_resolution: T = num_traits::cast((resolution - 1) as f32).unwrap();
let alpha = angle / float_resolution;
let offset = init_angle + Deg::half_pi();
for i in (0 .. resolution).rev() {
let float_i: T = num_traits::cast(i as f32).unwrap();
let omega = offset + alpha * float_i;
let mut v: U = zero();
v[0] = From::from(rx * omega.sin());
v[1] = From::from(ry * omega.cos());
f(center + v);
}
}
pub fn sphere_vertices<F>(rings: u32, sectors: u32, mut emit_vertex: F)
where F: FnMut(Vec3,u32,u32) {
let inv_r = 1.0/(rings) as f64;
let inv_s = 1.0/(sectors) as f64;
for r in 0 .. rings+1{
let y = ( -f64::consts::PI*0.5 + f64::consts::PI * r as f64 * inv_r ).sin();
let tr = ( f64::consts::PI * r as f64 * inv_r ).sin();
for s in 0 .. sectors {
let x = ( 2.0*f64::consts::PI * s as f64 * inv_s).cos() * tr;
let z = ( 2.0*f64::consts::PI * s as f64 * inv_s).sin() * tr;
emit_vertex( vec3(x as f32, y as f32, z as f32),r,s );
}
emit_vertex( vec3(tr as f32, y as f32, 0.0),r,sectors );
}
}
pub fn cone_vertices<F>(radius_segments: u32, height_segments: u32, mut emit_vertex: F)
where F: FnMut(Vec3,u32,u32)
{
const TWO_PI: f32 = 2.0 * f32::consts::PI;
let angle_step = -1. * TWO_PI / (radius_segments - 1) as f32;
let height_step = 1. / (height_segments - 1) as f32;
for iy in 0 .. height_segments {
for ix in 0 .. radius_segments {
let r = iy as f32 / (height_segments - 1) as f32;
let x = (ix as f32 * angle_step) * r;
let y = (height_step * iy as f32).cos() - 0.5;
let z = (ix as f32 * angle_step) * r;
emit_vertex(vec3!(x,y,z),ix,iy);
}
}
}
pub fn cone_cap_vertices<F>(radius_segments: u32, cap_segments: u32, mut emit_vertex: F)
where F: FnMut(Vec3,u32,u32)
{
const TWO_PI: f32 = 2.0 * f32::consts::PI;
let angle_step = -1. * TWO_PI / (radius_segments - 1) as f32;
for iy in 0 .. cap_segments {
for ix in 0 .. radius_segments {
let r = 1. - iy as f32 / (cap_segments - 1) as f32;
let x = (ix as f32 * angle_step).cos() * r;
let y = 0.5;
let z = (ix as f32 * angle_step).sin() * r;
emit_vertex(vec3(x,y,z), ix, iy);
}
}
}