@@ -5,13 +5,19 @@ use bevy_asset::{
55} ;
66use bevy_math:: Vec3 ;
77use bevy_reflect:: TypePath ;
8+ use bevy_tasks:: block_on;
89use bytemuck:: { Pod , Zeroable } ;
910use lz4_flex:: frame:: { FrameDecoder , FrameEncoder } ;
10- use serde:: { Deserialize , Serialize } ;
11- use std:: { io:: Cursor , sync:: Arc } ;
11+ use std:: {
12+ io:: { Read , Write } ,
13+ sync:: Arc ,
14+ } ;
15+
16+ /// Unique identifier for the [`MeshletMesh`] asset format.
17+ const MESHLET_MESH_ASSET_MAGIC : u64 = 1717551717668 ;
1218
1319/// The current version of the [`MeshletMesh`] asset format.
14- pub const MESHLET_MESH_ASSET_VERSION : u64 = 0 ;
20+ pub const MESHLET_MESH_ASSET_VERSION : u64 = 1 ;
1521
1622/// A mesh that has been pre-processed into multiple small clusters of triangles called meshlets.
1723///
@@ -27,24 +33,24 @@ pub const MESHLET_MESH_ASSET_VERSION: u64 = 0;
2733/// * Limited control over [`bevy_render::render_resource::RenderPipelineDescriptor`] attributes.
2834///
2935/// See also [`super::MaterialMeshletMeshBundle`] and [`super::MeshletPlugin`].
30- #[ derive( Asset , TypePath , Serialize , Deserialize , Clone ) ]
36+ #[ derive( Asset , TypePath , Clone ) ]
3137pub struct MeshletMesh {
3238 /// The total amount of triangles summed across all LOD 0 meshlets in the mesh.
33- pub worst_case_meshlet_triangles : u64 ,
39+ pub ( crate ) worst_case_meshlet_triangles : u64 ,
3440 /// Raw vertex data bytes for the overall mesh.
35- pub vertex_data : Arc < [ u8 ] > ,
41+ pub ( crate ) vertex_data : Arc < [ u8 ] > ,
3642 /// Indices into `vertex_data`.
37- pub vertex_ids : Arc < [ u32 ] > ,
43+ pub ( crate ) vertex_ids : Arc < [ u32 ] > ,
3844 /// Indices into `vertex_ids`.
39- pub indices : Arc < [ u8 ] > ,
45+ pub ( crate ) indices : Arc < [ u8 ] > ,
4046 /// The list of meshlets making up this mesh.
41- pub meshlets : Arc < [ Meshlet ] > ,
47+ pub ( crate ) meshlets : Arc < [ Meshlet ] > ,
4248 /// Spherical bounding volumes.
43- pub bounding_spheres : Arc < [ MeshletBoundingSpheres ] > ,
49+ pub ( crate ) bounding_spheres : Arc < [ MeshletBoundingSpheres ] > ,
4450}
4551
4652/// A single meshlet within a [`MeshletMesh`].
47- #[ derive( Serialize , Deserialize , Copy , Clone , Pod , Zeroable ) ]
53+ #[ derive( Copy , Clone , Pod , Zeroable ) ]
4854#[ repr( C ) ]
4955pub struct Meshlet {
5056 /// The offset within the parent mesh's [`MeshletMesh::vertex_ids`] buffer where the indices for this meshlet begin.
@@ -56,7 +62,7 @@ pub struct Meshlet {
5662}
5763
5864/// Bounding spheres used for culling and choosing level of detail for a [`Meshlet`].
59- #[ derive( Serialize , Deserialize , Copy , Clone , Pod , Zeroable ) ]
65+ #[ derive( Copy , Clone , Pod , Zeroable ) ]
6066#[ repr( C ) ]
6167pub struct MeshletBoundingSpheres {
6268 /// The bounding sphere used for frustum and occlusion culling for this meshlet.
@@ -68,84 +74,162 @@ pub struct MeshletBoundingSpheres {
6874}
6975
7076/// A spherical bounding volume used for a [`Meshlet`].
71- #[ derive( Serialize , Deserialize , Copy , Clone , Pod , Zeroable ) ]
77+ #[ derive( Copy , Clone , Pod , Zeroable ) ]
7278#[ repr( C ) ]
7379pub struct MeshletBoundingSphere {
7480 pub center : Vec3 ,
7581 pub radius : f32 ,
7682}
7783
7884/// An [`AssetLoader`] and [`AssetSaver`] for `.meshlet_mesh` [`MeshletMesh`] assets.
79- pub struct MeshletMeshSaverLoad ;
85+ pub struct MeshletMeshSaverLoader ;
8086
81- impl AssetLoader for MeshletMeshSaverLoad {
87+ impl AssetSaver for MeshletMeshSaverLoader {
8288 type Asset = MeshletMesh ;
8389 type Settings = ( ) ;
90+ type OutputLoader = Self ;
8491 type Error = MeshletMeshSaveOrLoadError ;
8592
86- async fn load < ' a > (
93+ async fn save < ' a > (
8794 & ' a self ,
88- reader : & ' a mut dyn Reader ,
89- _settings : & ' a Self :: Settings ,
90- _load_context : & ' a mut LoadContext < ' _ > ,
91- ) -> Result < Self :: Asset , Self :: Error > {
92- let version = read_u64 ( reader ) . await ? ;
93- if version != MESHLET_MESH_ASSET_VERSION {
94- return Err ( MeshletMeshSaveOrLoadError :: WrongVersion { found : version } ) ;
95- }
95+ writer : & ' a mut Writer ,
96+ asset : SavedAsset < ' a , MeshletMesh > ,
97+ _settings : & ' a ( ) ,
98+ ) -> Result < ( ) , MeshletMeshSaveOrLoadError > {
99+ // Write asset magic number
100+ writer
101+ . write_all ( & MESHLET_MESH_ASSET_MAGIC . to_le_bytes ( ) )
102+ . await ? ;
96103
97- let mut bytes = Vec :: new ( ) ;
98- reader. read_to_end ( & mut bytes) . await ?;
99- let asset = bincode:: deserialize_from ( FrameDecoder :: new ( Cursor :: new ( bytes) ) ) ?;
104+ // Write asset version
105+ writer
106+ . write_all ( & MESHLET_MESH_ASSET_VERSION . to_le_bytes ( ) )
107+ . await ?;
100108
101- Ok ( asset)
102- }
109+ // Compress and write asset data
110+ writer
111+ . write_all ( & asset. worst_case_meshlet_triangles . to_le_bytes ( ) )
112+ . await ?;
113+ let mut writer = FrameEncoder :: new ( AsyncWriteSyncAdapter ( writer) ) ;
114+ write_slice ( & asset. vertex_data , & mut writer) ?;
115+ write_slice ( & asset. vertex_ids , & mut writer) ?;
116+ write_slice ( & asset. indices , & mut writer) ?;
117+ write_slice ( & asset. meshlets , & mut writer) ?;
118+ write_slice ( & asset. bounding_spheres , & mut writer) ?;
119+ writer. finish ( ) ?;
103120
104- fn extensions ( & self ) -> & [ & str ] {
105- & [ "meshlet_mesh" ]
121+ Ok ( ( ) )
106122 }
107123}
108124
109- impl AssetSaver for MeshletMeshSaverLoad {
125+ impl AssetLoader for MeshletMeshSaverLoader {
110126 type Asset = MeshletMesh ;
111127 type Settings = ( ) ;
112- type OutputLoader = Self ;
113128 type Error = MeshletMeshSaveOrLoadError ;
114129
115- async fn save < ' a > (
130+ async fn load < ' a > (
116131 & ' a self ,
117- writer : & ' a mut Writer ,
118- asset : SavedAsset < ' a , Self :: Asset > ,
119- _settings : & ' a Self :: Settings ,
120- ) -> Result < ( ) , Self :: Error > {
121- writer
122- . write_all ( & MESHLET_MESH_ASSET_VERSION . to_le_bytes ( ) )
123- . await ?;
132+ reader : & ' a mut dyn Reader ,
133+ _settings : & ' a ( ) ,
134+ _load_context : & ' a mut LoadContext < ' _ > ,
135+ ) -> Result < MeshletMesh , MeshletMeshSaveOrLoadError > {
136+ // Load and check magic number
137+ let magic = async_read_u64 ( reader) . await ?;
138+ if magic != MESHLET_MESH_ASSET_MAGIC {
139+ return Err ( MeshletMeshSaveOrLoadError :: WrongFileType ) ;
140+ }
124141
125- let mut bytes = Vec :: new ( ) ;
126- let mut sync_writer = FrameEncoder :: new ( & mut bytes ) ;
127- bincode :: serialize_into ( & mut sync_writer , asset . get ( ) ) ? ;
128- sync_writer . finish ( ) ? ;
129- writer . write_all ( & bytes ) . await ? ;
142+ // Load and check asset version
143+ let version = async_read_u64 ( reader ) . await ? ;
144+ if version != MESHLET_MESH_ASSET_VERSION {
145+ return Err ( MeshletMeshSaveOrLoadError :: WrongVersion { found : version } ) ;
146+ }
130147
131- Ok ( ( ) )
148+ // Load and decompress asset data
149+ let worst_case_meshlet_triangles = async_read_u64 ( reader) . await ?;
150+ let reader = & mut FrameDecoder :: new ( AsyncReadSyncAdapter ( reader) ) ;
151+ let vertex_data = read_slice ( reader) ?;
152+ let vertex_ids = read_slice ( reader) ?;
153+ let indices = read_slice ( reader) ?;
154+ let meshlets = read_slice ( reader) ?;
155+ let bounding_spheres = read_slice ( reader) ?;
156+
157+ Ok ( MeshletMesh {
158+ worst_case_meshlet_triangles,
159+ vertex_data,
160+ vertex_ids,
161+ indices,
162+ meshlets,
163+ bounding_spheres,
164+ } )
165+ }
166+
167+ fn extensions ( & self ) -> & [ & str ] {
168+ & [ "meshlet_mesh" ]
132169 }
133170}
134171
135172#[ derive( thiserror:: Error , Debug ) ]
136173pub enum MeshletMeshSaveOrLoadError {
174+ #[ error( "file was not a MeshletMesh asset" ) ]
175+ WrongFileType ,
137176 #[ error( "expected asset version {MESHLET_MESH_ASSET_VERSION} but found version {found}" ) ]
138177 WrongVersion { found : u64 } ,
139- #[ error( "failed to serialize or deserialize asset data" ) ]
140- SerializationOrDeserialization ( #[ from] bincode:: Error ) ,
141178 #[ error( "failed to compress or decompress asset data" ) ]
142179 CompressionOrDecompression ( #[ from] lz4_flex:: frame:: Error ) ,
143180 #[ error( "failed to read or write asset data" ) ]
144181 Io ( #[ from] std:: io:: Error ) ,
145182}
146183
147- async fn read_u64 ( reader : & mut dyn Reader ) -> Result < u64 , bincode :: Error > {
184+ async fn async_read_u64 ( reader : & mut dyn Reader ) -> Result < u64 , std :: io :: Error > {
148185 let mut bytes = [ 0u8 ; 8 ] ;
149186 reader. read_exact ( & mut bytes) . await ?;
150187 Ok ( u64:: from_le_bytes ( bytes) )
151188}
189+
190+ fn read_u64 ( reader : & mut dyn Read ) -> Result < u64 , std:: io:: Error > {
191+ let mut bytes = [ 0u8 ; 8 ] ;
192+ reader. read_exact ( & mut bytes) ?;
193+ Ok ( u64:: from_le_bytes ( bytes) )
194+ }
195+
196+ fn write_slice < T : Pod > (
197+ field : & [ T ] ,
198+ writer : & mut dyn Write ,
199+ ) -> Result < ( ) , MeshletMeshSaveOrLoadError > {
200+ writer. write_all ( & ( field. len ( ) as u64 ) . to_le_bytes ( ) ) ?;
201+ writer. write_all ( bytemuck:: cast_slice ( field) ) ?;
202+ Ok ( ( ) )
203+ }
204+
205+ fn read_slice < T : Pod > ( reader : & mut dyn Read ) -> Result < Arc < [ T ] > , std:: io:: Error > {
206+ let len = read_u64 ( reader) ? as usize ;
207+
208+ let mut data: Arc < [ T ] > = std:: iter:: repeat_with ( T :: zeroed) . take ( len) . collect ( ) ;
209+ let slice = Arc :: get_mut ( & mut data) . unwrap ( ) ;
210+ reader. read_exact ( bytemuck:: cast_slice_mut ( slice) ) ?;
211+
212+ Ok ( data)
213+ }
214+
215+ // TODO: Use async for everything and get rid of this adapter
216+ struct AsyncWriteSyncAdapter < ' a > ( & ' a mut Writer ) ;
217+
218+ impl Write for AsyncWriteSyncAdapter < ' _ > {
219+ fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
220+ block_on ( self . 0 . write ( buf) )
221+ }
222+
223+ fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
224+ block_on ( self . 0 . flush ( ) )
225+ }
226+ }
227+
228+ // TODO: Use async for everything and get rid of this adapter
229+ struct AsyncReadSyncAdapter < ' a > ( & ' a mut dyn Reader ) ;
230+
231+ impl Read for AsyncReadSyncAdapter < ' _ > {
232+ fn read ( & mut self , buf : & mut [ u8 ] ) -> std:: io:: Result < usize > {
233+ block_on ( self . 0 . read ( buf) )
234+ }
235+ }
0 commit comments