Say you have a bunch of objects to check for collision. Say you're an enterprising hobbyist programmer learning collision physics. Say you've heard of this marvelous thing where you sort by X, Y or Z positi开发者_运维技巧on and the X, Y, or Z "worst-case" bounds which allows you to discard whole swathes of objects that "can't possibly" collide. (I haven't implemented swept/continuous collision yet, hence the quote marks).
Once that was implemented on the X-axis, I added further Z and Y filters , sorting the X, Z and Y axis lists in turn and breaking when I reached an object that could not be collided with.
That all worked rather well, although any speed increase from the last filter was negligible.
Then I thought "If I sort them on the X-axis, on the Z-axis if that check returns equivalency, then on the Y-axis if that check returns equivalency, I should be able to toss out sorting the secondary lists." This would drop about 40% from the time taken.
So I made it so. And it didn't work - Objects fell through the ground-plane. Other objects hit the ground-plane. It looked like the first set of objects fell through and all others bounced.
So, two questions - Could this work and please check my code for errors:
bodies.Sort(
(a, b) =>
{
// Should sort the list in X, then Z, then Y order.
int signX, signY, signZ;
return (signX = Math.Sign((a.LocalPosition.X - a.Bounds.X) - (b.LocalPosition.X - b.Bounds.X))) == 0 ?
(signZ = Math.Sign((a.LocalPosition.Z - a.Bounds.Z) - (b.LocalPosition.Z - b.Bounds.Z))) == 0 ?
(signY = Math.Sign((a.LocalPosition.Y - a.Bounds.Y) - (b.LocalPosition.Y - b.Bounds.Y))) == 0 ?
0 :
signY : signZ : signX;
}
);
Contact info;
List<BodyEnt> checkBodiesZ = new List<BodyEnt>();
List<BodyEnt> checkBodiesY = new List<BodyEnt>();
for (int t = 0; t < bodies.Count; ++t)
{
checkBodiesZ.Clear();
for (int t2 = t + 1; t2 < bodies.Count; ++t2)
{
// If we've reached the last object we could collide with, exit.
if (bodies[t].LocalPosition.X + bodies[t].Bounds.X <= bodies[t2].LocalPosition.X - bodies[t2].Bounds.X)
break;
checkBodiesZ.Add(bodies[t2]);
}
// checkBodiesZ.Sort((a, b) => { return Math.Sign((a.LocalPosition.Z - a.Bounds.Z) - (b.LocalPosition.Z - b.Bounds.Z)); });
checkBodiesY.Clear();
for (int t2 = 0; t2 < checkBodiesZ.Count; ++t2)
{
if (bodies[t].LocalPosition.Z + bodies[t].Bounds.Z <= checkBodiesZ[t2].LocalPosition.Z - checkBodiesZ[t2].Bounds.Z)
break;
checkBodiesY.Add(checkBodiesZ[t2]);
}
// One of the two sorts I removed in this test.
// checkBodiesY.Sort((a, b) => { return Math.Sign((a.LocalPosition.Y - a.Bounds.Y) - (b.LocalPosition.Y - b.Bounds.Y)); });
for (int t2 = 0; t2 < checkBodiesY.Count; ++t2)
{
if (bodies[t].LocalPosition.Y + bodies[t].Bounds.Y <= checkBodiesY[t2].LocalPosition.Y - checkBodiesY[t2].Bounds.Y)
break;
info = bodies[t].CheckCollision(checkBodiesY[t2]);
// .CheckCollision() returns null if no collision detected.
if (info != null)
contacts.Add(info);
}
}
Thanks. :)
精彩评论