diff --git a/.gitignore b/.gitignore index c06c151..254247d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ carpy-breakout output.log +cpu.prof diff --git a/Makefile b/Makefile index 00d834f..dd15eed 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,11 @@ release: linter dependencies linter: golangci-lint run +clean: + rm -f carpy-breakout + rm -f output.log + rm -f cpu.prof + cross_windows: export CGO_ENABLED=1 export CC=x86_64-w64-mingw32-gcc diff --git a/Readme.md b/Readme.md index 133dc16..8aaf793 100644 --- a/Readme.md +++ b/Readme.md @@ -16,6 +16,12 @@ Press `L` to toggle wireframe 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"? Because it's a funny misspelling of "Crappy". This was originally diff --git a/pkg/breakout/ball.go b/pkg/breakout/ball.go index 3b3b9f1..8f3be00 100644 --- a/pkg/breakout/ball.go +++ b/pkg/breakout/ball.go @@ -1,14 +1,17 @@ package breakout 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 { - Box *globjects.Box + Box *globject.Box } -func NewBall(box *globjects.Box) *Ball { +func NewBall(box *globject.Box) *Ball { ball := Ball{ Box: box, } @@ -32,7 +35,7 @@ func (self *Ball) ToggleWireframe() { self.Box.ToggleWireframe() } -func (self *Ball) GetAABB() *globjects.AABB { +func (self *Ball) GetAABB() *globject.AABB { return self.Box.GetAABB() } @@ -40,15 +43,15 @@ func (self *Ball) HandlePaddleCollision(paddle *Paddle) { aabb := self.GetAABB() p := paddle.GetAABB() - intersects := aabb.Intersects(p) + intersects, diff := aabb.Intersects(p) if intersects { newVelocity := self.Box.Velocity - if aabb.HorizontalCollision(p) { + if globject.XCollision(diff) { newVelocity[0] = -1 * newVelocity[0] } - if aabb.VerticalCollision(p) { + if globject.YCollision(diff) { // Change differently based on which part of the paddle we hit // TODO newVelocity[1] = -1 * newVelocity[1] @@ -59,49 +62,50 @@ func (self *Ball) HandlePaddleCollision(paddle *Paddle) { } func (self *Ball) HandleTargetCollisions(targets *Targets) { - intersects := false aabb := self.GetAABB() for _, brick := range targets.Bricks { if !brick.Broken() { b := brick.GetAABB() - intersects = aabb.Intersects(b) + intersects, diff := aabb.Intersects(b) if intersects { // TODO points brick.Break() - self.UpdateVelocityFromCollision(aabb, b) + self.UpdateElasticCollision(diff) } } } } func (self *Ball) HandleSideWallsCollisions(sidewalls *SideWalls) { - intersects := false - aabb := self.GetAABB() boxes := sidewalls.Boxes for _, box := range boxes { b := box.GetAABB() - intersects = aabb.Intersects(b) + intersects, diff := aabb.Intersects(b) 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 - if us.HorizontalCollision(them) { + if globject.XCollision(diff) { + log.Printf("X collision: %v\n", diff) 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] } + // No Z collisions for this game + self.Box.Velocity = newVelocity } diff --git a/pkg/breakout/brick.go b/pkg/breakout/brick.go index fbb187e..cb39b00 100644 --- a/pkg/breakout/brick.go +++ b/pkg/breakout/brick.go @@ -1,12 +1,12 @@ package breakout import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject" "github.com/go-gl/mathgl/mgl32" ) type Brick struct { - Box *globjects.Box + Box *globject.Box broken bool } @@ -15,10 +15,10 @@ func NewBrick( brickHeight float32, brickDepth float32, position mgl32.Vec3, - material *globjects.Material) *Brick { + material *globject.Material) *Brick { brick := Brick{ - Box: globjects.NewBox(brickWidth, brickHeight, brickDepth, position, material), + Box: globject.NewBox(brickWidth, brickHeight, brickDepth, position, material), broken: false, } return &brick @@ -42,7 +42,7 @@ func (b *Brick) ToggleWireframe() { b.Box.ToggleWireframe() } -func (b *Brick) GetAABB() *globjects.AABB { +func (b *Brick) GetAABB() *globject.AABB { return b.Box.GetAABB() } @@ -53,7 +53,7 @@ func (b *Brick) Broken() bool { func (b *Brick) Break() { b.broken = true - clear := globjects.NewMaterial() + clear := globject.NewMaterial() clear.Color = mgl32.Vec4{0, 0, 0, 0} clear.Shininess = 0 diff --git a/pkg/breakout/paddle.go b/pkg/breakout/paddle.go index 0f2b19d..9a84953 100644 --- a/pkg/breakout/paddle.go +++ b/pkg/breakout/paddle.go @@ -1,9 +1,9 @@ package breakout -import "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" +import "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject" type Paddle struct { - Box *globjects.Box + Box *globject.Box } func (self *Paddle) Update() { @@ -22,11 +22,11 @@ func (self *Paddle) ToggleWireframe() { self.Box.ToggleWireframe() } -func (self *Paddle) GetAABB() *globjects.AABB { +func (self *Paddle) GetAABB() *globject.AABB { return self.Box.GetAABB() } -func NewPaddle(box *globjects.Box) *Paddle { +func NewPaddle(box *globject.Box) *Paddle { paddle := Paddle{ Box: box, } diff --git a/pkg/breakout/sidewalls.go b/pkg/breakout/sidewalls.go index 576fb47..b476dd5 100644 --- a/pkg/breakout/sidewalls.go +++ b/pkg/breakout/sidewalls.go @@ -1,15 +1,15 @@ package breakout import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject" "github.com/go-gl/mathgl/mgl32" ) 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 bottomLeft := aabb.BottomLeft @@ -18,23 +18,23 @@ func NewSideWalls(aabb *globjects.AABB, material *globjects.Material) *SideWalls var height float32 = 4.0 var offset float32 = height / 2.0 - boxes := make([]*globjects.Box, 4) + boxes := make([]*globject.Box, 4) // Top 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 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 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 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{ Boxes: boxes, diff --git a/pkg/breakout/targets.go b/pkg/breakout/targets.go index ad41a4c..9be28ee 100644 --- a/pkg/breakout/targets.go +++ b/pkg/breakout/targets.go @@ -1,7 +1,7 @@ package breakout import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject" "github.com/go-gl/mathgl/mgl32" ) @@ -47,12 +47,12 @@ func NewTargets(numRows, numColumns int, adjustPos mgl32.Vec3) *Targets { targets.TopRight = topRightPos targets.BottomLeft = bottomLeftPos - materials := make([]*globjects.Material, numColumns) + materials := make([]*globject.Material, numColumns) for i := 0; i < numColumns; i++ { red := 0 + float32(i)/float32(numColumns) blue := 1 - float32(i)/float32(numColumns) - m := globjects.NewMaterial() + m := globject.NewMaterial() m.Color = mgl32.Vec4{red, 0, blue, 1} materials[i] = m } diff --git a/pkg/breakout/gamewindow.go b/pkg/game/gamewindow.go similarity index 83% rename from pkg/breakout/gamewindow.go rename to pkg/game/gamewindow.go index 66f41d6..647ac70 100644 --- a/pkg/breakout/gamewindow.go +++ b/pkg/game/gamewindow.go @@ -1,28 +1,36 @@ -package breakout +package game import ( "fmt" "log" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/breakout" "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/config" - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globjects" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/globject" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader" gl "github.com/go-gl/gl/v3.1/gles2" "github.com/go-gl/mathgl/mgl32" "github.com/veandco/go-sdl2/sdl" ) +type GLObject interface { + Update() + GLDraw() + GLInit(glProgram uint32) + ToggleWireframe() +} + type GameWindow struct { SDLWindow *sdl.Window GLContext *sdl.GLContext GLProgram uint32 - GLObjects []globjects.GLObject - Camera *globjects.Camera - Paddle *Paddle - Ball *Ball - Targets *Targets - SideWalls *SideWalls - AABB *globjects.AABB // This AABB represents the inside playable area + Globject []GLObject + Camera *globject.Camera + Paddle *breakout.Paddle + Ball *breakout.Ball + Targets *breakout.Targets + SideWalls *breakout.SideWalls + AABB *globject.AABB // This AABB represents the inside playable area keystates map[sdl.Keycode]bool mouseMoved bool @@ -71,7 +79,7 @@ func (w *GameWindow) GLInit(glProgram uint32) { } func (w *GameWindow) GLInitDefault() error { - glProgram, err := glhelpers.NewDefaultProgram() + glProgram, err := glshader.NewDefaultProgram() if err != nil { return err } @@ -81,8 +89,8 @@ func (w *GameWindow) GLInitDefault() error { return nil } -func (w *GameWindow) AddObject(object globjects.GLObject) { - w.GLObjects = append(w.GLObjects, object) +func (w *GameWindow) AddObject(object GLObject) { + w.Globject = append(w.Globject, object) } func (w *GameWindow) Destroy() { @@ -130,35 +138,35 @@ func (w *GameWindow) StopRunning() { func (w *GameWindow) WindowProjection() { width, height := w.SDLWindow.GLGetDrawableSize() 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) } -func (w *GameWindow) SetPaddle(paddle *Paddle) { +func (w *GameWindow) SetPaddle(paddle *breakout.Paddle) { w.Paddle = paddle } -func (w *GameWindow) SetBall(ball *Ball) { +func (w *GameWindow) SetBall(ball *breakout.Ball) { w.Ball = ball } -func (w *GameWindow) SetTargets(targets *Targets) { +func (w *GameWindow) SetTargets(targets *breakout.Targets) { w.Targets = targets } -func (w *GameWindow) SetSideWalls(sidewalls *SideWalls) { +func (w *GameWindow) SetSideWalls(sidewalls *breakout.SideWalls) { w.SideWalls = sidewalls } -func (w *GameWindow) SetCamera(camera *globjects.Camera) { +func (w *GameWindow) SetCamera(camera *globject.Camera) { w.Camera = camera } func (w *GameWindow) ToggleWireframe() { // TODO figure out concurrency // var wg sync.WaitGroup - // for _, o := range w.GLObjects { + // for _, o := range w.Globject { // wg.Add(1) // go func() { // o.ToggleWireframe() @@ -167,7 +175,7 @@ func (w *GameWindow) ToggleWireframe() { // } // wg.Wait() - for _, o := range w.GLObjects { + for _, o := range w.Globject { o.ToggleWireframe() } } @@ -176,8 +184,8 @@ func (w *GameWindow) GLDraw() { model := mgl32.Ident4() // Probably can't do concurrent drawing due to OpenGL - for _, o := range w.GLObjects { - glhelpers.SetUniformMatrix4f(w.GLProgram, "model", &model) + for _, o := range w.Globject { + glshader.SetUniformMatrix4f(w.GLProgram, "model", &model) o.GLDraw() } } @@ -185,7 +193,7 @@ func (w *GameWindow) GLDraw() { func (w *GameWindow) Update() { // TODO figure out concurrency // var wg sync.WaitGroup - // for _, o := range w.GLObjects { + // for _, o := range w.Globject { // wg.Add(1) // go func() { // o.Update() @@ -196,10 +204,8 @@ func (w *GameWindow) Update() { if w.IsFreelookOn() { w.handleFreelookMovement() - } else { - if !w.mouseMoved { - w.handleGameKeyboardMovement() - } + } else if !w.mouseMoved { + w.handleGameKeyboardMovement() } w.mouseMoved = false diff --git a/pkg/game/opengl.go b/pkg/game/opengl.go index 9f3fa0f..db7568f 100644 --- a/pkg/game/opengl.go +++ b/pkg/game/opengl.go @@ -6,7 +6,7 @@ import ( "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/breakout" "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" gl "github.com/go-gl/gl/v3.1/gles2" "github.com/go-gl/mathgl/mgl32" @@ -32,7 +32,7 @@ func Run(configMap gosimpleconf.ConfigMap) { log.Fatal(err) } - gameWindow, err := breakout.NewGameWindow(configMap["game.title"]) + gameWindow, err := NewGameWindow(configMap["game.title"]) if err != nil { log.Fatal(err) } @@ -55,10 +55,10 @@ func Run(configMap gosimpleconf.ConfigMap) { 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) - camera := globjects.NewCamera(gameWindow.GLProgram) + camera := globject.NewCamera(gameWindow.GLProgram) camera.Position = mgl32.Vec3{0, 0, 30} gameWindow.SetCamera(camera) gameWindow.AddObject(camera) @@ -76,11 +76,11 @@ func Run(configMap gosimpleconf.ConfigMap) { 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 // Side Walls - sideWallsMaterial := globjects.NewMaterial() + sideWallsMaterial := globject.NewMaterial() sideWallsMaterial.Color = mgl32.Vec4{0.3, 0.3, 0.3, 1} sideWalls := breakout.NewSideWalls(gameWindowAABB, sideWallsMaterial) sideWalls.GLInit(gameWindow.GLProgram) @@ -90,18 +90,18 @@ func Run(configMap gosimpleconf.ConfigMap) { } // Paddle - paddleMaterial := globjects.NewMaterial() + paddleMaterial := globject.NewMaterial() 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.GLInit(gameWindow.GLProgram) gameWindow.SetPaddle(paddle) gameWindow.AddObject(paddle) // Ball - ballMaterial := globjects.NewMaterial() + ballMaterial := globject.NewMaterial() 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.GLInit(gameWindow.GLProgram) gameWindow.SetBall(ball) diff --git a/pkg/globject/aabb.go b/pkg/globject/aabb.go new file mode 100644 index 0000000..c8ff81b --- /dev/null +++ b/pkg/globject/aabb.go @@ -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 +} diff --git a/pkg/globjects/box.go b/pkg/globject/box.go similarity index 94% rename from pkg/globjects/box.go rename to pkg/globject/box.go index 1e66a33..a9968ee 100644 --- a/pkg/globjects/box.go +++ b/pkg/globject/box.go @@ -1,7 +1,7 @@ -package globjects +package globject 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" "github.com/go-gl/mathgl/mgl32" ) @@ -130,7 +130,7 @@ func (b *Box) GetRotationMatrix() *mgl32.Mat4 { func (b *Box) GLDraw() { model := b.GetModelMatrix() - glhelpers.SetUniformMatrix4f(b.GLProgram, "model", model) + glshader.SetUniformMatrix4f(b.GLProgram, "model", model) b.Material.GLDraw(b.GLProgram) @@ -142,7 +142,7 @@ func (b *Box) GLDraw() { } func (b *Box) glDrawTriangles() { - glhelpers.SetUniformInt(b.GLProgram, "lightsOn", 1) + glshader.SetUniformInt(b.GLProgram, "lightsOn", 1) gl.BindVertexArray(b.GLVertexArrayID) gl.BindBuffer(gl.ARRAY_BUFFER, b.GLVertexBufferID) @@ -152,12 +152,12 @@ func (b *Box) glDrawTriangles() { 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 } func (b *Box) glDrawLineLoop() { - glhelpers.SetUniformInt(b.GLProgram, "lightsOn", 0) + glshader.SetUniformInt(b.GLProgram, "lightsOn", 0) for _, face := range b.Faces { face.GLDrawLineLoop(b.GLProgram) } diff --git a/pkg/globjects/camera.go b/pkg/globject/camera.go similarity index 93% rename from pkg/globjects/camera.go rename to pkg/globject/camera.go index 797a43a..f933887 100644 --- a/pkg/globjects/camera.go +++ b/pkg/globject/camera.go @@ -1,7 +1,7 @@ -package globjects +package globject import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader" "github.com/go-gl/mathgl/mgl32" ) @@ -47,8 +47,8 @@ func (c *Camera) GetCenter() mgl32.Vec3 { func (c *Camera) GLDraw() { cameraMatrix := mgl32.LookAtV(c.Position, c.GetCenter(), c.Up) - glhelpers.SetUniformMatrix4f(c.GLProgram, "camera", &cameraMatrix) - glhelpers.SetUniformVec3f(c.GLProgram, "cameraPos", c.Position) + glshader.SetUniformMatrix4f(c.GLProgram, "camera", &cameraMatrix) + glshader.SetUniformVec3f(c.GLProgram, "cameraPos", c.Position) } func (c *Camera) GLInit(glProgram uint32) { diff --git a/pkg/globjects/directional_light.go b/pkg/globject/directional_light.go similarity index 62% rename from pkg/globjects/directional_light.go rename to pkg/globject/directional_light.go index fbe1278..6f62413 100644 --- a/pkg/globjects/directional_light.go +++ b/pkg/globject/directional_light.go @@ -1,7 +1,7 @@ -package globjects +package globject import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader" "github.com/go-gl/mathgl/mgl32" ) @@ -24,8 +24,8 @@ func NewDirectionalLight(direction mgl32.Vec3) *DirectionalLight { } func (l *DirectionalLight) GLInit(glProgram uint32) { - glhelpers.SetUniformVec3f(glProgram, "dirLight.direction", l.Direction) - glhelpers.SetUniformVec4f(glProgram, "dirLight.ambient", l.AmbientColor) - glhelpers.SetUniformVec4f(glProgram, "dirLight.diffuse", l.DiffuseColor) - glhelpers.SetUniformVec4f(glProgram, "dirLight.specular", l.SpecularColor) + glshader.SetUniformVec3f(glProgram, "dirLight.direction", l.Direction) + glshader.SetUniformVec4f(glProgram, "dirLight.ambient", l.AmbientColor) + glshader.SetUniformVec4f(glProgram, "dirLight.diffuse", l.DiffuseColor) + glshader.SetUniformVec4f(glProgram, "dirLight.specular", l.SpecularColor) } diff --git a/pkg/globjects/face.go b/pkg/globject/face.go similarity index 90% rename from pkg/globjects/face.go rename to pkg/globject/face.go index 01d761d..5ee2a48 100644 --- a/pkg/globjects/face.go +++ b/pkg/globject/face.go @@ -1,10 +1,10 @@ -package globjects +package globject import ( "log" - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/mathhelpers" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/math" gl "github.com/go-gl/gl/v3.1/gles2" "github.com/go-gl/mathgl/mgl32" ) @@ -77,7 +77,7 @@ func newFaceVertex( v := mgl32.Vec3{xoffset, 0, zoffset} up := mgl32.Vec3{0, 1, 0} - angle, err := mathhelpers.AngleBetweenVectors(up, normal) + angle, err := math.AngleBetweenVectors(up, normal) if err != nil { log.Println(err) return nil @@ -135,12 +135,12 @@ func (f *Face) GLDrawLineLoop(glProgram uint32) { gl.BindVertexArray(f.GLLineLoopVertexArrayID) gl.BindBuffer(gl.ARRAY_BUFFER, f.GLLineLoopVertexBufferID) - glhelpers.UpdateVertexAttribs(glProgram, VertexSize) + glshader.UpdateVertexAttribs(glProgram, VertexSize) gl.DrawArrays(gl.LINE_LOOP, 0, 4) } func (f *Face) GLInit(glProgram uint32) { - glhelpers.UpdateVertexAttribs(glProgram, VertexSize) + glshader.UpdateVertexAttribs(glProgram, VertexSize) // LineLoop setup gl.GenVertexArrays(1, &f.GLLineLoopVertexArrayID) gl.BindVertexArray(f.GLLineLoopVertexArrayID) diff --git a/pkg/globjects/material.go b/pkg/globject/material.go similarity index 50% rename from pkg/globjects/material.go rename to pkg/globject/material.go index 7f27992..b232117 100644 --- a/pkg/globjects/material.go +++ b/pkg/globject/material.go @@ -1,7 +1,7 @@ -package globjects +package globject import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader" "github.com/go-gl/mathgl/mgl32" ) @@ -25,15 +25,15 @@ func NewMaterial() *Material { } func (m *Material) GLDraw(glProgram uint32) { - glhelpers.SetUniformInt(glProgram, "material.textureDiffuse", m.TextureDiffuse) - glhelpers.SetUniformInt(glProgram, "material.textureSpecular", m.TextureSpecular) + glshader.SetUniformInt(glProgram, "material.textureDiffuse", m.TextureDiffuse) + glshader.SetUniformInt(glProgram, "material.textureSpecular", m.TextureSpecular) - glhelpers.SetUniformFloat(glProgram, "material.shininess", m.Shininess) - glhelpers.SetUniformVec4f(glProgram, "material.color", m.Color) + glshader.SetUniformFloat(glProgram, "material.shininess", m.Shininess) + glshader.SetUniformVec4f(glProgram, "material.color", m.Color) var tOn int32 = 0 if m.TextureOn { tOn = 1 } - glhelpers.SetUniformInt(glProgram, "material.textureOn", tOn) + glshader.SetUniformInt(glProgram, "material.textureOn", tOn) } diff --git a/pkg/globjects/point_light.go b/pkg/globject/point_light.go similarity index 63% rename from pkg/globjects/point_light.go rename to pkg/globject/point_light.go index 7b91bc0..3f8f93b 100644 --- a/pkg/globjects/point_light.go +++ b/pkg/globject/point_light.go @@ -1,7 +1,7 @@ -package globjects +package globject import ( - "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glhelpers" + "gitea.wisellama.rocks/Wisellama/carpy-breakout/pkg/glshader" "github.com/go-gl/mathgl/mgl32" ) @@ -26,8 +26,8 @@ func NewPointLight(position mgl32.Vec3) *PointLight { } func (l *PointLight) GLInit(glProgram uint32) { - glhelpers.SetUniformVec3f(glProgram, "light.position", l.Position) - glhelpers.SetUniformVec4f(glProgram, "light.ambient", l.AmbientColor) - glhelpers.SetUniformVec4f(glProgram, "light.diffuse", l.DiffuseColor) - glhelpers.SetUniformVec4f(glProgram, "light.specular", l.SpecularColor) + glshader.SetUniformVec3f(glProgram, "light.position", l.Position) + glshader.SetUniformVec4f(glProgram, "light.ambient", l.AmbientColor) + glshader.SetUniformVec4f(glProgram, "light.diffuse", l.DiffuseColor) + glshader.SetUniformVec4f(glProgram, "light.specular", l.SpecularColor) } diff --git a/pkg/globjects/quaternions.md b/pkg/globject/quaternions.md similarity index 100% rename from pkg/globjects/quaternions.md rename to pkg/globject/quaternions.md diff --git a/pkg/globjects/triangle.go b/pkg/globject/triangle.go similarity index 95% rename from pkg/globjects/triangle.go rename to pkg/globject/triangle.go index 95dfd2d..a33c5c9 100644 --- a/pkg/globjects/triangle.go +++ b/pkg/globject/triangle.go @@ -1,4 +1,4 @@ -package globjects +package globject type Triangle struct { Vertices []*Vertex diff --git a/pkg/globjects/vertex.go b/pkg/globject/vertex.go similarity index 97% rename from pkg/globjects/vertex.go rename to pkg/globject/vertex.go index 78231ff..319028c 100644 --- a/pkg/globjects/vertex.go +++ b/pkg/globject/vertex.go @@ -1,4 +1,4 @@ -package globjects +package globject import ( "github.com/go-gl/mathgl/mgl32" diff --git a/pkg/globjects/README.md b/pkg/globjects/README.md deleted file mode 100644 index f3b037e..0000000 --- a/pkg/globjects/README.md +++ /dev/null @@ -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. diff --git a/pkg/globjects/aabb.go b/pkg/globjects/aabb.go deleted file mode 100644 index e6cbceb..0000000 --- a/pkg/globjects/aabb.go +++ /dev/null @@ -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 - -} diff --git a/pkg/globjects/globject.go b/pkg/globjects/globject.go deleted file mode 100644 index 31e8812..0000000 --- a/pkg/globjects/globject.go +++ /dev/null @@ -1,8 +0,0 @@ -package globjects - -type GLObject interface { - Update() - GLDraw() - GLInit(glProgram uint32) - ToggleWireframe() -} diff --git a/pkg/glhelpers/fragment_shader.go b/pkg/glshader/fragment_shader.go similarity index 99% rename from pkg/glhelpers/fragment_shader.go rename to pkg/glshader/fragment_shader.go index 42d40c2..1f1a966 100644 --- a/pkg/glhelpers/fragment_shader.go +++ b/pkg/glshader/fragment_shader.go @@ -1,4 +1,4 @@ -package glhelpers +package glshader var FragmentShaderSource string = ` #version 330 diff --git a/pkg/glhelpers/glhelpers.go b/pkg/glshader/glshader.go similarity index 99% rename from pkg/glhelpers/glhelpers.go rename to pkg/glshader/glshader.go index 9ebd910..9e23b33 100644 --- a/pkg/glhelpers/glhelpers.go +++ b/pkg/glshader/glshader.go @@ -1,4 +1,4 @@ -package glhelpers +package glshader // https://github.com/go-gl/example diff --git a/pkg/glhelpers/vertex_shader.go b/pkg/glshader/vertex_shader.go similarity index 98% rename from pkg/glhelpers/vertex_shader.go rename to pkg/glshader/vertex_shader.go index 670bb2d..fafd478 100644 --- a/pkg/glhelpers/vertex_shader.go +++ b/pkg/glshader/vertex_shader.go @@ -1,4 +1,4 @@ -package glhelpers +package glshader // Adapted from the OpenGL Superbible diff --git a/pkg/mathhelpers/mathhelpers.go b/pkg/math/math.go similarity index 82% rename from pkg/mathhelpers/mathhelpers.go rename to pkg/math/math.go index c7f4706..1e6a4df 100644 --- a/pkg/mathhelpers/mathhelpers.go +++ b/pkg/math/math.go @@ -1,4 +1,4 @@ -package mathhelpers +package math import ( "fmt" @@ -51,3 +51,13 @@ func Absf32(a float32) float32 { return a } + +func AbsVec3(v mgl32.Vec3) mgl32.Vec3 { + output := mgl32.Vec3{ + Absf32(v[0]), + Absf32(v[1]), + Absf32(v[2]), + } + + return output +}