use crate::{ffi, DecodePosition, VertexDataAdapter, VertexStream};
use std::mem;
pub fn generate_vertex_remap<T>(vertices: &[T], indices: Option<&[u32]>) -> (usize, Vec<u32>) {
let mut remap: Vec<u32> = vec![0; vertices.len()];
let vertex_count = unsafe {
match indices {
Some(indices) => ffi::meshopt_generateVertexRemap(
remap.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
vertices.as_ptr().cast(),
vertices.len(),
mem::size_of::<T>(),
),
None => ffi::meshopt_generateVertexRemap(
remap.as_mut_ptr(),
std::ptr::null(),
vertices.len(),
vertices.as_ptr().cast(),
vertices.len(),
mem::size_of::<T>(),
),
}
};
(vertex_count, remap)
}
pub fn generate_vertex_remap_multi(
vertex_count: usize,
streams: &[VertexStream<'_>],
indices: Option<&[u32]>,
) -> (usize, Vec<u32>) {
let streams: Vec<ffi::meshopt_Stream> = streams
.iter()
.map(|stream| ffi::meshopt_Stream {
data: stream.data.cast(),
size: stream.size,
stride: stream.stride,
})
.collect();
let mut remap: Vec<u32> = vec![0; vertex_count];
let vertex_count = unsafe {
match indices {
Some(indices) => ffi::meshopt_generateVertexRemapMulti(
remap.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
vertex_count,
streams.as_ptr(),
streams.len(),
),
None => ffi::meshopt_generateVertexRemapMulti(
remap.as_mut_ptr(),
std::ptr::null(),
vertex_count,
vertex_count,
streams.as_ptr(),
streams.len(),
),
}
};
(vertex_count, remap)
}
pub fn remap_index_buffer(indices: Option<&[u32]>, vertex_count: usize, remap: &[u32]) -> Vec<u32> {
let mut result: Vec<u32> = Vec::new();
if let Some(indices) = indices {
result.resize(indices.len(), 0u32);
unsafe {
ffi::meshopt_remapIndexBuffer(
result.as_mut_ptr(),
indices.as_ptr(),
indices.len(),
remap.as_ptr(),
);
}
} else {
result.resize(vertex_count, 0u32);
unsafe {
ffi::meshopt_remapIndexBuffer(
result.as_mut_ptr(),
std::ptr::null(),
vertex_count,
remap.as_ptr(),
);
}
}
result
}
pub fn remap_vertex_buffer<T: Clone + Default>(
vertices: &[T],
vertex_count: usize,
remap: &[u32],
) -> Vec<T> {
let mut result: Vec<T> = vec![T::default(); vertex_count];
unsafe {
ffi::meshopt_remapVertexBuffer(
result.as_mut_ptr().cast(),
vertices.as_ptr().cast(),
vertices.len(),
mem::size_of::<T>(),
remap.as_ptr(),
);
}
result
}
pub fn generate_position_remap(vertices: &VertexDataAdapter<'_>) -> Vec<u32> {
let mut remap: Vec<u32> = vec![0; vertices.vertex_count];
unsafe {
ffi::meshopt_generatePositionRemap(
remap.as_mut_ptr(),
vertices.pos_ptr(),
vertices.vertex_count,
vertices.vertex_stride,
);
}
remap
}
pub fn generate_position_remap_decoder<T: DecodePosition>(vertices: &[T]) -> Vec<u32> {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
let mut remap: Vec<u32> = vec![0; positions.len()];
unsafe {
ffi::meshopt_generatePositionRemap(
remap.as_mut_ptr(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
);
}
remap
}
#[cfg(test)]
mod tests {
use super::*;
use crate::typed_to_bytes;
#[test]
fn test_generate_position_remap() {
let vertices: &[f32] = &[
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.0, 2.0, 0.0, 0.0, ];
let vertices_adapter =
VertexDataAdapter::new(typed_to_bytes(vertices), 3 * mem::size_of::<f32>(), 0).unwrap();
let remap = generate_position_remap(&vertices_adapter);
let expected = vec![0, 1, 0, 1, 4];
assert_eq!(remap, expected);
}
}