1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::ffi;
use crate::VertexStream;
use std::mem;

/// Generates a vertex remap table from the vertex buffer and an optional index buffer and returns number of unique vertices.
///
/// As a result, all vertices that are binary equivalent map to the same (new) location, with no gaps in the resulting sequence.
/// Resulting remap table maps old vertices to new vertices and can be used in `remap_vertex_buffer`/`remap_index_buffer`.
///
/// The `indices` can be `None` if the input is unindexed.
pub fn generate_vertex_remap<T>(vertices: &[T], indices: Option<&[u32]>) -> (usize, Vec<u32>) {
    let remap: Vec<u32> = vec![0; vertices.len()];
    let vertex_count = unsafe {
        match indices {
            Some(indices) => ffi::meshopt_generateVertexRemap(
                remap.as_ptr() as *mut ::std::os::raw::c_uint,
                indices.as_ptr() as *const ::std::os::raw::c_uint,
                indices.len(),
                vertices.as_ptr() as *const ::std::os::raw::c_void,
                vertices.len(),
                mem::size_of::<T>(),
            ),
            None => ffi::meshopt_generateVertexRemap(
                remap.as_ptr() as *mut ::std::os::raw::c_uint,
                ::std::ptr::null(),
                vertices.len(),
                vertices.as_ptr() as *const ::std::os::raw::c_void,
                vertices.len(),
                mem::size_of::<T>(),
            ),
        }
    };
    (vertex_count, remap)
}

/// Generates a vertex remap table from multiple vertex streams and an optional index buffer and returns number of unique vertices.
///
/// As a result, all vertices that are binary equivalent map to the same (new) location, with no gaps in the resulting sequence.
/// Resulting remap table maps old vertices to new vertices and can be used in `remap_vertex_buffer`/`remap_index_buffer`.
///
/// To remap vertex buffers, you will need to call `remap_vertex_buffer` for each vertex stream.
///
/// The `indices` can be `None` if the input is unindexed.
pub fn generate_vertex_remap_multi<T>(
    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 as *const ::std::ffi::c_void,
            size: stream.size,
            stride: stream.stride,
        })
        .collect();
    let remap: Vec<u32> = vec![0; vertex_count];
    let vertex_count = unsafe {
        match indices {
            Some(indices) => ffi::meshopt_generateVertexRemapMulti(
                remap.as_ptr() as *mut ::std::os::raw::c_uint,
                indices.as_ptr() as *const ::std::os::raw::c_uint,
                indices.len(),
                vertex_count,
                streams.as_ptr(),
                streams.len(),
            ),
            None => ffi::meshopt_generateVertexRemapMulti(
                remap.as_ptr() as *mut ::std::os::raw::c_uint,
                ::std::ptr::null(),
                vertex_count,
                vertex_count,
                streams.as_ptr(),
                streams.len(),
            ),
        }
    };
    (vertex_count, remap)
}

/// Generate index buffer from the source index buffer and remap table generated by `generate_vertex_remap`.
///
/// `indices` can be `None` if the input is unindexed.
pub fn remap_index_buffer(indices: Option<&[u32]>, vertex_count: usize, remap: &[u32]) -> Vec<u32> {
    let mut result: Vec<u32> = Vec::new();
    match indices {
        Some(indices) => {
            result.resize(indices.len(), 0u32);
            unsafe {
                ffi::meshopt_remapIndexBuffer(
                    result.as_mut_ptr() as *mut ::std::os::raw::c_uint,
                    indices.as_ptr() as *const ::std::os::raw::c_uint,
                    indices.len(),
                    remap.as_ptr() as *const ::std::os::raw::c_uint,
                );
            }
        }
        None => {
            result.resize(vertex_count, 0u32);
            unsafe {
                ffi::meshopt_remapIndexBuffer(
                    result.as_mut_ptr() as *mut ::std::os::raw::c_uint,
                    ::std::ptr::null(),
                    vertex_count,
                    remap.as_ptr() as *const ::std::os::raw::c_uint,
                );
            }
        }
    }

    result
}

/// Generates vertex buffer from the source vertex buffer and remap table generated by `generate_vertex_remap`.
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() as *mut ::std::os::raw::c_void,
            vertices.as_ptr() as *const ::std::os::raw::c_void,
            vertices.len(),
            mem::size_of::<T>(),
            remap.as_ptr() as *const ::std::os::raw::c_uint,
        );
    }
    result
}