carpy-breakout/pkg/globject/aabb.go

106 lines
2.3 KiB
Go

package globject
import (
"git.wisellama.rocks/Wisellama/carpy-breakout/pkg/math"
"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{
math.Maxf32(topRight.X(), bottomLeft.X()),
math.Maxf32(topRight.Y(), bottomLeft.Y()),
math.Maxf32(topRight.Z(), bottomLeft.Z()),
}
min := mgl32.Vec3{
math.Minf32(topRight.X(), bottomLeft.X()),
math.Minf32(topRight.Y(), bottomLeft.Y()),
math.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, mgl32.Vec3) {
intersects := make([]bool, 3)
diff1 := self.BottomLeft.Sub(other.TopRight)
diff2 := self.TopRight.Sub(other.BottomLeft)
intersects[0] = (diff1.X() <= 0) && (diff2.X() >= 0)
intersects[1] = (diff1.Y() <= 0) && (diff2.Y() >= 0)
intersects[2] = (diff1.Z() <= 0) && (diff2.Z() >= 0)
intersected := intersects[0] && intersects[1] && intersects[2]
// Calculate how much they intersected by so we can guess which
// side the collision occurred.
smallerDiff := diff1
if diff2.LenSqr() < diff1.LenSqr() {
smallerDiff = diff2
}
return intersected, math.AbsVec3(smallerDiff)
}
func XCollision(diff mgl32.Vec3) bool {
if diff.X() < diff.Y() && diff.X() < diff.Z() {
return true
}
return false
}
func YCollision(diff mgl32.Vec3) bool {
// Slight bias for vertical collisions
if diff.Y() <= diff.X() && diff.Y() <= diff.Z() {
return true
}
return false
}
func ZCollision(diff mgl32.Vec3) bool {
if diff.Z() < diff.X() && diff.Z() < diff.Y() {
return true
}
return false
}