use std::str;
use std::fmt;
use core::num::Float;
use libc::{c_float, size_t, c_uchar, c_uint};
use std::ops::{Add, Div, Mul, Sub};
use vecmath as m;
use ffi;
const MAXLEN : usize = 1024;
#[doc(hidden)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(C)]
pub enum AiBool {
AiFalse = 0x0,
AiTrue = 0x1,
}
impl AiBool {
pub fn new(val: bool) -> AiBool {
match val {
true => AiBool::AiTrue,
false => AiBool::AiFalse,
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(C)]
pub enum Return {
Success = 0x0,
Failure = -0x1,
OutOfMemory = -0x3,
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Plane {
pub a: c_float,
pub b: c_float,
pub c: c_float,
pub d: c_float,
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Ray {
pub pos: Vector3D,
pub dir: Vector3D,
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Color3D {
pub r: c_float,
pub g: c_float,
pub b: c_float,
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Color4D {
pub r: c_float,
pub g: c_float,
pub b: c_float,
pub a: c_float,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(C)]
pub struct MemoryInfo {
pub textures: c_uint,
pub materials: c_uint,
pub meshes: c_uint,
pub nodes: c_uint,
pub animations: c_uint,
pub cameras: c_uint,
pub lights: c_uint,
pub total: c_uint,
}
#[derive(Copy)]
#[repr(C, packed)]
pub struct AiString {
length: size_t,
data: [c_uchar; MAXLEN],
}
impl AiString {
pub fn new() -> AiString {
AiString {
length: 0,
data: [0u8; MAXLEN],
}
}
pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
str::from_utf8(&(self.data))
}
pub fn into_string(&self) -> Option<String> {
match String::from_utf8((self.data)
.to_vec()) {
Err(_) => None,
Ok(s) => Some(s),
}
}
}
impl fmt::Debug for AiString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.as_str() {
Ok(s) => write!(f, "{}", s),
_ => write!(f, "{}", ""),
}
}
}
impl PartialEq for AiString {
fn eq(&self, other: &AiString) -> bool {
if self.length != other.length {
return false
}
for i in 0 .. self.length as usize {
if self.data[i] != other.data[i] {
return false
}
}
return true
}
}
impl Clone for AiString {
fn clone(&self) -> AiString {
AiString {
length: self.length,
data: self.data,
}
}
}
impl fmt::Display for AiString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.as_str() {
Ok(s) => write!(f, "{}", s),
_ => write!(f, "{}", ""),
}
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Vector2D {
pub x: c_float,
pub y: c_float,
}
impl Vector2D {
pub fn to_array(&self) -> [c_float; 2] {
[self.x, self.y]
}
#[inline(always)]
pub fn dot(&self, other: &Vector2D) -> f32 {
self.x * other.x +
self.y * other.y
}
#[inline]
pub fn norm(&self) -> f32 {
self.dot(self).sqrt()
}
#[inline]
pub fn rnorm(&self) -> f32 {
self.dot(self).rsqrt()
}
#[inline]
pub fn normalize(&mut self) -> Vector2D {
(*self) * self.rnorm()
}
}
impl Add for Vector2D {
type Output = Vector2D;
fn add(self, rhs: Vector2D) -> Vector2D {
Vector2D {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl Sub for Vector2D {
type Output = Vector2D;
fn sub(self, rhs: Vector2D) -> Vector2D {
Vector2D {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl Mul<f32> for Vector2D {
type Output = Vector2D;
fn mul(self, rhs: f32) -> Vector2D {
Vector2D {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl Mul<Vector2D> for f32 {
type Output = Vector2D;
fn mul(self, rhs: Vector2D) -> Vector2D {
Vector2D {
x: self * rhs.x,
y: self * rhs.y,
}
}
}
impl Div<f32> for Vector2D {
type Output = Vector2D;
fn div(self, rhs: f32) -> Vector2D {
Vector2D {
x: self.x / rhs,
y: self.y / rhs,
}
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Vector3D {
pub x: c_float,
pub y: c_float,
pub z: c_float,
}
impl Vector3D {
pub fn to_array(&self) -> [c_float; 3] {
[self.x, self.y, self.z]
}
pub fn translation_matrix(&self) -> Matrix4x4 {
Matrix4x4 {
a1: 1.0, a2: 0.0, a3: 0.0, a4: self.x,
b1: 0.0, b2: 1.0, b3: 0.0, b4: self.y,
c1: 0.0, c2: 0.0, c3: 1.0, c4: self.z,
d1: 0.0, d2: 0.0, d3: 0.0, d4: 1.0,
}
}
pub fn scaling_matrix(&self) -> Matrix4x4 {
Matrix4x4 {
a1: self.x, a2: 0.0, a3: 0.0, a4: 0.0,
b1: 0.0, b2: self.y, b3: 0.0, b4: 0.0,
c1: 0.0, c2: 0.0, c3: self.z, c4: 0.0,
d1: 0.0, d2: 0.0, d3: 0.0, d4: 1.0,
}
}
#[inline(always)]
pub fn dot(&self, other: &Vector3D) -> f32 {
self.x * other.x +
self.y * other.y +
self.z * other.z
}
#[inline]
pub fn norm(&self) -> f32 {
self.dot(self).sqrt()
}
#[inline]
pub fn rnorm(&self) -> f32 {
self.dot(self).rsqrt()
}
#[inline]
pub fn normalize(&mut self) -> Vector3D {
(*self) * self.rnorm()
}
}
impl Add for Vector3D {
type Output = Vector3D;
fn add(self, rhs: Vector3D) -> Vector3D {
Vector3D {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl Sub for Vector3D {
type Output = Vector3D;
fn sub(self, rhs: Vector3D) -> Vector3D {
Vector3D {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl Mul<f32> for Vector3D {
type Output = Vector3D;
fn mul(self, rhs: f32) -> Vector3D {
Vector3D {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl Mul<Vector3D> for f32 {
type Output = Vector3D;
fn mul(self, rhs: Vector3D) -> Vector3D {
Vector3D {
x: self * rhs.x,
y: self * rhs.y,
z: self * rhs.z,
}
}
}
impl Div<f32> for Vector3D {
type Output = Vector3D;
fn div(self, rhs: f32) -> Vector3D {
Vector3D {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Quaternion {
pub w: c_float,
pub x: c_float,
pub y: c_float,
pub z: c_float,
}
impl Quaternion {
fn zero() -> Quaternion {
Quaternion { w: 0.0, x: 0.0, y: 0.0, z: 0.0 }
}
}
impl Quaternion {
pub fn from_matrix(mat: &Matrix3x3) -> Quaternion {
let mut quat: Quaternion = Quaternion::zero();
unsafe {
ffi::aiCreateQuaternionFromMatrix(&mut quat, mat);
}
quat
}
pub fn to_array(&self) -> [c_float; 4] {
[self.w, self.x, self.y, self.z]
}
pub fn rotation_matrix(&self) -> Matrix4x4 {
let norm = self.dot(self);
let s = if norm < 1e-6 {
0.0
} else {
2.0 / norm
};
let (w, x, y, z) = (self.w, self.x, self.y, self.z);
let wx = s*w*x; let wy = s*w*y; let wz = s*w*z;
let xx = s*x*x; let xy = s*x*y; let xz = s*x*z;
let yy = s*y*y; let yz = s*y*z; let zz = s*z*z;
Matrix4x4 {
a1: 1. - (yy + zz), a2: (xy - wz), a3: (xz + wy), a4: 0.0,
b1: (xy + wz), b2: 1. - (xx + zz), b3: (yz - wx), b4: 0.0,
c1: (xz - wy), c2: (yz + wx), c3: 1. - (xx + yy), c4: 0.0,
d1: 0.0, d2: 0.0, d3: 0.0, d4: 1.0,
}
}
#[inline(always)]
pub fn dot(&self, other: &Quaternion) -> f32 {
self.w * other.w +
self.x * other.x +
self.y * other.y +
self.z * other.z
}
#[inline]
pub fn norm(&self) -> f32 {
self.dot(self).sqrt()
}
#[inline]
pub fn rnorm(&self) -> f32 {
self.dot(self).rsqrt()
}
#[inline]
pub fn normalize(&mut self) -> Quaternion {
(*self) * self.rnorm()
}
}
impl Add for Quaternion {
type Output = Quaternion;
fn add(self, rhs: Quaternion) -> Quaternion {
Quaternion {
w: self.w + rhs.w,
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl Sub for Quaternion {
type Output = Quaternion;
fn sub(self, rhs: Quaternion) -> Quaternion {
Quaternion {
w: self.w - rhs.w,
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl Mul<f32> for Quaternion {
type Output = Quaternion;
fn mul(self, rhs: f32) -> Quaternion {
Quaternion {
w: self.w * rhs,
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl Mul<Quaternion> for f32 {
type Output = Quaternion;
fn mul(self, rhs: Quaternion) -> Quaternion {
Quaternion {
w: self * rhs.w,
x: self * rhs.x,
y: self * rhs.y,
z: self * rhs.z,
}
}
}
impl Div<f32> for Quaternion {
type Output = Quaternion;
fn div(self, rhs: f32) -> Quaternion {
Quaternion {
w: self.w / rhs,
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Matrix3x3 {
pub a1: c_float, pub a2: c_float, pub a3: c_float,
pub b1: c_float, pub b2: c_float, pub b3: c_float,
pub c1: c_float, pub c2: c_float, pub c3: c_float,
}
impl Matrix3x3 {
pub fn identity() -> Matrix3x3 {
Matrix3x3 {
a1: 1.0, a2: 0.0, a3: 0.0,
b1: 0.0, b2: 1.0, b3: 0.0,
c1: 0.0, c2: 0.0, c3: 1.0,
}
}
pub fn inverse(self) -> Matrix3x3 {
let inv = m::mat3_inv([
[self.a1, self.a2, self.a3],
[self.b1, self.b2, self.b3],
[self.c1, self.c2, self.c3],
]);
Matrix3x3 {
a1: inv[0][0], a2: inv[0][1], a3: inv[0][2],
b1: inv[1][0], b2: inv[1][1], b3: inv[1][2],
c1: inv[2][0], c2: inv[2][1], c3: inv[2][2],
}
}
pub fn transpose(&self) -> Matrix3x3 {
let mut temp = self.clone();
unsafe {
ffi::aiTransposeMatrix3(&mut temp)
}
temp
}
}
impl Mul for Matrix3x3 {
type Output = Matrix3x3;
fn mul(self, rhs: Matrix3x3) -> Matrix3x3 {
let mut result = self.clone();
unsafe {
ffi::aiMultiplyMatrix3(&mut result, &rhs)
}
result
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C, packed)]
pub struct Matrix4x4 {
pub a1: c_float, pub a2: c_float, pub a3: c_float, pub a4: c_float,
pub b1: c_float, pub b2: c_float, pub b3: c_float, pub b4: c_float,
pub c1: c_float, pub c2: c_float, pub c3: c_float, pub c4: c_float,
pub d1: c_float, pub d2: c_float, pub d3: c_float, pub d4: c_float,
}
impl Matrix4x4 {
pub fn identity() -> Matrix4x4 {
Matrix4x4 {
a1: 1.0, a2: 0.0, a3: 0.0, a4: 0.0,
b1: 0.0, b2: 1.0, b3: 0.0, b4: 0.0,
c1: 0.0, c2: 0.0, c3: 1.0, c4: 0.0,
d1: 0.0, d2: 0.0, d3: 0.0, d4: 1.0,
}
}
pub fn to_array(&self) -> [[f32; 4]; 4] {
[
[self.a1, self.a2, self.a3, self.a4,],
[self.b1, self.b2, self.b3, self.b4,],
[self.c1, self.c2, self.c3, self.c4,],
[self.d1, self.d2, self.d3, self.d4,],
]
}
pub fn transpose(&self) -> Matrix4x4 {
let mut temp = self.clone();
unsafe {
ffi::aiTransposeMatrix4(&mut temp)
}
temp
}
pub fn inverse(&self) -> Matrix4x4 {
let inv = m::mat4_inv(self.to_array());
Matrix4x4 {
a1: inv[0][0], a2: inv[0][1], a3: inv[0][2], a4: inv[0][3],
b1: inv[1][0], b2: inv[1][1], b3: inv[1][2], b4: inv[1][3],
c1: inv[2][0], c2: inv[2][1], c3: inv[2][2], c4: inv[2][3],
d1: inv[3][0], d2: inv[3][1], d3: inv[3][2], d4: inv[3][3],
}
}
}
impl Mul for Matrix4x4 {
type Output = Matrix4x4;
fn mul(self, rhs: Matrix4x4) -> Matrix4x4 {
let mut result = self.clone();
unsafe {
ffi::aiMultiplyMatrix4(&mut result, &rhs)
}
result
}
}