2009/04/12

次はダブルバッファ

『OpenGLプログラミングガイド 第2版』の次のサンプル double.c も cl-opengl で書いてみた。

ダブルバッファを使うには defclass の :default-initargs の :mode で :double を指定し、glut:display の最後に glut:swap-buffers を呼ぶ。

ダブルバッファといえば、どうしてトリプルバッファとかは聞かないんだろう、と思っていたが、バッファは2つあれば十分だからなんだ。でも、CPU のマルチコアが進めばマルチバッファも必要になってきたりしないのかな。

あとは、cl-opengl の実装上の選択により、eql スペシャライザのメソッドしかないとそのメソッドは呼び出されなかったりする。気をつけよ。ちょっとの間、CLOS ってそういう仕様っだたかと本気で悩んでしまった。

(eval-when (:compile-toplevel :load-toplevel :execute)
(require :cl-glut))

(defclass double-window (glut:window)
((spin :initform 0.0)
(spin-p :initform nil))
(:default-initargs
:mode '(:double :rgb)))

(defmethod glut:keyboard ((window double-window) key x y)
(declare (ignore x y))
(case key
(#\q (glut:destroy-current-window))))

(defmethod glut:display-window :before ((window double-window))
(%gl:clear-color 0 0 0 0)
(%gl:shade-model :flat))

(defmethod glut:display ((window double-window))
(with-slots (spin) window
(gl:clear :color-buffer-bit)
(gl:with-pushed-matrix
(%gl:rotate-f spin 0.0 0.0 1.0)
(%gl:color-3f 1.0 1.0 1.0)
(%gl:rect-f -25.0 -25.0 25.0 25.0))
(glut:swap-buffers)))

(defgeneric spin-display (window))

(defmethod spin-display ((window double-window))
(with-slots (spin) window
(incf spin 2.0)
(when (< 360.0 spin)
(decf spin 360.0))
(glut:post-redisplay)))

(defmethod glut:reshape ((window double-window) w h)
(%gl:viewport 0 0 w h)
(%gl:matrix-mode :projection)
(%gl:load-identity)
(%gl:ortho -50.0 50.0 -50.0 50.0 -1.0 1.0)
(%gl:matrix-mode :modelview)
(%gl:load-identity))

(defmethod glut:idle ((window double-window))
(with-slots (spin-p) window
(when spin-p
(spin-display window))))

(defmethod glut:mouse ((window double-window)
(button (eql :left-button))
(state (eql :down))
x y)
(with-slots (spin-p) window
(setf spin-p t)))

(defmethod glut:mouse ((window double-window)
(button (eql :middle-button))
(state (eql :down))
x y)
(with-slots (spin-p) window
(setf spin-p nil)))

(defmethod glut:mouse ((window double-window) button state x y)
"cl-opengl の GLUT では eql スペシャライザを使わないメソッドがないと
メソッドが動いてくれないため、この空っぽのメソッドも必要となる。
glut:window にはデフォルトの実装のようなものがない。
display-window :around であらかじめ applicable メソッドを抽出しておく。
といったような理由から。詳細は inteface.lisp を参照"

(declare (ignore button state x y)))

(defun run ()
(glut:display-window (make-instance 'double-window)))
;;(run)


0 件のコメント: