FPS camera with pitch and yaw

This commit is contained in:
bloeys
2022-10-01 01:43:01 +04:00
parent bd79f6e274
commit 62194c4cad
4 changed files with 106 additions and 47 deletions

View File

@ -38,7 +38,7 @@ type Camera struct {
// Should be called whenever a camera parameter changes
func (c *Camera) Update() {
c.ViewMat = gglm.LookAt(&c.Pos, c.Pos.Clone().Add(&c.Forward), &c.WorldUp).Mat4
c.ViewMat = gglm.LookAtRH(&c.Pos, c.Pos.Clone().Add(&c.Forward), &c.WorldUp).Mat4
if c.Type == Type_Perspective {
c.ProjMat = *gglm.Perspective(c.Fov, c.AspectRatio, c.NearClip, c.FarClip)
@ -47,9 +47,15 @@ func (c *Camera) Update() {
}
}
func (c *Camera) LookAt(forward, worldUp *gglm.Vec3) {
c.Forward = *forward
c.WorldUp = *worldUp
// UpdateRotation calculates a new forward vector and then calls camera.Update()
func (c *Camera) UpdateRotation(pitch, yaw float32) {
dir := gglm.NewVec3(
gglm.Cos32(yaw)*gglm.Cos32(pitch),
gglm.Sin32(pitch),
gglm.Sin32(yaw)*gglm.Cos32(pitch),
)
c.Forward = *dir.Normalize()
c.Update()
}

8
go.mod
View File

@ -2,12 +2,12 @@ module github.com/bloeys/nmage
go 1.18
require github.com/veandco/go-sdl2 v0.4.10
require github.com/veandco/go-sdl2 v0.4.25
require github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784
require github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6
require (
github.com/bloeys/assimp-go v0.4.2
github.com/bloeys/gglm v0.41.10
github.com/inkyblackness/imgui-go/v4 v4.5.0
github.com/bloeys/gglm v0.42.0
github.com/inkyblackness/imgui-go/v4 v4.6.0
)

16
go.sum
View File

@ -1,17 +1,17 @@
github.com/bloeys/assimp-go v0.4.2 h1:ArVK74BCFcTO/rCGj2NgZG9xtbjnJdEn5npIeJx1Z04=
github.com/bloeys/assimp-go v0.4.2/go.mod h1:my3yRxT7CfOztmvi+0svmwbaqw0KFrxaHxncoyaEIP0=
github.com/bloeys/gglm v0.41.10 h1:R9FMiI+VQVXAI+vDwCB7z9xqzy5VAR1657u8TQTDNKA=
github.com/bloeys/gglm v0.41.10/go.mod h1:qwJQ0WzV191wAMwlGicbfbChbKoSedMk7gFFX6GnyOk=
github.com/bloeys/gglm v0.42.0 h1:UAUFGTaZv3dpZ0YSIQVum3bdeCZgNmx965VLnD2v11k=
github.com/bloeys/gglm v0.42.0/go.mod h1:qwJQ0WzV191wAMwlGicbfbChbKoSedMk7gFFX6GnyOk=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784 h1:1Zi56D0LNfvkzM+BdoxKryvUEdyWO7LP8oRT+oSYJW0=
github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/inkyblackness/imgui-go/v4 v4.5.0 h1:iUon7q0Hr0c0/Gc2V6bTP7Anu9WH7H26dI7JkPBmMEA=
github.com/inkyblackness/imgui-go/v4 v4.5.0/go.mod h1:g8SAGtOYUP7rYaOB2AsVKCEHmPMDmJKgt4z6d+flhb0=
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk=
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/inkyblackness/imgui-go/v4 v4.6.0 h1:ShcnXEYl80+xREGBY9OpGWePA6FfJChY9Varsm+3jjE=
github.com/inkyblackness/imgui-go/v4 v4.6.0/go.mod h1:g8SAGtOYUP7rYaOB2AsVKCEHmPMDmJKgt4z6d+flhb0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/veandco/go-sdl2 v0.4.10 h1:8QoD2bhWl7SbQDflIAUYWfl9Vq+mT8/boJFAUzAScgY=
github.com/veandco/go-sdl2 v0.4.10/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=
github.com/veandco/go-sdl2 v0.4.25 h1:J5ac3KKOccp/0xGJA1PaNYKPUcZm19IxhDGs8lJofPI=
github.com/veandco/go-sdl2 v0.4.25/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=

115
main.go
View File

@ -36,20 +36,23 @@ import (
// Material system editor with fields automatically extracted from the shader
const (
camSpeed float32 = 15
camSpeed = 15
mouseSensitivity = 0.5
)
var (
window *engine.Window
cam *camera.Camera
pitch float32 = 0
yaw float32 = -90
cam *camera.Camera
simpleMat *materials.Material
cubeMesh *meshes.Mesh
cubeModelMat = gglm.NewTrMatId()
lightPos1 = gglm.NewVec3(2, 2, 0)
lightPos1 = gglm.NewVec3(-2, 0, 2)
lightColor1 = gglm.NewVec3(1, 1, 1)
)
@ -175,8 +178,8 @@ func (g *OurGame) Init() {
// Camera
winWidth, winHeight := g.Win.SDLWin.GetSize()
cam = camera.NewPerspective(
gglm.NewVec3(0, 0, -10),
gglm.NewVec3(0, 0, 1),
gglm.NewVec3(0, 0, 10),
gglm.NewVec3(0, 0, -1),
gglm.NewVec3(0, 1, 0),
0.1, 20,
45*gglm.Deg2Rad,
@ -192,36 +195,28 @@ func (g *OurGame) Init() {
}
func vecRotByQuat(v *gglm.Vec3, q *gglm.Quat) *gglm.Vec3 {
// Reference: https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion
qVec := gglm.NewVec3(q.X(), q.Y(), q.Z())
rotatedVec := qVec.Clone().Scale(2 * gglm.DotVec3(v, qVec))
t1 := q.W()*q.W() - gglm.DotVec3(qVec, qVec)
rotatedVec.Add(v.Clone().Scale(t1))
rotatedVec.Add(gglm.Cross(qVec, v).Scale(2 * q.W()))
return rotatedVec
}
func (g *OurGame) Update() {
if input.IsQuitClicked() || input.KeyClicked(sdl.K_ESCAPE) {
engine.Quit()
}
//Camera movement
if input.KeyDown(sdl.K_w) {
cam.Pos.Add(cam.WorldUp.Clone().Scale(camSpeed * timing.DT()))
updateViewMat()
} else if input.KeyDown(sdl.K_s) {
cam.Pos.Sub(cam.WorldUp.Clone().Scale(camSpeed * timing.DT()))
updateViewMat()
}
if input.KeyDown(sdl.K_d) {
cam.Pos.Add(gglm.Cross(&cam.WorldUp, &cam.Forward).Scale(camSpeed * timing.DT()))
updateViewMat()
} else if input.KeyDown(sdl.K_a) {
cam.Pos.Sub(gglm.Cross(&cam.WorldUp, &cam.Forward).Scale(camSpeed * timing.DT()))
updateViewMat()
}
if input.GetMouseWheelYNorm() > 0 {
cam.Pos.Add(&cam.Forward)
updateViewMat()
} else if input.GetMouseWheelYNorm() < 0 {
cam.Pos.Sub(&cam.Forward)
updateViewMat()
}
g.updateCameraLookAround()
g.updateCameraPos()
//Rotating cubes
if input.KeyDown(sdl.K_SPACE) {
@ -229,10 +224,68 @@ func (g *OurGame) Update() {
simpleMat.SetUnifMat4("modelMat", &cubeModelMat.Mat4)
}
imgui.DragFloat3("Cam Pos", &cam.Pos.Data)
if imgui.DragFloat3("Cam Pos", &cam.Pos.Data) {
updateViewMat()
}
if imgui.DragFloat3("Cam Forward", &cam.Forward.Data) {
updateViewMat()
}
if input.KeyClicked(sdl.K_F4) {
fmt.Printf("Pos: %s; Forward: %s; Forward*WorldUp: %s\n", cam.Pos.String(), cam.Forward.String(), gglm.Cross(&cam.Forward, &cam.WorldUp))
fmt.Printf("Pos: %s; Forward: %s; |Forward|: %f\n", cam.Pos.String(), cam.Forward.String(), cam.Forward.Mag())
}
}
func (g *OurGame) updateCameraLookAround() {
mouseX, mouseY := input.GetMouseMotion()
if mouseX == 0 && mouseY == 0 {
return
}
// Yaw
yaw += float32(mouseX) * mouseSensitivity * timing.DT()
// Pitch
pitch += float32(-mouseY) * mouseSensitivity * timing.DT()
if pitch > 89.0 {
pitch = 89.0
}
if pitch < -89.0 {
pitch = -89.0
}
// Update cam forward
cam.UpdateRotation(pitch, yaw)
updateViewMat()
}
func (g *OurGame) updateCameraPos() {
update := false
// Forward and backward
if input.KeyDown(sdl.K_w) {
cam.Pos.Add(cam.Forward.Clone().Scale(camSpeed * timing.DT()))
update = true
} else if input.KeyDown(sdl.K_s) {
cam.Pos.Add(cam.Forward.Clone().Scale(-camSpeed * timing.DT()))
update = true
}
// Left and right
if input.KeyDown(sdl.K_d) {
cam.Pos.Add(gglm.Cross(&cam.Forward, &cam.WorldUp).Normalize().Scale(camSpeed * timing.DT()))
update = true
} else if input.KeyDown(sdl.K_a) {
cam.Pos.Add(gglm.Cross(&cam.Forward, &cam.WorldUp).Normalize().Scale(-camSpeed * timing.DT()))
update = true
}
if update {
updateViewMat()
}
}