开发者

Theoretically-plausible collision sorting algorithm

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. :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜