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
use crate::{ffi, DecodePosition, VertexDataAdapter, VertexStream};

/// Generate index buffer that can be used for more efficient rendering when only a subset of the vertex
/// attributes is necessary. All vertices that are binary equivalent (wrt first `vertex_size` bytes) map to
/// the first vertex in the original vertex buffer.
///
/// This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using
/// the original index buffer for regular rendering.
pub fn generate_shadow_indices(indices: &[u32], vertices: &VertexDataAdapter<'_>) -> Vec<u32> {
    let vertex_data = vertices.reader.get_ref();
    let vertex_data = vertex_data.as_ptr().cast::<u8>();
    let positions = unsafe { vertex_data.add(vertices.position_offset) };
    let mut shadow_indices: Vec<u32> = vec![0; indices.len()];
    unsafe {
        ffi::meshopt_generateShadowIndexBuffer(
            shadow_indices.as_mut_ptr(),
            indices.as_ptr(),
            indices.len(),
            positions.cast(),
            vertices.vertex_count,
            std::mem::size_of::<f32>() * 3,
            vertices.vertex_stride,
        );
    }
    shadow_indices
}

/// Generate index buffer that can be used for more efficient rendering when only a subset of the vertex
/// attributes is necessary. All vertices that are binary equivalent (wrt first `vertex_size` bytes) map to
/// the first vertex in the original vertex buffer.
///
/// This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using
/// the original index buffer for regular rendering.
pub fn generate_shadow_indices_decoder<T: DecodePosition>(
    indices: &[u32],
    vertices: &[T],
) -> Vec<u32> {
    let vertices = vertices
        .iter()
        .map(|vertex| vertex.decode_position())
        .collect::<Vec<[f32; 3]>>();
    let positions = vertices.as_ptr().cast();
    let mut shadow_indices: Vec<u32> = vec![0; indices.len()];
    unsafe {
        ffi::meshopt_generateShadowIndexBuffer(
            shadow_indices.as_mut_ptr(),
            indices.as_ptr(),
            indices.len(),
            positions,
            vertices.len() * 3,
            std::mem::size_of::<f32>() * 3,
            std::mem::size_of::<f32>() * 3,
        );
    }
    shadow_indices
}

/// Generate index buffer that can be used for more efficient rendering when only a subset of the vertex
/// attributes is necessary. All vertices that are binary equivalent (wrt specified streams) map to the
/// first vertex in the original vertex buffer.
///
/// This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using
/// the original index buffer for regular rendering.
pub fn generate_shadow_indices_multi(
    indices: &[u32],
    vertex_count: usize,
    streams: &[VertexStream<'_>],
) -> 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 shadow_indices: Vec<u32> = vec![0; indices.len()];
    unsafe {
        ffi::meshopt_generateShadowIndexBufferMulti(
            shadow_indices.as_mut_ptr(),
            indices.as_ptr(),
            indices.len(),
            vertex_count,
            streams.as_ptr(),
            streams.len(),
        );
    }
    shadow_indices
}