Rename stuff. Collisions don't work right

main
Sean Hickey 2022-06-18 23:00:11 -07:00
parent 95d58d4525
commit 343a43bed3
27 changed files with 254 additions and 239 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
carpy-breakout carpy-breakout
output.log output.log
cpu.prof

View File

@ -12,6 +12,11 @@ release: linter dependencies
linter: linter:
golangci-lint run golangci-lint run
clean:
rm -f carpy-breakout
rm -f output.log
rm -f cpu.prof
cross_windows: cross_windows:
export CGO_ENABLED=1 export CGO_ENABLED=1
export CC=x86_64-w64-mingw32-gcc export CC=x86_64-w64-mingw32-gcc

View File

@ -16,6 +16,12 @@ Press `L` to toggle wireframe mode.
Press `K` to toggle freelook mode. Press `K` to toggle freelook mode.
## Coordinate System
For the code, I was using the right-hand rule (turned around) for the
3d coordinates. If you were looking straight ahead, forward is
-Z, right is +X, and up is +Y.
## Why "Carpy"? ## Why "Carpy"?
Because it's a funny misspelling of "Crappy". This was originally Because it's a funny misspelling of "Crappy". This was originally

View File

@ -1,14 +1,17 @@
package breakout package breakout
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" "log"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
"github.com/go-gl/mathgl/mgl32"
) )
type Ball struct { type Ball struct {
Box *globjects.Box Box *globject.Box
} }
func NewBall(box *globjects.Box) *Ball { func NewBall(box *globject.Box) *Ball {
ball := Ball{ ball := Ball{
Box: box, Box: box,
} }
@ -32,7 +35,7 @@ func (self *Ball) ToggleWireframe() {
self.Box.ToggleWireframe() self.Box.ToggleWireframe()
} }
func (self *Ball) GetAABB() *globjects.AABB { func (self *Ball) GetAABB() *globject.AABB {
return self.Box.GetAABB() return self.Box.GetAABB()
} }
@ -40,15 +43,15 @@ func (self *Ball) HandlePaddleCollision(paddle *Paddle) {
aabb := self.GetAABB() aabb := self.GetAABB()
p := paddle.GetAABB() p := paddle.GetAABB()
intersects := aabb.Intersects(p) intersects, diff := aabb.Intersects(p)
if intersects { if intersects {
newVelocity := self.Box.Velocity newVelocity := self.Box.Velocity
if aabb.HorizontalCollision(p) { if globject.XCollision(diff) {
newVelocity[0] = -1 * newVelocity[0] newVelocity[0] = -1 * newVelocity[0]
} }
if aabb.VerticalCollision(p) { if globject.YCollision(diff) {
// Change differently based on which part of the paddle we hit // Change differently based on which part of the paddle we hit
// TODO // TODO
newVelocity[1] = -1 * newVelocity[1] newVelocity[1] = -1 * newVelocity[1]
@ -59,49 +62,50 @@ func (self *Ball) HandlePaddleCollision(paddle *Paddle) {
} }
func (self *Ball) HandleTargetCollisions(targets *Targets) { func (self *Ball) HandleTargetCollisions(targets *Targets) {
intersects := false
aabb := self.GetAABB() aabb := self.GetAABB()
for _, brick := range targets.Bricks { for _, brick := range targets.Bricks {
if !brick.Broken() { if !brick.Broken() {
b := brick.GetAABB() b := brick.GetAABB()
intersects = aabb.Intersects(b) intersects, diff := aabb.Intersects(b)
if intersects { if intersects {
// TODO points // TODO points
brick.Break() brick.Break()
self.UpdateVelocityFromCollision(aabb, b) self.UpdateElasticCollision(diff)
} }
} }
} }
} }
func (self *Ball) HandleSideWallsCollisions(sidewalls *SideWalls) { func (self *Ball) HandleSideWallsCollisions(sidewalls *SideWalls) {
intersects := false
aabb := self.GetAABB() aabb := self.GetAABB()
boxes := sidewalls.Boxes boxes := sidewalls.Boxes
for _, box := range boxes { for _, box := range boxes {
b := box.GetAABB() b := box.GetAABB()
intersects = aabb.Intersects(b) intersects, diff := aabb.Intersects(b)
if intersects { if intersects {
self.UpdateVelocityFromCollision(aabb, b) self.UpdateElasticCollision(diff)
} }
} }
} }
func (self *Ball) UpdateVelocityFromCollision(us, them *globjects.AABB) { func (self *Ball) UpdateElasticCollision(diff mgl32.Vec3) {
newVelocity := self.Box.Velocity newVelocity := self.Box.Velocity
if us.HorizontalCollision(them) { if globject.XCollision(diff) {
log.Printf("X collision: %v\n", diff)
newVelocity[0] = -1 * newVelocity[0] newVelocity[0] = -1 * newVelocity[0]
} }
if us.VerticalCollision(them) { if globject.YCollision(diff) {
log.Printf("Y collision: %v\n", diff)
newVelocity[1] = -1 * newVelocity[1] newVelocity[1] = -1 * newVelocity[1]
} }
// No Z collisions for this game
self.Box.Velocity = newVelocity self.Box.Velocity = newVelocity
} }

View File

@ -1,12 +1,12 @@
package breakout package breakout
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
type Brick struct { type Brick struct {
Box *globjects.Box Box *globject.Box
broken bool broken bool
} }
@ -15,10 +15,10 @@ func NewBrick(
brickHeight float32, brickHeight float32,
brickDepth float32, brickDepth float32,
position mgl32.Vec3, position mgl32.Vec3,
material *globjects.Material) *Brick { material *globject.Material) *Brick {
brick := Brick{ brick := Brick{
Box: globjects.NewBox(brickWidth, brickHeight, brickDepth, position, material), Box: globject.NewBox(brickWidth, brickHeight, brickDepth, position, material),
broken: false, broken: false,
} }
return &brick return &brick
@ -42,7 +42,7 @@ func (b *Brick) ToggleWireframe() {
b.Box.ToggleWireframe() b.Box.ToggleWireframe()
} }
func (b *Brick) GetAABB() *globjects.AABB { func (b *Brick) GetAABB() *globject.AABB {
return b.Box.GetAABB() return b.Box.GetAABB()
} }
@ -53,7 +53,7 @@ func (b *Brick) Broken() bool {
func (b *Brick) Break() { func (b *Brick) Break() {
b.broken = true b.broken = true
clear := globjects.NewMaterial() clear := globject.NewMaterial()
clear.Color = mgl32.Vec4{0, 0, 0, 0} clear.Color = mgl32.Vec4{0, 0, 0, 0}
clear.Shininess = 0 clear.Shininess = 0

View File

@ -1,9 +1,9 @@
package breakout package breakout
import "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" import "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
type Paddle struct { type Paddle struct {
Box *globjects.Box Box *globject.Box
} }
func (self *Paddle) Update() { func (self *Paddle) Update() {
@ -22,11 +22,11 @@ func (self *Paddle) ToggleWireframe() {
self.Box.ToggleWireframe() self.Box.ToggleWireframe()
} }
func (self *Paddle) GetAABB() *globjects.AABB { func (self *Paddle) GetAABB() *globject.AABB {
return self.Box.GetAABB() return self.Box.GetAABB()
} }
func NewPaddle(box *globjects.Box) *Paddle { func NewPaddle(box *globject.Box) *Paddle {
paddle := Paddle{ paddle := Paddle{
Box: box, Box: box,
} }

View File

@ -1,15 +1,15 @@
package breakout package breakout
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
type SideWalls struct { type SideWalls struct {
Boxes []*globjects.Box Boxes []*globject.Box
} }
func NewSideWalls(aabb *globjects.AABB, material *globjects.Material) *SideWalls { func NewSideWalls(aabb *globject.AABB, material *globject.Material) *SideWalls {
topRight := aabb.TopRight topRight := aabb.TopRight
bottomLeft := aabb.BottomLeft bottomLeft := aabb.BottomLeft
@ -18,23 +18,23 @@ func NewSideWalls(aabb *globjects.AABB, material *globjects.Material) *SideWalls
var height float32 = 4.0 var height float32 = 4.0
var offset float32 = height / 2.0 var offset float32 = height / 2.0
boxes := make([]*globjects.Box, 4) boxes := make([]*globject.Box, 4)
// Top // Top
topPos := mgl32.Vec3{0, topRight.Y() + offset, topRight.Z()} topPos := mgl32.Vec3{0, topRight.Y() + offset, topRight.Z()}
boxes[0] = globjects.NewBox(topRight.X()-bottomLeft.X()+height*2, height, depth, topPos, material) boxes[0] = globject.NewBox(topRight.X()-bottomLeft.X()+height*2, height, depth, topPos, material)
// Bottom // Bottom
bottomPos := mgl32.Vec3{0, bottomLeft.Y() - offset, bottomLeft.Z()} bottomPos := mgl32.Vec3{0, bottomLeft.Y() - offset, bottomLeft.Z()}
boxes[1] = globjects.NewBox(topRight.X()-bottomLeft.X()+height*2, height, depth, bottomPos, material) boxes[1] = globject.NewBox(topRight.X()-bottomLeft.X()+height*2, height, depth, bottomPos, material)
// Left // Left
leftPos := mgl32.Vec3{bottomLeft.X() - offset, 0, bottomLeft.Z()} leftPos := mgl32.Vec3{bottomLeft.X() - offset, 0, bottomLeft.Z()}
boxes[2] = globjects.NewBox(height, topRight.Y()-bottomLeft.Y(), depth, leftPos, material) boxes[2] = globject.NewBox(height, topRight.Y()-bottomLeft.Y(), depth, leftPos, material)
// Right // Right
rightPos := mgl32.Vec3{topRight.X() + offset, 0, topRight.Z()} rightPos := mgl32.Vec3{topRight.X() + offset, 0, topRight.Z()}
boxes[3] = globjects.NewBox(height, topRight.Y()-bottomLeft.Y(), depth, rightPos, material) boxes[3] = globject.NewBox(height, topRight.Y()-bottomLeft.Y(), depth, rightPos, material)
sideWalls := SideWalls{ sideWalls := SideWalls{
Boxes: boxes, Boxes: boxes,

View File

@ -1,7 +1,7 @@
package breakout package breakout
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -47,12 +47,12 @@ func NewTargets(numRows, numColumns int, adjustPos mgl32.Vec3) *Targets {
targets.TopRight = topRightPos targets.TopRight = topRightPos
targets.BottomLeft = bottomLeftPos targets.BottomLeft = bottomLeftPos
materials := make([]*globjects.Material, numColumns) materials := make([]*globject.Material, numColumns)
for i := 0; i < numColumns; i++ { for i := 0; i < numColumns; i++ {
red := 0 + float32(i)/float32(numColumns) red := 0 + float32(i)/float32(numColumns)
blue := 1 - float32(i)/float32(numColumns) blue := 1 - float32(i)/float32(numColumns)
m := globjects.NewMaterial() m := globject.NewMaterial()
m.Color = mgl32.Vec4{red, 0, blue, 1} m.Color = mgl32.Vec4{red, 0, blue, 1}
materials[i] = m materials[i] = m
} }

View File

@ -1,28 +1,36 @@
package breakout package game
import ( import (
"fmt" "fmt"
"log" "log"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/breakout"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/config" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/config"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
gl "github.com/go-gl/gl/v3.1/gles2" gl "github.com/go-gl/gl/v3.1/gles2"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
"github.com/veandco/go-sdl2/sdl" "github.com/veandco/go-sdl2/sdl"
) )
type GLObject interface {
Update()
GLDraw()
GLInit(glProgram uint32)
ToggleWireframe()
}
type GameWindow struct { type GameWindow struct {
SDLWindow *sdl.Window SDLWindow *sdl.Window
GLContext *sdl.GLContext GLContext *sdl.GLContext
GLProgram uint32 GLProgram uint32
GLObjects []globjects.GLObject Globject []GLObject
Camera *globjects.Camera Camera *globject.Camera
Paddle *Paddle Paddle *breakout.Paddle
Ball *Ball Ball *breakout.Ball
Targets *Targets Targets *breakout.Targets
SideWalls *SideWalls SideWalls *breakout.SideWalls
AABB *globjects.AABB // This AABB represents the inside playable area AABB *globject.AABB // This AABB represents the inside playable area
keystates map[sdl.Keycode]bool keystates map[sdl.Keycode]bool
mouseMoved bool mouseMoved bool
@ -71,7 +79,7 @@ func (w *GameWindow) GLInit(glProgram uint32) {
} }
func (w *GameWindow) GLInitDefault() error { func (w *GameWindow) GLInitDefault() error {
glProgram, err := glhelpers.NewDefaultProgram() glProgram, err := glshader.NewDefaultProgram()
if err != nil { if err != nil {
return err return err
} }
@ -81,8 +89,8 @@ func (w *GameWindow) GLInitDefault() error {
return nil return nil
} }
func (w *GameWindow) AddObject(object globjects.GLObject) { func (w *GameWindow) AddObject(object GLObject) {
w.GLObjects = append(w.GLObjects, object) w.Globject = append(w.Globject, object)
} }
func (w *GameWindow) Destroy() { func (w *GameWindow) Destroy() {
@ -130,35 +138,35 @@ func (w *GameWindow) StopRunning() {
func (w *GameWindow) WindowProjection() { func (w *GameWindow) WindowProjection() {
width, height := w.SDLWindow.GLGetDrawableSize() width, height := w.SDLWindow.GLGetDrawableSize()
projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(width)/float32(height), 0.01, 1000.0) projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(width)/float32(height), 0.01, 1000.0)
glhelpers.SetUniformMatrix4f(w.GLProgram, "projection", &projection) glshader.SetUniformMatrix4f(w.GLProgram, "projection", &projection)
gl.Viewport(0, 0, width, height) gl.Viewport(0, 0, width, height)
} }
func (w *GameWindow) SetPaddle(paddle *Paddle) { func (w *GameWindow) SetPaddle(paddle *breakout.Paddle) {
w.Paddle = paddle w.Paddle = paddle
} }
func (w *GameWindow) SetBall(ball *Ball) { func (w *GameWindow) SetBall(ball *breakout.Ball) {
w.Ball = ball w.Ball = ball
} }
func (w *GameWindow) SetTargets(targets *Targets) { func (w *GameWindow) SetTargets(targets *breakout.Targets) {
w.Targets = targets w.Targets = targets
} }
func (w *GameWindow) SetSideWalls(sidewalls *SideWalls) { func (w *GameWindow) SetSideWalls(sidewalls *breakout.SideWalls) {
w.SideWalls = sidewalls w.SideWalls = sidewalls
} }
func (w *GameWindow) SetCamera(camera *globjects.Camera) { func (w *GameWindow) SetCamera(camera *globject.Camera) {
w.Camera = camera w.Camera = camera
} }
func (w *GameWindow) ToggleWireframe() { func (w *GameWindow) ToggleWireframe() {
// TODO figure out concurrency // TODO figure out concurrency
// var wg sync.WaitGroup // var wg sync.WaitGroup
// for _, o := range w.GLObjects { // for _, o := range w.Globject {
// wg.Add(1) // wg.Add(1)
// go func() { // go func() {
// o.ToggleWireframe() // o.ToggleWireframe()
@ -167,7 +175,7 @@ func (w *GameWindow) ToggleWireframe() {
// } // }
// wg.Wait() // wg.Wait()
for _, o := range w.GLObjects { for _, o := range w.Globject {
o.ToggleWireframe() o.ToggleWireframe()
} }
} }
@ -176,8 +184,8 @@ func (w *GameWindow) GLDraw() {
model := mgl32.Ident4() model := mgl32.Ident4()
// Probably can't do concurrent drawing due to OpenGL // Probably can't do concurrent drawing due to OpenGL
for _, o := range w.GLObjects { for _, o := range w.Globject {
glhelpers.SetUniformMatrix4f(w.GLProgram, "model", &model) glshader.SetUniformMatrix4f(w.GLProgram, "model", &model)
o.GLDraw() o.GLDraw()
} }
} }
@ -185,7 +193,7 @@ func (w *GameWindow) GLDraw() {
func (w *GameWindow) Update() { func (w *GameWindow) Update() {
// TODO figure out concurrency // TODO figure out concurrency
// var wg sync.WaitGroup // var wg sync.WaitGroup
// for _, o := range w.GLObjects { // for _, o := range w.Globject {
// wg.Add(1) // wg.Add(1)
// go func() { // go func() {
// o.Update() // o.Update()
@ -196,10 +204,8 @@ func (w *GameWindow) Update() {
if w.IsFreelookOn() { if w.IsFreelookOn() {
w.handleFreelookMovement() w.handleFreelookMovement()
} else { } else if !w.mouseMoved {
if !w.mouseMoved { w.handleGameKeyboardMovement()
w.handleGameKeyboardMovement()
}
} }
w.mouseMoved = false w.mouseMoved = false

View File

@ -6,7 +6,7 @@ import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/breakout" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/breakout"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/config" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/config"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject"
"gitea.wisellama.rocks/Wisellama/gosimpleconf" "gitea.wisellama.rocks/Wisellama/gosimpleconf"
gl "github.com/go-gl/gl/v3.1/gles2" gl "github.com/go-gl/gl/v3.1/gles2"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
@ -32,7 +32,7 @@ func Run(configMap gosimpleconf.ConfigMap) {
log.Fatal(err) log.Fatal(err)
} }
gameWindow, err := breakout.NewGameWindow(configMap["game.title"]) gameWindow, err := NewGameWindow(configMap["game.title"])
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -55,10 +55,10 @@ func Run(configMap gosimpleconf.ConfigMap) {
log.Printf("error in gameWindow GLInitDefault: %v", err) log.Printf("error in gameWindow GLInitDefault: %v", err)
} }
sunLight := globjects.NewPointLight(mgl32.Vec3{-10, 10, 30}) sunLight := globject.NewPointLight(mgl32.Vec3{-10, 10, 30})
sunLight.GLInit(gameWindow.GLProgram) sunLight.GLInit(gameWindow.GLProgram)
camera := globjects.NewCamera(gameWindow.GLProgram) camera := globject.NewCamera(gameWindow.GLProgram)
camera.Position = mgl32.Vec3{0, 0, 30} camera.Position = mgl32.Vec3{0, 0, 30}
gameWindow.SetCamera(camera) gameWindow.SetCamera(camera)
gameWindow.AddObject(camera) gameWindow.AddObject(camera)
@ -76,11 +76,11 @@ func Run(configMap gosimpleconf.ConfigMap) {
gameWindow.AddObject(brick.Box) gameWindow.AddObject(brick.Box)
} }
gameWindowAABB := globjects.NewAABB(targets.TopRight, targets.TopRight.Mul(-1)) gameWindowAABB := globject.NewAABB(targets.TopRight, targets.TopRight.Mul(-1))
gameWindow.AABB = gameWindowAABB gameWindow.AABB = gameWindowAABB
// Side Walls // Side Walls
sideWallsMaterial := globjects.NewMaterial() sideWallsMaterial := globject.NewMaterial()
sideWallsMaterial.Color = mgl32.Vec4{0.3, 0.3, 0.3, 1} sideWallsMaterial.Color = mgl32.Vec4{0.3, 0.3, 0.3, 1}
sideWalls := breakout.NewSideWalls(gameWindowAABB, sideWallsMaterial) sideWalls := breakout.NewSideWalls(gameWindowAABB, sideWallsMaterial)
sideWalls.GLInit(gameWindow.GLProgram) sideWalls.GLInit(gameWindow.GLProgram)
@ -90,18 +90,18 @@ func Run(configMap gosimpleconf.ConfigMap) {
} }
// Paddle // Paddle
paddleMaterial := globjects.NewMaterial() paddleMaterial := globject.NewMaterial()
paddleMaterial.Color = mgl32.Vec4{0, 1, 0, 1} paddleMaterial.Color = mgl32.Vec4{0, 1, 0, 1}
paddleBox := globjects.NewBox(6.0, 1.0, 4.0, mgl32.Vec3{0, -8, 0}, paddleMaterial) paddleBox := globject.NewBox(6.0, 1.0, 4.0, mgl32.Vec3{0, -8, 0}, paddleMaterial)
paddle := breakout.NewPaddle(paddleBox) paddle := breakout.NewPaddle(paddleBox)
paddle.GLInit(gameWindow.GLProgram) paddle.GLInit(gameWindow.GLProgram)
gameWindow.SetPaddle(paddle) gameWindow.SetPaddle(paddle)
gameWindow.AddObject(paddle) gameWindow.AddObject(paddle)
// Ball // Ball
ballMaterial := globjects.NewMaterial() ballMaterial := globject.NewMaterial()
ballMaterial.Color = mgl32.Vec4{1, 1, 1, 1} ballMaterial.Color = mgl32.Vec4{1, 1, 1, 1}
ballBox := globjects.NewBox(1, 1, 1, mgl32.Vec3{-8, 0, 0}, ballMaterial) ballBox := globject.NewBox(1, 1, 1, mgl32.Vec3{-8, 0, 0}, ballMaterial)
ball := breakout.NewBall(ballBox) ball := breakout.NewBall(ballBox)
ball.GLInit(gameWindow.GLProgram) ball.GLInit(gameWindow.GLProgram)
gameWindow.SetBall(ball) gameWindow.SetBall(ball)

105
pkg/globject/aabb.go Normal file
View File

@ -0,0 +1,105 @@
package globject
import (
"gitea.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
}

View File

@ -1,7 +1,7 @@
package globjects package globject
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
gl "github.com/go-gl/gl/v3.1/gles2" gl "github.com/go-gl/gl/v3.1/gles2"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -130,7 +130,7 @@ func (b *Box) GetRotationMatrix() *mgl32.Mat4 {
func (b *Box) GLDraw() { func (b *Box) GLDraw() {
model := b.GetModelMatrix() model := b.GetModelMatrix()
glhelpers.SetUniformMatrix4f(b.GLProgram, "model", model) glshader.SetUniformMatrix4f(b.GLProgram, "model", model)
b.Material.GLDraw(b.GLProgram) b.Material.GLDraw(b.GLProgram)
@ -142,7 +142,7 @@ func (b *Box) GLDraw() {
} }
func (b *Box) glDrawTriangles() { func (b *Box) glDrawTriangles() {
glhelpers.SetUniformInt(b.GLProgram, "lightsOn", 1) glshader.SetUniformInt(b.GLProgram, "lightsOn", 1)
gl.BindVertexArray(b.GLVertexArrayID) gl.BindVertexArray(b.GLVertexArrayID)
gl.BindBuffer(gl.ARRAY_BUFFER, b.GLVertexBufferID) gl.BindBuffer(gl.ARRAY_BUFFER, b.GLVertexBufferID)
@ -152,12 +152,12 @@ func (b *Box) glDrawTriangles() {
gl.BindTexture(gl.TEXTURE_2D, b.Material.TextureID) gl.BindTexture(gl.TEXTURE_2D, b.Material.TextureID)
} }
glhelpers.UpdateVertexAttribs(b.GLProgram, VertexSize) glshader.UpdateVertexAttribs(b.GLProgram, VertexSize)
gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) // 6 sides, 2 triangles, 3 points each gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3) // 6 sides, 2 triangles, 3 points each
} }
func (b *Box) glDrawLineLoop() { func (b *Box) glDrawLineLoop() {
glhelpers.SetUniformInt(b.GLProgram, "lightsOn", 0) glshader.SetUniformInt(b.GLProgram, "lightsOn", 0)
for _, face := range b.Faces { for _, face := range b.Faces {
face.GLDrawLineLoop(b.GLProgram) face.GLDrawLineLoop(b.GLProgram)
} }

View File

@ -1,7 +1,7 @@
package globjects package globject
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -47,8 +47,8 @@ func (c *Camera) GetCenter() mgl32.Vec3 {
func (c *Camera) GLDraw() { func (c *Camera) GLDraw() {
cameraMatrix := mgl32.LookAtV(c.Position, c.GetCenter(), c.Up) cameraMatrix := mgl32.LookAtV(c.Position, c.GetCenter(), c.Up)
glhelpers.SetUniformMatrix4f(c.GLProgram, "camera", &cameraMatrix) glshader.SetUniformMatrix4f(c.GLProgram, "camera", &cameraMatrix)
glhelpers.SetUniformVec3f(c.GLProgram, "cameraPos", c.Position) glshader.SetUniformVec3f(c.GLProgram, "cameraPos", c.Position)
} }
func (c *Camera) GLInit(glProgram uint32) { func (c *Camera) GLInit(glProgram uint32) {

View File

@ -1,7 +1,7 @@
package globjects package globject
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -24,8 +24,8 @@ func NewDirectionalLight(direction mgl32.Vec3) *DirectionalLight {
} }
func (l *DirectionalLight) GLInit(glProgram uint32) { func (l *DirectionalLight) GLInit(glProgram uint32) {
glhelpers.SetUniformVec3f(glProgram, "dirLight.direction", l.Direction) glshader.SetUniformVec3f(glProgram, "dirLight.direction", l.Direction)
glhelpers.SetUniformVec4f(glProgram, "dirLight.ambient", l.AmbientColor) glshader.SetUniformVec4f(glProgram, "dirLight.ambient", l.AmbientColor)
glhelpers.SetUniformVec4f(glProgram, "dirLight.diffuse", l.DiffuseColor) glshader.SetUniformVec4f(glProgram, "dirLight.diffuse", l.DiffuseColor)
glhelpers.SetUniformVec4f(glProgram, "dirLight.specular", l.SpecularColor) glshader.SetUniformVec4f(glProgram, "dirLight.specular", l.SpecularColor)
} }

View File

@ -1,10 +1,10 @@
package globjects package globject
import ( import (
"log" "log"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/mathhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/math"
gl "github.com/go-gl/gl/v3.1/gles2" gl "github.com/go-gl/gl/v3.1/gles2"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -77,7 +77,7 @@ func newFaceVertex(
v := mgl32.Vec3{xoffset, 0, zoffset} v := mgl32.Vec3{xoffset, 0, zoffset}
up := mgl32.Vec3{0, 1, 0} up := mgl32.Vec3{0, 1, 0}
angle, err := mathhelpers.AngleBetweenVectors(up, normal) angle, err := math.AngleBetweenVectors(up, normal)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return nil return nil
@ -135,12 +135,12 @@ func (f *Face) GLDrawLineLoop(glProgram uint32) {
gl.BindVertexArray(f.GLLineLoopVertexArrayID) gl.BindVertexArray(f.GLLineLoopVertexArrayID)
gl.BindBuffer(gl.ARRAY_BUFFER, f.GLLineLoopVertexBufferID) gl.BindBuffer(gl.ARRAY_BUFFER, f.GLLineLoopVertexBufferID)
glhelpers.UpdateVertexAttribs(glProgram, VertexSize) glshader.UpdateVertexAttribs(glProgram, VertexSize)
gl.DrawArrays(gl.LINE_LOOP, 0, 4) gl.DrawArrays(gl.LINE_LOOP, 0, 4)
} }
func (f *Face) GLInit(glProgram uint32) { func (f *Face) GLInit(glProgram uint32) {
glhelpers.UpdateVertexAttribs(glProgram, VertexSize) glshader.UpdateVertexAttribs(glProgram, VertexSize)
// LineLoop setup // LineLoop setup
gl.GenVertexArrays(1, &f.GLLineLoopVertexArrayID) gl.GenVertexArrays(1, &f.GLLineLoopVertexArrayID)
gl.BindVertexArray(f.GLLineLoopVertexArrayID) gl.BindVertexArray(f.GLLineLoopVertexArrayID)

View File

@ -1,7 +1,7 @@
package globjects package globject
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -25,15 +25,15 @@ func NewMaterial() *Material {
} }
func (m *Material) GLDraw(glProgram uint32) { func (m *Material) GLDraw(glProgram uint32) {
glhelpers.SetUniformInt(glProgram, "material.textureDiffuse", m.TextureDiffuse) glshader.SetUniformInt(glProgram, "material.textureDiffuse", m.TextureDiffuse)
glhelpers.SetUniformInt(glProgram, "material.textureSpecular", m.TextureSpecular) glshader.SetUniformInt(glProgram, "material.textureSpecular", m.TextureSpecular)
glhelpers.SetUniformFloat(glProgram, "material.shininess", m.Shininess) glshader.SetUniformFloat(glProgram, "material.shininess", m.Shininess)
glhelpers.SetUniformVec4f(glProgram, "material.color", m.Color) glshader.SetUniformVec4f(glProgram, "material.color", m.Color)
var tOn int32 = 0 var tOn int32 = 0
if m.TextureOn { if m.TextureOn {
tOn = 1 tOn = 1
} }
glhelpers.SetUniformInt(glProgram, "material.textureOn", tOn) glshader.SetUniformInt(glProgram, "material.textureOn", tOn)
} }

View File

@ -1,7 +1,7 @@
package globjects package globject
import ( import (
"gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader"
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"
) )
@ -26,8 +26,8 @@ func NewPointLight(position mgl32.Vec3) *PointLight {
} }
func (l *PointLight) GLInit(glProgram uint32) { func (l *PointLight) GLInit(glProgram uint32) {
glhelpers.SetUniformVec3f(glProgram, "light.position", l.Position) glshader.SetUniformVec3f(glProgram, "light.position", l.Position)
glhelpers.SetUniformVec4f(glProgram, "light.ambient", l.AmbientColor) glshader.SetUniformVec4f(glProgram, "light.ambient", l.AmbientColor)
glhelpers.SetUniformVec4f(glProgram, "light.diffuse", l.DiffuseColor) glshader.SetUniformVec4f(glProgram, "light.diffuse", l.DiffuseColor)
glhelpers.SetUniformVec4f(glProgram, "light.specular", l.SpecularColor) glshader.SetUniformVec4f(glProgram, "light.specular", l.SpecularColor)
} }

View File

@ -1,4 +1,4 @@
package globjects package globject
type Triangle struct { type Triangle struct {
Vertices []*Vertex Vertices []*Vertex

View File

@ -1,4 +1,4 @@
package globjects package globject
import ( import (
"github.com/go-gl/mathgl/mgl32" "github.com/go-gl/mathgl/mgl32"

View File

@ -1,5 +0,0 @@
# globjects
This package contains things that can be drawn with OpenGL along with
any helpers. Effectively, anything in here should implement the
GLObject interface.

View File

@ -1,109 +0,0 @@
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
}

View File

@ -1,8 +0,0 @@
package globjects
type GLObject interface {
Update()
GLDraw()
GLInit(glProgram uint32)
ToggleWireframe()
}

View File

@ -1,4 +1,4 @@
package glhelpers package glshader
var FragmentShaderSource string = ` var FragmentShaderSource string = `
#version 330 #version 330

View File

@ -1,4 +1,4 @@
package glhelpers package glshader
// https://github.com/go-gl/example // https://github.com/go-gl/example

View File

@ -1,4 +1,4 @@
package glhelpers package glshader
// Adapted from the OpenGL Superbible // Adapted from the OpenGL Superbible

View File

@ -1,4 +1,4 @@
package mathhelpers package math
import ( import (
"fmt" "fmt"
@ -51,3 +51,13 @@ func Absf32(a float32) float32 {
return a return a
} }
func AbsVec3(v mgl32.Vec3) mgl32.Vec3 {
output := mgl32.Vec3{
Absf32(v[0]),
Absf32(v[1]),
Absf32(v[2]),
}
return output
}