Common Lisp、cl-openglでマンデルブロ集合を描画した
この記事はりひにーさんのLisp Advent Calendar24日目の記事です。
昨日はりひにーさんの本当はコワイ副作用の恐怖 - 想像力の欠如は深刻な欠点の一つである。でした。
以前(ほとんど1年前ですが)common lispでマンデルブロ集合を計算させました。前は計算結果を書き出してProcessingで描画しましたが、OpenGLを使えるようになったのでcl-opengl(cl-glut)を使ってlispで描画したいと思います。
OSはwindows8.1、処理系はclisp-2.49、エディタはEmacsのSLIME 2.5(たぶん)です。
コードはこちら。
cl-glutによるマンデルブロ集合の描画
下準備
freeglut.dllを用意する。
OpenGLで描画したものをウィンドウなどに表示させるためにfreeglutを使います。そのfreeglutをCommon Lispで扱うcl-glutを使用するためにはfreeglut.dllが必要らしく、これは自分でソースコードからコンパイルして入手する必要があります。ちょっと面倒ですね。検索すればたくさん関連の記事が見つかるので頑張ってください。
コードを書く
コード
OpenGL絡みのところのみを記載します。
(defclass my-window (glut:window) () (:default-initargs :title "mandelbrot" :width *width* :height *height* :mode '(:single :rgb :depth))) (defmethod glut:display-window :before ((w my-window)) (gl:clear-color 1 1 1 0) (gl:matrix-mode :projection) (gl:load-identity) (gl:ortho 0 *width* *height* 0 -1 1)) (defun set-mandelbrot-vertexes (latice-points) (mapcar #'(lambda (x) (let ((latice-point (car x)) (n (cadr x))) (cond ((= n -1) (%gl:color-3f 0 0 0)) (t (%gl:color-3f (* n 0.2) 0 0))) (gl:vertex (* *magnification* (realpart latice-point)) (* *magnification* (imagpart latice-point)) 0))) latice-points)) (defmethod glut:display ((window my-window)) (gl:clear :color-buffer-bit) (%gl:color-3f 0 0 0) (gl:push-matrix) (gl:translate (/ *width* 2) (/ *height* 2) 0) (gl:begin :points) (set-mandelbrot-vertexes *mandelbrot*) (gl:end) (gl:pop-matrix) (gl:flush)) (defparameter *mandelbrot* (get-mandelbrot)) (defun draw-mandelbrot () (glut:display-window (make-instance 'my-window)))
OpenGL、freeglutを触ったことがあればメソッド名はそのままなのであまり問題はないと思います。ウィンドウのクラスを作った後はdisplay、keyboard、reshapeなどのメソッドは書いて評価するだけでよく、登録は必要ないみたいです。スッキリして良いです。
気になったのは%gl:color-3fの部分で、ライブラリの指定に%をつける記法を見たことがありませんでした。ちゃんと調べていないのでまだ何なのかはわかっていません。
注意すべきところは正射影の設定を行うgl:orthoの部分です。サンプルからそのまま持ってきていたりすると画面の両端が-1から1までになってしまったりします。