Skip to content
Permalink
Browse files

[Physics] Split static mesh collider into new PR

  • Loading branch information
Eideren committed Jun 21, 2019
1 parent 0dda055 commit 05421ae96fb2232e1e94dbc2c4148ea578dc214b
@@ -95,17 +95,4 @@ public override ColliderShapeAsset New()
return Create();
}
}

public class ColliderShapeStaticMeshFactory : AssetFactory<ColliderShapeAsset>
{
public static ColliderShapeAsset Create()
{
return new ColliderShapeAsset { ColliderShapes = { new StaticMeshColliderShapeDesc() } };
}

public override ColliderShapeAsset New()
{
return Create();
}
}
}

This file was deleted.

@@ -49,180 +49,6 @@ public StaticMeshColliderShape(ICollection<Vector3> vertices, ICollection<int> i
Scaling = scaling;
}

/// <summary>
/// Can return null if the model is empty
/// </summary>
public static StaticMeshColliderShape FromModel(Model model, Vector3 localPosition, Quaternion localRotation, Vector3 scale)
{
int[] indices;
Vector3[] vertices;
{
int totalIndices = 0;
int totalVerts = 0;

foreach (var mesh in model.Meshes)
{
foreach (var bufferBinding in mesh.Draw.VertexBuffers)
{
// We have to duplicate the index buffer for each vertex buffers since
// bullet doesn't have a construct sharing index buffers
totalIndices += mesh.Draw.IndexBuffer.Count;
totalVerts += bufferBinding.Count;
}
}

if (totalIndices == 0 || totalVerts == 0)
return null;

indices = new int[totalIndices];
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)
{
var commandList = (CommandList)typeof(GraphicsDevice).GetField("InternalMainCommandList",
System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.GetField
| System.Reflection.BindingFlags.FlattenHierarchy).GetValue(mesh.Draw.IndexBuffer.Buffer.GraphicsDevice);

foreach (var bufferBinding in mesh.Draw.VertexBuffers)
{
// Take care of the index buffer
unsafe
{
fixed (byte* window = &gpuWindow[0])
{
var binding = mesh.Draw.IndexBuffer;
var buffer = binding.Buffer;
var elementCount = binding.Count;
var sizeInBytes = buffer.Description.SizeInBytes;

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*)start;
for (int i = 0; i < elementCount; i++)
{
indices[iCollOffset++] = vCollOffset + shortPtr[i];
}
}
// convert ushort gpu representation to uint
else
{
ushort* shortPtr = (ushort*)start;
for (int i = 0; i < elementCount; i++)
{
indices[iCollOffset++] = vCollOffset + shortPtr[i];
}
}
}
}

int stride = 0;
(int offset, VertexElement decl) posData;
// Find position within struct and buffer
{
int tempOffset = 0;
(int offset, VertexElement decl)? posDataNullable = null;
foreach (var elemDecl in bufferBinding.Declaration.VertexElements)
{
if (elemDecl.SemanticName.Equals("POSITION", StringComparison.Ordinal))
{
posDataNullable = (tempOffset, elemDecl);
}

// Get new offset (if specified)
var currentElementOffset = elemDecl.AlignedByteOffset;
if (currentElementOffset != VertexElement.AppendAligned)
tempOffset = currentElementOffset;

var elementSize = elemDecl.Format.SizeInBytes();

// Compute next offset (if automatic)
tempOffset += elementSize;

stride = Math.Max(stride, tempOffset); // element are not necessary ordered by increasing offsets
}

if (posDataNullable == null)
throw new Exception($"No position data within {mesh}'s {nameof(mesh.Draw.VertexBuffers)}");

posData = posDataNullable.Value;
}

// Fetch vertex position data from GPU
unsafe
{
fixed (byte* window = &gpuWindow[0])
{
var sizeInBytes = bufferBinding.Buffer.Description.SizeInBytes;
var elementCount = bufferBinding.Count;

FetchBufferData(bufferBinding.Buffer, commandList, new DataPointer(window, sizeInBytes));

byte* start = window + bufferBinding.Offset;

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

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

for (int i = 0; i < vertices.Length; i++)
{
localRotation.Rotate(ref vertices[i]);
vertices[i] += localPosition;
}

return new StaticMeshColliderShape(vertices, indices, scale);
}

static unsafe void FetchBufferData(Graphics.Buffer buffer, CommandList commandList, DataPointer ptr)
{
if (buffer.Description.Usage == GraphicsResourceUsage.Staging)
{
// Directly if this is a staging resource
buffer.GetData(commandList, buffer, ptr);
}
else
{
// Unefficient way to use the Copy method using dynamic staging texture
using (var throughStaging = buffer.ToStaging())
buffer.GetData(commandList, throughStaging, ptr);
}
}

public override MeshDraw CreateDebugPrimitive(GraphicsDevice device)
{
var verts = new VertexPositionNormalTexture[vertices.Length];
@@ -235,7 +61,6 @@ public override MeshDraw CreateDebugPrimitive(GraphicsDevice device)
return new GeometricPrimitive(device, meshData).ToMeshDraw();
}


class XenkoToBulletWrapper : ICollection<BulletSharp.Math.Vector3>
{
ICollection<Vector3> internalColl;

0 comments on commit 05421ae

Please sign in to comment.
You can’t perform that action at this time.