Quaternion rotations worked

main
Sean Hickey 2021-08-28 13:05:51 -07:00
parent d624077dd1
commit 8fb02993f4
4 changed files with 116 additions and 54 deletions

10
main.go
View File

@ -94,7 +94,7 @@ func run() {
}
gl.UseProgram(program)
projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(width)/float32(height), 0.1, 10.0)
projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(width)/float32(height), 0.01, 1000.0)
projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00"))
gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0])
@ -219,7 +219,7 @@ func handleEvents(running bool, window *sdl.Window, camera *gl_objects.Camera) b
}
if t.Keysym.Sym == sdl.K_w {
if t.Type == sdl.KEYDOWN {
camera.SetZVelocity(-1)
camera.SetZVelocity(1)
} else if t.Type == sdl.KEYUP {
camera.SetZVelocity(0)
}
@ -233,7 +233,7 @@ func handleEvents(running bool, window *sdl.Window, camera *gl_objects.Camera) b
}
if t.Keysym.Sym == sdl.K_s {
if t.Type == sdl.KEYDOWN {
camera.SetZVelocity(1)
camera.SetZVelocity(-1)
} else if t.Type == sdl.KEYUP {
camera.SetZVelocity(0)
} }
@ -260,14 +260,14 @@ func handleEvents(running bool, window *sdl.Window, camera *gl_objects.Camera) b
}
if t.Keysym.Sym == sdl.K_z {
if t.Type == sdl.KEYDOWN {
camera.SetRotationVelocity(1)
camera.SetRotationVelocity(-1)
} else if t.Type == sdl.KEYUP {
camera.SetRotationVelocity(0)
}
}
if t.Keysym.Sym == sdl.K_x {
if t.Type == sdl.KEYDOWN {
camera.SetRotationVelocity(-1)
camera.SetRotationVelocity(1)
} else if t.Type == sdl.KEYUP {
camera.SetRotationVelocity(0)
}

View File

@ -5,29 +5,37 @@ import (
gl "github.com/go-gl/gl/v3.1/gles2"
"github.com/go-gl/mathgl/mgl32"
"gitea.wisellama.rocks/carpy-breakout/pkg/math_helpers"
)
var OriginalDirection mgl32.Vec3 = mgl32.Vec3{0, 0, -1}
/*
Positive X = right
Positive Y = up
Positive Z = backward (outward, towards you)
Negative Z = forwards (inward)
*/
type Camera struct {
Position mgl32.Vec3
Direction mgl32.Vec3
OriginalDirection mgl32.Vec3
Up mgl32.Vec3
OriginalUp mgl32.Vec3
Velocity mgl32.Vec3
Movestep float32
MoveStep float32
RotationVelocity float32
Rotation mgl32.Vec3
RotateStep float32
MouseSensitivity float32
}
func NewCamera() (Camera) {
camera := Camera{}
camera.Up = mgl32.Vec3{0, 1, 0}
camera.Direction = OriginalDirection
camera.Movestep = 0.1
camera.RotateStep = 0.05
camera.OriginalUp = mgl32.Vec3{0, 1, 0}
camera.Direction = mgl32.Vec3{0, 0, -1}
camera.OriginalDirection = mgl32.Vec3{0, 0, -1}
camera.MoveStep = 0.1
camera.RotateStep = 0.02
camera.MouseSensitivity = 0.01
return camera
}
@ -43,42 +51,60 @@ func (c *Camera) Draw(program uint32) {
func (c *Camera) Update() {
c.Rotate(0, 0)
c.Move(c.Velocity.Mul(c.Movestep))
c.Move(c.Velocity)
}
func (c *Camera) Rotate(mouseX, mouseY int32) {
// X mouse movement = rotation about the Y axis
// Y mouse movement = rotation about the X axis
angle := mgl32.Vec3{}
// X Rotation (pitch) - mouse up/down
c.Rotation[0] = c.RotateStep * -1 * float32(mouseY) * .01
xRotate := mgl32.HomogRotate3DX(c.Rotation[0])
c.Up = mgl32.TransformNormal(c.Up, xRotate).Normalize()
c.Direction = mgl32.TransformNormal(c.Direction, xRotate).Normalize()
angle[0] = -1 * float32(mouseY) * c.MouseSensitivity
// Y Rotation (yaw) - mouse left/right
c.Rotation[1] = c.RotateStep * -1 * float32(mouseX) * .01
yRotate := mgl32.HomogRotate3DY(c.Rotation[1])
c.Up = mgl32.TransformNormal(c.Up, yRotate).Normalize()
c.Direction = mgl32.TransformNormal(c.Direction, yRotate).Normalize()
angle[1] = -1 * float32(mouseX) * c.MouseSensitivity
// Z Rotation (roll) - keyboard z/x
c.Rotation[2] = c.RotateStep * c.RotationVelocity
zRotate := mgl32.HomogRotate3DZ(c.Rotation[2])
c.Up = mgl32.TransformNormal(c.Up, zRotate).Normalize()
c.Direction = mgl32.TransformNormal(c.Direction, zRotate).Normalize()
angle[2] = c.RotationVelocity
if angle.LenSqr() == 0 {
return
}
angle = angle.Mul(c.RotateStep)
relativeY := c.Up
relativeZ := c.Direction
relativeX := relativeZ.Cross(relativeY)
quatX := mgl32.QuatRotate(angle.X(), relativeX)
c.Up = quatX.Rotate(c.Up)
c.Direction = quatX.Rotate(c.Direction)
quatY := mgl32.QuatRotate(angle.Y(), relativeY)
c.Up = quatY.Rotate(c.Up)
c.Direction = quatY.Rotate(c.Direction)
quatZ := mgl32.QuatRotate(angle.Z(), relativeZ)
c.Up = quatZ.Rotate(c.Up)
c.Direction = quatZ.Rotate(c.Direction)
}
func (c *Camera) Move(vec mgl32.Vec3) {
// Rotate our movement vector to apply in our current direction
rotation := math_helpers.RotationMatrix(vec, c.Direction)
t := mgl32.TransformCoordinate(vec, rotation)
log.Println(vec)
log.Println(t)
if vec.LenSqr() == 0 {
return
}
// Then translate
translation := mgl32.Translate3D(t.X(), t.Y(), t.Z())
c.Position = mgl32.TransformCoordinate(c.Position, translation)
vec = vec.Normalize()
vec = vec.Mul(c.MoveStep)
perp := c.Direction.Cross(c.Up)
relativeY := c.Up.Mul(vec.Y())
relativeZ := c.Direction.Mul(vec.Z())
relativeX := perp.Mul(vec.X())
relativeMove := mgl32.Vec3{}
relativeMove = relativeMove.Add(relativeX)
relativeMove = relativeMove.Add(relativeY)
relativeMove = relativeMove.Add(relativeZ)
log.Printf("relativeMove = %v, vec = %v", relativeMove.Len(), vec.Len())
c.Position = c.Position.Add(relativeMove)
}
func (c *Camera) SetXVelocity(v float32) {

View File

@ -0,0 +1,51 @@
# How to rotate using Quaternions
https://math.stackexchange.com/a/535223
To answer the question simply, given:
```
P = [0, p1, p2, p3] <-- point vector
R = [w, x, y, z] <-- rotation
R' = [w, -x, -y, -z]
```
For the example in the question, these are:
```
P = [0, 1, 0, 0]
R = [0.707, 0.0, 0.707, 0.0]
R' = [0.707, 0.0, -0.707, 0.0]
```
You can calculate the resulting vector using the Hamilton product H(a, b) by:
```
P' = RPR'
P' = H(H(R, P), R')
```
Performing the calculations:
```
H(R, P) = [0.0, 0.707, 0.0, -0.707]
P' = H(H(R, P), R') = [0.0, 0.0, 0.0, -1.0 ]
```
Thus, the example above illustrates a rotation of 90 degrees about the
y-axis for the point (1, 0, 0). The result is (0, 0, -1). (Note that
the first element of P' will always be 0 and can therefore be
discarded.)
For those unfamiliar with quaternions, it's worth noting that the
quaternion R may be determined using the formula:
```
a = angle to rotate
[x, y, z] = axis to rotate around (unit vector)
R = [cos(a/2), sin(a/2)*x, sin(a/2)*y, sin(a/2)*z]
```
See here for further reference.
http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

View File

@ -1,15 +0,0 @@
package math_helpers
import (
"github.com/go-gl/mathgl/mgl32"
)
func RotationMatrix(a, b mgl32.Vec3) mgl32.Mat4 {
axis := a.Cross(b)
angle := a.Dot(b)
if angle == 0 || axis.LenSqr() == 0 {
return mgl32.Ident4()
} else {
return mgl32.HomogRotate3D(angle, axis)
}
}