using Stride.Games; using Stride.Rendering; using System; using Stride.Core.Serialization; using Stride.Core; using Stride.Physics; using System.Collections.Generic; using Stride.Core.Mathematics; public static class MeshExtensions { public static (List verts, List indices) GetMeshVerticesAndIndices(this Model model, IGame game) { return GetMeshData(model, game.Services, game); } static unsafe (List verts, List indices) GetMeshData(Model model, IServiceRegistry services, IGame game) { Matrix[] nodeTransforms = null; int totalVerts = 0, totalIndices = 0; foreach (var meshData in model.Meshes) { totalVerts += meshData.Draw.VertexBuffers[0].Count; totalIndices += meshData.Draw.IndexBuffer.Count; } var combinedVerts = new List(totalVerts); var combinedIndices = new List(totalIndices); foreach (var meshData in model.Meshes) { var vBuffer = meshData.Draw.VertexBuffers[0].Buffer; var iBuffer = meshData.Draw.IndexBuffer.Buffer; byte[] verticesBytes = vBuffer.GetData(game.GraphicsContext.CommandList); ; byte[] indicesBytes = iBuffer.GetData(game.GraphicsContext.CommandList); ; if ((verticesBytes?.Length ?? 0) == 0 || (indicesBytes?.Length ?? 0) == 0) { throw new InvalidOperationException( $"Failed to find mesh buffers while attempting to build a {nameof(StaticMeshColliderShape)}. " + $"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" + $"You can also explicitly build a {nameof(StaticMeshColliderShape)} using the second constructor instead of this one."); } int vertMappingStart = combinedVerts.Count; fixed (byte* bytePtr = verticesBytes) { var vBindings = meshData.Draw.VertexBuffers[0]; int count = vBindings.Count; int stride = vBindings.Declaration.VertexStride; for (int i = 0, vHead = vBindings.Offset; i < count; i++, vHead += stride) { var pos = *(Vector3*)(bytePtr + vHead); if (nodeTransforms != null) { Matrix posMatrix = Matrix.Translation(pos); Matrix.Multiply(ref posMatrix, ref nodeTransforms[meshData.NodeIndex], out var finalMatrix); pos = finalMatrix.TranslationVector; } combinedVerts.Add(pos); } } fixed (byte* bytePtr = indicesBytes) { if (meshData.Draw.IndexBuffer.Is32Bit) { foreach (int i in new Span(bytePtr + meshData.Draw.IndexBuffer.Offset, meshData.Draw.IndexBuffer.Count)) { combinedIndices.Add(vertMappingStart + i); } } else { foreach (ushort i in new Span(bytePtr + meshData.Draw.IndexBuffer.Offset, meshData.Draw.IndexBuffer.Count)) { combinedIndices.Add(vertMappingStart + i); } } } } return (combinedVerts, combinedIndices); } }