Major collision refactor to correct AABB system
This commit is contained in:
231
AABB.cs
231
AABB.cs
@@ -1,9 +1,4 @@
|
||||
using OpenTK.Mathematics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Voxel
|
||||
{
|
||||
@@ -18,12 +13,53 @@ namespace Voxel
|
||||
Max = max;
|
||||
}
|
||||
|
||||
public AABB Copy()
|
||||
{
|
||||
return new AABB(Min, Max);
|
||||
}
|
||||
|
||||
public static AABB FromCenter(Vector3 center, float width, float height, float depth)
|
||||
{
|
||||
Vector3 half = new Vector3(width / 2f, 0, depth / 2f);
|
||||
return new AABB(center - half, center + new Vector3(half.X, height, half.Z));
|
||||
}
|
||||
|
||||
public AABB Expand(float x, float y, float z)
|
||||
{
|
||||
AABB returnValue = Copy();
|
||||
|
||||
if (x > 0)
|
||||
returnValue.Max.X += x;
|
||||
else
|
||||
returnValue.Min.X += x;
|
||||
|
||||
if (y > 0)
|
||||
returnValue.Max.Y += y;
|
||||
else
|
||||
returnValue.Min.Y += y;
|
||||
|
||||
if (z > 0)
|
||||
returnValue.Max.Z += z;
|
||||
else
|
||||
returnValue.Min.Z += z;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public AABB Grow(float x, float y, float z)
|
||||
{
|
||||
AABB returnValue = Copy();
|
||||
|
||||
returnValue.Min.X -= x;
|
||||
returnValue.Min.Y -= y;
|
||||
returnValue.Min.Z -= z;
|
||||
returnValue.Max.X += x;
|
||||
returnValue.Max.Y += y;
|
||||
returnValue.Max.Z += z;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void Move(float x, float y, float z)
|
||||
{
|
||||
Min.X += x;
|
||||
@@ -34,26 +70,6 @@ namespace Voxel
|
||||
Max.Z += z;
|
||||
}
|
||||
|
||||
public bool Intersects(AABB other)
|
||||
{
|
||||
return IntersectsX(other) && IntersectsY(other) && IntersectsZ(other);
|
||||
}
|
||||
|
||||
public bool IntersectsX(AABB other)
|
||||
{
|
||||
return Min.X < other.Max.X && Max.X > other.Max.X;
|
||||
}
|
||||
|
||||
public bool IntersectsY(AABB other)
|
||||
{
|
||||
return Min.Y < other.Max.Y && Max.Y > other.Max.Y;
|
||||
}
|
||||
|
||||
public bool IntersectsZ(AABB other)
|
||||
{
|
||||
return Min.Z < other.Max.Z && Max.Z > other.Max.Z;
|
||||
}
|
||||
|
||||
public bool Contains(Vector3 point)
|
||||
{
|
||||
return (point.X >= Min.X && point.X <= Max.X) &&
|
||||
@@ -61,151 +77,90 @@ namespace Voxel
|
||||
(point.Z >= Min.Z && point.Z <= Max.Z);
|
||||
}
|
||||
|
||||
public float GetClipX(AABB other, float deltaX)
|
||||
public bool IntersectsX(AABB against)
|
||||
{
|
||||
if (IntersectsY(other) && IntersectsZ(other))
|
||||
return Min.X < against.Max.X && Max.X > against.Min.X;
|
||||
}
|
||||
|
||||
public bool IntersectsY(AABB against)
|
||||
{
|
||||
return Min.Y < against.Max.Y && Max.Y > against.Min.Y;
|
||||
}
|
||||
|
||||
public bool IntersectsZ(AABB against)
|
||||
{
|
||||
return Min.Z < against.Max.Z && Max.Z > against.Min.Z;
|
||||
}
|
||||
|
||||
public bool Intersects(AABB against)
|
||||
{
|
||||
return IntersectsX(against) && IntersectsY(against) && IntersectsZ(against);
|
||||
}
|
||||
|
||||
public float GetClipX(AABB against, float deltaX)
|
||||
{
|
||||
if (IntersectsY(against) && IntersectsZ(against))
|
||||
{
|
||||
if (deltaX > 0 && Max.X <= other.Min.X)
|
||||
if (deltaX > 0 && Max.X <= against.Min.X)
|
||||
{
|
||||
float clip = other.Min.X - other.Min.X;
|
||||
|
||||
if (deltaX > clip)
|
||||
deltaX = clip;
|
||||
float clip = against.Min.X - Max.X;
|
||||
if (deltaX > clip) deltaX = clip;
|
||||
}
|
||||
|
||||
if (deltaX < 0 && Min.X >= other.Max.X)
|
||||
if (deltaX < 0 && Min.X >= against.Max.X)
|
||||
{
|
||||
float clip = other.Max.X - Max.X;
|
||||
if (deltaX < clip)
|
||||
deltaX = clip;
|
||||
float clip = against.Max.X - Min.X;
|
||||
if (deltaX < clip) deltaX = clip;
|
||||
}
|
||||
return deltaX;
|
||||
}
|
||||
return deltaX;
|
||||
}
|
||||
public float GetClipY(AABB other, float deltaY)
|
||||
|
||||
public float GetClipY(AABB against, float deltaY)
|
||||
{
|
||||
if (IntersectsX(other) && IntersectsZ(other))
|
||||
if (IntersectsX(against) && IntersectsZ(against))
|
||||
{
|
||||
if (deltaY > 0 && Max.Y <= other.Min.Y)
|
||||
if (deltaY > 0 && Max.Y <= against.Min.Y)
|
||||
{
|
||||
float clip = other.Min.Y - other.Min.Y;
|
||||
|
||||
if (deltaY > clip)
|
||||
deltaY = clip;
|
||||
float clip = against.Min.Y - Max.Y;
|
||||
if (deltaY > clip) deltaY = clip;
|
||||
}
|
||||
|
||||
if (deltaY < 0 && Min.X >= other.Max.X)
|
||||
if (deltaY < 0 && Min.Y >= against.Max.Y)
|
||||
{
|
||||
float clip = other.Max.X - Max.X;
|
||||
if (deltaY < clip)
|
||||
deltaY = clip;
|
||||
float clip = against.Max.Y - Min.Y;
|
||||
if (deltaY < clip) deltaY = clip;
|
||||
}
|
||||
return deltaY;
|
||||
}
|
||||
return deltaY;
|
||||
}
|
||||
public float GetClipZ(AABB other, float deltaZ)
|
||||
|
||||
public float GetClipZ(AABB against, float deltaZ)
|
||||
{
|
||||
if (IntersectsX(other) && IntersectsY(other))
|
||||
if (IntersectsX(against) && IntersectsY(against))
|
||||
{
|
||||
if (deltaZ > 0 && Max.Z <= other.Min.Z)
|
||||
if (deltaZ > 0 && Max.Z <= against.Min.Z)
|
||||
{
|
||||
float clip = other.Min.Z - other.Min.Z;
|
||||
|
||||
if (deltaZ > clip)
|
||||
deltaZ = clip;
|
||||
float clip = against.Min.Z - Max.Z;
|
||||
if (deltaZ > clip) deltaZ = clip;
|
||||
}
|
||||
|
||||
if (deltaZ < 0 && Min.Z >= other.Max.Z)
|
||||
if (deltaZ < 0 && Min.Z >= against.Max.Z)
|
||||
{
|
||||
float clip = other.Max.Z - Max.Z;
|
||||
if (deltaZ < clip)
|
||||
deltaZ = clip;
|
||||
float clip = against.Max.Z - Min.Z;
|
||||
if (deltaZ < clip) deltaZ = clip;
|
||||
}
|
||||
return deltaZ;
|
||||
}
|
||||
return deltaZ;
|
||||
}
|
||||
|
||||
public float GetBlockClipX(int blockX, int blockY, int blockZ, float deltaX)
|
||||
public Vector3 GetCenter()
|
||||
{
|
||||
// Use the current AABB as the collider (no new allocation)
|
||||
AABB collider = this;
|
||||
|
||||
// Block bounds
|
||||
float blockMinX = blockX;
|
||||
float blockMaxX = blockX + 1;
|
||||
|
||||
// Quick reject: if player is not overlapping the block in Y and Z, no collision.
|
||||
if (!(collider.Min.Y < blockY + 1 && collider.Max.Y > blockY) ||
|
||||
!(collider.Min.Z < blockZ + 1 && collider.Max.Z > blockZ))
|
||||
return deltaX;
|
||||
|
||||
// Moving right (positive delta)
|
||||
if (deltaX > 0 && collider.Max.X <= blockMinX)
|
||||
{
|
||||
float clip = blockMinX - collider.Max.X;
|
||||
if (deltaX > clip) deltaX = clip;
|
||||
}
|
||||
// Moving left (negative delta)
|
||||
else if (deltaX < 0 && collider.Min.X >= blockMaxX)
|
||||
{
|
||||
float clip = blockMaxX - collider.Min.X; // negative distance
|
||||
if (deltaX < clip) deltaX = clip;
|
||||
}
|
||||
|
||||
return deltaX;
|
||||
}
|
||||
|
||||
public float GetBlockClipY(int blockX, int blockY, int blockZ, float deltaY)
|
||||
{
|
||||
AABB collider = this;
|
||||
|
||||
float blockMinY = blockY;
|
||||
float blockMaxY = blockY + 1;
|
||||
|
||||
if (!(collider.Min.X < blockX + 1 && collider.Max.X > blockX) ||
|
||||
!(collider.Min.Z < blockZ + 1 && collider.Max.Z > blockZ))
|
||||
return deltaY;
|
||||
|
||||
if (deltaY > 0 && collider.Max.Y <= blockMinY)
|
||||
{
|
||||
float clip = blockMinY - collider.Max.Y;
|
||||
if (deltaY > clip) deltaY = clip;
|
||||
}
|
||||
else if (deltaY < 0 && collider.Min.Y >= blockMaxY)
|
||||
{
|
||||
float clip = blockMaxY - collider.Min.Y;
|
||||
if (deltaY < clip) deltaY = clip;
|
||||
}
|
||||
|
||||
return deltaY;
|
||||
}
|
||||
|
||||
public float GetBlockClipZ(int blockX, int blockY, int blockZ, float deltaZ)
|
||||
{
|
||||
AABB collider = this;
|
||||
|
||||
float blockMinZ = blockZ;
|
||||
float blockMaxZ = blockZ + 1;
|
||||
|
||||
if (!(collider.Min.X < blockX + 1 && collider.Max.X > blockX) ||
|
||||
!(collider.Min.Y < blockY + 1 && collider.Max.Y > blockY))
|
||||
return deltaZ;
|
||||
|
||||
if (deltaZ > 0 && collider.Max.Z <= blockMinZ)
|
||||
{
|
||||
float clip = blockMinZ - collider.Max.Z;
|
||||
if (deltaZ > clip) deltaZ = clip;
|
||||
}
|
||||
else if (deltaZ < 0 && collider.Min.Z >= blockMaxZ)
|
||||
{
|
||||
float clip = blockMaxZ - collider.Min.Z;
|
||||
if (deltaZ < clip) deltaZ = clip;
|
||||
}
|
||||
|
||||
return deltaZ;
|
||||
return new Vector3(
|
||||
(Min.X + Max.X) / 2,
|
||||
(Min.Y + Max.Y) / 2,
|
||||
(Min.Z + Max.Z) / 2
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user