Common Lisp用の軽量グラフィックスライブラリ「Mir」を作りました



# 軽量グラフィックスライブラリ「~~Mir~~Sikisai」

追記：
「Mir」という名前がCanonicalのディスプレイサーバと被っているので名前を「Sikisai」に変えました。
記事の内容は重要な部分については修正してあります。

追記：
fireflower0さんが記事を書いてくださいました。

* [RaspberryPiでグラフィックスライブラリSikisai](https://qiita.com/fireflower0/items/ee7e43345ead8e13b826#_reference-b64dd39e8713d0098283)

追記：
サンプルを動かす動画が投稿されました。

* [Common Lisp sikisai-sample](https://www.youtube.com/watch?v=15VN2QsfTOM)

## 概要

Common Lisp用の軽量グラフィックスライブラリ「~~Mir~~Sikisai」を作りました、GitHubで公開しています。  


* ~~[GitHub - Mir](https://github.com/singy15/mir)~~
* ~~[Github - Mir-sample （デモ）](https://github.com/singy15/mir-sample)~~
* [GitHub - Sikisai](https://github.com/singy15/sikisai)
* [Github - Sikisai-sample （デモ）](https://github.com/singy15/sikisai-sample)

~~Mir~~SikisaiはCommon Lispでグラフィックスを簡単に利用できるようにすることを目指して開発されました。

* OpenGLの知識はないけどグラフィックスを利用したプログラムを作ってみたい
* 複雑なことはしないからとにかく簡単に絵をだしたい

そんな人たちのためのライブラリです。

## 主な機能

![mir-sample.png](https://qiita-image-store.s3.amazonaws.com/0/74246/86f5ece3-8998-495f-c948-4dd2a858b584.png)

* 基本的な図形描画機能
* RAW画像の読込・描画機能
* 文字列描画機能
* キーボード・マウスの入力検出

追記：
3D機能を追加しました。

![sikisai-sample-3d.png](https://qiita-image-store.s3.amazonaws.com/0/74246/07388e20-9660-71bd-6156-5815e19aaaac.png)



## 利用方法

QuickLispに対応していますが、2017/11/11現在、~~Mir~~SikisaiはQuickLispに登録されていません。。。
なので直接cloneして利用します。

```
cd ~/quicklisp/local-projects
git clone https://github.com/singy15/sikisai.git
sbcl
(ql:quickload :sikisai)
```

もしくは、~~Mir~~Sikisaiは1ファイルで構成されるライブラリなので`sikisai.lisp`をダウンロードしてきてasdファイルの`components`に追加することでも動作します。その場合は`depends-on`に`cl-opengl`、`cl-glut`、`cl-glu`を追加してください。

```
; asdファイルのcomponentsに追加
(defsystem sikisai-sample
  :depends-on (:cl-opengl :cl-glut :cl-glu)
  :components (
    (:module "lib"
      :components (
        (:file "sikisai")
      ...
```

freeglutを利用するためWindowsの場合ははfreeglut.dll、Linux系OSの場合はlibfreeglutが必要です。

Windowsの場合は以下のURLからDLLが入手できます。
http://www.transmissionzero.co.uk/software/freeglut-devel/

## サンプルコード

簡単なサンプル。

```cl
(ql:quickload :sikisai)

(defclass window (sik:window) ())

(defmethod sik:user-display ((this window))
  (sik:textb "Hello world!" 100.0 100.0))

(sik:display-window (make-instance 'window))
```

![mir-sample2.png](https://qiita-image-store.s3.amazonaws.com/0/74246/6a5a7cab-164d-96b8-0cd1-33c92097bd23.png)

## 仕組み

基本的には`cl-opengl`をラップしてOpenGLっぽさをある程度隠しているだけなので`cl-opengl`で用意されている機能を直接使うことも可能です。

![mir-structure.png](https://qiita-image-store.s3.amazonaws.com/0/74246/042259e4-0d88-c762-009c-8c688086e37d.png)

## 開発の動機

* Common Lispでグラフィックスって結構めんどい
* 日本語の記事も少なくて調べるの辛い
* OpenGLとかSDLとかよく知らなくても簡単に絵が出せるものがあったらいいな

## TODO

* 3Dへの対応
* RAW以外の形式の画像も読み込みできるようにする
* QuickLispへの登録
* Wikiの作成

## 開発にあたって参考にしたサイト

* cl-openglのリファレンス
http://quickdocs.org/cl-opengl/api

* RAW画像の読み込み方法
http://progn.hateblo.jp/entry/20160913/1473767869

* 画像の描画方法
http://blog.bugyo.tk/lyrical/archives/262

* スクリーン座標系への座標変換
http://brilliantcurtain.web.fc2.com/text/BrightObject/04_mouse_object_put.html

* GLUTの文字列描画機能
http://slis.tsukuba.ac.jp/~fujisawa.makoto.fu/lecture/iml/text/screen_character.html

* FPSの維持
https://ledyba.org/2011/09/03205432.php

追記：

* DXFファイルの読み込み
http://www.komoto.org/opengl/sample11.html

## いろいろ

### 文字列描画機能について

文字列の描画機能についてはfreetypeつかおうかとかglisphつかおうかとかいろいろ悩んだけど、あんまり依存関係増やしたくない、DLL取得してきたりフォント準備したりとかの手間は極力なくしたいという考えがあり、日本語が描画できなかったり、フォントの数が少なかったりといろいろ不便な面はあるけど最低限描画できればいいかと割り切って、GLUTの文字列描画機能を使うことにした。地味にスクリーン座標系からの座標変換に苦労した。

### 画像の描画機能について

正確に言うとテクスチャを張り付けたポリゴンの描画だけど、とりあえず画像の描画ができればいいって人にとっては

1. 画像ファイルの読み込み
2. テクスチャの作成
3. 描画モードの設定（アルファチャンネルの利用のため）
4. 行列のプッシュ
5. プリミティブの描画とテクスチャ位置の設定
6. 行列のポップ
7. 描画モードの設定解除

こんなことをやるのはちょっとだるいのではないかと思っていっそのこと簡略化した。

RAW画像の読み込みはアルファチャンネルがあることが前提になっているのでここは改良の余地ありだと思う。

### FPSの維持について

今の方法は結構簡単で精度の悪い方法を使っているので、もう少し精度がよい方法で実装するべきかと思う。

### 3Dへの対応について

自分がまだプログラミングについて学び始めたばかりのとき、HSP（Hot Soup Processor）というスクリプト言語で3Dグラフィックスを簡単にする[d3Module](http://sprocket.babyblue.jp/html/hsp_d3m.htm)というものがあった、当時のインクルードしてカメラ座標を設定したらもう3Dのオブジェクトが書けるという手軽さに感動した記憶がある。~~Mir~~Sikisaiでもそんなお手軽な3Dグラフィックス描画機能が実現できればとなんとなく考えている。

追記：
簡易3D機能をつけた、開発中のためdevelopブランチにて公開中。

追記：
DXF読込機能をつけた。

### ドキュメント

作者は英作文が苦手です、誰かREADMEの英訳手伝ってくれないかなー。

[追記１]
ta2gchさんが英訳してくれました、とても助かりましたありがとうございます！