gml 1.1.0

Graphics Math Library. Generic Vector and Matrix Math library targetting graphics applications.
// Copyright 2015 Creekware Inc. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Graphics Math Library.
//!
//! A vector and matrix library for Rust targeting low level graphics
//! operations.  Similar to C++ libraries glm, cml, MathGeoLib, Eigen,
//! CGGeometry from Cocoa, and others.  It may be useful to anyone
//! working with low level graphic primitives in Rust.
//! 
//! This library was created to determine if header-only generic template
//! C++ libraries such as you would find in Boost, glm.g-truc.net, and the
//! like could be implemented in a simpler fashion in Rust with less
//! boilerplate while maintaining performance.  After several iterations
//! we are fairly happy with the result.  Version 1.0 of this library
//! (gml) implements a complete and tested fully generic vector and matrix
//! library, modelled after the functionality found in the OpenGL shader
//! language, the C++ library GLM, and the math portion of the Unity game
//! engine.  With OpenGL or DirectX bindings (not included here) and this
//! library you can be coding up spinning 3D geometries in no time.
//! 
//! ## Versioning
//! 
//! Version 1.0.0 represents a stable and tested API.  The third digit (ie
//! from 1.0.0 to 1.0.1) represents minor revisions, bug fixes and the
//! like.  The second digit (ie from 1.0.23 to 1.1.0) represents backwards
//! compatible feature additions.  The first digit (ie from 1.3.43 to
//! 2.0.0) represents breaking API changes.  Development prior to 1.0.0 were
//! done on a private repository.
//! 
//! ## Usage
//! 
//! To use the currently released version from crates.io (recommended),
//! add this to your `Cargo.toml`:
//! 
//! ```toml
//! [dependencies]
//! gml = "*"
//! ```
//! 
//! or to use the latest version from the github repository,
//! add this instead to your `Cargo.toml`:
//! 
//! ```toml
//! [dependencies.gml]
//! git = "https://github.com/creekware/rust-gml.git"
//! ```
//! 
//! and this to your crate root:
//! 
//! ```rust
//! extern crate gml;
//! ```
//! 
//! ## Example: triangle normal
//!
//! ```
//! use gml::*;
//!
//! let a = Vector3::new( 1.0,  3.0, 2.0);
//! let b = Vector3::new( 5.0, 11.0, 3.0);
//! let c = Vector3::new(-4.0, -8.0,-1.0);
//! let triangle_normal = (c - a).cross(b - a).normalize();
//! let expected_answer = Vector3::new(0.849837, -0.457604, 0.261488);
//!
//! assert!(triangle_normal.eq_approx(expected_answer , 1e-5 ));
//! ```
//!
//! ## Example: matrix transform
//!
//! ```
//! use gml::*;
//!
//! let translate = 3.0f32;
//! let rotate    = Vector3f::new(4.0, 7.0, 5.0);
//!
//! let projection     = perspective(45.0f32, 4.0f32 / 3.0f32, 0.1f32, 100.0f32);
//! let view_translate = Matrix4x4f::unit().translate( Vector3::new(0.0f32, 0.0f32, -translate));
//! let view_rotate_x  = view_translate.rotate(rotate.y, Vector3f::new(-1.0, 0.0, 0.0));
//! let view           = view_rotate_x.rotate(rotate.x, Vector3f::new(0.0, 1.0, 0.0));
//! let model          = Matrix4x4f::unit().scale(Vector3f::new_s(0.5));
//! let mvp            = projection * view * model;
//!
//! let expect = Matrix4x4f::new(-0.439393,  0.445646, -0.285849, -0.285278,
//!                               0.0     ,  0.675719,  0.329151,  0.328493,
//!                              -0.508739, -0.384901,  0.246885,  0.246392,
//!                               0.0     ,  0.0     ,  3.006006,  3.0      );
//! assert!(mvp.eq_approx(expect, 1e-5) );
//! ```

extern crate num;

use num::traits::*;

pub use vector::*;
pub use matrix::*;
pub use matrix_transform::*;
pub use quaternion::*;
pub use geometry::*;

pub mod vector;
pub mod matrix;
pub mod matrix_transform;
pub mod quaternion;
pub mod geometry;

/// Approximate equality comparison for floating point types.
/// Floating point calculation inaccuracies make direct equality
/// comparison problematic.  This function returns true if two
/// floating point types are equal within a error range defined
/// by the argument epsilon; and false otherwise.
///
/// ```
/// let a = 3.039348;
/// let b = 3.039589;
///
/// assert!(gml::eq_approx(a, b, 0.001) == true);
/// assert!(gml::eq_approx(a, b, 0.0001) == false);
/// ```
pub fn eq_approx<T:Float>(a:T, b:T, epsilon:T) -> bool {
    (a - b).abs() < epsilon
}