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
//! Meshlet rendering for dense high-poly scenes (experimental).

// Note: This example showcases the meshlet API, but is not the type of scene that would benefit from using meshlets.

#[path = "../helpers/camera_controller.rs"]
mod camera_controller;

use bevy::{
    pbr::{
        experimental::meshlet::{MeshletPlugin, DEFAULT_VERTEX_POSITION_QUANTIZATION_FACTOR},
        DirectionalLightShadowMap,
    },
    prelude::*,
    render::render_resource::AsBindGroup,
};
use bytemuck::Pod;
use camera_controller::CameraControllerPlugin;
use lz4_flex::frame::FrameEncoder;
use std::{io::Write, process::ExitCode};

fn main() -> ExitCode {
    App::new()
        .insert_resource(DirectionalLightShadowMap { size: 4096 })
        .add_plugins((
            DefaultPlugins,
            MeshletPlugin {
                cluster_buffer_slots: 8192,
            },
            MaterialPlugin::<MeshletDebugMaterial>::default(),
            CameraControllerPlugin,
        ))
        .add_systems(Startup, setup)
        .add_systems(Update, draw_bounding_spheres)
        .run();

    ExitCode::SUCCESS
}

#[derive(Resource)]
struct Foo(Handle<Mesh>);

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.insert_resource(Foo(asset_server.load("models/bunny.glb#Mesh0/Primitive0")));
}

#[derive(Asset, TypePath, AsBindGroup, Clone, Default)]
struct MeshletDebugMaterial {
    _dummy: (),
}
impl Material for MeshletDebugMaterial {}

fn draw_bounding_spheres(mut assets: ResMut<Assets<Mesh>>, foo: ResMut<Foo>) {
    if let Some(mesh) = assets.get_mut(foo.0.id()) {
        let asset = bevy::pbr::experimental::meshlet::MeshletMesh::from_mesh(
            mesh,
            DEFAULT_VERTEX_POSITION_QUANTIZATION_FACTOR,
        )
        .unwrap();

        let mut f = std::io::BufWriter::new(
            std::fs::File::create("assets/models/bunny.meshlet_mesh").unwrap(),
        );

        // Write asset magic number
        f.write_all(&1717551717668u64.to_le_bytes()).unwrap();

        // Write asset version
        f.write_all(&1u64.to_le_bytes()).unwrap();

        // Compress and write asset data
        let mut writer = FrameEncoder::new(f);
        write_slice(&asset.vertex_positions, &mut writer);
        write_slice(&asset.vertex_normals, &mut writer);
        write_slice(&asset.vertex_uvs, &mut writer);
        write_slice(&asset.indices, &mut writer);
        write_slice(&asset.meshlets, &mut writer);
        write_slice(&asset.meshlet_bounding_spheres, &mut writer);
        writer.finish().unwrap();

        panic!("Exit program");
    }
}

fn write_slice<T: Pod>(field: &[T], writer: &mut dyn Write) {
    writer
        .write_all(&(field.len() as u64).to_le_bytes())
        .unwrap();
    writer.write_all(bytemuck::cast_slice(field)).unwrap();
}