Make navigation actually usable

pull/47/head
rexim 5 years ago
parent 750044855c
commit 4892848c3b

@ -71,7 +71,8 @@ proc draw(screenshot: Image, camera: var Camera, shader, vao, texture: GLuint) =
glUseProgram(shader) glUseProgram(shader)
glUniformMatrix4fv(glGetUniformLocation(shader, "transform".cstring), 1, false, camera.matrix.caddr) glUniform2f(glGetUniformLocation(shader, "cameraPos".cstring), camera.position[0], camera.position[1])
glUniform1f(glGetUniformLocation(shader, "cameraScale".cstring), camera.scale)
glBindVertexArray(vao) glBindVertexArray(vao)
glDrawElements(GL_TRIANGLES, count = 6, GL_UNSIGNED_INT, indices = nil) glDrawElements(GL_TRIANGLES, count = 6, GL_UNSIGNED_INT, indices = nil)
@ -248,7 +249,7 @@ proc main() =
var var
quitting = false quitting = false
camera = Camera(scale: 1.0, matrix: mat4f(1)) camera = Camera(scale: 1.0)
mouse: Mouse mouse: Mouse
while not quitting: while not quitting:
@ -263,13 +264,13 @@ proc main() =
discard discard
of MotionNotify: of MotionNotify:
mouse.curr = vec2(xev.xmotion.x.float32 / screenshot.width.float32 * 2.0'f32 - 1.0'f32, mouse.curr = vec2(xev.xmotion.x.float32,
xev.xmotion.y.float32 / screenshot.height.float32 * 2.0'f32 - 1.0'f32) xev.xmotion.y.float32)
if mouse.drag: if mouse.drag:
let mouseDelta = mouse.prev - mouse.curr let delta = world(mouse.prev, screenshot, camera) - world(mouse.curr, screenshot, camera)
camera.position += mouseDelta camera.position += delta
camera.velocity = mouseDelta * config.dragVelocityFactor camera.velocity = delta * config.dragVelocityFactor
mouse.prev = mouse.curr mouse.prev = mouse.curr
of ClientMessage: of ClientMessage:
@ -316,7 +317,7 @@ proc main() =
else: else:
discard discard
camera.update(config, 1.0 / config.fps.float, mouse) camera.update(config, 1.0 / config.fps.float, mouse, screenshot)
screenshot.draw(camera, shaderProgram, vao, texture) screenshot.draw(camera, shaderProgram, vao, texture)

@ -5,7 +5,6 @@ type Config* = object
dragVelocityFactor*: float dragVelocityFactor*: float
dragFriction*: float dragFriction*: float
scaleFriction*: float scaleFriction*: float
scalePanning*: float
fps*: int fps*: int
const defaultConfig* = Config( const defaultConfig* = Config(
@ -13,7 +12,6 @@ const defaultConfig* = Config(
dragVelocityFactor: 10.0, dragVelocityFactor: 10.0,
dragFriction: 1.0, dragFriction: 1.0,
scaleFriction: 10.0, scaleFriction: 10.0,
scalePanning: 0.05,
fps: 60 fps: 60
) )

@ -1,18 +1,23 @@
import math import math
type Vec2f* = tuple[x: float32, y: float32] type Vec2f* = tuple[x: float32, y: float32]
type Mat4f* = array[0 .. 15, float32]
proc vec2*(x: float32, y: float32): Vec2f = (x, y) proc vec2*(x: float32, y: float32): Vec2f = (x, y)
proc caddr*(a: var Mat4f): ptr float32 =
addr a[0]
proc `*`*(a: Vec2f, s: float32): Vec2f = proc `*`*(a: Vec2f, s: float32): Vec2f =
(a.x * s, a.y * s) vec2(a.x * s, a.y * s)
proc `*`*(a: Vec2f, b: Vec2f): Vec2f =
vec2(a.x * b.x, a.y * b.y)
proc `/`*(a: Vec2f, b: Vec2f): Vec2f =
vec2(a.x / b.x, a.y / b.y)
proc `-`*(a: Vec2f, b: Vec2f): Vec2f = proc `-`*(a: Vec2f, b: Vec2f): Vec2f =
(a.x - b.x, a.y - b.y) vec2(a.x - b.x, a.y - b.y)
proc `+`*(a: Vec2f, b: Vec2f): Vec2f =
vec2(a.x + b.x, a.y + b.y)
proc `+=`*(a: var Vec2f, b: Vec2f) = proc `+=`*(a: var Vec2f, b: Vec2f) =
a.x += b.x a.x += b.x
@ -28,24 +33,6 @@ proc length*(a: Vec2f): float32 =
proc normalize*(a: Vec2f): Vec2f = proc normalize*(a: Vec2f): Vec2f =
let b = a.length let b = a.length
if b == 0.0'f32: if b == 0.0'f32:
return (0.0'f32, 0.0'f32) return vec2(0.0'f32, 0.0'f32)
else: else:
return (a.x / b, a.y / b) return vec2(a.x / b, a.y / b)
proc mat4f*(x: float32): Mat4f =
[x, 0.0'f32, 0.0'f32, 0.0'f32,
0.0'f32, x, 0.0'f32, 0.0'f32,
0.0'f32, 0.0'f32, x, 0.0'f32,
0.0'f32, 0.0'f32, 0.0'f32, x]
proc translate*(mat: Mat4f, x: float32, y: float32, z: float32): Mat4f =
result = mat
result[12] += x
result[13] += y
result[14] += z
proc scale*(mat: Mat4f, s: float32): Mat4f =
result = mat
result[0 * 4 + 0] *= s
result[1 * 4 + 1] *= s
result[2 * 4 + 2] *= s

@ -1,6 +1,7 @@
import math import math
import config import config
import la import la
import image
type Mouse* = object type Mouse* = object
curr*: Vec2f curr*: Vec2f
@ -10,19 +11,22 @@ type Mouse* = object
type Camera* = object type Camera* = object
position*: Vec2f position*: Vec2f
velocity*: Vec2f velocity*: Vec2f
scale*: float scale*: float32
deltaScale*: float deltaScale*: float
matrix*: Mat4f
proc update*(camera: var Camera, config: Config, dt: float, mouse: Mouse) = proc world*(point: Vec2f, image: Image, camera: Camera): Vec2f =
let f = (camera.position + vec2(1.0f32, 1.0f32)) / vec2(2.0f32, 2.0f32)
let ps = vec2(image.width.float32 * camera.scale, image.height.float32 * camera.scale) * f
let ms = vec2(point.x.float32, point.y.float32) + ps
return vec2(ms.x / (image.width.float32 * camera.scale) * 2.0f32 - 1.0f32,
ms.y / (image.height.float32 * camera.scale) * 2.0f32 - 1.0f32)
proc update*(camera: var Camera, config: Config, dt: float, mouse: Mouse, image: Image) =
if abs(camera.deltaScale) > 0.5: if abs(camera.deltaScale) > 0.5:
camera.scale = max(camera.scale + camera.deltaScale * dt, 1.0) # TODO: camera position adjustment doesn't work anymore
if camera.scale > 1.0: camera.scale = max(camera.scale + camera.delta_scale * dt, 1.0)
camera.position += mouse.curr * (camera.deltaScale / camera.scale * config.scalePanning) camera.delta_scale -= sgn(camera.delta_scale).float * config.scale_friction * dt
camera.deltaScale -= sgn(camera.deltaScale).float * config.scaleFriction * dt
if not mouse.drag and (camera.velocity.length > 0.01): if not mouse.drag and (camera.velocity.length > 0.01):
camera.position += camera.velocity * dt camera.position += camera.velocity * dt
camera.velocity -= camera.velocity.normalize * (config.dragFriction * dt) camera.velocity -= camera.velocity.normalize * (config.dragFriction * dt)
camera.matrix = mat4f(1).translate(-camera.position.x, camera.position.y, 0).scale(camera.scale)

@ -2,9 +2,10 @@
in vec3 aPos; in vec3 aPos;
in vec2 aTexCoord; in vec2 aTexCoord;
out vec2 texcoord; out vec2 texcoord;
uniform mat4 transform; uniform vec2 cameraPos;
uniform float cameraScale;
void main() void main()
{ {
gl_Position = transform * vec4(aPos, 1.0f); gl_Position = vec4((aPos.x - cameraPos.x) * cameraScale, (aPos.y + cameraPos.y) * cameraScale, 0.0, 1.0);
texcoord = aTexCoord; texcoord = aTexCoord;
} }

Loading…
Cancel
Save