Levanaバージョン0.2.2リリース、OpenGL APIをバインディング

なんとかリリースできました。
早朝に0.2.1をリリースしたものの、Windows特有の動作バグとかあったので、
修正しまくってバージョン0.2.2としました。
あと、OpenGLのバインディングでLinuxではうまくいってたのに、
何故かWindowsではGLプレフィックスの変数型が色々邪魔して思いの外手間かかりました。
コンパイラが悪いのか、Windows用OpenGLのヘッダファイルが悪いのか……


一応0.1系列からは大幅に機能・仕様変更したので0.2にしたんですが、
未だ不安定版だから奇数で0.3にした方が良かったんだろうか。その辺の感覚がまだ掴めてません。


ずっと開発段階でドキュメントすら書けてないので、大っぴらに宣伝できないしするつもりもないんですが、
興味ある方、一緒に人柱して下さる方は、こちらからダウンロードして試してみて下さい。


https://sourceforge.net/projects/levana/


現状で実装に着手かかってるのが、

  • アプリケーション管理
  • フレーム(ウィンドウ)の生成・破棄
  • メニュー、メニューバー
  • GUIコントロールの幾つか、サイザーによるレイアウト
  • タスクバーアイコン(システムトレイとも言う)
  • イベントハンドリング
  • アイコン
  • OpenGLバインディング


近いうちに実装予定だけど、現状全く手付かずなのが、

  • 画像のロード、ブロック転送
  • サウンド周辺
  • アーカイバ周辺
  • ネットワーク周辺
  • シリアライザ周辺
  • フォント周辺
  • 小物オブジェクトの整備


うーん。この辺の実装済むまではドキュメント書くどころじゃないなぁ……
誰か時間を下さい。


とりあえず、今回のリリースでOpenGLの生APIを叩けるようにしたので、どんな感じで使えるかを紹介しておきます。
実際のリアルタイム処理には、こっちでこさえてるクラスライブラリの機能の中で覆い込むので、
普段使いでGL APIが必要になることは少くなると思うんですが、
高度なエフェクトとか必要になってくる場合の選択肢として用意しておきます。
OpenGLの学習環境としても最適なんじゃないでしょうか。


先ずは簡単なサンプルをば。


[entry.lua]

require 'lev/std'  -- 標準機能(現状ではクラス再ラッピング等)
require 'lev/gl'   -- GL使用モード(現状ではプレフィックスが短くなるだけ)

frm = lev.frame()
draw = lev.draw(frm, 640, 480)
frm:fit()  -- フレームサイズの自動調整。
frm:show()

draw:using()  -- GLコンテキストの設定
-- ただのカラフル正方形だけどコンパイルして記録してみる
gl.newlist(1, gl.COMPILE)
gl.beginprim(gl.QUADS)
  gl.color3ub(255, 0, 0)
  gl.vertex2d(-0.5, -0.5)
  gl.color3ub(0, 255, 0)
  gl.vertex2d(-0.5, 0.5)
  gl.color3ub(255, 255, 0)
  gl.vertex2d(0.5, 0.5)
  gl.color3ub(0, 0, 255)
  gl.vertex2d(0.5, -0.5)
gl.endprim()
gl.endlist()

while frm:exists() do
  draw:using()  -- 基本的に毎回GL API使う前にコンテキスト設定をする
  gl.clearcolor(0, 0, 0, 0)
  gl.clear(gl.COLOR_BUFFER_BIT)  -- とりあえず定数は大文字にしておいた。
  gl.loadidentity()  -- 一応行列操作も大丈夫って事で
  gl.scaled(1.2, 1.5, 0)  -- 伸縮してみたり。
  gl.calllist(1)  -- リスト召喚。関係無いけど小文字のlが3つ並ぶのは見た目良くないよね。
  gl.flush()  -- 描画処理の最後にフラッシュするのはお約束。
  draw:swap()  -- ダブルバッファリングが前提の実装にしようと思ってるのでスワップ。
  -- Luaランタイムが喰ってるメモリ量表示。ステータスバーの操作もプロパティで簡単になりました。
  frm.status = string.format("Used Memory: %d KB", collectgarbage("count"))
  app:yield()
end


OpenGLのAPIは、Levanaをロード(require 'lev/std')した時点で一緒にロードされますが、
levana.glテーブル内に全て設置されるので、毎回こんなプレフィックス書くのは面倒です。
自分で

gl = levana.gl

してもいいんですが、今後LevライブラリでAPIラッピングするかも知れないので一応、

require 'lev/gl'

としておいて下さい。特に配列渡しのあるAPIはLuaが苦手な分野だったりするので。


関数名は基本的に元の名前からglプレフィックスを取り除いて全部小文字にした状態でglテーブルに放りこまれてて、
glLoadIdentityみたいな単語が連続してる場合でも、

gl.loadidentity()

となります。可読性は低いけど記述性は高い。読みにくいって怒らないで下さい。
ただ、この法則でいくとglBeginとglEndの対の場合にキーワード予約されたendが問題おこすので、代わりに、

gl.beginprim(gl.プリミティブ名)

-- ..

gl.endprim()

と書くようにしました。あと、glEnableClientStateは流石に小文字じゃ読みにくいというか関数名長すぎるので、
gl.enable_cstateとしてます。変更の可能性有り。察して下さい。Disableも同様。
定数は見ての通り、GL_プレフィックスを外したものがそのままglテーブルに入ってます。
まだよく使う関数しか放りこんでないですが、リクエストがあればすぐに対応させます。
GLU関数も同様にプレフィックス外して放りこんでく予定ですが、GLUT関数は入れない予定です。


だいたいそんな感じです。