142 lines
2.8 KiB
Go
142 lines
2.8 KiB
Go
package fpscontrols
|
|
|
|
import (
|
|
"math"
|
|
|
|
"github.com/go-gl/glfw/v3.3/glfw"
|
|
"github.com/go-gl/mathgl/mgl32"
|
|
)
|
|
|
|
type FPSControls struct {
|
|
lookSpeed float32
|
|
moveSpeed float32
|
|
|
|
position mgl32.Vec3
|
|
rotation mgl32.Vec2
|
|
|
|
currentMove mgl32.Vec3
|
|
currentLook mgl32.Vec2
|
|
lastMousePos mgl32.Vec2
|
|
|
|
view mgl32.Mat4
|
|
|
|
lastTime float64
|
|
}
|
|
|
|
var instance *FPSControls
|
|
|
|
func (c *FPSControls) Update() {
|
|
time := glfw.GetTime()
|
|
|
|
deltaTime := time - c.lastTime
|
|
c.lastTime = time
|
|
|
|
forward, right, up := c.directions()
|
|
|
|
globalUp := mgl32.Vec3{0, 1, 0}
|
|
move := right.Mul(c.currentMove.X()).Add(globalUp.Mul(c.currentMove.Y())).Add(forward.Mul(c.currentMove.Z()))
|
|
c.position = c.position.Add(move.Mul(float32(deltaTime) * c.moveSpeed))
|
|
|
|
c.rotation = c.rotation.Add(c.currentLook.Mul(float32(deltaTime) * c.lookSpeed))
|
|
c.currentLook = mgl32.Vec2{}
|
|
c.view = mgl32.LookAtV(c.position, c.position.Add(forward), up)
|
|
|
|
}
|
|
|
|
func Get(lookSpeed, moveSpeed float32, position mgl32.Vec3, rotation mgl32.Vec2, window *glfw.Window) *FPSControls {
|
|
if instance != nil {
|
|
return instance
|
|
}
|
|
|
|
instance = &FPSControls{
|
|
moveSpeed: moveSpeed,
|
|
lookSpeed: lookSpeed,
|
|
position: position,
|
|
rotation: rotation,
|
|
}
|
|
|
|
window.SetKeyCallback(func(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
|
|
var val float32
|
|
|
|
switch action {
|
|
case glfw.Repeat:
|
|
return
|
|
case glfw.Press:
|
|
val = 1
|
|
case glfw.Release:
|
|
val = 0
|
|
}
|
|
|
|
switch key {
|
|
case glfw.KeyW:
|
|
instance.currentMove[2] = val
|
|
case glfw.KeyS:
|
|
instance.currentMove[2] = -val
|
|
case glfw.KeyA:
|
|
instance.currentMove[0] = val
|
|
case glfw.KeyD:
|
|
instance.currentMove[0] = -val
|
|
case glfw.KeySpace:
|
|
instance.currentMove[1] = val
|
|
case glfw.KeyLeftShift:
|
|
instance.currentMove[1] = -val
|
|
}
|
|
})
|
|
|
|
window.SetCursorPosCallback(func(window *glfw.Window, y float64, x float64) {
|
|
pos := mgl32.Vec2{float32(x), float32(y)}
|
|
instance.currentLook = instance.lastMousePos.Sub(pos)
|
|
instance.currentLook[0] *= -1
|
|
instance.lastMousePos = pos
|
|
})
|
|
|
|
window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
|
|
|
|
return instance
|
|
}
|
|
|
|
func (c *FPSControls) directions() (mgl32.Vec3, mgl32.Vec3, mgl32.Vec3) {
|
|
rad := mgl32.Vec2{
|
|
mgl32.DegToRad(c.rotation.X()),
|
|
mgl32.DegToRad(c.rotation.Y()),
|
|
}
|
|
|
|
sin := mgl32.Vec2{
|
|
float32(math.Sin(float64(rad.X()))),
|
|
float32(math.Sin(float64(rad.Y()))),
|
|
}
|
|
|
|
cos := mgl32.Vec2{
|
|
float32(math.Cos(float64(rad.X()))),
|
|
float32(math.Cos(float64(rad.Y()))),
|
|
}
|
|
|
|
forward := mgl32.Vec3{
|
|
cos.X() * sin.Y(),
|
|
-sin.X(),
|
|
cos.X() * cos.Y(),
|
|
}
|
|
|
|
right := mgl32.Vec3{
|
|
cos.Y(),
|
|
0,
|
|
-sin.Y(),
|
|
}
|
|
|
|
up := forward.Cross(right)
|
|
|
|
return forward, right, up
|
|
}
|
|
|
|
func (c *FPSControls) View() mgl32.Mat4 {
|
|
return c.view
|
|
}
|
|
|
|
func (c *FPSControls) Position() mgl32.Vec3 {
|
|
return c.position
|
|
}
|
|
|
|
func (c *FPSControls) Rotation() mgl32.Vec2 {
|
|
return c.rotation
|
|
}
|