#[cfg(feature="dds")]
pub extern crate dds;
#[doc(inline)]
pub use self::mesh::Mesh;
#[doc(inline)]
pub use self::mesh_slice::MeshSlice;
#[doc(inline)]
pub use self::mesh::IndexT;
#[doc(inline)]
pub use self::mesh::PrimitiveType;
#[doc(inline)]
pub use self::mesh::mesh;
#[doc(inline)]
pub use self::mesh_slice::mesh_slice;
#[doc(inline)]
pub use self::mesh::load_ply;
#[doc(inline)]
pub use self::primitives::*;
#[doc(inline)]
pub use self::path::Path2D;
#[doc(inline)]
pub use self::node::Node;
#[cfg(feature="ecs")]
#[doc(inline)]
pub use self::node::NodeParts;
#[doc(inline)]
pub use self::node::{NodeRef, NodeMut};
#[doc(inline)]
pub use self::projection::{Projection,CoordinateOrigin};
#[doc(inline)]
pub use self::mvp::{Mvp, Model, CameraMatrices, ModelMatrices};
#[doc(inline)]
pub use self::gradient::{Gradient, LinearGradientDirection};
#[doc(inline)]
#[cfg(feature="dds")]
pub use self::dds::Dds;
#[doc(inline)]
pub use self::camera::{
Camera, CameraExt, CameraPerspective, CameraOrthographic,
arcball_camera::{self, ArcballCamera},
ortho_camera::{self, OrthoCamera},
};
#[cfg(feature="ttf")]
#[doc(inline)]
pub use self::ttf::Ttf;
#[cfg(feature="ttf_rusttype")]
pub use self::ttf_rusttype as ttf;
#[cfg(feature="ttf_rusttype")]
#[doc(inline)]
pub use self::ttf::Ttf;
#[cfg(not(any(feature="ttf", feature="ttf_rusttype")))]
pub type Ttf = ();
pub use self::vertex::*;
#[cfg(feature = "freeimage")]
pub mod freeimage;
#[cfg(feature = "freeimage")]
pub use self::freeimage as image;
#[doc(no_inline)]
#[cfg(feature = "freeimage")]
pub use self::freeimage::Image;
#[cfg(feature = "image")]
pub mod image;
#[doc(no_inline)]
#[cfg(feature = "image")]
pub use self::image::Image;
pub use self::polyline::Polyline;
pub use self::polyline_slice::PolylineSlice;
#[cfg(feature = "libhdr")]
pub use libhdr::Hdr;
mod mesh;
mod mesh_slice;
mod primitives;
pub mod node;
pub mod path;
mod gradient;
pub mod vertex;
pub mod projection;
pub mod mvp;
pub mod camera;
#[cfg(feature="ttf")]
pub mod ttf;
#[cfg(all(feature="ttf_rusttype", feature="image"))]
pub mod ttf_rusttype;
mod polyline;
mod polyline_slice;
use std::f32;
use rin_math::{
pnt4, Rect, Pnt2, convert, pnt2, zero, BaseNum, Mat4, vec4, vec2, Pnt3, Vec2,
NumCast, RealField, ToVec, ToPnt, cast
};
#[cfg(feature="serialize")]
use serde_derive::{Serialize, Deserialize};
pub type Mesh2D = Mesh<Vertex2D>;
pub type Mesh2DColor = Mesh<Vertex2DColor>;
pub type Mesh2DTex = Mesh<Vertex2DTex>;
pub type Mesh2DTexColor = Mesh<Vertex2DTexColor>;
pub type Mesh2DTex3D = Mesh<Vertex2DTex3D>;
pub type Mesh3D = Mesh<Vertex3D>;
pub type Mesh3DColor = Mesh<Vertex3DColor>;
pub type Mesh3DColorNormal = Mesh<Vertex3DColorNormal>;
pub type Mesh3DNormal = Mesh<Vertex3DNormal>;
pub type Mesh3DTexColor = Mesh<Vertex3DTexColor>;
pub type Mesh3DTexNormal = Mesh<Vertex3DTexNormal>;
pub type Mesh3DTex = Mesh<Vertex3DTex>;
#[derive(Clone, Copy, PartialEq, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum ScreenZ{
World(f32),
Depth(f32),
}
impl ScreenZ{
pub fn to_world(self, projection_view: &Mat4) -> ScreenZ{
match self{
ScreenZ::World(_) => self,
ScreenZ::Depth(z) => {
let w = projection_view.try_inverse().unwrap() * vec4(0., 0., z, 1.);
let w = w.xyz() / w.w;
ScreenZ::World(w.z)
}
}
}
pub fn to_depth(self, projection_view: &Mat4) -> ScreenZ{
match self{
ScreenZ::Depth(_) => self,
ScreenZ::World(z) => {
let w = projection_view * vec4(0., 0., z, 1.);
let w = w.xyz() / w.w;
ScreenZ::Depth(w.z)
}
}
}
pub fn value(self) -> f32{
match self{
ScreenZ::Depth(z) => z,
ScreenZ::World(z) => z,
}
}
}
pub fn world_to_screen(p: &Pnt3, viewport: &Rect<i32>, projection_view: &Mat4) -> (Pnt2, ScreenZ){
let c = *projection_view * pnt4!(*p, 1.0);
let c = c.xyz() / c.w;
let mut p = pnt2(((c.x + 1.0f32) / 2.0f32 * viewport.width as f32).round(),
((1.0f32 - c.y) / 2.0f32 * viewport.height as f32).round());
let viewport_pos: Pnt2 = convert(viewport.pos);
p += viewport_pos.to_vec();
(p, ScreenZ::Depth(c.z))
}
pub fn screen_to_world(screen: &Pnt2, depth: ScreenZ, projection_view: &Mat4, viewport: &Rect<i32>) -> Pnt3 {
let x = 2.0f32 * (screen.x - viewport.pos.x as f32) / viewport.width as f32 - 1.0f32;
let y = 1.0f32 - 2.0f32 * (screen.y - viewport.pos.y as f32) / viewport.height as f32;
let z = depth.to_depth(projection_view).value();
let camera_xyz = vec4(x, y, z, 1.);
let v4 = projection_view.try_inverse().unwrap() * camera_xyz;
(v4.xyz() / v4.w).to_pnt()
}
fn num_partial_min<T:PartialOrd>(a: T, b: T) -> T{
if a<b {a} else {b}
}
fn num_partial_max<T:PartialOrd>(a: T, b: T) -> T{
if a>b {a} else {b}
}
pub fn bounding_box<T: BaseNum>(mesh: &[Vec2<T>]) -> Rect<T>{
if mesh.is_empty(){
return Rect{pos: pnt2(zero(), zero()), width: zero(), height: zero()}
}else{
let mut iter = mesh.iter();
let (max, min) = iter.next()
.map(|head| iter.fold((head.clone(), head.clone()), |(max, min), v| {
let max_x = num_partial_max(max.x.inlined_clone(), v.x.inlined_clone());
let max_y = num_partial_max(max.y.inlined_clone(), v.y.inlined_clone());
let min_x = num_partial_min(min.x.inlined_clone(), v.x.inlined_clone());
let min_y = num_partial_min(min.y.inlined_clone(), v.y.inlined_clone());
(vec2(max_x, max_y), vec2(min_x, min_y))
}))
.unwrap();
Rect{
pos: pnt2(min.x.inlined_clone(), min.y.inlined_clone()),
width: max.x.inlined_clone() - min.x.inlined_clone(),
height: max.y.inlined_clone() - min.y.inlined_clone()
}
}
}
pub trait InsidePolygon<T: RealField>{
fn inside_polygon(&self, polygon: &Polyline<T>, bound: bool) -> bool;
}
impl<T: RealField + NumCast> InsidePolygon<T> for Pnt2<T>{
fn inside_polygon(&self, polygon: &Polyline<T>, bound: bool) -> bool{
let mut count = 0;
let mut p1 = polygon[0];
for i in 0 .. polygon.len()+1
{
if *self == p1 { return bound; }
let p2 = polygon[i % polygon.len()];
if self.y < p1.y.min(p2.y) || self.y > p1.y.max(p2.y){
p1 = p2; continue;
}
if self.y > p1.y.min(p2.y) && self.y < p1.y.max(p2.y){
if self.x <= p1.x.max(p2.x){
if p1.y == p2.y && self.x >= p1.x.min(p2.x) { return bound; }
if p1.x == p2.x {
if p1.x == self.x { return bound; }
else { count += 1; }
}else{
let xinters = (self.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if self.x == xinters { return bound; }
if self.x < xinters { count += 1; }
}
}
}else{
if self.y == p2.y && self.x <= p2.x {
let p3 = polygon[(i+1) % polygon.len()];
if self.y >= p1.y.min(p3.y) && self.y <= p1.y.max(p3.y){
count += 1;
}else{
count += 2;
}
}
}
p1 = p2;
}
if count % 2 == 0{
false
}else{
true
}
}
}
pub trait GeometryIterator {
type Point;
type Field;
fn signed_area(self) -> Self::Field;
fn centroid(self) -> Option<Self::Point>;
}
impl<T, I: Iterator<Item = Pnt2<T>>> GeometryIterator for I
where
T: RealField + NumCast
{
type Point = Pnt2<T>;
type Field = T;
fn signed_area(mut self) -> T {
let mut area = zero();
let first = self.next();
let mut next = first.clone();
loop {
let p0 = next.take();
let p1 = self.next();
if let (Some(p0), Some(p1)) = (p0, p1) {
area = area + (p0.x * p1.y - p1.x * p0.y);
next = Some(p1);
}else {
if p0.is_some() {
next = p0;
}
break;
}
}
if let (Some(p0), Some(p1)) = (next, first) {
area = area + (p0.x * p1.y - p1.x * p0.y);
}
area = area * cast(0.5).unwrap();
area
}
fn centroid(self) -> Option<Pnt2<T>> {
let (num, acc) = self
.fold((0, Pnt2::origin()), |(i, acc), p|
(i + 1, acc + p.to_vec())
);
if num > 0 {
Some(acc / cast(num).unwrap())
}else{
None
}
}
}
#[cfg(feature="gl")]
use glin::gl;
#[cfg(feature="gl")]
pub trait PrimitiveTypeToGl{
fn to_gl(self) -> gl::types::GLenum;
}
#[cfg(all(feature="gl", not(any(feature="gles", feature="webgl"))))]
impl PrimitiveTypeToGl for PrimitiveType{
fn to_gl(self) -> gl::types::GLenum {
match self{
PrimitiveType::Triangles => gl::TRIANGLES,
PrimitiveType::TriangleStrip => gl::TRIANGLE_STRIP,
PrimitiveType::TriangleFan => gl::TRIANGLE_FAN,
PrimitiveType::Lines => gl::LINES,
PrimitiveType::LineStrip => gl::LINE_STRIP,
PrimitiveType::LineLoop => gl::LINE_LOOP,
PrimitiveType::LinesAdjacency => gl::LINES_ADJACENCY,
PrimitiveType::LineStripAdjacency => gl::LINE_STRIP_ADJACENCY,
PrimitiveType::Points => gl::POINTS,
PrimitiveType::Patches => gl::PATCHES,
}
}
}
#[cfg(any(feature="gles", feature="webgl"))]
impl PrimitiveTypeToGl for PrimitiveType{
fn to_gl(self) -> gl::types::GLenum {
match self{
PrimitiveType::Triangles => gl::TRIANGLES,
PrimitiveType::TriangleStrip => gl::TRIANGLE_STRIP,
PrimitiveType::TriangleFan => gl::TRIANGLE_FAN,
PrimitiveType::Lines => gl::LINES,
PrimitiveType::LineStrip => gl::LINE_STRIP,
PrimitiveType::LineLoop => gl::LINE_LOOP,
PrimitiveType::Points => gl::POINTS,
_ => unimplemented!()
}
}
}