Skip to content

Commit

Permalink
[Physics] Fix very large meshes throwing
Browse files Browse the repository at this point in the history
  • Loading branch information
Eideren committed Jun 5, 2019
1 parent 0241b15 commit 42f0910
Showing 1 changed file with 53 additions and 32 deletions.
85 changes: 53 additions & 32 deletions sources/engine/Xenko.Physics/Shapes/StaticMeshColliderShape.cs
Expand Up @@ -78,6 +78,23 @@ public static StaticMeshColliderShape FromModel(Model model, Vector3 localPositi
vertices = new Vector3[totalVerts];
}

// Allocate one byte array to push GPU data onto
byte[] gpuWindow;
{
int largestBuffer = 0;
foreach (var mesh in model.Meshes)
{
largestBuffer = Math.Max(largestBuffer, mesh.Draw.IndexBuffer.Buffer.Description.SizeInBytes);
foreach (var bufferBinding in mesh.Draw.VertexBuffers)
{
largestBuffer = Math.Max(largestBuffer, bufferBinding.Buffer.Description.SizeInBytes);
}
}

gpuWindow = new byte[largestBuffer];
}


int iCollOffset = 0;
int vCollOffset = 0;
foreach (var mesh in model.Meshes)
Expand All @@ -93,32 +110,34 @@ public static StaticMeshColliderShape FromModel(Model model, Vector3 localPositi
// Take care of the index buffer
unsafe
{
var binding = mesh.Draw.IndexBuffer;
var buffer = binding.Buffer;
var elementCount = binding.Count;
var sizeInBytes = buffer.Description.SizeInBytes;
fixed (byte* window = &gpuWindow[0])
{
var binding = mesh.Draw.IndexBuffer;
var buffer = binding.Buffer;
var elementCount = binding.Count;
var sizeInBytes = buffer.Description.SizeInBytes;

byte* window = stackalloc byte[sizeInBytes];
FetchBufferData(buffer, commandList, new DataPointer(window, sizeInBytes));
window += binding.Offset;
FetchBufferData(buffer, commandList, new DataPointer(window, sizeInBytes));
byte* start = window + binding.Offset;

if (binding.Is32Bit)
{
// For multiple meshes, indices have to be offset
// since we're merging all the meshes together
int* shortPtr = (int*)window;
for (int i = 0; i < elementCount; i++)
if (binding.Is32Bit)
{
indices[iCollOffset++] = vCollOffset + shortPtr[i];
// For multiple meshes, indices have to be offset
// since we're merging all the meshes together
int* shortPtr = (int*)start;
for (int i = 0; i < elementCount; i++)
{
indices[iCollOffset++] = vCollOffset + shortPtr[i];
}
}
}
// convert ushort gpu representation to uint
else
{
ushort* shortPtr = (ushort*)window;
for (int i = 0; i < elementCount; i++)
// convert ushort gpu representation to uint
else
{
indices[iCollOffset++] = vCollOffset + shortPtr[i];
ushort* shortPtr = (ushort*)start;
for (int i = 0; i < elementCount; i++)
{
indices[iCollOffset++] = vCollOffset + shortPtr[i];
}
}
}
}
Expand Down Expand Up @@ -158,21 +177,23 @@ public static StaticMeshColliderShape FromModel(Model model, Vector3 localPositi
// Fetch vertex position data from GPU
unsafe
{
var sizeInBytes = bufferBinding.Buffer.Description.SizeInBytes;
var elementCount = bufferBinding.Count;
fixed (byte* window = &gpuWindow[0])
{
var sizeInBytes = bufferBinding.Buffer.Description.SizeInBytes;
var elementCount = bufferBinding.Count;

byte* window = stackalloc byte[sizeInBytes];
FetchBufferData(bufferBinding.Buffer, commandList, new DataPointer(window, sizeInBytes));
FetchBufferData(bufferBinding.Buffer, commandList, new DataPointer(window, sizeInBytes));

window += bufferBinding.Offset;
byte* start = window + bufferBinding.Offset;

if (posData.decl.Format != PixelFormat.R32G32B32_Float)
throw new NotImplementedException(posData.decl.Format.ToString());
if (posData.decl.Format != PixelFormat.R32G32B32_Float)
throw new NotImplementedException(posData.decl.Format.ToString());

for (int i = 0; i < elementCount; i++)
{
byte* vStart = &window[i * stride + posData.offset];
vertices[vCollOffset++] = *(Vector3*)vStart;
for (int i = 0; i < elementCount; i++)
{
byte* vStart = &start[i * stride + posData.offset];
vertices[vCollOffset++] = *(Vector3*)vStart;
}
}
}
}
Expand Down

0 comments on commit 42f0910

Please sign in to comment.