66using Stride . BepuPhysics . Definitions ;
77using Stride . BepuPhysics . Definitions . Colliders ;
88using Stride . Core ;
9- using Stride . Core . IO ;
109using Stride . Core . Mathematics ;
11- using Stride . Core . Serialization ;
12- using Stride . Core . Serialization . Contents ;
1310using Stride . Graphics ;
14- using Stride . Graphics . Data ;
1511using Stride . Graphics . GeometricPrimitives ;
12+ using Stride . Graphics . Semantics ;
1613using Stride . Rendering ;
1714using BufferPool = BepuUtilities . Memory . BufferPool ;
1815using Mesh = BepuPhysics . Collidables . Mesh ;
@@ -140,72 +137,6 @@ private static void ExtractHull(DecomposedHulls hullDesc, out VertexPosition3[]
140137 }
141138 }
142139
143- internal static IEnumerable < ( Stride . Rendering . Mesh mesh , byte [ ] verticesBytes , byte [ ] indicesBytes ) > ExtractMeshes ( Model model , IServiceRegistry services )
144- {
145- foreach ( var meshData in model . Meshes )
146- {
147- byte [ ] ? verticesBytes = TryFetchBufferContent ( meshData . Draw . VertexBuffers [ 0 ] . Buffer , services ) ;
148- byte [ ] ? indicesBytes = TryFetchBufferContent ( meshData . Draw . IndexBuffer . Buffer , services ) ;
149-
150- if ( verticesBytes is null || indicesBytes is null || verticesBytes . Length == 0 || indicesBytes . Length == 0 )
151- {
152- throw new InvalidOperationException (
153- $ "Failed to find mesh buffers while attempting to { nameof ( ExtractMeshes ) } . " +
154- $ "Make sure that the { nameof ( model ) } is either an asset on disk, or has its buffer data attached to the buffer through '{ nameof ( AttachedReference ) } '\n ") ;
155- }
156-
157- yield return ( meshData , verticesBytes , indicesBytes ) ;
158- }
159-
160- // Get mesh data from GPU, shared memory or disk
161- static unsafe byte [ ] ? TryFetchBufferContent ( Graphics . Buffer buffer , IServiceRegistry services )
162- {
163- var bufRef = AttachedReferenceManager . GetAttachedReference ( buffer ) ;
164- if ( bufRef ? . Data != null && ( ( BufferData ) bufRef . Data ) . Content is { } output )
165- return output ;
166-
167- // Try to load it from disk, a file provider is required, editor does not provide one
168- if ( bufRef ? . Url != null && services . GetService < IDatabaseFileProviderService > ( ) is { } provider && provider . FileProvider is not null )
169- {
170- // We have to create a new one without providing services to ensure that it dumps the graphics buffer data to the attached reference below
171- var cleanManager = new ContentManager ( provider ) ;
172- var bufferCopy = cleanManager . Load < Graphics . Buffer > ( bufRef . Url ) ;
173- try
174- {
175- return bufferCopy . GetSerializationData ( ) . Content ;
176- }
177- finally
178- {
179- cleanManager . Unload ( bufRef . Url ) ;
180- }
181- }
182-
183- // When the mesh is created at runtime, or when the file provider is null as can be the case in editor, fetch from GPU
184- // will most likely break on non-dx11 APIs
185- if ( services . GetService < GraphicsContext > ( ) is { } context )
186- {
187- output = new byte [ buffer . SizeInBytes ] ;
188- fixed ( byte * window = output )
189- {
190- var ptr = new DataPointer ( window , output . Length ) ;
191- if ( buffer . Description . Usage == GraphicsResourceUsage . Staging ) // Directly if this is a staging resource
192- {
193- buffer . GetData ( context . CommandList , buffer , ptr ) ;
194- }
195- else // inefficient way to use the Copy method using dynamic staging texture
196- {
197- using var throughStaging = buffer . ToStaging ( ) ;
198- buffer . GetData ( context . CommandList , throughStaging , ptr ) ;
199- }
200- }
201-
202- return output ;
203- }
204-
205- return null ;
206- }
207- }
208-
209140 internal static unsafe BepuUtilities . Memory . Buffer < Triangle > ExtractBepuMesh ( Model model , IServiceRegistry services , BufferPool pool )
210141 {
211142 int totalIndices = 0 ;
@@ -215,42 +146,23 @@ internal static unsafe BepuUtilities.Memory.Buffer<Triangle> ExtractBepuMesh(Mod
215146 }
216147
217148 pool . Take < Triangle > ( totalIndices / 3 , out var triangles ) ;
218- var triangleAsV3 = triangles . As < Vector3 > ( ) ;
219- int triangleV3Index = 0 ;
220-
221- foreach ( ( Rendering . Mesh mesh , byte [ ] verticesBytes , byte [ ] indicesBytes ) in ExtractMeshes ( model , services ) )
149+ var bepuTriangles = triangles . As < Vector3 > ( ) ;
150+ var spanLeft = new Span < Vector3 > ( bepuTriangles . Memory , bepuTriangles . Length ) ;
151+ foreach ( var mesh in model . Meshes )
222152 {
223- var vBindings = mesh . Draw . VertexBuffers [ 0 ] ;
224- int vStride = vBindings . Declaration . VertexStride ;
225- var position = vBindings . Declaration . EnumerateWithOffsets ( ) . First ( x => x . VertexElement . SemanticName == VertexElementUsage . Position ) ;
153+ mesh . Draw . IndexBuffer . AsReadable ( services , out var indexHelper , out int indexCount ) ;
154+ mesh . Draw . VertexBuffers [ 0 ] . AsReadable ( services , out var vertexHelper , out int vertexCount ) ;
226155
227- if ( position . VertexElement . Format is PixelFormat . R32G32B32_Float or PixelFormat . R32G32B32A32_Float == false )
228- throw new ArgumentException ( $ " { model } 's vertex position must be declared as float3 or float4" ) ;
156+ var copyJob = new VertexBufferHelper . CopyAsTriangleList { IndexBufferHelper = indexHelper } ;
157+ vertexHelper . Read < PositionSemantic , Vector3 , VertexBufferHelper . CopyAsTriangleList > ( spanLeft [ .. indexCount ] , copyJob ) ;
229158
230- fixed ( byte * vBuffer = & verticesBytes [ vBindings . Offset ] )
231- fixed ( byte * iBuffer = indicesBytes )
232- {
233- if ( mesh . Draw . IndexBuffer . Is32Bit )
234- {
235- foreach ( int i in new Span < int > ( iBuffer + mesh . Draw . IndexBuffer . Offset , mesh . Draw . IndexBuffer . Count ) )
236- {
237- triangleAsV3 [ triangleV3Index ++ ] = * ( Vector3 * ) ( vBuffer + vStride * i + position . Offset ) ; // start of the buffer, move to the 'i'th vertex, and read from the position field of that vertex
238- }
239- }
240- else
241- {
242- foreach ( ushort i in new Span < ushort > ( iBuffer + mesh . Draw . IndexBuffer . Offset , mesh . Draw . IndexBuffer . Count ) )
243- {
244- triangleAsV3[ triangleV3Index ++ ] = * ( Vector3 * ) ( vBuffer + vStride * i + position . Offset ) ;
245- }
246- }
247- }
159+ spanLeft = spanLeft [ indexCount ..] ;
248160 }
249161
250162 return triangles ;
251163 }
252164
253- private static unsafe void ExtractMeshBuffers( Model model , IServiceRegistry services , out VertexPosition3 [ ] vertices , out int [ ] indices )
165+ private static void ExtractMeshBuffers ( Model model , IServiceRegistry services , out VertexPosition3 [ ] vertices , out int [ ] indices )
254166 {
255167 int totalVertices = 0 , totalIndices = 0 ;
256168 foreach ( var meshData in model . Meshes )
@@ -262,42 +174,19 @@ private static unsafe void ExtractMeshBuffers(Model model, IServiceRegistry serv
262174 vertices = new VertexPosition3 [ totalVertices ] ;
263175 indices = new int [ totalIndices ] ;
264176
265- int vertexWriteHead = 0 ;
266- int indexWriteHead = 0 ;
267- foreach ( ( Rendering . Mesh mesh , byte [ ] verticesBytes , byte [ ] indicesBytes ) in ExtractMeshes( model , services ) )
268- {
269- int vertMappingStart = vertexWriteHead ;
270- fixed ( byte * bytePtr = verticesBytes )
271- {
272- var vBindings = mesh . Draw . VertexBuffers [ 0 ] ;
273- int count = vBindings. Count;
274- int stride = vBindings. Declaration. VertexStride;
177+ var verticesLeft = MemoryMarshal . Cast < VertexPosition3 , Vector3 > ( vertices . AsSpan ( ) ) ;
178+ var indicesLeft = indices . AsSpan ( ) ;
275179
276- for ( int i = 0 , vHead = vBindings . Offset ; i < count ; i++ , vHead += stride )
277- {
278- vertices [ vertexWriteHead ++ ] . Position = * ( Vector3 * ) ( bytePtr + vHead ) ;
279- }
280- }
180+ foreach ( var mesh in model . Meshes )
181+ {
182+ mesh . Draw . IndexBuffer . AsReadable ( services , out var indexHelper , out int indexCount ) ;
183+ mesh . Draw . VertexBuffers [ 0 ] . AsReadable ( services , out var vertexHelper , out int vertexCount ) ;
281184
282- fixed ( byte * bytePtr = indicesBytes)
283- {
284- var count = mesh. Draw . IndexBuffer . Count ;
185+ vertexHelper . Copy < PositionSemantic , Vector3 > ( verticesLeft [ ..vertexCount ] ) ;
186+ indexHelper . CopyTo ( indicesLeft [ ..indexCount ] ) ;
285187
286- if ( mesh . Draw . IndexBuffer . Is32Bit )
287- {
288- foreach ( int indexBufferValue in new Span < int > ( bytePtr + mesh . Draw . IndexBuffer . Offset , count ) )
289- {
290- indices[ indexWriteHead ++ ] = vertMappingStart + indexBufferValue ;
291- }
292- }
293- else
294- {
295- foreach ( ushort indexBufferValue in new Span < ushort > ( bytePtr + mesh . Draw . IndexBuffer . Offset , count ) )
296- {
297- indices[ indexWriteHead ++ ] = vertMappingStart + indexBufferValue ;
298- }
299- }
300- }
188+ verticesLeft = verticesLeft [ vertexCount ..] ;
189+ indicesLeft = indicesLeft [ indexCount ..] ;
301190 }
302191 }
303192
0 commit comments