use crate::{ffi, DecodePosition, VertexDataAdapter};
use bitflags::bitflags;
use std::mem;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SimplifyOptions : u32 {
const None = 0;
const LockBorder = 1;
const Sparse = 2;
const ErrorAbsolute = 4;
const Prune = 8;
const Regularize = 16;
const Permissive = 32;
}
}
pub fn simplify(
indices: &[u32],
vertices: &VertexDataAdapter<'_>,
target_count: usize,
target_error: f32,
options: SimplifyOptions,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplify(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
vertices.pos_ptr(),
vertices.vertex_count,
vertices.vertex_stride,
target_count,
target_error,
options.bits(),
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_decoder<T: DecodePosition>(
indices: &[u32],
vertices: &[T],
target_count: usize,
target_error: f32,
options: SimplifyOptions,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplify(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
target_count,
target_error,
options.bits(),
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_with_locks(
indices: &[u32],
vertices: &VertexDataAdapter<'_>,
vertex_lock: &[bool],
target_count: usize,
target_error: f32,
options: SimplifyOptions,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifyWithAttributes(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
vertices.pos_ptr(),
vertices.vertex_count,
vertices.vertex_stride,
std::ptr::null(),
0,
std::ptr::null(),
0,
vertex_lock.as_ptr().cast(),
target_count,
target_error,
options.bits(),
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_with_locks_decoder<T: DecodePosition>(
indices: &[u32],
vertices: &[T],
vertex_lock: &[bool],
target_count: usize,
target_error: f32,
options: SimplifyOptions,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifyWithAttributes(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
std::ptr::null(),
0,
std::ptr::null(),
0,
vertex_lock.as_ptr().cast(),
target_count,
target_error,
options.bits(),
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
#[allow(clippy::too_many_arguments)]
pub fn simplify_with_attributes_and_locks(
indices: &[u32],
vertices: &VertexDataAdapter<'_>,
vertex_attributes: &[f32],
vertex_attribute_weights: &[f32],
vertex_attributes_stride: usize,
vertex_lock: &[bool],
target_count: usize,
target_error: f32,
options: SimplifyOptions,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifyWithAttributes(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
vertices.pos_ptr(),
vertices.vertex_count,
vertices.vertex_stride,
vertex_attributes.as_ptr(),
vertex_attributes_stride,
vertex_attribute_weights.as_ptr(),
vertex_attribute_weights.len(),
vertex_lock.as_ptr().cast(),
target_count,
target_error,
options.bits(),
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
#[allow(clippy::too_many_arguments)]
pub fn simplify_with_attributes_and_locks_decoder<T: DecodePosition>(
indices: &[u32],
vertices: &[T],
vertex_attributes: &[f32],
vertex_attribute_weights: &[f32],
vertex_attributes_stride: usize,
vertex_lock: &[bool],
target_count: usize,
target_error: f32,
options: SimplifyOptions,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifyWithAttributes(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
vertex_attributes.as_ptr(),
vertex_attributes_stride,
vertex_attribute_weights.as_ptr(),
vertex_attribute_weights.len(),
vertex_lock.as_ptr().cast(),
target_count,
target_error,
options.bits(),
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_sloppy(
indices: &[u32],
vertices: &VertexDataAdapter<'_>,
target_count: usize,
target_error: f32,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifySloppy(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
vertices.pos_ptr(),
vertices.vertex_count,
vertices.vertex_stride,
std::ptr::null(),
target_count,
target_error,
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_sloppy_decoder<T: DecodePosition>(
indices: &[u32],
vertices: &[T],
target_count: usize,
target_error: f32,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifySloppy(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
std::ptr::null(),
target_count,
target_error,
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_sloppy_with_locks(
indices: &[u32],
vertices: &VertexDataAdapter<'_>,
vertex_lock: &[bool],
target_count: usize,
target_error: f32,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let positions = vertices.pos_ptr();
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifySloppy(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
positions.cast(),
vertices.vertex_count,
vertices.vertex_stride,
vertex_lock.as_ptr().cast(),
target_count,
target_error,
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_sloppy_with_locks_decoder<T: DecodePosition>(
indices: &[u32],
vertices: &[T],
vertex_lock: &[bool],
target_count: usize,
target_error: f32,
result_error: Option<&mut f32>,
) -> Vec<u32> {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
let mut result: Vec<u32> = vec![0; indices.len()];
let index_count = unsafe {
ffi::meshopt_simplifySloppy(
result.as_mut_ptr().cast(),
indices.as_ptr().cast(),
indices.len(),
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
vertex_lock.as_ptr().cast(),
target_count,
target_error,
result_error.map_or_else(std::ptr::null_mut, |v| v as *mut _),
)
};
result.resize(index_count, 0u32);
result
}
pub fn simplify_scale(vertices: &VertexDataAdapter<'_>) -> f32 {
unsafe {
ffi::meshopt_simplifyScale(
vertices.pos_ptr(),
vertices.vertex_count,
vertices.vertex_stride,
)
}
}
pub fn simplify_scale_decoder<T: DecodePosition>(vertices: &[T]) -> f32 {
let positions = vertices
.iter()
.map(|vertex| vertex.decode_position())
.collect::<Vec<[f32; 3]>>();
unsafe {
ffi::meshopt_simplifyScale(
positions.as_ptr().cast(),
positions.len(),
mem::size_of::<f32>() * 3,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::typed_to_bytes;
#[test]
fn test_simplify_sloppy_with_locks() {
let indices = &[
0, 2, 1, 1, 2, 3, 3, 2, 4, 2, 5, 4, ];
let vertices: &[f32] = &[
0.0, 4.0, 0.0, 0.0, 1.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 4.0, 0.0, 0.0, ];
let vertex_locks = &[true, false, true, false, false, true];
let vertices_adapter =
VertexDataAdapter::new(typed_to_bytes(vertices), 3 * mem::size_of::<f32>(), 0).unwrap();
let mut result_error = 0.0f32;
let result = simplify_sloppy_with_locks(
indices,
&vertices_adapter,
vertex_locks,
3, 1.0,
Some(&mut result_error),
);
assert_eq!(result.len(), 6);
assert_eq!(result_error, 0.0);
let expected = &[0, 2, 1, 1, 2, 5];
assert_eq!(result, expected);
}
}