mirror of
https://github.com/drewcassidy/vector-victor.git
synced 2024-09-01 14:58:35 +00:00
Add a swizzle! macro
Allows for arbitrarily rearranging the rows of a matrix like in HLSL/GLSL.
This commit is contained in:
parent
bd1bde1657
commit
61b1d211c1
17
src/lib.rs
17
src/lib.rs
@ -12,6 +12,7 @@ pub mod index;
|
|||||||
mod math;
|
mod math;
|
||||||
mod ops;
|
mod ops;
|
||||||
|
|
||||||
|
mod swizzle;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
/** A 2D array of values which can be operated upon.
|
/** A 2D array of values which can be operated upon.
|
||||||
@ -522,9 +523,11 @@ impl<T: Copy, const M: usize, const N: usize> Matrix<T, M, N> {
|
|||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
|
|
||||||
* `ms`: a [`Vector`] of [`usize`] of length M. Each entry is the index of the row that will
|
* `ms`: a [`Vector`] of [`usize`] of length P. Each entry is the index of the row that will
|
||||||
appear in the result
|
appear in the result
|
||||||
|
|
||||||
|
Returns: a P×N matrix
|
||||||
|
|
||||||
# Panics
|
# Panics
|
||||||
|
|
||||||
Panics if any of the row indices in `ms` is out of bounds
|
Panics if any of the row indices in `ms` is out of bounds
|
||||||
@ -543,29 +546,31 @@ impl<T: Copy, const M: usize, const N: usize> Matrix<T, M, N> {
|
|||||||
[7, 8, 9]]))
|
[7, 8, 9]]))
|
||||||
``` */
|
``` */
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn permute_rows(&self, ms: &Vector<usize, M>) -> Self
|
pub fn permute_rows<const P: usize>(&self, ms: &Vector<usize, P>) -> Matrix<T, P, N>
|
||||||
where
|
where
|
||||||
T: Default,
|
T: Default,
|
||||||
{
|
{
|
||||||
Self::from_rows(ms.elements().map(|&m| self.row(m)))
|
Matrix::<T, P, N>::from_rows(ms.elements().map(|&m| self.row(m)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Apply a permutation matrix to the columns of a matrix
|
/** Apply a permutation matrix to the columns of a matrix
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
|
|
||||||
* `ns`: a [`Vector`] of [`usize`] of length N. Each entry is the index of the column that will
|
* `ns`: a [`Vector`] of [`usize`] of length P. Each entry is the index of the column that will
|
||||||
appear in the result
|
appear in the result
|
||||||
|
|
||||||
|
Returns: a P×N matrix
|
||||||
|
|
||||||
# Panics
|
# Panics
|
||||||
|
|
||||||
Panics if any of the column indices in `ns` is out of bounds */
|
Panics if any of the column indices in `ns` is out of bounds */
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn permute_cols(&self, ns: &Vector<usize, N>) -> Self
|
pub fn permute_cols<const P: usize>(&self, ns: &Vector<usize, P>) -> Matrix<T, M, P>
|
||||||
where
|
where
|
||||||
T: Default,
|
T: Default,
|
||||||
{
|
{
|
||||||
Self::from_cols(ns.elements().map(|&n| self.col(n)))
|
Matrix::<T, M, P>::from_cols(ns.elements().map(|&n| self.col(n)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the transpose $M^T$ of the matrix, or the matrix flipped across its diagonal.
|
/** Returns the transpose $M^T$ of the matrix, or the matrix flipped across its diagonal.
|
||||||
|
119
src/swizzle.rs
Normal file
119
src/swizzle.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/** Rearrange the rows of a matrix by the given row identifiers
|
||||||
|
# Arguments
|
||||||
|
|
||||||
|
* `mat`: the matrix to manipulate
|
||||||
|
* `i...`: variadic comma-seperated list of row selectors. The row selectors are each one of:
|
||||||
|
* const expression representing the row index of the input to copy. eg: `0` or `2`
|
||||||
|
* a letter representing the same. you can use `r,g,b,a` or `x,y,z,w` to represent index 0 through 3,
|
||||||
|
or `u,v` to represent indices 0 through 1.
|
||||||
|
* an expression in curly braces, representing a value to be copied to an entire row of
|
||||||
|
the result, eg: `{1.0}` or `{5}`
|
||||||
|
|
||||||
|
note that the number of selectors doesnt need to match the height of the input!
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
```
|
||||||
|
# use vector_victor::{swizzle, Vector};
|
||||||
|
let myvec = Vector::vec([0, 1, 2, 3]);
|
||||||
|
|
||||||
|
// each element can be selected with:
|
||||||
|
// 0: r, x, u, or 0
|
||||||
|
// 1: g, y, v, or 1
|
||||||
|
// 2: b, z, or 2
|
||||||
|
// 3: a, w, or 3
|
||||||
|
// or a result row can be filled by a new value
|
||||||
|
|
||||||
|
assert_eq!(swizzle!(myvec, a, z, v, 0, {7}), Vector::vec([3, 2, 1, 0, 7]));
|
||||||
|
```
|
||||||
|
|
||||||
|
More often you wont mix and match selector "flavors".
|
||||||
|
This example unpacks a [DXT5nm](http://wiki.polycount.com/wiki/Normal_Map_Compression) color
|
||||||
|
into the red and green channels, with blue filled with 0.
|
||||||
|
```
|
||||||
|
# use vector_victor::{swizzle, Vector};
|
||||||
|
let myvec = Vector::vec([0, 120, 0, 255]);
|
||||||
|
assert_eq!(swizzle!(myvec, a, g, {0}), Vector::vec([255, 120, 0]));
|
||||||
|
``` */
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! swizzle {
|
||||||
|
($mat: expr, $( $i:tt),+) => {{
|
||||||
|
let mut result = $mat.permute_rows(&$crate::Vector::vec([$( $crate::get!($mat, $i), )+]));
|
||||||
|
let mut _p = 0usize;
|
||||||
|
$(
|
||||||
|
$crate::sub_literal!(result, _p, $i);
|
||||||
|
_p += 1;
|
||||||
|
)+
|
||||||
|
result
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! get {
|
||||||
|
($mat:expr, x) => {
|
||||||
|
0usize
|
||||||
|
};
|
||||||
|
($mat:expr, y) => {
|
||||||
|
1usize
|
||||||
|
};
|
||||||
|
($mat:expr, z) => {
|
||||||
|
2usize
|
||||||
|
};
|
||||||
|
($mat:expr, w) => {
|
||||||
|
3usize
|
||||||
|
};
|
||||||
|
($mat:expr, r) => {
|
||||||
|
0usize
|
||||||
|
};
|
||||||
|
($mat:expr, g) => {
|
||||||
|
1usize
|
||||||
|
};
|
||||||
|
($mat:expr, b) => {
|
||||||
|
2usize
|
||||||
|
};
|
||||||
|
($mat:expr, a) => {
|
||||||
|
3usize
|
||||||
|
};
|
||||||
|
($mat:expr, u) => {
|
||||||
|
0usize
|
||||||
|
};
|
||||||
|
($mat:expr, v) => {
|
||||||
|
1usize
|
||||||
|
};
|
||||||
|
($mat:expr, {$i:expr}) => {
|
||||||
|
0usize /* will be replaced later */
|
||||||
|
};
|
||||||
|
($mat:expr, $i:expr) => {
|
||||||
|
$i
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! sub_literal {
|
||||||
|
($result:expr, $p:expr, {$i:expr}) => {
|
||||||
|
$result.set_row($p, &$crate::Vector::fill($i))
|
||||||
|
};
|
||||||
|
($result:expr, $p:expr, $i:expr) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::Matrix;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_swizzle() {
|
||||||
|
let identity = Matrix::<i32, 4, 4>::identity();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
swizzle!(identity, a, x, b, (1 + 0), { 2 - 3 }),
|
||||||
|
Matrix::mat([
|
||||||
|
[0, 0, 0, 1], // a
|
||||||
|
[1, 0, 0, 0], // x
|
||||||
|
[0, 0, 1, 0], // b
|
||||||
|
[0, 1, 0, 0], // row 1
|
||||||
|
[-1, -1, -1, -1] // fill(-1)
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user