#![allow(
clippy::too_many_arguments,
clippy::let_and_return,
clippy::from_over_into
)]
use super::{Euler, Quaternion};
use std::mem;
// @short_description: Functions for initializing and manipulating 4x4 matrices
//
// Matrices are used in to describe affine model-view transforms, texture
// transforms, and projective transforms. This exposes a utility API that can
// be used for direct manipulation of these matrices.
//
// * These identify different kinds of 4x4 transformation matrices and we use
// * this information to find fast-paths when available.
// */
// enum MatrixType {
// MATRIX_TYPE_GENERAL, /**< general 4x4 matrix */
// MATRIX_TYPE_IDENTITY, /**< identity matrix */
// MATRIX_TYPE_3D_NO_ROT, /**< orthogonal projection and others... */
// MATRIX_TYPE_PERSPECTIVE, /**< perspective projection matrix */
// MATRIX_TYPE_2D, /**< 2-D transformation */
// MATRIX_TYPE_2D_NO_ROT, /**< 2-D scale & translate only */
// MATRIX_TYPE_3D, /**< 3-D transformation */
// MATRIX_N_TYPES
// } ;
// Matrix:
//
// A Matrix holds a 4x4 transform matrix. This is a single precision,
// column-major matrix which means it is compatible with what OpenGL expects.
//
// A Matrix can represent transforms such as, rotations, scaling,
// translation, sheering, and linear projections. You can combine these
// transforms by multiplying multiple matrices in the order you want them
// applied.
//
// The transformation of a vertex (x, y, z, w) by a Matrix is given by:
//
// |[
// x_new = xx * x + xy * y + xz * z + xw * w
// y_new = yx * x + yy * y + yz * z + yw * w
// z_new = zx * x + zy * y + zz * z + zw * w
// w_new = wx * x + wy * y + wz * z + ww * w
// ]|
//
// Where w is normally 1
//
// You must consider the members of the Matrix structure read only,
// and all matrix modifications must be done via the matrix API. This
// allows to annotate the matrices internally. Violation of this will give
// undefined results. If you need to initialize a matrix with a constant other
// than the identity matrix you can use matrix_init_from_array().
#[derive(Default, Debug, Clone, PartialOrd)] // Hash
pub struct Matrix {
// column 0
pub xx: f32,
pub yx: f32,
pub zx: f32,
pub wx: f32,
// column 1
pub xy: f32,
pub yy: f32,
pub zy: f32,
pub wy: f32,
// column 2
pub xz: f32,
pub yz: f32,
pub zz: f32,
pub wz: f32,
// column 3
pub xw: f32,
pub yw: f32,
pub zw: f32,
pub ww: f32,
// < private >
// Note: we may want to extend this later with private flags
// and a cache of the inverse transform matrix.
// float PRIVATE (inv)[16];
// unsigned long PRIVATE (type);
// unsigned long PRIVATE (flags);
// unsigned long PRIVATE (_padding3);
}
#[inline]
fn idx(row: usize, col: usize) -> usize {
col * 4 + row
}
impl Matrix {
/// Multiplies `self` by the given frustum perspective matrix.
/// ## `left`
/// X position of the left clipping plane where it
/// intersects the near clipping plane
/// ## `right`
/// X position of the right clipping plane where it
/// intersects the near clipping plane
/// ## `bottom`
/// Y position of the bottom clipping plane where it
/// intersects the near clipping plane
/// ## `top`
/// Y position of the top clipping plane where it intersects
/// the near clipping plane
/// ## `z_near`
/// The distance to the near clipping plane (Must be positive)
/// ## `z_far`
/// The distance to the far clipping plane (Must be positive)
pub fn frustum(
&mut self,
left: f32,
right: f32,
bottom: f32,
top: f32,
z_near: f32,
z_far: f32,
) {
let mut matrix: [f32; 16] = [0.0; 16];
let mx = (2.0 * z_near) / (right - left);
let my = (2.0 * z_near) / (top - bottom);
let ma = (right + left) / (right - left);
let mb = (top + bottom) / (top - bottom);
let mc = -(z_far + z_near) / (z_far - z_near);
let md = -(2.0 * z_far * z_near) / (z_far - z_near); /* error? */
matrix[idx(0, 0)] = mx;
matrix[idx(0, 1)] = 0.0;
matrix[idx(0, 2)] = ma;
matrix[idx(0, 3)] = 0.0;
matrix[idx(1, 0)] = 0.0;
matrix[idx(1, 1)] = my;
matrix[idx(1, 2)] = mb;
matrix[idx(1, 3)] = 0.0;
matrix[idx(2, 0)] = 0.0;
matrix[idx(2, 1)] = 0.0;
matrix[idx(2, 2)] = mc;
matrix[idx(2, 3)] = md;
matrix[idx(3, 0)] = 0.0;
matrix[idx(3, 1)] = 0.0;
matrix[idx(3, 2)] = -1.0;
matrix[idx(3, 3)] = 0.0;
// matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_PERSPECTIVE);
unimplemented!()
}
//TODO:
// /// Casts `self` to a float array which can be directly passed to OpenGL.
// ///
// /// # Returns
// ///
// /// a pointer to the float array
// pub fn array(&self) -> &[f32] {
// unimplemented!()
// }
/// Gets the inverse transform of a given matrix and uses it to initialize
/// a new `Matrix`.
///
/// Although the first parameter is annotated as const to indicate
/// that the transform it represents isn't modified this fn may
/// technically save a copy of the inverse transform within the given
/// `Matrix` so that subsequent requests for the inverse transform may
/// avoid costly inversion calculations.
/// ## `inverse`
/// The destination for a 4x4 inverse transformation matrix
///
/// # Returns
///
/// `true` if the inverse was successfully calculated or `false`
/// for degenerate transformations that can't be inverted (in this case the
/// `inverse` matrix will simply be initialized with the identity matrix)
pub fn inverse(&self) -> (bool, Matrix) {
// if (_matrix_update_inverse ((Matrix *)matrix))
// {
// matrix_init_from_array (inverse, matrix->inv);
// return true;
// }
// else
// {
// matrix_init_identity (inverse);
// return false;
// }
unimplemented!()
}
/// Initializes `self` with the contents of `array`
/// ## `array`
/// A linear array of 16 floats (column-major order)
pub fn init_from_array(&mut self, array: &[f32]) {
// memcpy (matrix, array, 16 * sizeof (float));
// matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL);
}
/// Initializes `self` from a `Euler` rotation.
///
/// ## `euler`
/// A `Euler`
pub fn init_from_euler(&mut self, euler: &Euler) {
// Convert angles to radians */
// float heading_rad = euler->heading / 180.0f * G_PI;
// float pitch_rad = euler->pitch / 180.0f * G_PI;
// float roll_rad = euler->roll / 180.0f * G_PI;
// Pre-calculate the sin and cos */
// float sin_heading = sinf (heading_rad);
// float cos_heading = cosf (heading_rad);
// float sin_pitch = sinf (pitch_rad);
// float cos_pitch = cosf (pitch_rad);
// float sin_roll = sinf (roll_rad);
// float cos_roll = cosf (roll_rad);
// These calculations are based on the following website but they
// use a different order for the rotations so it has been modified
// slightly.
// http://www.euclideanspace.com/maths/geometry/
// rotations/conversions/eulerToMatrix/index.htm
//
// Heading rotation x=0, y=1, z=0 gives:
//
// [ ch 0 sh 0 ]
// [ 0 1 0 0 ]
// [ -sh 0 ch 0 ]
// [ 0 0 0 1 ]
//
// Pitch rotation x=1, y=0, z=0 gives:
// [ 1 0 0 0 ]
// [ 0 cp -sp 0 ]
// [ 0 sp cp 0 ]
// [ 0 0 0 1 ]
//
// Roll rotation x=0, y=0, z=1 gives:
// [ cr -sr 0 0 ]
// [ sr cr 0 0 ]
// [ 0 0 1 0 ]
// [ 0 0 0 1 ]
//
// Heading matrix * pitch matrix =
// [ ch sh*sp cp*sh 0 ]
// [ 0 cp -sp 0 ]
// [ -sh ch*sp ch*cp 0 ]
// [ 0 0 0 1 ]
//
// That matrix * roll matrix =
// [ ch*cr + sh*sp*sr sh*sp*cr - ch*sr sh*cp 0 ]
// [ cp*sr cp*cr -sp 0 ]
// [ ch*sp*sr - sh*cr sh*sr + ch*sp*cr ch*cp 0 ]
// [ 0 0 0 1 ]
//
// matrix->xx = cos_heading * cos_roll + sin_heading * sin_pitch * sin_roll;
// matrix->yx = cos_pitch * sin_roll;
// matrix->zx = cos_heading * sin_pitch * sin_roll - sin_heading * cos_roll;
// matrix->wx = 0.0f;
// matrix->xy = sin_heading * sin_pitch * cos_roll - cos_heading * sin_roll;
// matrix->yy = cos_pitch * cos_roll;
// matrix->zy = sin_heading * sin_roll + cos_heading * sin_pitch * cos_roll;
// matrix->wy = 0.0f;
// matrix->xz = sin_heading * cos_pitch;
// matrix->yz = -sin_pitch;
// matrix->zz = cos_heading * cos_pitch;
// matrix->wz = 0;
// matrix->xw = 0;
// matrix->yw = 0;
// matrix->zw = 0;
// matrix->ww = 1;
// matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL);
unimplemented!()
}
/// Initializes `self` from a `Quaternion` rotation.
/// ## `quaternion`
/// A `Quaternion`
pub fn init_from_quaternion(&mut self, quaternion: &Quaternion) {
// float qnorm = _QUATERNION_NORM (quaternion);
// float s = (qnorm > 0.0f) ? (2.0f / qnorm) : 0.0f;
// float xs = quaternion->x * s;
// float ys = quaternion->y * s;
// float zs = quaternion->z * s;
// float wx = quaternion->w * xs;
// float wy = quaternion->w * ys;
// float wz = quaternion->w * zs;
// float xx = quaternion->x * xs;
// float xy = quaternion->x * ys;
// float xz = quaternion->x * zs;
// float yy = quaternion->y * ys;
// float yz = quaternion->y * zs;
// float zz = quaternion->z * zs;
// matrix->xx = 1.0f - (yy + zz);
// matrix->yx = xy + wz;
// matrix->zx = xz - wy;
// matrix->xy = xy - wz;
// matrix->yy = 1.0f - (xx + zz);
// matrix->zy = yz + wx;
// matrix->xz = xz + wy;
// matrix->yz = yz - wx;
// matrix->zz = 1.0f - (xx + yy);
// matrix->xw = matrix->yw = matrix->zw = 0.0f;
// matrix->wx = matrix->wy = matrix->wz = 0.0f;
// matrix->ww = 1.0f;
// matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL);
}
/// Resets matrix to the identity matrix:
///
///
/// ```text
/// .xx=1; .xy=0; .xz=0; .xw=0;
/// .yx=0; .yy=1; .yz=0; .yw=0;
/// .zx=0; .zy=0; .zz=1; .zw=0;
/// .wx=0; .wy=0; .wz=0; .ww=1;
/// ```
pub fn init_identity(&mut self) {
// memcpy (matrix, identity, 16 * sizeof (float));
// matrix->type = MATRIX_TYPE_IDENTITY;
// matrix->flags = MAT_DIRTY_INVERSE;
unimplemented!()
}
/// Resets matrix to the (tx, ty, tz) translation matrix:
///
///
/// ```text
/// .xx=1; .xy=0; .xz=0; .xw=tx;
/// .yx=0; .yy=1; .yz=0; .yw=ty;
/// .zx=0; .zy=0; .zz=1; .zw=tz;
/// .wx=0; .wy=0; .wz=0; .ww=1;
/// ```
///
/// ## `tx`
/// x coordinate of the translation vector
/// ## `ty`
/// y coordinate of the translation vector
/// ## `tz`
/// z coordinate of the translation vector
pub fn init_translation(&mut self, tx: f32, ty: f32, tz: f32) {
// memcpy (matrix, identity, 16 * sizeof (float));
// matrix->xw = tx;
// matrix->yw = ty;
// matrix->zw = tz;
// matrix->type = MATRIX_TYPE_3D;
// matrix->flags = MAT_FLAG_TRANSLATION | MAT_DIRTY_INVERSE;
}
/// Determines if the given matrix is an identity matrix.
///
/// # Returns
///
/// `true` if `self` is an identity matrix else `false`
pub fn is_identity(&self) -> bool {
// if (!(matrix->flags & MAT_DIRTY_TYPE) &&
// matrix->type == MATRIX_TYPE_IDENTITY)
// return true;
// else
// return memcmp (matrix, identity, sizeof (float) * 16) == 0;
unimplemented!()
}
/// Applies a view transform `self` that positions the camera at
/// the coordinate (`eye_position_x`, `eye_position_y`, `eye_position_z`)
/// looking towards an object at the coordinate (`object_x`, `object_y`,
/// `object_z`). The top of the camera is aligned to the given world up
/// vector, which is normally simply (0, 1, 0) to map up to the
/// positive direction of the y axis.
///
/// Because there is a lot of missleading documentation online for
/// gluLookAt regarding the up vector we want to try and be a bit
/// clearer here.
///
/// The up vector should simply be relative to your world coordinates
/// and does not need to change as you move the eye and object
/// positions. Many online sources may claim that the up vector needs
/// to be perpendicular to the vector between the eye and object
/// position (partly because the man page is somewhat missleading) but
/// that is not necessary for this function.
///
/// You should never look directly along the world-up
/// vector.
///
/// It is assumed you are using a typical projection matrix where
/// your origin maps to the center of your viewport.
///
/// Almost always when you use this fn it should be the first
/// transform applied to a new modelview transform
/// ## `eye_position_x`
/// The X coordinate to look from
/// ## `eye_position_y`
/// The Y coordinate to look from
/// ## `eye_position_z`
/// The Z coordinate to look from
/// ## `object_x`
/// The X coordinate of the object to look at
/// ## `object_y`
/// The Y coordinate of the object to look at
/// ## `object_z`
/// The Z coordinate of the object to look at
/// ## `world_up_x`
/// The X component of the world's up direction vector
/// ## `world_up_y`
/// The Y component of the world's up direction vector
/// ## `world_up_z`
/// The Z component of the world's up direction vector
pub fn look_at(
&mut self,
eye_position_x: f32,
eye_position_y: f32,
eye_position_z: f32,
object_x: f32,
object_y: f32,
object_z: f32,
world_up_x: f32,
world_up_y: f32,
world_up_z: f32,
) {
// Matrix tmp;
// float forward[3];
// float side[3];
// float up[3];
// Get a unit viewing direction vector */
// vector3_init (forward,
// object_x - eye_position_x,
// object_y - eye_position_y,
// object_z - eye_position_z);
// vector3_normalize (forward);
// vector3_init (up, world_up_x, world_up_y, world_up_z);
// Take the sideways direction as being perpendicular to the viewing
// direction and the word up vector. */
// vector3_cross_product (side, forward, up);
// vector3_normalize (side);
// Now we have unit sideways and forward-direction vectors calculate
// a new mutually perpendicular up vector. */
// vector3_cross_product (up, side, forward);
// tmp.xx = side[0];
// tmp.yx = side[1];
// tmp.zx = side[2];
// tmp.wx = 0;
// tmp.xy = up[0];
// tmp.yy = up[1];
// tmp.zy = up[2];
// tmp.wy = 0;
// tmp.xz = -forward[0];
// tmp.yz = -forward[1];
// tmp.zz = -forward[2];
// tmp.wz = 0;
// tmp.xw = 0;
// tmp.yw = 0;
// tmp.zw = 0;
// tmp.ww = 1;
// tmp.flags = (MAT_FLAG_GENERAL_3D | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
// matrix_translate (&tmp, -eye_position_x, -eye_position_y, -eye_position_z);
// matrix_multiply (matrix, matrix, &tmp);
unimplemented!()
}
/// Multiplies the two supplied matrices together and stores
/// the resulting matrix inside `self`.
///
/// It is possible to multiply the `a` matrix in-place, so
/// `self` can be equal to `a` but can't be equal to `b`.
/// ## `a`
/// A 4x4 transformation matrix
/// ## `b`
/// A 4x4 transformation matrix
pub fn multiply(&mut self, a: &Matrix, b: &Matrix) {
// result->flags = (a->flags |
// b->flags |
// MAT_DIRTY_TYPE |
// MAT_DIRTY_INVERSE);
// if (TEST_MAT_FLAGS(result, MAT_FLAGS_3D))
// matrix_multiply3x4 ((float *)result, (float *)a, (float *)b);
// else
// matrix_multiply4x4 ((float *)result, (float *)a, (float *)b);
unimplemented!()
}
/// Multiplies `self` by a parallel projection matrix.
/// ## `x_1`
/// The x coordinate for the first vertical clipping plane
/// ## `y_1`
/// The y coordinate for the first horizontal clipping plane
/// ## `x_2`
/// The x coordinate for the second vertical clipping plane
/// ## `y_2`
/// The y coordinate for the second horizontal clipping plane
/// ## `near`
/// The distance to the near clipping
/// plane (will be negative if the plane is
/// behind the viewer)
/// ## `far`
/// The distance to the far clipping
/// plane (will be negative if the plane is
/// behind the viewer)
pub fn orthographic(&mut self, x_1: f32, y_1: f32, x_2: f32, y_2: f32, near: f32, far: f32) {
// float m[16];
// M (0,0) = 2.0f / (x_2 - x_1);
// M (0,1) = 0.0f;
// M (0,2) = 0.0f;
// M (0,3) = -(x_2 + x_1) / (x_2 - x_1);
// M (1,0) = 0.0f;
// M (1,1) = 2.0f / (y_1 - y_2);
// M (1,2) = 0.0f;
// M (1,3) = -(y_1 + y_2) / (y_1 - y_2);
// M (2,0) = 0.0f;
// M (2,1) = 0.0f;
// M (2,2) = -2.0f / (far - near);
// M (2,3) = -(far + near) / (far - near);
// M (3,0) = 0.0f;
// M (3,1) = 0.0f;
// M (3,2) = 0.0f;
// M (3,3) = 1.0f;
// matrix_multiply_array_with_flags (matrix, m,
// (MAT_FLAG_GENERAL_SCALE |
// MAT_FLAG_TRANSLATION));
unimplemented!()
}
/// Multiplies `self` by the described perspective matrix
///
/// You should be careful not to have to great a `z_far` / `z_near`
/// ratio since that will reduce the effectiveness of depth testing
/// since there wont be enough precision to identify the depth of
/// objects near to each other.
/// ## `fov_y`
/// Vertical field of view angle in degrees.
/// ## `aspect`
/// The (width over height) aspect ratio for display
/// ## `z_near`
/// The distance to the near clipping plane (Must be positive,
/// and must not be 0)
/// ## `z_far`
/// The distance to the far clipping plane (Must be positive)
pub fn perspective(&mut self, fov_y: f32, aspect: f32, z_near: f32, z_far: f32) {
// float ymax = z_near * tan (fov_y * G_PI / 360.0);
// matrix_frustum (matrix,
// -ymax * aspect, /* left */
// ymax * aspect, /* right */
// -ymax, /* bottom */
// ymax, /* top */
// z_near,
// z_far);
// _MATRIX_DEBUG_PRINT (matrix);
unimplemented!()
}
pub fn project_points(
&self,
n_components: i32,
stride_in: usize,
points_in: &[u8],
stride_out: usize,
points_out: &[u8],
n_points: i32,
) {
// if (n_components == 2)
// _matrix_project_points_f2 (matrix,
// stride_in, points_in,
// stride_out, points_out,
// n_points);
// else if (n_components == 3)
// _matrix_project_points_f3 (matrix,
// stride_in, points_in,
// stride_out, points_out,
// n_points);
// else
// {
// _RETURN_IF_FAIL (n_components == 4);
// _matrix_project_points_f4 (matrix,
// stride_in, points_in,
// stride_out, points_out,
// n_points);
// }
}
/// Multiplies `self` with a rotation matrix that applies a rotation
/// of `angle` degrees around the specified 3D vector.
/// ## `angle`
/// The angle you want to rotate in degrees
/// ## `x`
/// X component of your rotation vector
/// ## `y`
/// Y component of your rotation vector
/// ## `z`
/// Z component of your rotation vector
pub fn rotate(&mut self, angle: f32, x: f32, y: f32, z: f32) {
// float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
// float m[16];
// Bool optimized;
// s = sinf (angle * DEG2RAD);
// c = cosf (angle * DEG2RAD);
// memcpy (m, identity, 16 * sizeof (float));
// optimized = false;
// #define M(row,col) m[col*4+row]
// if (x == 0.0f)
// {
// if (y == 0.0f)
// {
// if (z != 0.0f)
// {
// optimized = true;
// /* rotate only around z-axis */
// M (0,0) = c;
// M (1,1) = c;
// if (z < 0.0f)
// {
// M (0,1) = s;
// M (1,0) = -s;
// }
// else
// {
// M (0,1) = -s;
// M (1,0) = s;
// }
// }
// }
// else if (z == 0.0f)
// {
// optimized = true;
// /* rotate only around y-axis */
// M (0,0) = c;
// M (2,2) = c;
// if (y < 0.0f)
// {
// M (0,2) = -s;
// M (2,0) = s;
// }
// else
// {
// M (0,2) = s;
// M (2,0) = -s;
// }
// }
// }
// else if (y == 0.0f)
// {
// if (z == 0.0f)
// {
// optimized = true;
// /* rotate only around x-axis */
// M (1,1) = c;
// M (2,2) = c;
// if (x < 0.0f)
// {
// M (1,2) = s;
// M (2,1) = -s;
// }
// else
// {
// M (1,2) = -s;
// M (2,1) = s;
// }
// }
// }
// if (!optimized)
// {
// const float mag = sqrtf (x * x + y * y + z * z);
// if (mag <= 1.0e-4)
// {
// /* no rotation, leave mat as-is */
// return;
// }
// x /= mag;
// y /= mag;
// z /= mag;
// /*
// * Arbitrary axis rotation matrix.
// *
// * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
// * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
// * (which is about the X-axis), and the two composite transforms
// * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
// * from the arbitrary axis to the X-axis then back. They are
// * all elementary rotations.
// *
// * Rz' is a rotation about the Z-axis, to bring the axis vector
// * into the x-z plane. Then Ry' is applied, rotating about the
// * Y-axis to bring the axis vector parallel with the X-axis. The
// * rotation about the X-axis is then performed. Ry and Rz are
// * simply the respective inverse transforms to bring the arbitrary
// * axis back to it's original orientation. The first transforms
// * Rz' and Ry' are considered inverses, since the data from the
// * arbitrary axis gives you info on how to get to it, not how
// * to get away from it, and an inverse must be applied.
// *
// * The basic calculation used is to recognize that the arbitrary
// * axis vector (x, y, z), since it is of unit length, actually
// * represents the sines and cosines of the angles to rotate the
// * X-axis to the same orientation, with theta being the angle about
// * Z and phi the angle about Y (in the order described above)
// * as follows:
// *
// * cos ( theta ) = x / sqrt ( 1 - z^2 )
// * sin ( theta ) = y / sqrt ( 1 - z^2 )
// *
// * cos ( phi ) = sqrt ( 1 - z^2 )
// * sin ( phi ) = z
// *
// * Note that cos ( phi ) can further be inserted to the above
// * formulas:
// *
// * cos ( theta ) = x / cos ( phi )
// * sin ( theta ) = y / sin ( phi )
// *
// * ...etc. Because of those relations and the standard trigonometric
// * relations, it is pssible to reduce the transforms down to what
// * is used below. It may be that any primary axis chosen will give the
// * same results (modulo a sign convention) using thie method.
// *
// * Particularly nice is to notice that all divisions that might
// * have caused trouble when parallel to certain planes or
// * axis go away with care paid to reducing the expressions.
// * After checking, it does perform correctly under all cases, since
// * in all the cases of division where the denominator would have
// * been zero, the numerator would have been zero as well, giving
// * the expected result.
// */
// xx = x * x;
// yy = y * y;
// zz = z * z;
// xy = x * y;
// yz = y * z;
// zx = z * x;
// xs = x * s;
// ys = y * s;
// zs = z * s;
// one_c = 1.0f - c;
// /* We already hold the identity-matrix so we can skip some statements */
// M (0,0) = (one_c * xx) + c;
// M (0,1) = (one_c * xy) - zs;
// M (0,2) = (one_c * zx) + ys;
// /* M (0,3) = 0.0f; */
// M (1,0) = (one_c * xy) + zs;
// M (1,1) = (one_c * yy) + c;
// M (1,2) = (one_c * yz) - xs;
// /* M (1,3) = 0.0f; */
// M (2,0) = (one_c * zx) - ys;
// M (2,1) = (one_c * yz) + xs;
// M (2,2) = (one_c * zz) + c;
// /* M (2,3) = 0.0f; */
// /*
// M (3,0) = 0.0f;
// M (3,1) = 0.0f;
// M (3,2) = 0.0f;
// M (3,3) = 1.0f;
// */
// }
// #undef M
// matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_ROTATION);
unimplemented!()
}
/// Multiplies `self` with a rotation transformation described by the
/// given `Euler`.
///
/// ## `euler`
/// A euler describing a rotation
pub fn rotate_euler(&mut self, euler: &Euler) {
// Matrix rotation_transform;
// matrix_init_from_euler (&rotation_transform, euler);
// matrix_multiply (matrix, matrix, &rotation_transform);
unimplemented!()
}
/// Multiplies `self` with a rotation transformation described by the
/// given `Quaternion`.
///
/// ## `quaternion`
/// A quaternion describing a rotation
pub fn rotate_quaternion(&mut self, quaternion: &Quaternion) {
// Matrix rotation_transform;
// matrix_init_from_quaternion (&rotation_transform, quaternion);
// matrix_multiply (matrix, matrix, &rotation_transform);
unimplemented!()
}
/// Multiplies `self` with a transform matrix that scales along the X,
/// Y and Z axis.
/// ## `sx`
/// The X scale factor
/// ## `sy`
/// The Y scale factor
/// ## `sz`
/// The Z scale factor
pub fn scale(&mut self, sx: f32, sy: f32, sz: f32) {
// float *m = (float *)matrix;
// m[0] *= x; m[4] *= y; m[8] *= z;
// m[1] *= x; m[5] *= y; m[9] *= z;
// m[2] *= x; m[6] *= y; m[10] *= z;
// m[3] *= x; m[7] *= y; m[11] *= z;
// if (fabsf (x - y) < 1e-8 && fabsf (x - z) < 1e-8)
// matrix->flags |= MAT_FLAG_UNIFORM_SCALE;
// else
// matrix->flags |= MAT_FLAG_GENERAL_SCALE;
// matrix->flags |= (MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
unimplemented!()
}
/// Transforms a point whos position is given and returned as four float
/// components.
/// ## `x`
/// The X component of your points position
/// ## `y`
/// The Y component of your points position
/// ## `z`
/// The Z component of your points position
/// ## `w`
/// The W component of your points position
pub fn transform_point(&self, x: &mut f32, y: &mut f32, z: &mut f32, w: &mut f32) {
// float _x = *x, _y = *y, _z = *z, _w = *w;
//x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w;
//y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w;
//z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w;
//w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w;
unimplemented!()
}
pub fn transform_points(
&self,
n_components: i32,
stride_in: usize,
points_in: &[u8],
stride_out: usize,
points_out: &[u8],
n_points: i32,
) {
// The results of transforming always have three components... */
// _RETURN_IF_FAIL (stride_out >= sizeof (Point3f));
// if (n_components == 2)
// _matrix_transform_points_f2 (matrix,
// stride_in, points_in,
// stride_out, points_out,
// n_points);
// else
// {
// _RETURN_IF_FAIL (n_components == 3);
// _matrix_transform_points_f3 (matrix,
// stride_in, points_in,
// stride_out, points_out,
// n_points);
// }
unimplemented!()
}
/// Multiplies `self` with a transform matrix that translates along
/// the X, Y and Z axis.
/// ## `x`
/// The X translation you want to apply
/// ## `y`
/// The Y translation you want to apply
/// ## `z`
/// The Z translation you want to apply
pub fn translate(&mut self, x: f32, y: f32, z: f32) {
// float *m = (float *)matrix;
// m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
// m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
// m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
// m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
// matrix->flags |= (MAT_FLAG_TRANSLATION |
// MAT_DIRTY_TYPE |
// MAT_DIRTY_INVERSE);
unimplemented!()
}
/// Replaces `self` with its transpose. Ie, every element (i,j) in the
/// new matrix is taken from element (j,i) in the old matrix.
pub fn transpose(&mut self) {
// float new_values[16];
// We don't need to do anything if the matrix is the identity matrix */
// if (!(matrix->flags & MAT_DIRTY_TYPE) &&
// matrix->type == MATRIX_TYPE_IDENTITY)
// return;
// _matrix_util_transposef (new_values, matrix_get_array (matrix));
// matrix_init_from_array (matrix, new_values);
unimplemented!()
}
/// Multiplies `self` by a view transform that maps the 2D coordinates
/// (0,0) top left and (`width_2d`,`height_2d`) bottom right the full viewport
/// size. Geometry at a depth of 0 will now lie on this 2D plane.
///
/// Note: this doesn't multiply the matrix by any projection matrix,
/// but it assumes you have a perspective projection as defined by
/// passing the corresponding arguments to `Matrix::frustum`.
///
/// Toolkits such as Clutter that mix 2D and 3D drawing can use this to
/// create a 2D coordinate system within a 3D perspective projected
/// view frustum.
/// ## `left`
/// coord of left vertical clipping plane
/// ## `right`
/// coord of right vertical clipping plane
/// ## `bottom`
/// coord of bottom horizontal clipping plane
/// ## `top`
/// coord of top horizontal clipping plane
/// ## `z_near`
/// The distance to the near clip plane. Never pass 0 and always pass
/// a positive number.
/// ## `z_2d`
/// The distance to the 2D plane. (Should always be positive and
/// be between `z_near` and the z_far value that was passed to
/// `Matrix::frustum`)
/// ## `width_2d`
/// The width of the 2D coordinate system
/// ## `height_2d`
/// The height of the 2D coordinate system
pub fn view_2d_in_frustum(
&mut self,
left: f32,
right: f32,
bottom: f32,
top: f32,
z_near: f32,
z_2d: f32,
width_2d: f32,
height_2d: f32,
) {
// float left_2d_plane = left / z_near * z_2d;
// float right_2d_plane = right / z_near * z_2d;
// float bottom_2d_plane = bottom / z_near * z_2d;
// float top_2d_plane = top / z_near * z_2d;
// float width_2d_start = right_2d_plane - left_2d_plane;
// float height_2d_start = top_2d_plane - bottom_2d_plane;
// Factors to scale from framebuffer geometry to frustum
// cross-section geometry. */
// float width_scale = width_2d_start / width_2d;
// float height_scale = height_2d_start / height_2d;
// matrix_translate (matrix,
// left_2d_plane, top_2d_plane, -z_2d);
// matrix_scale (matrix, width_scale, -height_scale, width_scale);
unimplemented!()
}
/// Multiplies `self` by a view transform that maps the 2D coordinates
/// (0,0) top left and (`width_2d`,`height_2d`) bottom right the full viewport
/// size. Geometry at a depth of 0 will now lie on this 2D plane.
///
/// Note: this doesn't multiply the matrix by any projection matrix,
/// but it assumes you have a perspective projection as defined by
/// passing the corresponding arguments to `Matrix::perspective`.
///
/// Toolkits such as Clutter that mix 2D and 3D drawing can use this to
/// create a 2D coordinate system within a 3D perspective projected
/// view frustum.
/// ## `fov_y`
/// A field of view angle for the Y axis
/// ## `aspect`
/// The ratio of width to height determining the field of view angle
/// for the x axis.
/// ## `z_near`
/// The distance to the near clip plane. Never pass 0 and always pass
/// a positive number.
/// ## `z_2d`
/// The distance to the 2D plane. (Should always be positive and
/// be between `z_near` and the z_far value that was passed to
/// `Matrix::frustum`)
/// ## `width_2d`
/// The width of the 2D coordinate system
/// ## `height_2d`
/// The height of the 2D coordinate system
pub fn view_2d_in_perspective(
&mut self,
fov_y: f32,
aspect: f32,
z_near: f32,
z_2d: f32,
width_2d: f32,
height_2d: f32,
) {
// float top = z_near * tan (fov_y * G_PI / 360.0);
// matrix_view_2d_in_frustum (matrix,
// -top * aspect,
// top * aspect,
// -top,
// top,
// z_near,
// z_2d,
// width_2d,
// height_2d);
unimplemented!()
}
fn equal(v1: &Self, v2: &Self) -> bool {
// const Matrix *a = v1;
// const Matrix *b = v2;
// _RETURN_VAL_IF_FAIL (v1 != NULL, false);
// _RETURN_VAL_IF_FAIL (v2 != NULL, false);
// We want to avoid having a fuzzy _equal() fn (e.g. that uses
// an arbitrary epsilon value) since this fn noteably conforms
// to the prototype suitable for use with g_hash_table_new() and a
// fuzzy hash fn isn't really appropriate for comparing hash
// table keys since it's possible that you could end up fetching
// different values if you end up with multiple similar keys in use
// at the same time. If you consider that fuzzyness allows cases
// such as A == B == C but A != C then you could also end up loosing
// values in a hash table.
//
// We do at least use the == operator to compare values though so
// that -0 is considered equal to 0.
//
// XXX: We don't compare the flags, inverse matrix or padding */
// if (a->xx == b->xx &&
// a->xy == b->xy &&
// a->xz == b->xz &&
// a->xw == b->xw &&
// a->yx == b->yx &&
// a->yy == b->yy &&
// a->yz == b->yz &&
// a->yw == b->yw &&
// a->zx == b->zx &&
// a->zy == b->zy &&
// a->zz == b->zz &&
// a->zw == b->zw &&
// a->wx == b->wx &&
// a->wy == b->wy &&
// a->wz == b->wz &&
// a->ww == b->ww)
// return true;
// else
// return false;
unimplemented!()
}
}
impl PartialEq for Matrix {
#[inline]
fn eq(&self, other: &Self) -> bool {
Matrix::equal(self, other)
}
}
impl Eq for Matrix {}