carpy-breakout/pkg/globjects/aabb.go

110 lines
2.8 KiB
Go

package globjects
import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/mathhelpers"
"github.com/go-gl/mathgl/mgl32"
)
// AABB implements a simple Axis-Aligned Bounding Box for collision detection.
type AABB struct {
TopRight mgl32.Vec3
BottomLeft mgl32.Vec3
}
func NewAABB(topRight, bottomLeft mgl32.Vec3) *AABB {
aabb := AABB{
TopRight: topRight,
BottomLeft: bottomLeft,
}
return &aabb
}
func NewAABBFromBox(box *Box) *AABB {
xOffset := box.Width / 2.0
yOffset := box.Height / 2.0
zOffset := box.Depth / 2.0
offset := mgl32.Vec4{
xOffset,
yOffset,
zOffset,
1,
}
// Apply the rotation to the offset vector
rotatedOffset := box.GetRotationMatrix().Mul4x1(offset)
// Use the offset and the negation as the top right and bottom left
topRight := rotatedOffset
bottomLeft := rotatedOffset.Mul(-1)
// Then get the axis-align version of this box using min/max
max := mgl32.Vec3{
mathhelpers.Maxf32(topRight.X(), bottomLeft.X()),
mathhelpers.Maxf32(topRight.Y(), bottomLeft.Y()),
mathhelpers.Maxf32(topRight.Z(), bottomLeft.Z()),
}
min := mgl32.Vec3{
mathhelpers.Minf32(topRight.X(), bottomLeft.X()),
mathhelpers.Minf32(topRight.Y(), bottomLeft.Y()),
mathhelpers.Minf32(topRight.Z(), bottomLeft.Z()),
}
// Then move it into position based on the translation
pos := box.Translation
return NewAABB(max.Add(pos), min.Add(pos))
}
func (self *AABB) Intersects(other *AABB) bool {
boolArray := self.IntersectsArray(other)
intersects := boolArray[0] && boolArray[1] && boolArray[2]
return intersects
}
func (self *AABB) IntersectsArray(other *AABB) []bool {
boolArray := make([]bool, 3)
if other == nil {
return boolArray
}
boolArray[0] = self.BottomLeft.X() <= other.TopRight.X() && self.TopRight.X() >= other.BottomLeft.X()
boolArray[1] = self.BottomLeft.Y() <= other.TopRight.Y() && self.TopRight.Y() >= other.BottomLeft.Y()
boolArray[2] = self.BottomLeft.Z() <= other.TopRight.Z() && self.TopRight.Z() >= other.BottomLeft.Z()
return boolArray
}
// HorizontalCollisions returns true if the our box hit the 'other' box on the X axis.
// This is expected to be called after checking for a general intersection with Intersects()
func (self *AABB) HorizontalCollision(other *AABB) bool {
right := self.TopRight.X() - other.BottomLeft.X()
left := self.BottomLeft.X() - other.TopRight.X()
right = mathhelpers.Absf32(right)
left = mathhelpers.Absf32(left)
min := mathhelpers.Minf32(right, left)
return mathhelpers.Absf32(min) < 0.1
}
func (self *AABB) VerticalCollision(other *AABB) bool {
top := self.TopRight.Y() - other.BottomLeft.Y()
bottom := self.BottomLeft.Y() - other.TopRight.Y()
top = mathhelpers.Absf32(top)
bottom = mathhelpers.Absf32(bottom)
min := mathhelpers.Minf32(top, bottom)
return mathhelpers.Absf32(min) < 0.1
}