public IEnumerable<EntityBase> GetEntitiesWithinBoundingBoxExcludingEntity(EntityBase entity, BoundingBox boundingBox) { return (from e in Server.GetEntitiesWithinBoundingBox(boundingBox) where e != entity select e); }
/// <summary> /// Yields each <see cref="StructBlock"/> found within the bounds of a <see cref="BoundingBox"/> /// </summary> /// <param name="boundingBox"></param> /// <returns></returns> public IEnumerable<StructBlock> GetBlocksInBoundingBox(BoundingBox boundingBox) { UniversalCoords minimum = UniversalCoords.FromAbsWorld( boundingBox.Minimum.X < 0.0 ? boundingBox.Minimum.X - 1.0 : boundingBox.Minimum.X, boundingBox.Minimum.Y < 0.0 ? boundingBox.Minimum.Y - 1.0 : boundingBox.Minimum.Y, boundingBox.Minimum.Z < 0.0 ? boundingBox.Minimum.Z - 1.0 : boundingBox.Minimum.Z); UniversalCoords maximum = UniversalCoords.FromAbsWorld(boundingBox.Maximum.X + 1.0, boundingBox.Maximum.Y + 1.0, boundingBox.Maximum.Z + 1.0); return GetBlocksBetweenCoords(minimum, maximum); }
public BoundingBox[] GetCollidingBoundingBoxes(EntityBase entity, BoundingBox boundingBox) { List<BoundingBox > collidingBoundingBoxes = new List<BoundingBox>(); UniversalCoords minimumBlockXYZ = UniversalCoords.FromAbsWorld(boundingBox.Minimum.X, boundingBox.Minimum.Y, boundingBox.Minimum.Z); UniversalCoords maximumBlockXYZ = UniversalCoords.FromAbsWorld(boundingBox.Maximum.X + 1.0D, boundingBox.Maximum.Y + 1.0D, boundingBox.Maximum.Z + 1.0D); for (int x = minimumBlockXYZ.WorldX; x < maximumBlockXYZ.WorldX; x++) { for (int z = minimumBlockXYZ.WorldZ; z < maximumBlockXYZ.WorldZ; z++) { Chunk chunk = GetChunkFromWorld(x, z); if (chunk == null) continue; for (int y = minimumBlockXYZ.WorldY - 1; y < maximumBlockXYZ.WorldY; y++) { StructBlock block = chunk.GetBlock(UniversalCoords.FromWorld(x, y, z)); BlockBase blockInstance = BlockHelper.Instance(block.Type); if (blockInstance != null && blockInstance.IsCollidable) { BoundingBox blockBox = blockInstance.GetCollisionBoundingBox(block); if (blockBox.IntersectsWith(boundingBox)) { collidingBoundingBoxes.Add(blockBox); } } } } } foreach (var e in GetEntitiesWithinBoundingBoxExcludingEntity(entity, boundingBox.Expand(new Vector3(0.25, 0.25, 0.25)))) { collidingBoundingBoxes.Add(e.BoundingBox); // TODO: determine if overridable collision boxes between two entities is necessary BoundingBox? collisionBox = entity.GetCollisionBox(e); if (collisionBox != null && collisionBox.Value != e.BoundingBox && collisionBox.Value.IntersectsWith(boundingBox)) { collidingBoundingBoxes.Add(collisionBox.Value); } } return collidingBoundingBoxes.ToArray(); }
/// <summary> /// Yields an enumerable of entities where their BoundingBox intersects with <paramref name="boundingBox"/> /// </summary> /// <returns> /// The entities within bounding box. /// </returns> /// <param name='boundingBox'> /// Bounding box. /// </param> public IEnumerable<EntityBase> GetEntitiesWithinBoundingBox(BoundingBox boundingBox) { return from e in GetEntities() where e.BoundingBox.IntersectsWith(boundingBox) select e; }
public BoundingBox[] GetCollidingBoundingBoxes(EntityBase entity, BoundingBox boundingBox) { List<BoundingBox > collidingBoundingBoxes = new List<BoundingBox>(); UniversalCoords minimumBlockXYZ = UniversalCoords.FromWorld((int)Math.Floor(boundingBox.Minimum.X), (int)Math.Floor(boundingBox.Minimum.Y), (int)Math.Floor(boundingBox.Minimum.Z)); UniversalCoords maximumBlockXYZ = UniversalCoords.FromWorld((int)Math.Floor(boundingBox.Maximum.X + 1.0D), (int)Math.Floor(boundingBox.Maximum.Y + 1.0D), (int)Math.Floor(boundingBox.Maximum.Z + 1.0D)); for (int x = minimumBlockXYZ.WorldX; x < maximumBlockXYZ.WorldX; x++) { for (int z = minimumBlockXYZ.WorldZ; z < maximumBlockXYZ.WorldZ; z++) { for (int y = minimumBlockXYZ.WorldY - 1; y < maximumBlockXYZ.WorldY; y++) { byte block = this.GetBlockId(x, y, z); // TODO: this needs to move into block logic BoundingBox blockBox = new BoundingBox( new Vector3(x, y, z), new Vector3(x + 1, y + 1, z + 1) ); if (blockBox.IntersectsWith(boundingBox)) { collidingBoundingBoxes.Add(blockBox); } } } } foreach (var e in GetEntitiesWithinBoundingBoxExcludingEntity(entity, boundingBox.Expand(new Vector3(0.25, 0.25, 0.25)))) { collidingBoundingBoxes.Add(e.BoundingBox); // TODO: determine if overridable collision boxes between two entities is necessary BoundingBox? collisionBox = entity.GetCollisionBox(e); if (collisionBox != null && collisionBox.Value != e.BoundingBox && collisionBox.Value.IntersectsWith(boundingBox)) { collidingBoundingBoxes.Add(collisionBox.Value); } } return collidingBoundingBoxes.ToArray(); }
/// <summary> /// Offsets the BoundingBox with motion, with clipping based on potential collisions. /// </summary> /// <returns> /// The BoundingBox in the new location after clipping, and set motion to the actual offset used after clipping is applied. /// </returns> /// <param name='motion'> /// Motion to be applied. The value will be changed to reflect the actual offset used after clipping is applied. /// </param> /// <param name='potentialCollisions'> /// Potential collisions. /// </param> public BoundingBox OffsetWithClipping(ref Vector3 motion, BoundingBox[] potentialCollisions) { if (potentialCollisions == null || potentialCollisions.Length == 0) return this + motion; BoundingBox offsetBB = this; // If there is Y movement, calculate new Y offset for collisions // Y is calculated first to adjust for jumping height/falling before applying restrictions on X and Z if (Math.Abs(motion.Y) >= double.Epsilon) { foreach (var collision in potentialCollisions) { // If the collision is on the same X or Z axis, then adjust the Y movement if (collision.IsVectorWithinXZ(offsetBB.Minimum) || collision.IsVectorWithinXZ(offsetBB.Maximum)) { if (motion.Y > 0.0d && offsetBB.Maximum.Y <= collision.Minimum.Y) { motion.Y = Math.Min(motion.Y, collision.Minimum.Y - offsetBB.Maximum.Y); } else if (motion.Y < 0.0d && offsetBB.Minimum.Y >= collision.Maximum.Y) { motion.Y = Math.Max(motion.Y, collision.Maximum.Y - offsetBB.Minimum.Y); } } } offsetBB = offsetBB + new Vector3(0, motion.Y, 0); } // If there is an X movement, calculate new X offset for collisions if (Math.Abs(motion.X) >= double.Epsilon) { foreach (var collision in potentialCollisions) { // If the collision is on the same Y or Z axis, then adjust the X movement if (collision.IsVectorWithinYZ(offsetBB.Minimum) || collision.IsVectorWithinYZ(offsetBB.Maximum)) { if (motion.X > 0.0d && offsetBB.Maximum.X <= collision.Minimum.X) { motion.X = Math.Min(motion.X, collision.Minimum.X - offsetBB.Maximum.X); } else if (motion.X < 0.0d && offsetBB.Minimum.X >= collision.Maximum.X) { motion.X = Math.Max(motion.X, collision.Maximum.X - offsetBB.Minimum.X); } } } offsetBB = offsetBB + new Vector3(motion.X, 0, 0); } // If there is any Z movement, calculate new Z offset based on any collisions if (Math.Abs(motion.Z) >= double.Epsilon) { foreach (var collision in potentialCollisions) { // If the collision is on the same Y or Z axis, then adjust the X movement if (collision.IsVectorWithinXY(offsetBB.Minimum) || collision.IsVectorWithinXY(offsetBB.Maximum)) { if (motion.Z > 0.0d && offsetBB.Maximum.Z <= collision.Minimum.Z) { motion.Z = Math.Min(motion.Z, collision.Minimum.Z - offsetBB.Maximum.Z); } else if (motion.Z < 0.0d && offsetBB.Minimum.Z >= collision.Maximum.Z) { motion.Z = Math.Max(motion.Z, collision.Maximum.Z - offsetBB.Minimum.Z); } } } offsetBB = offsetBB + new Vector3(motion.X, 0, 0); } return offsetBB; }
/// <summary> /// Determines if this intersects with <paramref name="boundingBox"/>. /// </summary> /// <returns> /// If true the bounding boxes intersect /// </returns> /// <param name='boundingBox'> /// The bounding box to check for an intersection with /// </param> public bool IntersectsWith(BoundingBox boundingBox) { return boundingBox.Maximum.X > Minimum.X && boundingBox.Minimum.X < Maximum.X && boundingBox.Maximum.Y > Minimum.Y && boundingBox.Minimum.Y < Maximum.Y && boundingBox.Maximum.Z > Minimum.Z && boundingBox.Minimum.Z < Maximum.Z; }
public bool Equals(BoundingBox other) { return other._minimum.Equals(_minimum) && other._maximum.Equals(_maximum); }