use crate::core::*;
use std::{ffi};
use std::{result::Result, error::Error};
use windows::{
core::*
};
#[macro_export]
macro_rules! prec_eq_c_array {
($a:expr, $b:expr, $p:expr) => {{
let m = unsafe { &$b } as *const [[f32; 4]; 0];
$a.prec_eq(&XMat44F32::from_float_m04(m), $p)
}};
}
pub use prec_eq_c_array;
#[macro_export]
macro_rules! prec_eq_c_array_transposed {
($a:expr, $b:expr, $p:expr) => {
prec_eq_c_array!($a.transpose()?, $b, $p)
};
}
pub use prec_eq_c_array_transposed;
#[derive(Clone)]
pub struct XMat44F32 (pub [[ffi::c_float; 4]; 4]);
impl XMat44F32 {
#[inline]
pub fn o() -> Self {
XMat44F32([[0.0f32; 4]; 4])
}
#[inline]
pub fn set_from(&mut self, b: &Self) -> &mut Self {
self.0 = b.0;
self
}
#[inline]
pub fn from_float_p(m: *const f32) -> Self {
XMat44F32::from_float_m4(m as *const [f32; 4])
}
#[inline]
pub fn from_float_m0(m: *const [f32; 0]) -> Self {
XMat44F32::from_float_m4(m as *const [f32; 4])
}
pub fn from_float_m4(m: *const [f32; 4]) -> Self {
XMat44F32(unsafe { std::slice::from_raw_parts(m, 4) }
.try_into().expect("float m44"))
}
#[inline]
pub fn from_float_m04(m: *const [[f32; 4]; 0]) -> Self {
XMat44F32::from_float_m4(m as *const [f32; 4])
}
#[inline]
pub fn from_float_m44(m: *const [[f32; 4]; 4]) -> Self {
XMat44F32::from_float_m4(m as *const [f32; 4])
}
pub fn prec_diff(&self, b: &Self, p: f32) -> Result<Self, Box<dyn Error>> {
Ok(XMat44F32(
toarray!(self.0.iter().zip(b.0.iter()).map(|(&vf, &vg)|
toarray!(vf.iter().zip(vg.iter()).map(|(&f, &g)|
prec_diff(f, g, p)))))
))
}
#[inline]
pub fn prec_eq(&self, b: &Self, p: f32) ->
Result<bool, Box<dyn Error>> {
Ok(self.prec_diff(b, p)?.0 == XMat44F32::o().0)
}
#[inline]
pub fn prec_eq_transposed(&self, b: &Self, p: f32) ->
Result<bool, Box<dyn Error>> {
self.transpose()?.prec_eq(b, p)
}
#[inline]
pub fn prec_eq_array(&self, b: &[[f32; 4]; 4], p: f32) ->
Result<bool, Box<dyn Error>> {
self.prec_eq(&XMat44F32(*b), p)
}
#[inline]
pub fn prec_eq_array_transposed(&self, b: &[[f32; 4]; 4], p: f32) ->
Result<bool, Box<dyn Error>> {
self.transpose()?.prec_eq(&XMat44F32(*b), p)
}
pub fn i() -> Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixIdentity(
m.ptr_mut() as *mut D3DXMATRIX
)) { Err("identity".into()) }
else { Ok(m) }
}
}
pub fn set_i(&mut self) -> Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixIdentity(
self.ptr_mut() as *mut D3DXMATRIX
)) { Err("set_identity".into()) }
else { Ok(self) }
}
}
pub fn transpose(&self) -> Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixTranspose(
m.ptr_mut() as *mut D3DXMATRIX,
self.ptr() as *const D3DXMATRIX
)) { Err("transpose".into()) }
else { Ok(m) }
}
}
pub fn set_transpose(&mut self) -> Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixTranspose(
self.ptr_mut() as *mut D3DXMATRIX,
self.ptr() as *const D3DXMATRIX
)) { Err("set_transpose".into()) }
else { Ok(self) }
}
}
#[inline]
pub fn det(&self, prec: f32) -> Result<f32, Box<dyn Error>> {
let d = unsafe { D3DXMatrixDeterminant(self.ptr() as *const D3DXMATRIX) };
if prec_eq(d, 0.0f32, prec) { Ok(0.0f32) } else { Ok(d) }
}
pub fn inverse(&self, det: Option<&mut f32>) ->
Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixInverse(
m.ptr_mut() as *mut D3DXMATRIX,
match det { None => 0 as *mut f32, Some(det) => det as *mut f32 },
self.ptr() as *const D3DXMATRIX
)) { Err("inverse".into()) }
else { Ok(m) }
}
}
pub fn set_inverse(&mut self, det: Option<&mut f32>) ->
Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixInverse(
self.ptr_mut() as *mut D3DXMATRIX,
match det { None => 0 as *mut f32, Some(det) => det as *mut f32 },
self.ptr() as *const D3DXMATRIX
)) { Err("set_inverse".into()) }
else { Ok(self) }
}
}
pub fn mul(&self, b: &Self) -> Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixMultiply(
m.ptr_mut() as *mut D3DXMATRIX,
self.ptr() as *const D3DXMATRIX,
b.ptr() as *const D3DXMATRIX
)) { Err("mul".into()) }
else { Ok(m) }
}
}
pub fn set_mul(&mut self, b: &Self) -> Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixMultiply(
self.ptr_mut() as *mut D3DXMATRIX,
self.ptr() as *const D3DXMATRIX,
b.ptr() as *const D3DXMATRIX
)) { Err("set_mul".into()) }
else { Ok(self) }
}
}
pub fn translation(x: f32, y: f32, z: f32) ->
Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixTranslation(
m.ptr_mut() as *mut D3DXMATRIX, x, y, z
)) { Err("translation".into()) }
else { Ok(m) }
}
}
pub fn set_translation(&mut self, x: f32, y: f32, z: f32) ->
Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixTranslation(
self.ptr_mut() as *mut D3DXMATRIX, x, y, z
)) { Err("set_translation".into()) }
else { Ok(self) }
}
}
pub fn scaling(x: f32, y: f32, z: f32) ->
Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixScaling(
m.ptr_mut() as *mut D3DXMATRIX, x, y, z
)) { Err("scaling".into()) }
else { Ok(m) }
}
}
pub fn set_scaling(&mut self, x: f32, y: f32, z: f32) ->
Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixScaling(
self.ptr_mut() as *mut D3DXMATRIX, x, y, z
)) { Err("set_scaling".into()) }
else { Ok(self) }
}
}
pub fn rotation_axis(v: &XV3F32, r: f32) ->
Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixRotationAxis(
m.ptr_mut() as *mut D3DXMATRIX,
v.ptr() as *const D3DXVECTOR3,
r
)) { Err("matrix rotation axis".into()) }
else { Ok(m) }
}
}
pub fn set_rotation_axis(&mut self, v: &XV3F32, r: f32) ->
Result<&mut Self, Box<dyn Error>> {
unsafe {
if isnull!(D3DXMatrixRotationAxis(
self.ptr_mut() as *mut D3DXMATRIX,
v.ptr() as *const D3DXVECTOR3,
r
)) { Err("matrix set rotation axis".into()) }
else { Ok(self) }
}
}
pub fn look_at_lh(eye: &XV3F32, lookat: &XV3F32, up: &XV3F32) ->
Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixLookAtLH(
m.ptr_mut() as *mut D3DXMATRIX,
eye.ptr() as *const D3DXVECTOR3,
lookat.ptr() as *const D3DXVECTOR3,
up.ptr() as *const D3DXVECTOR3
)) { Err("?".into()) }
else { Ok(m) }
}
}
pub fn perspective_fov_lh(r: f32, ratio: f32, z0: f32, z1: f32) ->
Result<Self, Box<dyn Error>> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixPerspectiveFovLH(
m.ptr_mut() as *mut D3DXMATRIX,
r, ratio, z0, z1
)) { Err("?".into()) }
else { Ok(m) }
}
}
pub fn mulmv(&self, v: &XV4F32) -> Result<XV4F32, Box<dyn Error>> {
Ok(XV4F32(toarray!(self.0.iter().map(|&r| XV4F32(r).dot(v))))) }
#[inline]
pub fn mulvm(&self, v: &XV4F32) -> Result<XV4F32, Box<dyn Error>> {
self.transpose()?.mulmv(v) }
pub fn quaternion(axis: &XV3F32, th: f32) -> Result<Self, Box<dyn Error>> {
let q = XV4F32::quaternion(axis, th)?;
let q_l = XMat44F32::quaternion_l(&q)?;
let q_r = XMat44F32::quaternion_r(&q.conjugate()?)?;
let m = q_r.mul(&q_l);
m?.transpose() }
#[inline]
pub fn set_quaternion(&mut self, axis: &XV3F32, th: f32) ->
Result<&mut Self, Box<dyn Error>> {
self.0 = XMat44F32::quaternion(axis, th)?.0;
Ok(self)
}
pub fn quaternion_l(q: &XV4F32) -> Result<Self, Box<dyn Error>> {
let q = q.0;
Ok(XMat44F32([
[ q[3], -q[2], q[1], q[0]], [ q[2], q[3], -q[0], q[1]], [-q[1], q[0], q[3], q[2]], [-q[0], -q[1], -q[2], q[3]] ])) }
#[inline]
pub fn set_quaternion_l(&mut self, q: &XV4F32) ->
Result<&mut Self, Box<dyn Error>> {
self.0 = XMat44F32::quaternion_l(q)?.0;
Ok(self)
}
pub fn quaternion_r(q: &XV4F32) -> Result<Self, Box<dyn Error>> {
let q = q.0;
Ok(XMat44F32([
[ q[3], q[2], -q[1], q[0]], [-q[2], q[3], q[0], q[1]], [ q[1], -q[0], q[3], q[2]], [-q[0], -q[1], -q[2], q[3]] ])) }
#[inline]
pub fn set_quaternion_r(&mut self, q: &XV4F32) ->
Result<&mut Self, Box<dyn Error>> {
self.0 = XMat44F32::quaternion_r(q)?.0;
Ok(self)
}
pub fn rot_cg(axis: &XV3F32, a: f32, cg: &XV3F32) ->
Result<Self, Box<dyn Error>> {
unsafe {
let mut m = Self::o();
if failed!(HRESULT(rotCG(
m.ptr_mut() as *mut D3DXMATRIX,
axis.ptr() as *const D3DXVECTOR3,
a,
cg.ptr() as *const D3DXVECTOR3
))) { Err("rotCG".into()) }
else { Ok(m) }
}
}
}
impl TryFrom<XV4F32> for XMat44F32 {
type Error = Box<dyn Error>;
fn try_from(q: XV4F32) -> Result<Self, Self::Error> {
let mut m = Self::o();
unsafe {
if isnull!(D3DXMatrixRotationQuaternion(
m.ptr_mut() as *mut D3DXMATRIX,
q.ptr() as *const D3DXQUATERNION
)) { Err("matrix rotation quaternion".into()) }
else { Ok(m) }
}
}
}
impl Ptr<f32> for XMat44F32 {
#[inline]
fn ptr(&self) -> *const f32 { self as *const XMat44F32 as *const f32 }
#[inline]
fn ptr_mut(&mut self) -> *mut f32 { self as *mut XMat44F32 as *mut f32 }
}
impl Dump for XMat44F32 {
fn dump(&self) -> String {
let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 4, cols: 4,
fmt: "%08x\0".as_ptr(), di: 8, df: 0, r: 0, c: 0};
let f = cb_x;
let mut s = [0u8; SZBUF];
unsafe {
let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
String::from_utf8(s[..l].to_vec()).expect("utf8")
}
}
}
impl Disp for XMat44F32 {
fn disp(&self, di: usize, df: usize) -> String {
let fmt = format!("%{}.{}f\0", di, df).as_str().as_ptr();
let mut p = DispMatParam{m: self.voidp(), w: SZF32, rows: 4, cols: 4,
fmt, di, df, r: 0, c: 0};
let f = cb_f32; let mut s = [0u8; SZBUF];
unsafe {
let l = disp_mat(&mut s as *mut u8, SZBUF, &mut p, Some(f));
String::from_utf8(s[..l].to_vec()).expect("utf8")
}
}
}
impl std::fmt::Display for XMat44F32 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.disp(17, 7))
}
}
impl std::fmt::Debug for XMat44F32 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.disp(17, 7))
}
}