예제 #1
0
        void CollideWithReachableBlocks(int count, ref AABB entityBB, ref AABB extentBB)
        {
            // Reset collision detection states
            bool wasOn = entity.onGround;

            entity.onGround = false;
            hitXMin         = false; hitYMin = false; hitZMin = false;
            hitXMax         = false; hitYMax = false; hitZMax = false;

            AABB    blockBB;
            Vector3 bPos, size = entity.Size;

            for (int i = 0; i < count; i++)
            {
                // Unpack the block and coordinate data
                State state = Searcher.stateCache[i];
                bPos.X = state.X >> 3; bPos.Y = state.Y >> 4; bPos.Z = state.Z >> 3;
                int block = (state.X & 0x7) | (state.Y & 0xF) << 3 | (state.Z & 0x7) << 7;

                blockBB.Min    = BlockInfo.MinBB[block];
                blockBB.Min.X += bPos.X; blockBB.Min.Y += bPos.Y; blockBB.Min.Z += bPos.Z;
                blockBB.Max    = BlockInfo.MaxBB[block];
                blockBB.Max.X += bPos.X; blockBB.Max.Y += bPos.Y; blockBB.Max.Z += bPos.Z;
                if (!extentBB.Intersects(blockBB))
                {
                    continue;
                }

                // Recheck time to collide with block (as colliding with blocks modifies this)
                float tx, ty, tz;
                Searcher.CalcTime(ref entity.Velocity, ref entityBB, ref blockBB, out tx, out ty, out tz);
                if (tx > 1 || ty > 1 || tz > 1)
                {
                    Utils.LogDebug("t > 1 in physics calculation.. this shouldn't have happened.");
                }

                // Calculate the location of the entity when it collides with this block
                Vector3 v = entity.Velocity;
                v.X *= tx; v.Y *= ty; v.Z *= tz;
                AABB finalBB = entityBB;
                finalBB.Min += v; finalBB.Max += v;                 // Inlined ABBB.Offset

                // if we have hit the bottom of a block, we need to change the axis we test first.
                if (!hitYMin)
                {
                    if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y)
                    {
                        ClipYMax(ref blockBB, ref entityBB, ref extentBB, ref size);
                    }
                    else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y)
                    {
                        ClipYMin(ref blockBB, ref entityBB, ref extentBB, ref size);
                    }
                    else if (finalBB.Min.X + Adjustment >= blockBB.Max.X)
                    {
                        ClipXMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                    }
                    else if (finalBB.Max.X - Adjustment <= blockBB.Min.X)
                    {
                        ClipXMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                    }
                    else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z)
                    {
                        ClipZMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                    }
                    else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z)
                    {
                        ClipZMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                    }
                    continue;
                }

                // if flying or falling, test the horizontal axes first.
                if (finalBB.Min.X + Adjustment >= blockBB.Max.X)
                {
                    ClipXMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                }
                else if (finalBB.Max.X - Adjustment <= blockBB.Min.X)
                {
                    ClipXMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                }
                else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z)
                {
                    ClipZMax(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                }
                else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z)
                {
                    ClipZMin(ref blockBB, ref entityBB, wasOn, ref finalBB, ref extentBB, ref size);
                }
                else if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y)
                {
                    ClipYMax(ref blockBB, ref entityBB, ref extentBB, ref size);
                }
                else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y)
                {
                    ClipYMin(ref blockBB, ref entityBB, ref extentBB, ref size);
                }
            }
        }
예제 #2
0
        void CollideWithReachableBlocks(int count, ref Vector3 size,
                                        ref AABB entityBB, ref AABB entityExtentBB)
        {
            bool wasOn = entity.onGround;

            entity.onGround = false;
            hitXMin         = false; hitYMin = false; hitZMin = false;
            hitXMax         = false; hitYMax = false; hitZMax = false;
            AABB blockBB = default(AABB);

            for (int i = 0; i < count; i++)
            {
                State   state    = Searcher.stateCache[i];
                Vector3 blockPos = new Vector3(state.X >> 3, state.Y >> 3, state.Z >> 3);
                int     block    = (state.X & 0x7) | (state.Y & 0x7) << 3 | (state.Z & 0x7) << 6;
                blockBB.Min = blockPos + info.MinBB[block];
                blockBB.Max = blockPos + info.MaxBB[block];
                if (!entityExtentBB.Intersects(blockBB))
                {
                    continue;
                }

                float tx = 0, ty = 0, tz = 0;
                Searcher.CalcTime(ref entity.Velocity, ref entityBB, ref blockBB, out tx, out ty, out tz);
                if (tx > 1 || ty > 1 || tz > 1)
                {
                    Utils.LogDebug("t > 1 in physics calculation.. this shouldn't have happened.");
                }

                Vector3 v = entity.Velocity;
                v.X *= tx; v.Y *= ty; v.Z *= tz;
                AABB finalBB = entityBB.Offset(v);

                // if we have hit the bottom of a block, we need to change the axis we test first.
                if (!hitYMin)
                {
                    if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y)
                    {
                        ClipYMax(ref blockBB, ref entityBB, ref entityExtentBB, ref size);
                    }
                    else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y)
                    {
                        ClipYMin(ref blockBB, ref entityBB, ref entityExtentBB, ref size);
                    }
                    else if (finalBB.Min.X + Adjustment >= blockBB.Max.X)
                    {
                        ClipXMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                    }
                    else if (finalBB.Max.X - Adjustment <= blockBB.Min.X)
                    {
                        ClipXMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                    }
                    else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z)
                    {
                        ClipZMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                    }
                    else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z)
                    {
                        ClipZMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                    }
                    continue;
                }

                // if flying or falling, test the horizontal axes first.
                if (finalBB.Min.X + Adjustment >= blockBB.Max.X)
                {
                    ClipXMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                }
                else if (finalBB.Max.X - Adjustment <= blockBB.Min.X)
                {
                    ClipXMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                }
                else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z)
                {
                    ClipZMax(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                }
                else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z)
                {
                    ClipZMin(ref blockBB, ref entityBB, wasOn, finalBB, ref entityExtentBB, ref size);
                }
                else if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y)
                {
                    ClipYMax(ref blockBB, ref entityBB, ref entityExtentBB, ref size);
                }
                else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y)
                {
                    ClipYMin(ref blockBB, ref entityBB, ref entityExtentBB, ref size);
                }
            }
        }