mirror of
https://github.com/bloeys/nmage.git
synced 2025-12-29 13:28:20 +00:00
FPS camera with pitch and yaw
This commit is contained in:
@ -38,7 +38,7 @@ type Camera struct {
|
|||||||
// Should be called whenever a camera parameter changes
|
// Should be called whenever a camera parameter changes
|
||||||
func (c *Camera) Update() {
|
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 {
|
if c.Type == Type_Perspective {
|
||||||
c.ProjMat = *gglm.Perspective(c.Fov, c.AspectRatio, c.NearClip, c.FarClip)
|
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) {
|
// UpdateRotation calculates a new forward vector and then calls camera.Update()
|
||||||
c.Forward = *forward
|
func (c *Camera) UpdateRotation(pitch, yaw float32) {
|
||||||
c.WorldUp = *worldUp
|
|
||||||
|
dir := gglm.NewVec3(
|
||||||
|
gglm.Cos32(yaw)*gglm.Cos32(pitch),
|
||||||
|
gglm.Sin32(pitch),
|
||||||
|
gglm.Sin32(yaw)*gglm.Cos32(pitch),
|
||||||
|
)
|
||||||
|
c.Forward = *dir.Normalize()
|
||||||
c.Update()
|
c.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
go.mod
8
go.mod
@ -2,12 +2,12 @@ module github.com/bloeys/nmage
|
|||||||
|
|
||||||
go 1.18
|
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 (
|
require (
|
||||||
github.com/bloeys/assimp-go v0.4.2
|
github.com/bloeys/assimp-go v0.4.2
|
||||||
github.com/bloeys/gglm v0.41.10
|
github.com/bloeys/gglm v0.42.0
|
||||||
github.com/inkyblackness/imgui-go/v4 v4.5.0
|
github.com/inkyblackness/imgui-go/v4 v4.6.0
|
||||||
)
|
)
|
||||||
|
|||||||
16
go.sum
16
go.sum
@ -1,17 +1,17 @@
|
|||||||
github.com/bloeys/assimp-go v0.4.2 h1:ArVK74BCFcTO/rCGj2NgZG9xtbjnJdEn5npIeJx1Z04=
|
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/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.42.0 h1:UAUFGTaZv3dpZ0YSIQVum3bdeCZgNmx965VLnD2v11k=
|
||||||
github.com/bloeys/gglm v0.41.10/go.mod h1:qwJQ0WzV191wAMwlGicbfbChbKoSedMk7gFFX6GnyOk=
|
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 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk=
|
||||||
github.com/go-gl/gl v0.0.0-20211025173605-bda47ffaa784/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
||||||
github.com/inkyblackness/imgui-go/v4 v4.5.0 h1:iUon7q0Hr0c0/Gc2V6bTP7Anu9WH7H26dI7JkPBmMEA=
|
github.com/inkyblackness/imgui-go/v4 v4.6.0 h1:ShcnXEYl80+xREGBY9OpGWePA6FfJChY9Varsm+3jjE=
|
||||||
github.com/inkyblackness/imgui-go/v4 v4.5.0/go.mod h1:g8SAGtOYUP7rYaOB2AsVKCEHmPMDmJKgt4z6d+flhb0=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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/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 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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.25 h1:J5ac3KKOccp/0xGJA1PaNYKPUcZm19IxhDGs8lJofPI=
|
||||||
github.com/veandco/go-sdl2 v0.4.10/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=
|
github.com/veandco/go-sdl2 v0.4.25/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY=
|
||||||
|
|||||||
115
main.go
115
main.go
@ -36,20 +36,23 @@ import (
|
|||||||
// Material system editor with fields automatically extracted from the shader
|
// Material system editor with fields automatically extracted from the shader
|
||||||
|
|
||||||
const (
|
const (
|
||||||
camSpeed float32 = 15
|
camSpeed = 15
|
||||||
|
mouseSensitivity = 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
window *engine.Window
|
window *engine.Window
|
||||||
|
|
||||||
cam *camera.Camera
|
pitch float32 = 0
|
||||||
|
yaw float32 = -90
|
||||||
|
cam *camera.Camera
|
||||||
|
|
||||||
simpleMat *materials.Material
|
simpleMat *materials.Material
|
||||||
cubeMesh *meshes.Mesh
|
cubeMesh *meshes.Mesh
|
||||||
|
|
||||||
cubeModelMat = gglm.NewTrMatId()
|
cubeModelMat = gglm.NewTrMatId()
|
||||||
|
|
||||||
lightPos1 = gglm.NewVec3(2, 2, 0)
|
lightPos1 = gglm.NewVec3(-2, 0, 2)
|
||||||
lightColor1 = gglm.NewVec3(1, 1, 1)
|
lightColor1 = gglm.NewVec3(1, 1, 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -175,8 +178,8 @@ func (g *OurGame) Init() {
|
|||||||
// Camera
|
// Camera
|
||||||
winWidth, winHeight := g.Win.SDLWin.GetSize()
|
winWidth, winHeight := g.Win.SDLWin.GetSize()
|
||||||
cam = camera.NewPerspective(
|
cam = camera.NewPerspective(
|
||||||
gglm.NewVec3(0, 0, -10),
|
gglm.NewVec3(0, 0, 10),
|
||||||
gglm.NewVec3(0, 0, 1),
|
gglm.NewVec3(0, 0, -1),
|
||||||
gglm.NewVec3(0, 1, 0),
|
gglm.NewVec3(0, 1, 0),
|
||||||
0.1, 20,
|
0.1, 20,
|
||||||
45*gglm.Deg2Rad,
|
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() {
|
func (g *OurGame) Update() {
|
||||||
|
|
||||||
if input.IsQuitClicked() || input.KeyClicked(sdl.K_ESCAPE) {
|
if input.IsQuitClicked() || input.KeyClicked(sdl.K_ESCAPE) {
|
||||||
engine.Quit()
|
engine.Quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
//Camera movement
|
g.updateCameraLookAround()
|
||||||
if input.KeyDown(sdl.K_w) {
|
g.updateCameraPos()
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
//Rotating cubes
|
//Rotating cubes
|
||||||
if input.KeyDown(sdl.K_SPACE) {
|
if input.KeyDown(sdl.K_SPACE) {
|
||||||
@ -229,10 +224,68 @@ func (g *OurGame) Update() {
|
|||||||
simpleMat.SetUnifMat4("modelMat", &cubeModelMat.Mat4)
|
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) {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user