第5章 LuaによるCGプログラミング
著者:梅谷 武
語句:ToposNote, Lua, OpenGL, 描画機構, 照明, シェーディング, Lua拡張命令
LuaによるCGプログラミングの概要について述べる。
作成:2009-12-26
更新:2011-03-08
ToposNoteにはLuaインタプリタを拡張したものが組み込まれています。ToposNoteを使うにあたって必ずしもLuaの知識は必要ありませんが、Luaを習得することによってさらに便利なツールとなります。
Lua言語については、文献[
1,
2,
3]のような解説書や多数のWebコンテンツがありますから、本マニュアルではToposNote向け拡張機能についてのみ述べることにします。
Luaを使う際の注意事項として、Luaは日本語に対応していないということがあります。LuaスクリプトはすべてASCIIコードで書かなければなりません。スクリプト中で参照するファイル名、フォルダ名も例外ではありません。
このため、ToposNoteをインストールするフォルダ名、ToposNoteに貼り付けるさまざまなデータを含むフォルダ名もASCIIコードで書かれている必要があります。
OpenGLはコンピュータグラフィックスのためのクロスプラットフォームAPIを定めるもので、現在は
Khronos Groupが管理しています。OpenGLの詳細については、文献[
4]あるいはその原書を読む必要がありますが、これは古典幾何やコンピュータグラフィックスに関する素養、コンピュータアーキテクチャに関する基本知識やC言語によるプログラミングスキルを前提にして、OpenGLというCG専用の状態機械の構造とその機能、プログラミングインターフェースについて説明したもので、誰でもすぐに読めるようなものではありません。
OpenGL入門としては、サンプルとしてOpenGLに添付されているGLUTと呼ばれるC言語のライブラリの使い方を学ぶのが定石です。しかし、これもCコンパイラを使うことが要求されますので、それなりの手間がかかってしまいます。ToposNoteにおいてはスクリプト言語Luaを組み込むことにより、Cコンパイラを使わずに手軽にCGを使えるようにしています。もちろん、高度な使い方をする場合にはC/C++が必要になりますが、そうでなければほとんどの場合はLuaで間に合うでしょう。
OpenGLを学ぶにあたっては、次の三段階を必要に応じて一段ずつ登っていくのが望ましいと思われます。
第一段階
| スクリプト言語による方法
|
第二段階
| C言語による方法
|
第三段階
| GLSLによる方法
|
おそらくほとんどの人はスクリプト言語だけで十分目的を達せられるはずです。
ToposNoteはこの最初の段階をLuaにより提供するもので、C言語に関する知識が無くても使えるようになっています。ToposNoteで感覚的に学んだ後に、C言語で本格的に学ぶと学習効果が上がるでしょう。
本章ではおもにOpenGLとの関係性について解説します。OpenGLをある程度知らないと理解できない部分が多いと思いますが、次章以降で具体例を使って説明します。
ToposNoteに貼り付けられた物体はプログラム内部では、トポスオブジェクトの連想配列としてオブジェクトの種類に固有な方法で格納されています。
ToposNoteの状態が変化し、再描画が必要となったときにイベントが発生し、それをきっかけとしてこの連想配列が走査され、オブジェクトの種類に固有な方法で描画されます。そのイベント発生要因には次の三種類があります。
- デスクトップの状態が変化し、ウィンドウの再描画が必要となった。
- ToposNoteを操作した結果、再描画が必要となった。
- アニメーションタイマーが起動しており、その描画周期が来た。
Wavefront OBJ形式とはOpenGLではよく使われる3Dモデルデータ交換用ファイル形式です。ToposNoteにおいては、これを次のようなデータ群としてメモリ上に格納します。
- 頂点座標配列
- 法線ベクトル配列
- テクスチャ座標配列
- 三角形配列
- 材質・テクスチャ情報
描画するときは、このデータ群を解析し、OpenGL状態機械に対して必要な状態設定命令列を発行した後に、三角形からなる多面体群を描画する命令列を発行します。
JPEG形式の画像が貼り付けられたときには、そのサムネイルをテクスチャとして保持し、描画するときはそれが正規化された長方形に貼り付けられます。
Lua形式は他の形式とは異なり、データではなく、中間言語形式のOpenGL命令列として保存されています。描画するときには、単にこの命令列がそのまま実行されます。
このことにより、OpenGL状態機械をかなり自由に制御できるため、ToposNoteが動作の前提としている既定状態を破壊する可能性があります。これを避けるため、Lua形式においては、変更した状態は必ず元に戻すという原則でプログラミングされなければなりません。
ToposNoteにおいて作図するときには、ユーザーはOpenGLで作図する手順の最初の段階である図形データを世界座標系で定義することだけを行ないます。それ以降の透視変換・クリッピング・ビューポート変換等のパラメータ設定は自動的に行なわれます。
ToposNoteにおいては、照明として白色平行光源が固定され、ユーザーが照明に関知しなくてもいいようになっています。具体的には次のようなパラメータの照明が設定されています。
環境光
| ( 0.6, 0.6, 0.6, 1.0 ) |
拡散光
| ( 1.0, 1.0, 1.0, 1.0 ) |
鏡面光
| ( 0.8, 0.8, 0.8, 1.0 ) |
位置
| ( 50.0, 50.0, 50.0, 0.0 ) |
ユーザーがLuaプログラム中で照明をOFF(シェーディングしない)したい場合は、描画終了時に必ず照明をON(シェーディングする)にしてください。
glDisable( GL_LIGHTING ) シェーディングOFF
描画命令列
glEnable( GL_LIGHTING ) シェーディングON
ToposNoteにおいては、材質特性を有効にするか無効にするかをトポスオブジェクト側の設定にゆだねています。
ToposNoteにおいては、シェーディングはスムースシェーディングに固定されています。
ToposNoteをインストールしたディレクトリがカレントディレクトリとなり、相対パス指定はこれを基準とします。相対パス指定したい場合は、作業ディレクトリをインストールディレクトリ下に置いてください。そうで無い場合は、絶対パス指定してください。
なお、パス指定に日本語は使えませんので注意してください。
ToposNoteには標準のLua5.1が組み込まれていますが、GUIプログラムのため、標準入出力用コンソールを持っていません。したがって、入出力をすべてファイルに対して行なうようにしなければなりません。このようにすれば普通のLuaプログラムもそのまま実行することができます。
ToposNoteにおけるLua拡張命令は、トポスオブジェクトを定義するというToposNoteのアーキテクチャに特化した目的をもつものです。そのためにやや特殊な動作をします。
例で説明します。
(0) 準備
package.path = "std/?.lua" 標準ライブラリパス指定
require( "OpenGL" ) OpenGL定数ファイル
(1) 状態変更
glDisable( GL_LIGHTING ) シェーディングOFF
glEnableClientState( GL_VERTEX_ARRAY ) 頂点配列ON
(2) 頂点定義
glArray( GL_VERTEX_ARRAY, 3, { 頂点配列指定
0.1, 0.1, 0.0,
0.2, 0.2, 0.0,
0.3, 0.3, 0.0
} )
(3) 描画指定
glColor3( 1.0, 0.0, 0.0 ) 描画色指定
glPointSize( 5.0 ) 点の大きさ指定
glDrawElements( GL_POINTS, 3, { 0, 1, 2 } ) 点描画
(4) 状態復帰
glDisableClientState( GL_VERTEX_ARRAY ) 頂点配列OFF
glEnable( GL_LIGHTING ) シェーディングON
(5) トポスオブジェクト生成
tnNewObject()
空間プログラミングに必要なOpenGLの定数ファイルをインクルードします。これはLua標準命令です。
OpenGL状態機械に対して状態変更を指示するGL命令です。
OpenGL状態機械に対して頂点配列を書き込むGL命令です。
OpenGL状態機械に対して描画を指示するGL命令です。
OpenGL状態機械に対して状態復帰を指示するGL命令です。
ToposNoteに対して、GL命令バッファから新しいトポスオブジェクトを生成し、GL命令バッファを消去させるTN命令です。
ToposNoteにおけるLua拡張命令には、TN命令とGL命令の二種類があります。TN命令はToposNote本体プロセスあるいはLua拡張インタプリタスレッドに対する動作指示で、Luaインタプリタで解釈された時点で実行されます。GL命令はOpenGL状態機械に対する命令で、Luaインタプリタでの解釈時には、中間言語に変換されてGL命令バッファに格納されるだけです。TN命令:tnNewObject()が実行されたときに、GL命令バッファ全体が新しいトポスオブジェクトとして生成され、GL命令バッファが消去されます。
ToposNoteはOpenGLと同じ右手系を採用していますが、その実空間との対応が異なっています。このためGL命令を中間言語に変換する際に座標変換を施しています。
引数
| 無し
|
機能
| Windowsにおける一般警告音を発する。
|
引数
| 無し
|
機能
| Windowsにおけるシステムエラー音を発する。
|
引数
| 待ち時間[msec]
|
機能
| 指定時間だけLuaインタプリタスレッドを停止する。
|
引数(1)
| 無し |
引数(2)
| 名前 |
引数(3)
| 名前, Mx, My, Mz, Yaw, Pitch, Roll, Scale |
機能
| GL命令バッファから新しいトポスオブジェクトを生成し、GL命令バッファを消去する。引数で連想配列に登録するときの名前、位置座標、オイラー角、拡大縮小係数を指定することができる。
|
引数
| 名前, Lat, Lng, Alt, Yaw, Pitch, Roll, Scale |
機能
| tnNewObjectにおいて、位置を緯度・経度・標高で指定するときに使う。
|
引数(1)
| 名前, ファイル名 |
引数(2)
| 名前, GPSファイル名, r, g, b, LineWidth |
引数(3)
| 名前, ファイル名, Mx, My, Mz, Yaw, Pitch, Roll, Scale |
機能
| 指定ファイルから指定名の新しいトポスオブジェクトを生成する。引数で連想配列に登録するときの名前、位置座標、オイラー角、拡大縮小係数を指定することができる。GPSファイルにより、GPS軌跡を生成するときは表示線色と線幅を指定する。
|
引数
| 名前, ファイル名, Lat, Lng, Alt, Yaw, Pitch, Roll, Scale |
機能
| tnLoadObjectにおいて、位置を緯度・経度・標高で指定するときに使う。
|
引数(1)
| 名前, 運動軌跡数, 運動軌跡配列
|
引数(2)
| 名前, GPSファイル名
|
機能
| 指定した名前のトポスオブジェクトに運動軌跡を設定する。GPS軌跡ファイルからも運動軌跡を設定することができる。
|
引数
| 名前, ファイル名
|
機能
| 指定した名前のトポスオブジェクトにファイルを関連付ける。
|
引数(1)
| Cx, Cy, Cz |
引数(2)
| Cx, Cy, Cz, Lat, Lng, Zoom, Proj, Coord |
機能
| カーソルを指定位置に移動する。引数にカーソル中心位置、カメラ緯度、カメラ経度、ズーム番号、投影法(0:平面/1:立体)、座標系(0:幾何/1:測地)を指定することができる。
|
引数
| Lat, Lng, Alt |
機能
| tnCursorにおいて、位置を緯度・経度・標高で指定するときに使う。
|
引数
| r, g, b (0.0 ≦ r,g,b ≦ 1.0) |
機能
| RGB形式で色指定する。
|
引数
| H, S, V (0.0 ≦ H ≦ 360.0, 0.0 ≦ S,V ≦ 1.0) |
機能
| HSV形式で色指定する。
|
引数
| r, g, b, a (0.0 ≦ r,g,b,a ≦ 1.0) |
機能
| RGBA形式で色指定する。
|
引数
| 面指定, 種類, r, g, b, a |
面指定
| GL_FRONT/GL_BACK/GL_FRONT_AND_BACK
|
種類
| GL_AMBIENT/GL_DIFFUSE/GL_SPECULAR/GL_SHININESS
|
機能
| OpenGLの照明モデルによる材質指定を行なう。
|
引数
| 材質配列( = {Ra, Ga, Ba, Rd, Gd, Bd, Rs, Gs, Bs, Shininess} )
|
機能
| 材質配列により表面に材質指定する。
|
引数
| GL_TRUE/GL_FALSE
|
機能
| 深度バッファを有効/無効にする。
|
引数
| 現混合法, 新混合法
|
混合法
| GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA,
GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA_SATURATE
|
機能
| 混合法を指定する。
|
引数
| 拡大係数, ビットパターン
|
機能
| 破線形状を指定する。
|
引数
| 面指定, 種類
|
面指定
| GL_FRONT/GL_BACK/GL_FRONT_AND_BACK
|
種類
| GL_POINT/GL_LINE/GL_FILL
|
機能
| 多面体描画法を指定する。
|
引数
| 種類
|
種類
| GL_POINTS, GL_LINE_STRIP,
GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP,
GL_QUADS, GL_POLYGON
|
機能
| 指定した種類の図形定義を開始する。
|
引数
| x, y, z |
機能
| 指定座標の頂点を定義する。
|
引数
| 種類
|
種類
| GL_VERTEX_ARRAY/GL_NORMAL_ARRAY/GL_COLOR_ARRAY
|
機能
| 指定した種類の配列を有効にする。
|
引数
| 種類
|
種類
| GL_VERTEX_ARRAY/GL_NORMAL_ARRAY/GL_COLOR_ARRAY
|
機能
| 指定した種類の配列を無効にする。
|
引数
| 種類, データ数, 配列
|
種類
| GL_VERTEX_ARRAY/GL_NORMAL_ARRAY/GL_COLOR_ARRAY
|
機能
| 指定した種類の配列にデータを書き込む。
|
引数
| 種類, データ数, 配列
|
種類
| GL_POINTS, GL_LINE_STRIP,
GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP,
GL_QUADS, GL_POLYGON
|
機能
| 指定した種類の図形を描画する。
|
引数
| 無し
|
機能
| 変換行列スタックの先頭に単位行列を格納します。
|
引数
| (4,4)行列(C言語形式の16個の数列)
|
機能
| 変換行列スタックの先頭に指定行列を格納します。
|
引数
| (4,4)行列(C言語形式の16個の数列)
|
機能
| 変換行列スタックの先頭に指定行列を右から乗じます。
|
引数
| 無し
|
機能
| 変換行列スタックを一段下に押し下げます。最上位行列はそのまま保持されますので、最上位と二段目には同じ行列が格納されます。
|
引数
| 無し
|
機能
| 変換行列スタックを一段上に押し上げます。最上位行列は破棄され、二段目の行列が最上位に格納されます。
|
引数
| 角度,x,y,z |
機能
| 原点から指定座標までのベクトルを軸とし、指定した角度だけ回転させる行列を、変換行列スタックの先頭に右から乗じます。
|
引数
| 角度
|
機能
| X軸に関して指定した角度だけ回転させる行列を、変換行列スタックの先頭に右から乗じます。
|
引数
| 角度
|
機能
| Y軸に関して指定した角度だけ回転させる行列を、変換行列スタックの先頭に右から乗じます。
|
引数
| 角度
|
機能
| Z軸に関して指定した角度だけ回転させる行列を、変換行列スタックの先頭に右から乗じます。
|
引数
| x,y,z |
機能
| 指定したx,y,z値だけ平行移動させる行列を、変換行列スタックの先頭に右から乗じます。
|
引数
| x,y,z |
機能
| X-Y-Z軸方向に指定したx,y,z値だけ拡大縮小する行列を、変換行列スタックの先頭に右から乗じます。
|
引数
| Mx, My, Mz, 文字列[256文字以下] |
機能
| 指定位置を左下座標とするように指定文字列を視線と垂直に描画する。
|
引数
| x0, y0, x1, y1, w, h, 標高配列 |
機能
| 左下座標(x0, y0)、右上座標(x1, y1)に囲まれる直方体領域内の幅h、高さwの格子点上の標高データを与え、それらを結合する三角形メッシュを描画する。法線ベクトルが自動的に計算され、設定されている材質でシェーディングを行なう。
|
引数
| テクスチャファイル名, x0, y0, x1, y1, w, h, 標高配列 |
機能
| 左下座標(x0, y0)、右上座標(x1, y1)に囲まれる直方体領域内の幅h、高さwの格子点上の標高データを与え、それらを結合する三角形メッシュを描画する。指定したテクスチャが貼り付けられる。
|
引数
| 半径, 経線数, 緯線数[, 形状] |
形状
| GLU_POINT/GLU_LINE/GLU_FILL/GLU_SILHOUETTE
|
機能
| 指定したパラメータの球を描画する。
|
引数
| 底面半径, 天井半径, 高さ, 経線数, 緯線数[, 形状] |
形状
| GLU_POINT/GLU_LINE/GLU_FILL/GLU_SILHOUETTE
|
機能
| 指定したパラメータの円柱を描画する。
|
引数
| 内径, 外径, 経線数, 緯線数[, 形状] |
形状
| GLU_POINT/GLU_LINE/GLU_FILL/GLU_SILHOUETTE
|
機能
| 指定したパラメータの円盤を描画する。
|
引数
| 内径, 外径, 経線数, 緯線数, 開始角, 範囲角[, 形状] |
形状
| GLU_POINT/GLU_LINE/GLU_FILL/GLU_SILHOUETTE
|
機能
| 指定したパラメータの扇形を描画する。
|