(#24) Introduce navigation

pull/31/head
rexim 5 years ago
parent 6e0e8656ce
commit eb67e39fb9

@ -3,12 +3,9 @@ import opengl, opengl/glx
import math import math
import vec2 import vec2
import navigation
const FPS: int = 60 const FPS: int = 60
const SCROLL_SPEED = 1.0
const DRAG_VELOCITY_FACTOR: float = 20.0
const FRICTION: float = 2000.0
const SCALE_FRICTION: float = 5.0
template checkError(context: string) = template checkError(context: string) =
let error = glGetError() let error = glGetError()
@ -21,21 +18,10 @@ type Image* = object
# TODO(#11): is there any way to make image not a global variable in GLUT? # TODO(#11): is there any way to make image not a global variable in GLUT?
var image: Image var image: Image
var camera_position: Vec2 = (0.0, 0.0) var camera = Camera(scale: 1.0)
var camera_prev: Vec2 = (0.0, 0.0) var mouse: Mouse
var camera_velocity: Vec2 = (0.0, 0.0)
var camera_scale = 1.0
var camera_delta_scale = 0.0
var mouse_position = (0.0, 0.0)
var window: Vec2 = (0.0, 0.0) var window: Vec2 = (0.0, 0.0)
var drag: bool = false
proc screen(v: Vec2): Vec2 =
v * camera_scale + camera_position
proc world(v: Vec2): Vec2 =
(v - camera_position) / camera_scale
proc saveToPPM(filePath: string, image: Image) = proc saveToPPM(filePath: string, image: Image) =
var f = open(filePath, fmWrite) var f = open(filePath, fmWrite)
@ -54,8 +40,8 @@ proc display() =
glPushMatrix() glPushMatrix()
glScalef(camera_scale, camera_scale, 1.0) glScalef(camera.scale, camera.scale, 1.0)
glTranslatef(camera_position.x, camera_position.y, 0.0) glTranslatef(camera.position.x, camera.position.y, 0.0)
glBegin(GL_QUADS) glBegin(GL_QUADS)
glTexCoord2i(0, 0) glTexCoord2i(0, 0)
@ -77,21 +63,6 @@ proc display() =
glPopMatrix() glPopMatrix()
proc update(dt: float) =
echo camera_velocity.len
if abs(camera_delta_scale) > 0.5:
let wp0 = mouse_position.world
camera_scale = max(camera_scale + camera_delta_scale * dt, 1.0)
let wp1 = mouse_position.world
let dwp = wp1 - wp0
camera_position += dwp
camera_delta_scale -= sgn(camera_delta_scale).float * SCALE_FRICTION * dt
if not drag and (camera_velocity.len > 20.0):
camera_position += camera_velocity * dt
camera_velocity = camera_velocity - camera_velocity.norm * FRICTION * dt
# TODO(#29): get rid of custom X11 button constants # TODO(#29): get rid of custom X11 button constants
const const
LEFT_BUTTON = 1 LEFT_BUTTON = 1
@ -224,13 +195,13 @@ proc main() =
discard discard
of MotionNotify: of MotionNotify:
mouse_position = (xev.xmotion.x.float, mouse.curr = (xev.xmotion.x.float,
xev.xmotion.y.float) xev.xmotion.y.float)
if drag: if mouse.drag:
camera_position += mouse_position.world - camera_prev.world camera.position += camera.world(mouse.curr) - camera.world(mouse.prev)
camera_velocity = (mouse_position - camera_prev) * DRAG_VELOCITY_FACTOR camera.velocity = (mouse.curr - mouse.prev) * DRAG_VELOCITY_FACTOR
camera_prev = mouse_position mouse.prev = mouse.curr
of ClientMessage: of ClientMessage:
if cast[TAtom](xev.xclient.data.l[0]) == wmDeleteMessage: if cast[TAtom](xev.xclient.data.l[0]) == wmDeleteMessage:
@ -239,24 +210,24 @@ proc main() =
of KeyPress: of KeyPress:
case xev.xkey.keycode case xev.xkey.keycode
of 19: of 19:
camera_scale = 1.0 camera.scale = 1.0
camera_delta_scale = 0.0 camera.delta_scale = 0.0
camera_position = (0.0, 0.0) camera.position = (0.0, 0.0)
camera_velocity = (0.0, 0.0) camera.velocity = (0.0, 0.0)
else: else:
discard discard
of ButtonPress: of ButtonPress:
case xev.xbutton.button case xev.xbutton.button
of LEFT_BUTTON: of LEFT_BUTTON:
camera_prev = mouse_position mouse.prev = mouse.curr
drag = true mouse.drag = true
of WHEEL_UP: of WHEEL_UP:
camera_delta_scale += SCROLL_SPEED camera.delta_scale += SCROLL_SPEED
of WHEEL_DOWN: of WHEEL_DOWN:
camera_delta_scale -= SCROLL_SPEED camera.delta_scale -= SCROLL_SPEED
else: else:
discard discard
@ -264,13 +235,13 @@ proc main() =
of ButtonRelease: of ButtonRelease:
case xev.xbutton.button case xev.xbutton.button
of LEFT_BUTTON: of LEFT_BUTTON:
drag = false mouse.drag = false
else: else:
discard discard
else: else:
discard discard
update(1.0 / FPS.float) camera.update(1.0 / FPS.float, mouse)
display() display()
glXSwapBuffers(display, win) glXSwapBuffers(display, win)

@ -0,0 +1,39 @@
import vec2
import math
const SCROLL_SPEED* = 1.0
const DRAG_VELOCITY_FACTOR*: float = 20.0
const FRICTION*: float = 2000.0
const SCALE_FRICTION*: float = 5.0
type Mouse* = object
curr*: Vec2
prev*: Vec2
drag*: bool
type Camera* = object
position*: Vec2
velocity*: Vec2
scale*: float
delta_scale*: float
proc world*(camera: Camera, v: Vec2): Vec2 =
(v - camera.position) / camera.scale
proc screen*(camera: Camera, v: Vec2): Vec2 =
v * camera.scale + camera.position
proc update*(camera: var Camera, dt: float, mouse: Mouse) =
echo camera.velocity.len
if abs(camera.delta_scale) > 0.5:
let wp0 = camera.world(mouse.curr)
camera.scale = max(camera.scale + camera.delta_scale * dt, 1.0)
let wp1 = camera.world(mouse.curr)
let dwp = wp1 - wp0
camera.position += dwp
camera.delta_scale -= sgn(camera.delta_scale).float * SCALE_FRICTION * dt
if not mouse.drag and (camera.velocity.len > 20.0):
camera.position += camera.velocity * dt
camera.velocity = camera.velocity - camera.velocity.norm * FRICTION * dt
Loading…
Cancel
Save