136 lines
2.5 KiB
Go
136 lines
2.5 KiB
Go
package world
|
|
|
|
import (
|
|
"math"
|
|
|
|
"aego/core/mathx"
|
|
)
|
|
|
|
type (
|
|
Vec2 = mathx.Vec2
|
|
AABB = mathx.AABB2
|
|
)
|
|
|
|
const fltEpsilon float32 = 1.1920929e-7
|
|
|
|
type Rot struct {
|
|
C, S float32
|
|
}
|
|
|
|
func makeRot(a float32) Rot {
|
|
return Rot{C: mathx.Cos(a), S: mathx.Sin(a)}
|
|
}
|
|
|
|
func (q Rot) apply(v Vec2) Vec2 {
|
|
return Vec2{X: q.C*v.X - q.S*v.Y, Y: q.S*v.X + q.C*v.Y}
|
|
}
|
|
|
|
func (q Rot) invApply(v Vec2) Vec2 {
|
|
return Vec2{X: q.C*v.X + q.S*v.Y, Y: -q.S*v.X + q.C*v.Y}
|
|
}
|
|
|
|
func (q Rot) invMul(o Rot) Rot {
|
|
return Rot{C: q.C*o.C + q.S*o.S, S: q.C*o.S - q.S*o.C}
|
|
}
|
|
|
|
type xform struct {
|
|
p Vec2
|
|
q Rot
|
|
}
|
|
|
|
func identityXf() xform {
|
|
return xform{q: Rot{C: 1}}
|
|
}
|
|
|
|
func (x xform) apply(v Vec2) Vec2 {
|
|
return x.q.apply(v).Add(x.p)
|
|
}
|
|
|
|
func (x xform) invApply(v Vec2) Vec2 {
|
|
return x.q.invApply(v.Sub(x.p))
|
|
}
|
|
|
|
func invMulXf(a, b xform) xform {
|
|
return xform{p: a.q.invApply(b.p.Sub(a.p)), q: a.q.invMul(b.q)}
|
|
}
|
|
|
|
func crossSV(s float32, v Vec2) Vec2 {
|
|
return Vec2{X: -s * v.Y, Y: s * v.X}
|
|
}
|
|
|
|
func crossVS(v Vec2, s float32) Vec2 {
|
|
return Vec2{X: s * v.Y, Y: -s * v.X}
|
|
}
|
|
|
|
func rightPerp(v Vec2) Vec2 {
|
|
return Vec2{X: v.Y, Y: -v.X}
|
|
}
|
|
|
|
func normalizeLen(v Vec2) (Vec2, float32) {
|
|
l := v.Len()
|
|
if l < fltEpsilon {
|
|
return Vec2{}, 0
|
|
}
|
|
return v.Scale(1 / l), l
|
|
}
|
|
|
|
func min2(a, b Vec2) Vec2 {
|
|
return Vec2{X: min(a.X, b.X), Y: min(a.Y, b.Y)}
|
|
}
|
|
|
|
func max2(a, b Vec2) Vec2 {
|
|
return Vec2{X: max(a.X, b.X), Y: max(a.Y, b.Y)}
|
|
}
|
|
|
|
func abs2(v Vec2) Vec2 {
|
|
return Vec2{X: mathx.Abs(v.X), Y: mathx.Abs(v.Y)}
|
|
}
|
|
|
|
func clampf(v, lo, hi float32) float32 {
|
|
return mathx.Clamp(v, lo, hi)
|
|
}
|
|
|
|
func finite(f float32) bool {
|
|
g := float64(f)
|
|
return !math.IsNaN(g) && !math.IsInf(g, 0)
|
|
}
|
|
|
|
func finite2(v Vec2) bool {
|
|
return finite(v.X) && finite(v.Y)
|
|
}
|
|
|
|
func boxOverlap(a, b AABB) bool {
|
|
return a.Min.X <= b.Max.X && b.Min.X <= a.Max.X && a.Min.Y <= b.Max.Y && b.Min.Y <= a.Max.Y
|
|
}
|
|
|
|
func boxContains(outer, inner AABB) bool {
|
|
return outer.Min.X <= inner.Min.X && outer.Min.Y <= inner.Min.Y && inner.Max.X <= outer.Max.X && inner.Max.Y <= outer.Max.Y
|
|
}
|
|
|
|
func boxPerimeter(a AABB) float32 {
|
|
return 2 * ((a.Max.X - a.Min.X) + (a.Max.Y - a.Min.Y))
|
|
}
|
|
|
|
func boxUnion(a, b AABB) AABB {
|
|
return AABB{Min: min2(a.Min, b.Min), Max: max2(a.Max, b.Max)}
|
|
}
|
|
|
|
func boxExpand(a AABB, m float32) AABB {
|
|
return AABB{Min: Vec2{X: a.Min.X - m, Y: a.Min.Y - m}, Max: Vec2{X: a.Max.X + m, Y: a.Max.Y + m}}
|
|
}
|
|
|
|
func boxSweep(a AABB, d Vec2) AABB {
|
|
b := a
|
|
if d.X < 0 {
|
|
b.Min.X += d.X
|
|
} else {
|
|
b.Max.X += d.X
|
|
}
|
|
if d.Y < 0 {
|
|
b.Min.Y += d.Y
|
|
} else {
|
|
b.Max.Y += d.Y
|
|
}
|
|
return b
|
|
}
|