-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2d-viewer.lisp
191 lines (164 loc) · 5.8 KB
/
2d-viewer.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
;; 2d-viewer.lisp
;;
;; Copyright (c) 2023 Jeremiah LaRocco <[email protected]>
(in-package #:simple-gl)
(defparameter *default-center* (vec2 0.0 0.0))
(defclass 2d-viewer (viewer)
((center-pt
:initform (vec2 0 0)
:type vec2
:initarg :center-pt
:documentation "The point that is transformed to the center of the view.")
(ϴ
:initform 0.0f0
:type real
:initarg :theta
:documentation "The current rotation angle around the center.")
(radius
:initform 100
:type number
:initarg :radius
:documentation "")
(rotation-enabled
:initform t
:type (or t nil)
:initarg :rotation-enabled
:documentation "nil if view rotation is disabled. non-nil if rotation is enabled.")
(zoom
:initform t
:type (or t nil)
:initarg :zoom
:documentation "nil if view zooming is disabled. non-nil if zooming is enabled.")
(pan
:initform t
:type (or t nil)
:initarg :pan
:documentation "nil if view panning is disabled. non-nil if panning is enabled."))
(:documentation "A 2d viewer with panning, zooming and rotation using the 3d mouse and the keyboard."))
(defmethod sgl::view-matrix ((viewer 2d-viewer))
(with-slots (center-pt aspect-ratio width height radius ϴ) viewer
(m*
(if (< width height )
(mortho (- (vx center-pt) radius)
(+ (vx center-pt) radius)
(- (vy center-pt) (* aspect-ratio radius))
(+ (vy center-pt) (* aspect-ratio radius))
(* -100 radius) (* 100 radius))
(mortho (- (vx center-pt) (* aspect-ratio radius))
(+ (vx center-pt) (* aspect-ratio radius))
(- (vy center-pt) radius)
(+ (vy center-pt) radius)
(* -100 radius) (* 100 radius)))
(mrotation (vec3 0 0 1) (* 2 ϴ))
)))
(defmethod sgl::reset-view-safe ((viewer 2d-viewer))
(with-slots (sgl:view-changed center-pt radius ϴ) viewer
(setf center-pt (vec2 0 0)
ϴ 0.0f0
radius 100
view-changed t)))
(defmethod sgl::handle-key ((viewer 2d-viewer) window key scancode action mod-keys)
(declare (ignorable window scancode mod-keys))
(sgl::with-viewer-lock (viewer)
(with-slots (center-pt radius zoom pan sgl:view-changed sgl:objects ) viewer
(let* ((multiplier (if (find :shift mod-keys) 4 1.0))
(offset (/ (* multiplier radius)
30.0)))
(prog1
(cond
((and (eq key :r)
(find action '(:repeat :press)))
(sgl::reset-view-safe viewer)
(setf sgl:view-changed t)
t)
((and pan
(eq key :left)
(find action '(:repeat :press)))
(decf (vx center-pt) offset)
(setf sgl:view-changed t)
t)
((and pan
(eq key :right)
(find action '(:repeat :press)))
(incf (vx center-pt) offset)
(setf sgl:view-changed t)
t)
((and pan
(eq key :up)
(find action '(:repeat :press)))
(incf (vy center-pt) offset)
(setf sgl:view-changed t)
t)
((and pan
(eq key :down)
(find action '(:repeat :press)))
(decf (vy center-pt) offset)
(setf sgl:view-changed t)
t)
((and zoom
(eq key :page-down)
(find action '(:repeat :press)))
(setf radius (+ multiplier radius))
(setf sgl:view-changed t)
t)
((and zoom
(eq key :page-up)
(find action '(:repeat :press)))
(setf radius (max 1
(- radius multiplier)))
(setf sgl:view-changed t)
t)
(t
nil))
(update-all-view-transforms-safe viewer)))))
(call-next-method))
#+spacenav
(defmethod sgl:handle-3d-mouse-event ((viewer 2d-viewer) (event sn:motion-event))
(sgl:with-viewer-lock (viewer)
(with-slots
(center-pt
radius
ϴ
rotation-enabled
zoom
pan
sgl:view-changed) viewer
(with-slots (sn:x sn:y sn:z sn:rx sn:ry sn:rz) event
(let ((n-scale 1/160))
(setf center-pt (if pan
(v+ center-pt
(vec2 (* radius (- sn:x) n-scale)
(* radius (- sn:z) n-scale)))
center-pt)
radius (if zoom
(max 1.0
(+ radius (* radius (+ sn:y) n-scale)))
radius)
ϴ (if rotation-enabled
(mod (+ ϴ
(* sn:ry n-scale))
(* 4 pi))
ϴ)
sgl:view-changed t))))))
#+spacenav
(defmethod handle-3d-mouse-event ((viewer 2d-viewer) (event sn:button-event))
(sgl:with-viewer-lock (viewer)
(with-slots (sgl:view-changed
rotation-enabled
sgl:objects
window) viewer
(cond
((sn:button-press-p event :fit)
(format t ":fit pressed!~%")
(reset-view-safe viewer)
(setf view-changed t)
t)
((sn:button-press-p event :esc)
(format t ":esc pressed!~%")
(glfw:set-window-should-close window)
(setf view-changed t)
t)
((sn:button-press-p event :joystick)
(format t ":joystick pressed!~%")
(setf rotation-enabled (not rotation-enabled))
t)))))