1 (defpackage :gtk-glext-demo
2 (:use
:cl
:gtk
:gtkglext
:gobject
:glib
:iter
)
7 (in-package :gtk-glext-demo
)
11 (defun draw (widget event
)
12 (declare (ignore widget event
))
13 (gl:clear-color
0 0 0 0)
17 (gl:shade-model
:smooth
)
18 (gl:light-model
:light-model-local-viewer
1)
19 (gl:color-material
:front
:ambient-and-diffuse
)
20 (gl:enable
:light0
:lighting
:cull-face
:depth-test
)
23 (gl:rotate
*theta
* 1 1 0)
24 (gl:light
:light0
:position
'(0 1 1 0))
25 (gl:light
:light0
:diffuse
'(0.2
0.4 0.6 0))
26 (gl:clear
:color-buffer-bit
:depth-buffer-bit
)
29 (glut:solid-teapot
1.5)
36 (let ((window (make-instance 'gtk-window
38 :window-position
:center
42 (v-box (make-instance 'v-box
))
43 (label (make-instance 'label
:label
"Click me!"))
44 (drawing (make-instance 'gl-drawing-area
:on-expose
#'draw
)))
45 (box-pack-start v-box drawing
)
46 (box-pack-start v-box label
:expand nil
)
47 (container-add window v-box
)
48 (let ((source-id (gtk-main-add-timeout 100 (lambda ()
50 (mod (+ *theta
* 0.5) 360))
51 (widget-queue-draw drawing
)
52 (setf (label-label label
)
53 (format nil
"Theta = ~A" *theta
*))
55 (connect-signal window
"delete-event" (lambda (w e
)
56 (declare (ignore w e
))
57 (g-source-remove source-id
)
59 (widget-show window
:all t
))))
67 (let ((window (make-instance 'gtk-window
68 :window-position
:center
72 (area (make-instance 'gl-drawing-area
:on-expose
#'planet-draw
:on-resize
#'planet-resize
)))
73 (container-add window area
)
74 (pushnew :key-press-mask
(gdk:gdk-window-events
(widget-window window
)))
75 (connect-signal window
"key-press-event"
79 (let ((c (aref (gdk:event-key-string e
) 0)))
81 (#\d
(incf *d
* 10) (widget-queue-draw area
))
82 (#\D
(incf *d
* -
10) (widget-queue-draw area
))
83 (#\y
(incf *y
* 5) (widget-queue-draw area
))
84 (#\Y
(incf *y
* -
5) (widget-queue-draw area
)))))
86 (let ((timer-id (gtk-main-add-timeout 10 (lambda ()
87 (incf *d
* 1) (incf *y
* 0.5)
88 (widget-queue-draw area
)
90 (connect-signal window
"delete-event" (lambda (w e
)
91 (declare (ignore w e
))
92 (g-source-remove timer-id
)
94 (widget-show window
))))
96 (defun planet-draw (w e
)
97 (declare (ignore w e
))
98 (gl:clear-color
0 0 0 0)
99 (gl:shade-model
:flat
)
100 (gl:clear
:color-buffer
)
102 (gl:with-pushed-matrix
104 (gl:translate
0 0 -
2)
106 (glut:wire-sphere
1 20 16)
107 ;; draw smaller planet
108 (gl:rotate
*y
* 0 1 0)
110 (gl:rotate
*d
* 0 1 0)
111 (glut:wire-sphere
0.2 10 8))
114 (defun planet-resize (w width height
)
116 (gl:viewport
0 0 width height
)
117 (gl:matrix-mode
:projection
)
119 (glu:perspective
60 (/ width height
) 1 20)
120 (gl:matrix-mode
:modelview
)
122 (glu:look-at
0 0 5 0 0 0 0 1 0))
124 (defclass opengl-window
(gtk-window)
125 ((expose-fn-text-view :initform
(make-instance 'text-view
) :reader opengl-window-expose-fn-text-view
)
126 (resize-fn-text-view :initform
(make-instance 'text-view
) :reader opengl-window-resize-fn-text-view
)
127 (expose-fn :initform nil
:accessor opengl-window-expose-fn
)
128 (resize-fn :initform nil
:accessor opengl-window-resize-fn
)
129 (drawing-area :initform
(make-instance 'gl-drawing-area
:height-request
100) :reader opengl-window-drawing-area
))
130 (:metaclass gobject-class
)
132 :title
"Lisp interactive OpenGL"
135 :window-position
:center
))
137 (defmethod initialize-instance :after
((window opengl-window
) &key
&allow-other-keys
)
138 (setf (text-buffer-text (text-view-buffer (opengl-window-expose-fn-text-view window
)))
141 (text-buffer-text (text-view-buffer (opengl-window-resize-fn-text-view window
)))
142 ";; Resize-fn. Parameters: w h
144 (let-ui (v-paned :var v
145 (:expr
(opengl-window-drawing-area window
))
146 :resize t
:shrink nil
150 :hscrollbar-policy
:automatic
151 :vscrollbar-policy
:automatic
152 (:expr
(opengl-window-expose-fn-text-view window
)))
153 :resize t
:shrink nil
155 :hscrollbar-policy
:automatic
156 :vscrollbar-policy
:automatic
157 (:expr
(opengl-window-resize-fn-text-view window
)))
158 :resize t
:shrink nil
)
160 (button :label
"Update functions" :var update-fns-button
) :expand nil
161 (button :label
"Redraw" :var redraw-button
) :expand nil
)
163 :resize t
:shrink nil
)
164 (container-add window v
)
165 (connect-signal update-fns-button
"clicked"
168 (update-fns window
)))
169 (connect-signal redraw-button
"clicked"
172 (widget-queue-draw (opengl-window-drawing-area window
))))
173 (let ((area (opengl-window-drawing-area window
)))
174 (setf (gl-drawing-area-on-expose area
)
176 (declare (ignore w e
))
177 (opengl-interactive-on-expose window
))
178 (gl-drawing-area-on-resize area
)
180 (declare (ignore widget
))
181 (opengl-interactive-on-resize window w h
))))))
183 (defun opengl-interactive-on-expose (window)
184 (if (opengl-window-expose-fn window
)
186 (funcall (opengl-window-expose-fn window
))
189 (setf (opengl-window-expose-fn window
) nil
)
190 (progn (gl:clear-color
0 0 0 0)
192 (gl:depth-func
:less
)
194 (gl:shade-model
:smooth
)
195 (gl:light-model
:light-model-local-viewer
1)
196 (gl:color-material
:front
:ambient-and-diffuse
)
197 (gl:enable
:light0
:lighting
:cull-face
:depth-test
)
199 (gl:translate
0 0 -
5)
200 (gl:rotate
*theta
* 1 1 0)
201 (gl:light
:light0
:position
'(0 1 1 0))
202 (gl:light
:light0
:diffuse
'(0.2
0.4 0.6 0))
203 (gl:clear
:color-buffer-bit
:depth-buffer-bit
)
206 (glut:solid-teapot
1.5)
209 (progn (gl:clear-color
0 0 0 0)
211 (gl:depth-func
:less
)
213 (gl:shade-model
:smooth
)
214 (gl:light-model
:light-model-local-viewer
1)
215 (gl:color-material
:front
:ambient-and-diffuse
)
216 (gl:enable
:light0
:lighting
:cull-face
:depth-test
)
218 (gl:translate
0 0 -
5)
219 (gl:rotate
*theta
* 1 1 0)
220 (gl:light
:light0
:position
'(0 1 1 0))
221 (gl:light
:light0
:diffuse
'(0.2
0.4 0.6 0))
222 (gl:clear
:color-buffer-bit
:depth-buffer-bit
)
225 (glut:solid-teapot
1.5)
229 (defun opengl-interactive-on-resize (window w h
)
230 (if (opengl-window-resize-fn window
)
232 (funcall (opengl-window-resize-fn window
) w h
)
235 (setf (opengl-window-resize-fn window
) nil
)
236 (gl:viewport
0 0 w h
)
237 (gl:matrix-mode
:projection
)
239 (glu:perspective
60 (/ w h
) 1 20)
240 (gl:matrix-mode
:modelview
)
243 (gl:viewport
0 0 w h
)
244 (gl:matrix-mode
:projection
)
246 (glu:perspective
60 (/ w h
) 1 20)
247 (gl:matrix-mode
:modelview
)
249 #+nil
(glu:look-at
0 0 5 0 0 0 0 1 0)
252 (defpackage :cl-gtk2-gl-demo-read-package
253 (:use
:cl
:cl-opengl
))
255 (defun read-exprs (string)
256 (with-input-from-string
258 (let ((eof (gensym)))
259 (iter (for expr
= (read stream nil eof
))
260 (until (eq expr eof
))
263 (defun read-fn (string fn-args
)
264 (let ((*package
* (find-package :cl-gtk2-gl-demo-read-package
)))
265 (let ((exprs (read-exprs string
)))
267 (eval `(lambda (,@fn-args
)
270 (defparameter *resize-fn-args
* (list (intern "W" :cl-gtk2-gl-demo-read-package
)
271 (intern "H" :cl-gtk2-gl-demo-read-package
)))
273 (defun update-fns (window)
274 (with-gtk-message-error-handler
275 (let ((expose-fn (read-fn (text-buffer-text (text-view-buffer (opengl-window-expose-fn-text-view window
))) nil
))
276 (resize-fn (read-fn (text-buffer-text (text-view-buffer (opengl-window-resize-fn-text-view window
)))
278 (assert (or (null expose-fn
) (functionp expose-fn
)))
279 (assert (or (null resize-fn
) (functionp resize-fn
)))
280 (setf (opengl-window-expose-fn window
) expose-fn
281 (opengl-window-resize-fn window
) resize-fn
)
282 (widget-queue-draw (opengl-window-drawing-area window
)))))
284 (defun opengl-interactive ()
285 (let ((output *standard-output
*))
287 (setf *standard-output
* output
)
288 (let ((w (make-instance 'opengl-window
)))