commit 1ec5b8b3dd5c6bd525846632517b91f1b97d2c84
parent 73e44436dd889b8a44ef3d90175e20983653b7c2
Author: Matsuda Kenji <info@mtkn.jp>
Date: Fri, 8 Nov 2024 11:55:46 +0900
move camera
Diffstat:
3 files changed, 166 insertions(+), 13 deletions(-)
diff --git a/cmd/sample/main.go b/cmd/sample/main.go
@@ -17,6 +17,8 @@ const (
winW, winH = 800, 600
)
+var camera *tofu.Camera
+
func init() {
runtime.LockOSThread()
}
@@ -28,7 +30,8 @@ func framebufferSizeCallback(w *glfw.Window, width int, height int) {
gl.Viewport(0, 0, int32(width), int32(height))
}
-func processInput(w *glfw.Window) {
+func keyboardCallback(w *glfw.Window) {
+ const speed = 0.3
if w.GetKey(glfw.KeyQ) == glfw.Press {
w.SetShouldClose(true)
}
@@ -44,33 +47,106 @@ func processInput(w *glfw.Window) {
alpha = 0
}
}
+ if w.GetKey(glfw.KeyW) == glfw.Press {
+ camera.Move(0, 0, -speed)
+ }
+ if w.GetKey(glfw.KeyS) == glfw.Press {
+ camera.Move(0, 0, speed)
+ }
+ if w.GetKey(glfw.KeyA) == glfw.Press {
+ camera.Move(-speed, 0, 0)
+ }
+ if w.GetKey(glfw.KeyD) == glfw.Press {
+ camera.Move(speed, 0, 0)
+ }
+ if w.GetKey(glfw.KeySpace) == glfw.Press {
+ camera.Move(0, speed, 0)
+ }
+ if w.GetKey(glfw.KeyLeftShift) == glfw.Press {
+ camera.Move(0, -speed, 0)
+ }
+}
+
+var (
+ cursorX, cursorY float32
+ mouseCallbackFirstTime = true
+)
+
+func mouseCallback(w *glfw.Window, x, y float64) {
+ const sensitivity = 0.01
+ if mouseCallbackFirstTime {
+ cursorX, cursorY = float32(x), float32(y)
+ mouseCallbackFirstTime = false
+ return
+ }
+ dx, dy := cursorX - float32(x), float32(y) - cursorY
+ cursorX, cursorY = float32(x), float32(y)
+ dx *= sensitivity
+ dy *= sensitivity
+ camera.Yaw(dx)
+ camera.Pitch(dy)
}
var object = tofu.Object{
Vertices: []tofu.Point3D{
- tofu.Point3D{0.5, 0.5, 0.0},
- tofu.Point3D{0.5, -0.5, 0.0},
- tofu.Point3D{-0.5, -0.5, 0.0},
- tofu.Point3D{-0.5, 0.5, 0.0},
+ tofu.Point3D{0.5, 0.5, -0.5},
+ tofu.Point3D{0.5, -0.5, -0.5},
+ tofu.Point3D{-0.5, -0.5, -0.5},
+ tofu.Point3D{-0.5, 0.5, -0.5},
+ tofu.Point3D{0.5, 0.5, 0.5},
+ tofu.Point3D{0.5, -0.5, 0.5},
+ tofu.Point3D{-0.5, -0.5, 0.5},
+ tofu.Point3D{-0.5, 0.5, 0.5},
},
Colors: []color.Color{
color.RGBA{255, 0, 0, 255},
color.RGBA{0, 255, 0, 255},
color.RGBA{0, 0, 255, 255},
color.RGBA{255, 255, 0, 255},
+ color.RGBA{255, 0, 0, 255},
+ color.RGBA{0, 255, 0, 255},
+ color.RGBA{0, 0, 255, 255},
+ color.RGBA{255, 255, 0, 255},
},
TexCoords: []tofu.Point2D{
tofu.Point2D{1.0, 1.0},
tofu.Point2D{1.0, 0.0},
tofu.Point2D{0.0, 0.0},
tofu.Point2D{0.0, 1.0},
+ tofu.Point2D{1.0, 1.0},
+ tofu.Point2D{1.0, 0.0},
+ tofu.Point2D{0.0, 0.0},
+ tofu.Point2D{0.0, 1.0},
},
Faces: [][3]uint32{
{0, 1, 2},
{0, 2, 3},
+ {0, 1, 5},
+ {0, 5, 4},
+ {1, 2, 6},
+ {1, 6, 5},
+ {2, 3, 7},
+ {2, 7, 6},
+ {3, 0, 4},
+ {3, 4, 7},
+ {4, 5, 6},
+ {4, 6, 7},
},
}
+var cubePositions = []tofu.Vec3{
+ {0, 0, 0},
+ {2, 5, -15},
+ {-1.5, -2.2, -2.5},
+ {-3.8, -2, -12.3},
+ {2.4, -0.4, -3.5},
+ {-1.7, 3.0, -7.5},
+ {1.3, -2.0, -2.5},
+ {1.5, 2.0, -2.5},
+ {1.5, 0.2, -1.5},
+ {-1.3, 1.0, -1.5},
+}
+
var alpha float32 = 0.2
func main() {
@@ -122,18 +198,32 @@ func main() {
if err := program.SetTexture(texture2, "texture2"); err != nil {
log.Fatalf("set texture: %v", err)
}
+ gl.Enable(gl.DEPTH_TEST)
- window.SetFramebufferSizeCallback(framebufferSizeCallback)
+ camera = tofu.NewCamera()
+ camera.MoveTo(tofu.Vec3{0, 0, 3})
+ camera.LookAt(tofu.Vec3{0, 0, 0})
- transform := tofu.Rotate(math.Pi/4, tofu.Vec3{0, 0, 1})
+ window.SetFramebufferSizeCallback(framebufferSizeCallback)
+ window.SetCursorPosCallback(mouseCallback)
+ window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
for !window.ShouldClose() {
- processInput(window)
+ keyboardCallback(window)
gl.ClearColor(0.2, 0.3, 0.3, 1.0)
- gl.Clear(gl.COLOR_BUFFER_BIT)
+ gl.Clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT)
program.SetFloat32("alpha", alpha)
- program.SetMat4("transform", transform)
- gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil)
+ view := camera.View()
+ projection := tofu.Perspective(80*math.Pi/180, 800/600, 0.1, 100)
+ program.SetMat4("view", view)
+ program.SetMat4("projection", projection)
+ for _, p := range cubePositions {
+ model := tofu.Translate(p).
+ Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 0, 1})).
+ Mul(tofu.Rotate(float32(glfw.GetTime()), tofu.Vec3{0, 1, 0}))
+ program.SetMat4("model", model)
+ gl.DrawElements(gl.TRIANGLES, 36, gl.UNSIGNED_INT, nil)
+ }
window.SwapBuffers()
glfw.PollEvents()
}
diff --git a/cmd/sample/vertex.glsl b/cmd/sample/vertex.glsl
@@ -4,9 +4,9 @@ layout (location = 1) in vec3 col;
layout (location = 2) in vec2 vtexCoord;
out vec3 vcol;
out vec2 texCoord;
-uniform mat4 transform;
+uniform mat4 projection, view, model;
void main() {
- gl_Position = transform * vec4(pos, 1.0);
+ gl_Position = projection * view * model * vec4(pos, 1.0);
vcol = col;
texCoord = vtexCoord;
}
diff --git a/math.go b/math.go
@@ -4,6 +4,55 @@ import "math"
type Vec3 [3]float32
+
+func (v Vec3) Normalize() Vec3 {
+ r := float32(math.Sqrt(float64(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])))
+ return Vec3{v[0] / r, v[1] / r, v[2] / r}
+}
+
+func (v Vec3) Add(w Vec3) Vec3 {
+ return Vec3{v[0]+w[0], v[1]+w[1], v[2]+w[2]}
+}
+
+func (v Vec3) Sub(w Vec3) Vec3 {
+ return Vec3{v[0]-w[0], v[1]-w[1], v[2]-w[2]}
+}
+
+func (v Vec3) Inverse() Vec3 {
+ return Vec3{-v[0], -v[1], -v[2]}
+}
+
+func (v Vec3) Cross(w Vec3) Vec3 {
+ return Vec3{
+ v[1]*w[2] - v[2]*w[1],
+ v[2]*w[0] - v[0]*w[2],
+ v[0]*w[1] - v[1]*w[0],
+ }
+}
+
+func (v Vec3) MulF(x float32) Vec3{
+ return Vec3{v[0]*x, v[1]*x, v[2]*x}
+}
+
+type Mat3 [9]float32
+
+func Rotate3(rad float32, axis Vec3) Mat3 {
+ x, y, z := axis[0], axis[1], axis[2]
+ c := float32(math.Cos(float64(rad)))
+ d := 1 - c
+ s := float32(math.Sin(float64(rad)))
+ return Mat3{c + x*x*d, y*x*d + z*s, z*x*d - y*s,
+ x*y*d - z*s, c + y*y*d, z*y*d + x*s,
+ x*z*d + y*s, y*z*d - x*s, c + z*z*d}
+}
+
+func (m Mat3) MulV(v Vec3) Vec3 {
+ return Vec3{
+ m[0]*v[0]+m[3]*v[1]+m[6]*v[2],
+ m[1]*v[0]+m[4]*v[1]+m[7]*v[2],
+ m[2]*v[0]+m[5]*v[1]+m[8]*v[2]}
+}
+
// column major
type Mat4 [16]float32
@@ -42,3 +91,17 @@ func Rotate(rad float32, axis Vec3) Mat4 {
x*z*d + y*s, y*z*d - x*s, c + z*z*d, 0,
0, 0, 0, 1}
}
+
+func Perspective(fov, asp, min, max float32) Mat4 {
+ tan := float32(math.Tan(float64(fov/2)))
+ w := min * tan
+ h := w / asp
+
+ var mat Mat4
+ mat[0] = min / w
+ mat[5] = min / h
+ mat[10] = -(max + min) / (max - min)
+ mat[11] = -1
+ mat[14] = -(2 * min * max) / (max - min)
+ return mat
+}