2 (in-package :lambdamundo
)
4 (defparameter *one-shot-fn
* nil
)
5 (defparameter *in-main-loop
* nil
)
6 (defparameter *fps
* 0.0)
7 (defparameter *sample-interval
* 100)
8 (defparameter *time-last-sample
* 0)
9 (defparameter *frame
* 0)
10 (defparameter *dalek-md2
* nil
)
11 (defparameter *dalek-mesh
* nil
)
12 (defparameter *dalek-actor
* nil
)
14 ;; callbacks --------------------
16 ;; window size / projection
18 (cffi:defcallback lambdamundo-resize-callback
19 :void
((w :int
) (h :int
))
20 (setf (win-width-of glrepl
:*glwindow
*) w
)
21 (setf (win-height-of glrepl
:*glwindow
*) h
)
27 (gl:with-setup-projection
28 (glu:perspective
45.0 h
/w
0.1 50.0))))
30 ;; (gl:with-setup-projection
31 ;; (gl:frustum (- xmax) xmax (* (- xmax) h/w) (* xmax h/w) znear zfar))
34 ;; (gl:translate-f 0 0 -20)))
39 (cffi:defcallback lambdamundo-char-callback
:void
((key :int
) (action :int
))
40 ;; (format t "Char ~A " key)
41 (when (and glrepl
:*console
* (= action glfw
:+press
+))
42 (let ((c (code-char key
)))
44 (glrepl:add-char glrepl
:*glwindow
* (code-char key
))))))
46 (cffi:defcallback lambdamundo-key-callback
:void
((key :int
) (action :int
))
47 (unless glrepl
:*console
* (when-funcall (gethash key
*standard-key-fns
*) action
))
48 (when glrepl
:*console
* (when-funcall (gethash key
*console-key-fns
*) action
)))
52 (defparameter *mouse-wheel-pos
* 0)
53 (defparameter *mouse-wheel-delta
* 0)
54 (defparameter *mouse-wheel-changed
* nil
)
56 (defun render-debug ()
57 (glrepl::render-string
58 (format nil
"~6,2F ~6,2F ~6,2F ~6,3F " (aref *modelview-debug
* 0) (aref *modelview-debug
* 1) (aref *modelview-debug
* 2) (aref *modelview-debug
* 3))
60 (glrepl::render-string
61 (format nil
"~6,2F ~6,2F ~6,2F ~6,3F " (aref *modelview-debug
* 4) (aref *modelview-debug
* 5) (aref *modelview-debug
* 6) (aref *modelview-debug
* 7))
63 (glrepl::render-string
64 (format nil
"~6,2F ~6,2F ~6,2F ~6,3F " (aref *modelview-debug
* 8) (aref *modelview-debug
* 9) (aref *modelview-debug
* 10) (aref *modelview-debug
* 11))
66 (glrepl::render-string
67 (format nil
"~6,2F ~6,2F ~6,2F ~6,3F " (aref *modelview-debug
* 12) (aref *modelview-debug
* 13) (aref *modelview-debug
* 14) (aref *modelview-debug
* 14))
71 (cffi:defcallback lambdamundo-mouse-wheel-callback
:void
((pos :int
))
72 (setf *mouse-wheel-delta
* (- pos
*mouse-wheel-pos
*))
73 (setf *mouse-wheel-pos
* pos
)
74 (setf *mouse-wheel-changed
* t
))
76 (defun callback-set ()
77 (glfw:set-key-callback
(cffi:callback lambdamundo-key-callback
))
78 (glfw:set-char-callback
(cffi:callback lambdamundo-char-callback
))
79 (glfw:set-mouse-wheel-callback
(cffi:callback lambdamundo-mouse-wheel-callback
))
80 ;; (glfw:set-window-size-callback (cffi:callback lambdamundo-resize-callback))
84 (defun callback-clear ()
85 (glfw:set-key-callback
(cffi:null-pointer
))
86 (glfw:set-char-callback
(cffi:null-pointer
))
87 (glfw:set-window-size-callback
(cffi:null-pointer
))
88 (glfw:set-mouse-wheel-callback
(cffi:null-pointer
)))
90 ;; gl init and de-init --------------------
93 (gl:enable gl
:+texture-2d
+)
94 (gl:enable gl
:+blend
+)
95 (gl:enable gl
:+depth-test
+)
96 (gl:disable gl
:+cull-face
+)
97 (gl:disable gl
:+lighting
+))
101 ;; drawing --------------------
102 ;; each cell will have to know how to cull itself
104 (eval-when ( :load-toplevel
:compile-toplevel
:execute
)
105 (defparameter *draw-fns
* (make-hash-table :test
'equalp
)
106 "An table of functions called in order to render the scene")
108 (defparameter *draw-array
* (make-array 0 :adjustable t
:fill-pointer
0)
109 "An array that indexes *draw-fns* to establish draw order" )
111 (defun extend-draw-array (name priority
)
112 "If the name is in the array, adjust priority, else add it to the array"
113 (assert (not (null (gethash name
*draw-fns
*))) (name) "~S is not a drawable")
116 (position-if #'(lambda (x) (equal (car x
) name
)) *draw-array
*)))
117 (if draw-priority-pos
118 (setf (aref *draw-array
* draw-priority-pos
) (cons name priority
))
119 (vector-push-extend (cons name priority
) *draw-array
*)))))
121 (defmacro make-draw-function
(name priority
&body forms
)
123 (setf (gethash ,name
*draw-fns
*)
124 (compile nil
'(lambda () ,@forms
)))
125 (extend-draw-array ,name
,priority
)
126 (sort *draw-array
* #'(lambda (a b
)
127 (< (car a
) (car b
))))))
129 (defun render-world ()
130 (when (glrepl:*console
*)
131 (gl:disable gl
:+blend
+))
132 (with-camera *camera
*
135 (for entry in-vector
*draw-array
*)
136 (funcall (gethash (car entry
) *draw-fns
*)))
139 (for (key actor
) in-hashtable
*actors
*)
162 (gl:with-begin gl
:+quads
+
163 (gl:color-3f
0.0 1.0 0.0)
168 (apply #'gl
:vertex-3f
(nth (1- vertex
) vertices
)))))))
171 ;; animation --------------------
173 (defun update-world (dt)
174 (when *mouse-wheel-changed
*
175 (pan *camera
* 0.0 (* *mouse-wheel-delta
* dt
))
176 (setf *mouse-wheel-changed
* nil
))
178 (for (key actor
) in-hashtable
*actors
*)
181 (defmacro one-shot
(&rest forms
)
182 `(setf *one-shot-fn
* #'(lambda () ,@forms
)))
184 (defmacro one-shot-compile
(pathname)
185 `(setf *one-shot-fn
* #'(lambda ()
187 (output-file warnings-p failure-p
)
188 (compile-file (merge-pathnames ,pathname
) :verbose t
:print t
)
189 (declare (ignore warnings-p
))
190 (when (not failure-p
)
191 (load output-file
:print t
))))))
194 (defun sample-function (t0)
195 (unless (zerop *frame
*)
196 (format *debug-io
* "Frame ~D " *frame
*)
197 (format *debug-io
* "Elapsed time ~D " (- t0
*time-last-sample
*))
198 (format *debug-io
* "Fps ~D " (/ (- t0
*time-last-sample
*) *sample-interval
*))
199 (format *debug-io
* "Actors ~D~%" (1- (hash-table-size *actors
*))))
200 (setf *time-last-sample
* t0
)
203 :location
(make-vertex3d* 0.0 0.0 0.0 1.0)
204 :orientation
(make-quaternion* 0.0 0.0 0.0 1.0)
209 (vector3d (random 1.0) 0.0 (random 1.0))))))
211 ;; main routine -------------------
213 (let ((t0 (coerce (glfw:get-time
) 'single-float
))
215 (setf *mouse-wheel-pos
* (glfw:get-mouse-wheel
))
216 (setf *mouse-wheel-delta
* 0)
217 (setf glrepl
:*console-render-debug-fn
* #'render-debug
)
219 (gl:clear-color
0.0 0.0 0.0 1.0)
220 (setf *in-main-loop
* t
)
222 (setf glrepl
:*console
* nil
)
224 (while (= (glfw::get-window-param glfw
:+opened
+) glfw
:+true
+))
225 (gl:clear
(logior gl
:+color-buffer-bit
+ gl
:+depth-buffer-bit
+))
226 (setf dt
(- (coerce (glfw:get-time
) 'single-float
) t0
))
227 (setf t0
(coerce (glfw:get-time
) 'single-float
))
228 (when (zerop (mod *frame
* *sample-interval
*))
229 (sample-function t0
))
231 (gl:viewport
0 0 (win-width-of glrepl
:*glwindow
*) (win-height-of glrepl
:*glwindow
*))
232 (gl:matrix-mode gl
:+projection
+)
234 (glu:perspective
45.0 (/ (win-height-of glrepl
:*glwindow
*) (win-width-of glrepl
:*glwindow
*)) 0.1 50.0)
235 (gl:matrix-mode gl
:+modelview
+)
237 (when glrepl
:*console
*
238 (glrepl:render-console
))
240 (funcall *one-shot-fn
*)
241 (setf *one-shot-fn
* nil
))
243 ;; check for time available if time is avaliable render
244 ;; surrender any cpu time..
247 (setf *in-main-loop
* nil
)))
249 (defun begin-swank ()
251 (setf *swank-port
* (swank::start-session
4112))
252 (format t
"Please fire up your emacs and connect.~%")
254 (while (zerop (length swank
::*connections
*)))
258 (format t
"~%Connected.~%")))
261 (when (not (zerop (length swank
::*connections
*)))
262 (swank::end-session
*swank-port
*))
263 (setf *swank-port
* nil
))
267 "Cleanup when something went wrong."
269 (when (not *in-main-loop
*)
271 (destroy-font (font-of glrepl
:*glwindow
*))
273 (for (key actor
) in
*actors
*)
278 ;; to do -- wipe out previous state
280 ;; (setf *bounding-boxes* )
281 ;; (setf *compiled-meshes* )
282 ;; (setf *textures* )
285 ;; wipe out ogl resources
286 (defun glfw-cleanup ()
287 (when (not *in-main-loop
*)
294 (defun lambdamundo ()
297 (setf glrepl
:*glwindow
* (make-instance 'glrepl-window
))
298 (add-line glrepl
:*glwindow
*)
299 (add-line glrepl
:*glwindow
*)
300 (add-string glrepl
:*glwindow
* "(one-shot-compile #P\"mesh-compiler.lisp)\"")
301 (if (glfw:open-window
302 (win-width-of *glwindow
*)
303 (win-height-of *glwindow
*)
306 (glfw:set-window-title
"Lambdmundo")
310 (format t
"Making font..~%")
311 (setf (font-of glrepl
:*glwindow
*) (make-font (merge-pathnames #P
"VeraMono.ttf")))
313 (format t
"Compiling mesh compiler..~%")
314 (gl-ext:load-extension
"ARB_vertex_program")
315 (gl-ext:load-extension
"ARB_vertex_buffer_object")
316 (one-shot-compile #P
"mesh-compiler.lisp")
317 (format t
"Done..~%")
318 (format t
"Loading Dalek.. ~%")
322 (merge-pathnames #P
"dalekx/tris.md2")
324 :element-type
'(unsigned-byte 8))
325 (lodematron:parse-md2-file dalek-md2
)))
326 (format t
"Processing Dalek.. ~%")
327 (setf *dalek-mesh
* (mixamesh:make-mesh
'lodematron
:md2-mesh
))
328 (lodematron::pose
*dalek-md2
* (gethash *dalek-mesh
* *meshes
*) "stand16" "brit")
329 (format t
"Compiling Dalek.. ~%")
330 (mixamesh::make-compiled-mesh
*dalek-mesh
* :skin
(lodematron::skin-of
(gethash *dalek-mesh
* *meshes
*)))
331 (format t
"Dalek compiled into VBO.. ~%")
332 (glfw:swap-interval
1)
333 (glfw:enable glfw
:+key-repeat
+)
335 (set-current-camera (make-camera))
340 (if (= (glfw::get-window-param glfw
:+opened
+) glfw
:+true
+)
345 (error "Failed to open window"))))
346 (error "Failed to init glfw")))
349 ;; (lambdamundo-window ("Lambdamundo"
350 ;; :dimensions (640 480)
351 ;; :colourbits (0 0 0 0)
354 ;; :mode glfw:+window+)
356 ;; (:void ((key :int) (action :int)) )
358 ;; (:void ((width :int) (height :int))
361 ;; ((glfw:enable glfw:+key-repeat+)
362 ;; (glfw:swap-interval 0)
364 ;; (glfw:set-window-size-callback (cffi:callback window-size-callback))
365 ;; (glfw:set-key-callback (cffi:callback key-callback)))
367 ;; ;; to do -- we need to drop in and out of body forms