Пример #1
0
        public bool RayIntersectsWithCuboid(Cuboidf selectionBox, double posX, double posY, double posZ)
        {
            if (selectionBox == null)
            {
                return(false);
            }

            tmpCuboidd.Set(selectionBox).Translate(posX, posY, posZ);
            return(RayIntersectsWithCuboid(tmpCuboidd, ref hitOnBlockFace, ref hitPosition));
        }
Пример #2
0
 /// <summary>
 /// Sets the minimum and maximum values of the cuboid
 /// </summary>
 public Cuboidd Set(Cuboidf selectionBox)
 {
     this.X1 = selectionBox.X1;
     this.Y1 = selectionBox.Y1;
     this.Z1 = selectionBox.Z1;
     this.X2 = selectionBox.X2;
     this.Y2 = selectionBox.Y2;
     this.Z2 = selectionBox.Z2;
     return(this);
 }
Пример #3
0
 /// <summary>
 /// Sets the cuboid to the selectionBox, translated by vec
 /// </summary>
 public Cuboidd SetAndTranslate(Cuboidf selectionBox, Vec3d vec)
 {
     this.X1 = selectionBox.X1 + vec.X;
     this.Y1 = selectionBox.Y1 + vec.Y;
     this.Z1 = selectionBox.Z1 + vec.Z;
     this.X2 = selectionBox.X2 + vec.X;
     this.Y2 = selectionBox.Y2 + vec.Y;
     this.Z2 = selectionBox.Z2 + vec.Z;
     return(this);
 }
Пример #4
0
        /// <summary>
        /// Returns the shortest horizontal distance to any point between this and given cuboid
        /// </summary>
        public double ShortestHorizontalDistanceFrom(Cuboidf cuboid, BlockPos offset)
        {
            double cx = offset.X + cuboid.X1 - GameMath.Clamp(offset.X + cuboid.X1, X1, X2);
            double cz = offset.Z + cuboid.Z1 - GameMath.Clamp(offset.Z + cuboid.Z1, Z1, Z2);

            double dx = offset.X + cuboid.X2 - GameMath.Clamp(offset.X + cuboid.X2, X1, X2);
            double dz = offset.Z + cuboid.Z2 - GameMath.Clamp(offset.Z + cuboid.Z2, Z1, Z2);

            return(Math.Sqrt(
                       Math.Min(cx * cx, dx * dx) + Math.Min(cz * cz, dz * dz)
                       ));
        }
Пример #5
0
        /// <summary>
        /// If the given cuboid intersects with this cuboid
        /// </summary>
        public bool IntersectsOrTouches(Cuboidf other, double offsetX, double offsetY, double offsetZ)
        {
            bool isOutSide =
                X2 <other.X1 + offsetX ||
                    X1> other.X2 + offsetX ||
                Y2 <other.Y1 + offsetY ||
                    Y1> other.Y2 + offsetY ||
                Z2 <other.Z1 + offsetZ ||
                    Z1> other.Z2 + offsetZ
            ;

            return(!isOutSide);
        }
Пример #6
0
        /// <summary>
        /// If the given cuboid intersects with this cuboid
        /// </summary>
        public bool IntersectsOrTouches(Cuboidf other, Vec3d offset)
        {
            bool isOutSide =
                X2 <other.X1 + offset.X ||
                    X1> other.X2 + offset.X ||
                Y2 <other.Y1 + offset.Y ||
                    Y1> other.Y2 + offset.Y ||
                Z2 <other.Z1 + offset.Z ||
                    Z1> other.Z2 + offset.Z
            ;

            return(!isOutSide);
        }
Пример #7
0
        public static bool AabbIntersect(Cuboidf aabb, double x, double y, double z, Cuboidf aabb2, Vec3d pos)
        {
            if (aabb2 == null)
            {
                return(true);
            }

            return
                (x + aabb.X1 < aabb2.X2 + pos.X &&
                 y + aabb.Y1 < aabb2.Y2 + pos.Y &&
                 z + aabb.Z1 < aabb2.Z2 + pos.Z &&
                 x + aabb.X2 > aabb2.X1 + pos.X &&
                 y + aabb.Y2 > aabb2.Y1 + pos.Y &&
                 z + aabb.Z2 > aabb2.Z1 + pos.Z
                );
        }
Пример #8
0
        /// <summary>
        /// If the given cuboid intersects with this cuboid
        /// </summary>
        public bool IntersectsOrTouches(Cuboidf other, Vec3d offset)
        {
            // For performance, this is a conditional statement with && conjunction: the conditional will fail early if any is false
            if (X2 >= other.X1 + offset.X &&
                X1 <= other.X2 + offset.X &&
                Z2 >= other.Z1 + offset.Z &&
                Z1 <= other.Z2 + offset.Z &&
                Y2 >= other.Y1 + offset.Y &&
                Y1 <= Math.Round(other.Y2 + offset.Y, 5) // Fix float/double rounding errors. Only need to fix the vertical because gravity. Thankfully we don't have horizontal gravity.
                )
            {
                return(true);
            }

            return(false);
        }
Пример #9
0
        /// <summary>
        /// Tests given cuboidf collides with the terrain. By default also checks if the cuboid is merely touching the terrain, set alsoCheckTouch to disable that.
        /// </summary>
        /// <param name="blockAccessor"></param>
        /// <param name="entityBoxRel"></param>
        /// <param name="pos"></param>
        /// <param name="alsoCheckTouch"></param>
        /// <returns></returns>
        public Cuboidd GetCollidingCollisionBox(IBlockAccessor blockAccessor, Cuboidf entityBoxRel, Vec3d pos, bool alsoCheckTouch = true)
        {
            BlockPos blockPos    = new BlockPos();
            Vec3d    blockPosVec = new Vec3d();
            Cuboidd  entityBox   = entityBoxRel.ToDouble().Translate(pos);

            entityBox.Y1 = Math.Round(entityBox.Y1, 5); // Fix float/double rounding errors. Only need to fix the vertical because gravity.

            int minX = (int)(entityBoxRel.X1 + pos.X);
            int minY = (int)(entityBoxRel.Y1 + pos.Y - 1);  // -1 for the extra high collision box of fences
            int minZ = (int)(entityBoxRel.Z1 + pos.Z);
            int maxX = (int)Math.Ceiling(entityBoxRel.X2 + pos.X);
            int maxY = (int)Math.Ceiling(entityBoxRel.Y2 + pos.Y);
            int maxZ = (int)Math.Ceiling(entityBoxRel.Z2 + pos.Z);

            for (int y = minY; y <= maxY; y++)
            {
                for (int x = minX; x <= maxX; x++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        Block block = blockAccessor.GetBlock(x, y, z);
                        blockPos.Set(x, y, z);
                        blockPosVec.Set(x, y, z);

                        Cuboidf[] collisionBoxes = block.GetCollisionBoxes(blockAccessor, blockPos);

                        for (int i = 0; collisionBoxes != null && i < collisionBoxes.Length; i++)
                        {
                            Cuboidf collBox = collisionBoxes[i];
                            if (collBox == null)
                            {
                                continue;
                            }

                            bool colliding = alsoCheckTouch ? entityBox.IntersectsOrTouches(collBox, blockPosVec) : entityBox.Intersects(collBox, blockPosVec);
                            if (colliding)
                            {
                                return(collBox.ToDouble().Translate(blockPos));
                            }
                        }
                    }
                }
            }

            return(null);
        }
Пример #10
0
        public Block GetCollidingBlock(IBlockAccessor blockAccessor, Cuboidf entityBoxRel, Vec3d pos, bool alsoCheckTouch = true)
        {
            Cuboidd entityBox = tmpBox.SetAndTranslate(entityBoxRel, pos);

            int minX = (int)(entityBox.X1);
            int minY = (int)(entityBox.Y1) - 1;  // -1 for the extra high collision box of fences
            int minZ = (int)(entityBox.Z1);

            int maxX = (int)(entityBox.X2);
            int maxY = (int)(entityBox.Y2);
            int maxZ = (int)(entityBox.Z2);

            for (int y = minY; y <= maxY; y++)
            {
                for (int x = minX; x <= maxX; x++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        Block block = blockAccessor.GetBlock(x, y, z);
                        blockPos.Set(x, y, z);

                        Cuboidf[] collisionBoxes = block.GetCollisionBoxes(blockAccessor, blockPos);
                        if (collisionBoxes == null || collisionBoxes.Length == 0)
                        {
                            continue;
                        }

                        blockPosVec.Set(x, y, z);
                        for (int i = 0; i < collisionBoxes.Length; i++)
                        {
                            Cuboidf collBox = collisionBoxes[i];
                            if (collBox == null)
                            {
                                continue;
                            }

                            if (alsoCheckTouch ? entityBox.IntersectsOrTouches(collBox, blockPosVec) : entityBox.Intersects(collBox, blockPosVec))
                            {
                                return(block);
                            }
                        }
                    }
                }
            }

            return(null);
        }
Пример #11
0
        /// <summary>
        /// Tests given cuboidf collides with the terrain. By default also checks if the cuboid is merely touching the terrain, set alsoCheckTouch to disable that.
        /// </summary>
        /// <param name="blockAccessor"></param>
        /// <param name="entityBoxRel"></param>
        /// <param name="pos"></param>
        /// <param name="alsoCheckTouch"></param>
        /// <returns></returns>
        public bool GetCollidingCollisionBox(IBlockAccessor blockAccessor, Cuboidf entityBoxRel, Vec3d pos, ref Cuboidd intoCubuid, bool alsoCheckTouch = true)
        {
            BlockPos blockPos    = new BlockPos();
            Vec3d    blockPosVec = new Vec3d();
            Cuboidd  entityBox   = entityBoxRel.ToDouble().Translate(pos);

            int minX = (int)(entityBoxRel.X1 + pos.X);
            int minY = (int)(entityBoxRel.Y1 + pos.Y - 1);  // -1 for the extra high collision box of fences
            int minZ = (int)(entityBoxRel.Z1 + pos.Z);
            int maxX = (int)Math.Ceiling(entityBoxRel.X2 + pos.X);
            int maxY = (int)Math.Ceiling(entityBoxRel.Y2 + pos.Y);
            int maxZ = (int)Math.Ceiling(entityBoxRel.Z2 + pos.Z);

            for (int y = minY; y <= maxY; y++)
            {
                for (int x = minX; x <= maxX; x++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        Block block = blockAccessor.GetBlock(x, y, z);
                        blockPos.Set(x, y, z);
                        blockPosVec.Set(x, y, z);

                        Cuboidf[] collisionBoxes = block.GetCollisionBoxes(blockAccessor, blockPos);

                        for (int i = 0; collisionBoxes != null && i < collisionBoxes.Length; i++)
                        {
                            Cuboidf collBox = collisionBoxes[i];
                            if (collBox == null)
                            {
                                continue;
                            }

                            bool colliding = alsoCheckTouch ? entityBox.IntersectsOrTouches(collBox, blockPosVec) : entityBox.Intersects(collBox, blockPosVec);
                            if (colliding)
                            {
                                intoCubuid.Set(collBox).Translate(blockPos);
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Пример #12
0
        /// <summary>
        /// Returns the shortest distance to any point between this and given cuboid
        /// </summary>
        public double ShortestVerticalDistanceFrom(Cuboidf cuboid, EntityPos offset)
        {
            double oY1 = offset.Y + cuboid.Y1;
            double oY2 = offset.Y + cuboid.Y2;

            double cy = oY1 - GameMath.Clamp(oY1, Y1, Y2);

            // Test if inside
            if (oY1 <= Y1 && oY2 >= Y2)
            {
                cy = 0;
            }

            double dy = oY2 - GameMath.Clamp(oY2, Y1, Y2);

            return(Math.Min(cy, dy));
        }
Пример #13
0
        /// <summary>
        /// Returns the shortest distance to any point between this and given cuboid
        /// </summary>
        public double ShortestDistanceFrom(Cuboidf cuboid, BlockPos offset)
        {
            double oX1 = offset.X + cuboid.X1;
            double oY1 = offset.Y + cuboid.Y1;
            double oZ1 = offset.Z + cuboid.Z1;

            double oX2 = offset.X + cuboid.X2;
            double oY2 = offset.Y + cuboid.Y2;
            double oZ2 = offset.Z + cuboid.Z2;


            double cx = oX1 - GameMath.Clamp(oX1, X1, X2);
            double cy = oY1 - GameMath.Clamp(oY1, Y1, Y2);
            double cz = oZ1 - GameMath.Clamp(oZ1, Z1, Z2);

            // Test if inside
            if (oX1 <= X1 && oX2 >= X2)
            {
                cx = 0;
            }
            if (oY1 <= Y1 && oY2 >= Y2)
            {
                cy = 0;
            }
            if (oZ1 <= Z1 && oZ2 >= Z2)
            {
                cz = 0;
            }

            double dx = oX2 - GameMath.Clamp(oX2, X1, X2);
            double dy = oY2 - GameMath.Clamp(oY2, Y1, Y2);
            double dz = oZ2 - GameMath.Clamp(oZ2, Z1, Z2);

            return(Math.Sqrt(
                       Math.Min(cx * cx, dx * dx) + Math.Min(cy * cy, dy * dy) + Math.Min(cz * cz, dz * dz)
                       ));
        }
Пример #14
0
 /// <summary>
 /// Tests given cuboidf collides with the terrain. By default also checks if the cuboid is merely touching the terrain, set alsoCheckTouch to disable that.
 /// </summary>
 /// <param name="blockAccessor"></param>
 /// <param name="entityBoxRel"></param>
 /// <param name="pos"></param>
 /// <param name="alsoCheckTouch"></param>
 /// <returns></returns>
 public bool IsColliding(IBlockAccessor blockAccessor, Cuboidf entityBoxRel, Vec3d pos, bool alsoCheckTouch = true)
 {
     return(GetCollidingBlock(blockAccessor, entityBoxRel, pos, alsoCheckTouch) != null);
 }
Пример #15
0
        private BlockFacing(string code, byte flag, int index, int oppositeIndex, int horizontalAngleIndex, Vec3i facingVector, Vec3f planeCenter, EnumAxis axis, Cuboidf plane)
        {
            this.index                = index;
            this.meshDataIndex        = (byte)(index + 1);
            this.horizontalAngleIndex = horizontalAngleIndex;
            this.flag          = flag;
            this.code          = code;
            this.oppositeIndex = oppositeIndex;
            this.normali       = facingVector;
            this.normalf       = new Vec3f(facingVector.X, facingVector.Y, facingVector.Z);
            this.normald       = new Vec3d((double)facingVector.X, (double)facingVector.Y, (double)facingVector.Z);
            this.plane         = plane;

            normalPacked = NormalUtil.PackNormal(normalf.X, normalf.Y, normalf.Z);
            normalb      = (byte)(
                (axis == EnumAxis.Z ? 1 : 0) << 0
                    | (facingVector.Z < 0 ? 1 : 0) << 1

                    | (axis == EnumAxis.Y ? 1 : 0) << 2
                    | (facingVector.Y < 0 ? 1 : 0) << 3

                    | (axis == EnumAxis.X ? 1 : 0) << 4
                    | (facingVector.X < 0 ? 1 : 0) << 5
                );

            normalPackedFlags = VertexFlags.PackNormal(normalf);

            this.planeCenter = planeCenter;
            this.axis        = axis;
        }