LoginSignup
18
17

More than 5 years have passed since last update.

cl-openglでグラフィックス

Last updated at Posted at 2015-09-05

Qiitaの記事をはじめて書きます。
どうぞ生暖かい目で見てやってください。

common lispでグラフィックスやりましょう。

使うのはcl-openglです、QuickLispを使ってインストールします。

まずはcl-openglをインストールしましょう。
cl-openglと一緒にcl-glutとcl-glutもインストールします。

replを起動して。

(ql:quickload :cl-opengl)
(ql:quickload :cl-glu)
(ql:quickload :cl-glut) 

とするとインストールされます。

画面にグラフィックを描画するための最低限のソースを書いていきます。

glib.lisp
;; Require libralies
(require 'asdf)
(require 'cl-opengl)
(require 'cl-glut)
(require 'cl-glu)

;; Parameters
(defvar *width* 500)
(defvar *height* 500)

;; USER FUNCTIONS
(defun user-display () ())
(defun user-init () ())
(defun user-idle () ())

;; Derived window class
(defclass main-window (glut:window) ()
    (:default-initargs :title "opengl test" :mode '(:double :rgb :depth) :width *width* :height *height*))

;; glut:display
;; Draw.
(defmethod glut:display ((window main-window))
    ;; Clear buffer
    (gl:clear :color-buffer :depth-buffer)

    ;; Draw shape
    ;;(glDisable GL_CULL_FACE)  
    (gl:shade-model :flat)
    (gl:normal 0 0 1)

    ;; user display process
    (user-display)

    ;; Swap buffer
    (glut:swap-buffers))

;; glut:idle
;; Application idle.
(defmethod glut:idle ((window main-window))
    ;; user idling process
    (user-idle)
    (glut:post-redisplay))

;; glut:reshape
(defmethod glut:reshape ((w main-window) width height)
    (gl:viewport 0 0 width height)
    (gl:load-identity)
    (glu:ortho-2d 0.0 *width* *height* 0.0))

;; glut-display
;; Draw.
(defmethod glut:display-window :before ((window main-window)) )

;; main
;; Main function (Program entry point).
(defun main ()
    ;; user initalization process
    (user-init)
    ;;(glut:special-func #'key-special)
    (glut:display-window (make-instance 'main-window)))

gltest.lisp

(load "glib.lisp")

(defun user-init ())

(defun user-idle ()
  (sleep (/ 1.0 60.0)))

(defun user-display ())

では実行してみましょう。

(load "gltest.lisp")
(main)

sample1.png

真っ黒な画面がでてきます。

さて、それではなにか描いてみましょう。
線分を描画する関数を定義します。

;; Draw 2D line.
(defun g2line (x y x2 y2)
    (gl:with-primitives :lines
        (gl:vertex x y 0.0)
        (gl:vertex x2 y2 0.0)))

そしてこんな感じにしてみます。

gltest.lisp
(load "glib.lisp")

(defun user-init ()
  (defparameter *theta* 0.0)
  (defparameter *length* 100.0)
  (defparameter *n* 500)
  (defparameter *pi-part* (/ (* 2.0 PI) *n*))
)

(defun user-idle ()
  (sleep (/ 1.0 60.0)))

(defun user-display ()
  (setf *theta* (+ *theta* 0.01))

  (mapcar 
    (lambda (n)
      (let ((rand-len (random 100)))
        (g2line (/ *width* 2.0)
                (/ *height* 2.0)
                (+ (/ *width* 2.0) (* (cos (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
                (+ (/ *height* 2.0) (* (sin (+ *theta* (* n *pi-part*))) (+ *length* rand-len))))))
    (iota *n*))
)


;; Draw 2D line.
(defun g2line (x y x2 y2)
    (gl:with-primitives :lines
        (gl:vertex x y 0.0)
        (gl:vertex x2 y2 0.0)))

;; iota
(defun iota (m &optional (n 0) (step 1))
  (if (>= n m)
    nil
    (cons n (iota m (+ n step) step))))

sample1.png

ええ、目がチカチカしますね。

線に色をつけるにはこんな感じにします。

;; Draw 2D line.
(defun g2linec (x y x2 y2 r g b)
    (gl:with-primitives :lines
        (gl:color r g b)
        (gl:vertex x y 0.0)
        (gl:vertex x2 y2 0.0))
        (gl:color 1.0 1.0 1.0))
(defun user-display ()
  (setf *theta* (+ *theta* 0.01))

  (mapcar 
    (lambda (n)
      (let ((rand-len (random 100)))
        (g2linec (/ *width* 2.0)
                 (/ *height* 2.0)
                 (+ (/ *width* 2.0) (* (cos (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
                 (+ (/ *height* 2.0) (* (sin (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
                 (random 1.0)
                 (random 1.0)
                 (random 1.0))))
    (iota *n*))
)

sample1.png

もう目がこわれてしまいそうです。

さあ、あなたの目にトドメを刺しましょう ( ̄ー ̄)ニヤリッ

;; draw filled rect
(defun g2fillrectc (x y x2 y2 r g b)
    (gl:with-primitives :polygon
        (gl:color r g b)
        (gl:vertex x y 0.0)
        (gl:vertex x2 y 0.0)
        (gl:vertex x2 y2 0.0)
        (gl:vertex x y2 0.0)
        (gl:color 1.0 1.0 1.0)))

(defun user-display ()
  (setf *theta* (+ *theta* 0.01))

  (g2fillrectc 0.0 0.0 *width* *height* 
               (random 1.0)
               (random 1.0)
               (random 1.0))

  (mapcar 
    (lambda (n)
      (let ((rand-len (random 100)))
        (g2linec (/ *width* 2.0)
                 (/ *height* 2.0)
                 (+ (/ *width* 2.0) (* (cos (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
                 (+ (/ *height* 2.0) (* (sin (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
                 (random 1.0)
                 (random 1.0)
                 (random 1.0))))
    (iota *n*))
)

sample1.png

画像ではわかんないですが、背景がぴかぴかしています。
もう眼球が取れそうです。

さて、今日はここまで。
ここまで読んでくださった皆様、ありがとうございました。

追記1
環境を書き忘れました。
OS:Windows 7 64bit
処理系:SBCL 1.2.15 x86

追記2
cl-openglを使ったグラフィックスライブラリをつくりました。
より手軽にグラフィックスを扱うことができます。

18
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
17