Skip to content

Commit 44565ac

Browse files
Eiderenxen2
authored andcommitted
fix: Multiple model collision issues with more complex meshes
1 parent 9e873cc commit 44565ac

File tree

3 files changed

+103
-27
lines changed

3 files changed

+103
-27
lines changed

sources/engine/Stride.BepuPhysics/Stride.BepuPhysics/Systems/CollidableGizmo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ private void PrepareModels()
112112
var bepuShapeCacheSys = _services.GetOrCreate<ShapeCacheSystem>();
113113
var graphicsDevice = _services.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice;
114114

115-
if (_component.Collider is MeshCollider meshCollider && (meshCollider.Model.Meshes.Count == 0 || meshCollider.Model == null!/*May be null in editor*/))
115+
if (_component.Collider is MeshCollider meshCollider && (meshCollider.Model == null!/*May be null in editor*/ || meshCollider.Model.Meshes.Count == 0))
116116
{
117117
// It looks like meshes take some time before being filled in by the editor ... ?
118118
// Schedule it for later

sources/engine/Stride.BepuPhysics/Stride.BepuPhysics/Systems/ShapeCacheSystem.cs

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ private static void ExtractHull(DecomposedHulls hullDesc, out VertexPosition3[]
139139

140140
internal static unsafe BepuUtilities.Memory.Buffer<Triangle> ExtractBepuMesh(Model model, IServiceRegistry services, BufferPool pool)
141141
{
142+
var nodeTransforms = ExtractNodeTransforms(model);
143+
142144
int totalIndices = 0;
143145
foreach (var meshData in model.Meshes)
144146
{
@@ -148,13 +150,24 @@ internal static unsafe BepuUtilities.Memory.Buffer<Triangle> ExtractBepuMesh(Mod
148150
pool.Take<Triangle>(totalIndices / 3, out var triangles);
149151
var bepuTriangles = triangles.As<Vector3>();
150152
var spanLeft = new Span<Vector3>(bepuTriangles.Memory, bepuTriangles.Length);
151-
foreach (var mesh in model.Meshes)
153+
foreach (var meshData in model.Meshes)
152154
{
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);
155+
meshData.Draw.IndexBuffer.AsReadable(services, out var indexHelper, out int indexCount);
156+
meshData.Draw.VertexBuffers[0].AsReadable(services, out var vertexHelper, out int vertexCount);
155157

156158
var copyJob = new VertexBufferHelper.CopyAsTriangleList { IndexBufferHelper = indexHelper };
157-
vertexHelper.Read<PositionSemantic, Vector3, VertexBufferHelper.CopyAsTriangleList>(spanLeft[..indexCount], copyJob);
159+
var vertSlice = spanLeft[..indexCount];
160+
vertexHelper.Read<PositionSemantic, Vector3, VertexBufferHelper.CopyAsTriangleList>(vertSlice, copyJob);
161+
162+
if (nodeTransforms != null)
163+
{
164+
for (int i = 0; i < vertSlice.Length; i++)
165+
{
166+
Matrix posMatrix = Matrix.Translation(vertSlice[i]);
167+
Matrix.Multiply(ref posMatrix, ref nodeTransforms[meshData.NodeIndex], out var finalMatrix);
168+
vertSlice[i] = finalMatrix.TranslationVector;
169+
}
170+
}
158171

159172
spanLeft = spanLeft[indexCount..];
160173
}
@@ -164,30 +177,87 @@ internal static unsafe BepuUtilities.Memory.Buffer<Triangle> ExtractBepuMesh(Mod
164177

165178
private static void ExtractMeshBuffers(Model model, IServiceRegistry services, out VertexPosition3[] vertices, out int[] indices)
166179
{
167-
int totalVertices = 0, totalIndices = 0;
180+
var nodeTransforms = ExtractNodeTransforms(model);
181+
182+
int totalVerts = 0, totalIndices = 0;
168183
foreach (var meshData in model.Meshes)
169184
{
170-
totalVertices += meshData.Draw.VertexBuffers[0].Count;
185+
totalVerts += meshData.Draw.VertexBuffers[0].Count;
171186
totalIndices += meshData.Draw.IndexBuffer.Count;
172187
}
173188

174-
vertices = new VertexPosition3[totalVertices];
175-
indices = new int[totalIndices];
189+
var combinedVerts = new VertexPosition3[totalVerts];
190+
var combinedIndices = new int[totalIndices];
191+
var verticesLeft = MemoryMarshal.Cast<VertexPosition3, Vector3>(combinedVerts.AsSpan());
192+
var indicesLeft = combinedIndices.AsSpan();
176193

177-
var verticesLeft = MemoryMarshal.Cast<VertexPosition3, Vector3>(vertices.AsSpan());
178-
var indicesLeft = indices.AsSpan();
179-
180-
foreach (var mesh in model.Meshes)
194+
int indexOffset = 0;
195+
foreach (var meshData in model.Meshes)
181196
{
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);
197+
meshData.Draw.VertexBuffers[0].AsReadable(services, out var vertexHelper, out var vertexCount);
198+
meshData.Draw.IndexBuffer.AsReadable(services, out var indexHelper, out var indexCount);
199+
200+
var vertSlice = verticesLeft[..vertexCount];
201+
vertexHelper.Copy<PositionSemantic, Vector3>(vertSlice);
202+
203+
if (nodeTransforms != null)
204+
{
205+
for (int i = 0; i < vertSlice.Length; i++)
206+
{
207+
Matrix posMatrix = Matrix.Translation(vertSlice[i]);
208+
Matrix.Multiply(ref posMatrix, ref nodeTransforms[meshData.NodeIndex], out var finalMatrix);
209+
vertSlice[i] = finalMatrix.TranslationVector;
210+
}
211+
}
184212

185-
vertexHelper.Copy<PositionSemantic, Vector3>(verticesLeft[..vertexCount]);
186-
indexHelper.CopyTo(indicesLeft[..indexCount]);
213+
var indicesForSlice = indicesLeft[..indexCount];
214+
indexHelper.CopyTo(indicesForSlice);
215+
for (int i = 0; i < indicesForSlice.Length; i++)
216+
indicesForSlice[i] += indexOffset;
217+
indexOffset += vertexCount;
187218

188219
verticesLeft = verticesLeft[vertexCount..];
189220
indicesLeft = indicesLeft[indexCount..];
190221
}
222+
223+
vertices = combinedVerts;
224+
indices = combinedIndices;
225+
}
226+
227+
private static Matrix[]? ExtractNodeTransforms(Model model)
228+
{
229+
Matrix[]? nodeTransforms = null;
230+
if (model.Skeleton == null)
231+
return nodeTransforms;
232+
233+
var nodesLength = model.Skeleton.Nodes.Length;
234+
nodeTransforms = new Matrix[nodesLength];
235+
nodeTransforms[0] = Matrix.Identity;
236+
for (var i = 0; i < nodesLength; i++)
237+
{
238+
var node = model.Skeleton.Nodes[i];
239+
Matrix.Transformation(ref node.Transform.Scale, ref node.Transform.Rotation, ref node.Transform.Position, out var localMatrix);
240+
241+
Matrix worldMatrix;
242+
if (node.ParentIndex != -1)
243+
{
244+
if (node.ParentIndex >= i)
245+
throw new InvalidOperationException("Skeleton nodes are not sorted");
246+
var nodeTransform = nodeTransforms[node.ParentIndex];
247+
Matrix.Multiply(ref localMatrix, ref nodeTransform, out worldMatrix);
248+
}
249+
else
250+
{
251+
worldMatrix = localMatrix;
252+
}
253+
254+
if (i != 0)
255+
{
256+
nodeTransforms[i] = worldMatrix;
257+
}
258+
}
259+
260+
return nodeTransforms;
191261
}
192262

193263
/// <summary>

sources/engine/Stride.Physics/Shapes/StaticMeshColliderShape.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,28 +158,34 @@ static SharedMeshData BuildAndShareMeshes(Model model, IServiceRegistry services
158158
var combinedIndices = new int[totalIndices];
159159
var verticesLeft = combinedVerts.AsSpan();
160160
var indicesLeft = combinedIndices.AsSpan();
161-
161+
162+
int indexOffset = 0;
162163
foreach (var meshData in model.Meshes)
163164
{
164165
meshData.Draw.VertexBuffers[0].AsReadable(services, out var vertexHelper, out var vertexCount);
165166
meshData.Draw.IndexBuffer.AsReadable(services, out var indexHelper, out var indexCount);
166167

167-
var sliceForTheseVertices = verticesLeft[..vertexCount];
168-
vertexHelper.Copy<PositionSemantic, Vector3>(sliceForTheseVertices);
169-
indexHelper.CopyTo(indicesLeft[..indexCount]);
170-
171-
verticesLeft = verticesLeft[vertexCount..];
172-
indicesLeft = indicesLeft[indexCount..];
168+
var vertSlice = verticesLeft[..vertexCount];
169+
vertexHelper.Copy<PositionSemantic, Vector3>(vertSlice);
173170

174171
if (nodeTransforms != null)
175172
{
176-
for (int i = 0; i < sliceForTheseVertices.Length; i++)
173+
for (int i = 0; i < vertSlice.Length; i++)
177174
{
178-
Matrix posMatrix = Matrix.Translation(sliceForTheseVertices[i]);
175+
Matrix posMatrix = Matrix.Translation(vertSlice[i]);
179176
Matrix.Multiply(ref posMatrix, ref nodeTransforms[meshData.NodeIndex], out var finalMatrix);
180-
sliceForTheseVertices[i] = finalMatrix.TranslationVector;
177+
vertSlice[i] = finalMatrix.TranslationVector;
181178
}
182179
}
180+
181+
var indicesForSlice = indicesLeft[..indexCount];
182+
indexHelper.CopyTo(indicesForSlice);
183+
for (int i = 0; i < indicesForSlice.Length; i++)
184+
indicesForSlice[i] += indexOffset;
185+
indexOffset += vertexCount;
186+
187+
verticesLeft = verticesLeft[vertexCount..];
188+
indicesLeft = indicesLeft[indexCount..];
183189
}
184190

185191
if (string.IsNullOrWhiteSpace(modelUrl))

0 commit comments

Comments
 (0)