/**/

チュートリアル 40:
jit.gl.sketch を用いた OpenGLでの描画

JitterのOpenGL機能は、私たちに様々な3Dアニメーションシーンを創るための様々なツールを提供します。これまで見てきたOpenGLオブジェクトは、シンプルなジオメトリ(幾何学的図形)を作るもの(jit.gl.gridshape jit.gl.plato)、OBJモデルのインポート(jit.gl.model)、オブジェクトやシーンの位置を操作するもの(jit.gl.handle)といった、それぞれ、かなり簡単なタスクを実行するものでした。より複雑なシーンは、これらのオブジェクトのいくつかを同時に用いて創ることができます。しかし、一定の段階を過ぎると、OpenGLコマンドを直接理解し、多くの描画コマンドを一度に実行できるようなオブジェクトを用いるほうが理にかなっているかも知れません。そんなオブジェクトが jit.gl.sketch であり、それがこのチュートリアルのテーマです。

jit.gl.sketchオブジェクトは他のOpenGLオブジェクトと同様、JitterでのOpenGLシステムに対するインターフェイスとなります。始める前に、「チュートリアル30:3Dテキストの描画」「チュートリアル31:レンダリングのデスティネーション」に目を通しておくとよいかもしれません。さらに、jit.gl.sketch によって理解されるメッセージとアトリビュートは、Max の jsui オブジェクトで用いられる JavaScript sketchオブジェクトのメソッドとプロパティに非常に類似しています。Max チュートリアルマニュアルのチュートリアル51:JavaScript によるユーザ・インターフェイスの設計」はこの両方のシステムに共通したOpenGLベクタグラフィックスの機能に関しての追加情報を与えてくれることでしょう。

jit.gl.sketchで用いられる大多数のメッセージは、標準のOpenGL API関数にわずかな変更を加えたものです。すべてのAPIに関することは、このチュートリアルの範囲外ですが、これらの関数についての標準のリファレンス(the OpenGL "RedBook")は下記のアドレスからオンラインで利用することができます。

http://www.opengl.org/documentation/red_book_1.0/

"RedBook"や他の場所で(C言語で)得られるOpenGLコードと、jit.gl.sketch へのメッセージの間での変換は、次の規則を覚えておけば、かなり簡単に行うことができます。

・すべてのOpenGLコマンドは、jit.gl.sketch では小文字を用います。例えば、OpenGL関数 gColor() はMaxメッセージ gcolor として jit.gl.sketch に送ります。

・OpenGLのシンポル定数は、小文字に直した上に"GL_"というプリフィックスを省きます。従って、例えば、GL_CLIP_PLANE1(OpenGLでの表記)は、jit.gl.sketchで用いられる場合、clip_plane1 となります。

jit.gl.sketchは、基本的なOpenGL APIに加え、多くのハイレベルな描画コマンドを理解し、オブジェクトに対して基本的図形を描画したり、ベクタグラフィックススタイルの描画命令を実行するよう指示します。

・Jitter Tutorialフォルダにある 40jSketch というチュートリアルパッチを開いて下さい。

このチュートリアルパッチは、OpenGLでのレンダリングに使われる一連の Jitterオブジェクト、jit.gl.render オブジェクト、jit.pwindow オブジェクト、jit.gl.sketch オブジェクトからできています。jit.gl.sketch オブジェクトは、コマンドのリストを持ったメッセージボックスオブジェクトが配置された bpatcher オブジェクトからメッセージを送られます。 bpatcher の様々な画面は、接続された ubumenu オブジェクトから異なった「オフセット」を選ぶことによって表示されます。このチュートリアルでは、bpatcher の異なるセクションを順にたどりながら、それぞれの画面に現れるメッセージについて見ていきたいと思います。


jit.gl.sketchオブジェクトは bpatcher 内からメッセージを受け取ります

・パッチャーの左上の qmetro オブジェクトに接続された、Display という表示のある toggle ボックスをクリックして下さい。

qmetro オブジェクトをスタートさせることによって、OpenGL画面のレンダリングが開始されています。jit.gl.render オブジェクトはその名前(sketchy)をパッチの中にある jit.pwindow オブジェクト、および jit.gl.sketch オブジェクトと共有しています。これにより 、jit.pwindow は、jit.gl.render オブジェクトによって描かれるものをすべて表示しますが、これらはjit.gl.sketchオブジェクトの指示によって順に描かれるものです。

コマンドリスト

bpatcher に接続された ubumenu オブジェクトを"one"を読み込むようにセットして下さい。bpatcher オブジェクトはコンマで区切られた一連のメッセージを含んだメッセージボックスを表示します。メッセージボックスをクリックして、その中身を jit.gl.sketch オブジェクトに送って下さい。

緑色の三角形が jit.pwindow に現れるはずです。


jit.gl.sketch への一連のメッセージによって描かれた緑色の三角形

技術的な詳細:jit.gl.sketch オブジェクトはOpenGLのコマンドからなるコマンドリストを保持することによって機能します。そのため、これらのコマンドはシーンが描画されるごとに(このパッチでは、jit.gl.render オブジェクトが bang を受け取るごとに)実行されます。jit.gl.sketch に送るほとんどのメッセージは、このコマンドリストになります。

コマンドリストは、オブジェクトの内部的なメモリエリアに保存されますが、jit.gl.sketchdisplaylist アトリビュートが 1にセットされている場合には、コンピュータのGPUに保存されることもあります。多くのコマンドによって動作する場合、displaylist アトリビュートをオンにすることによってレンダリングのスピードが速くなります。しかし、リストに新しいコマンドが付け加えられると、そのコマンドをGPU上にロードする必要が生じるため、コマンドが非常に速く送られてくる場合には、かえって時間がかかってしまうかもしれません。

メッセージボックスは以下のようなメッセージを順に jit.gl.sketch に送ります。

reset,
glcolor 0 1 0 1,
glbegin line_loop,
glvertex -0.5 -0.5,
glvertex 0 0.5,
glvertex 0.5 -0.5,
glend

jit.gl.sketch へ送られる reset メッセージは、オブジェクトに対して、保持しているコマンドリストをクリアし、再初期化を行うよう指示するだけのものです。その後に続いているものがOpenGLのコマンドです。glcolor コマンドは、 jit.gl.sketch に描画色を変更するよう指示します。JitterのあらゆるOpenGLオブジェクトと同じように、色はRGBA(赤、緑、青、アルファ)の順で、浮動小数点値によって設定されます。従って、glcolor 0 1 0 1 は、jit.gl.sketch に対して完全に不透明な(アルファの値 = 1 )緑色で描画するように指示するものです。

glbegin メッセージは、その後に続く文字列を、オブジェクトを定義する命令として解釈するよう jit.gl.sketch に指示します。glbegin へのアーギュメントはシェイプのレンダリングの際に使用する描画プリミティブを指定します。ここで選ばれているプリミティブ line_loop は点の集合(頂点-vertex-と呼ばれます)を取り、それらを線によって結び、最後の頂点と最初の頂点を結ぶことによってシェイプの描画を完了します。従って、4つの点、A、B、C、D、によるシェイプの場合、オブジェクトはA から B、B から C、C から D、D から Aという線を含みます。

glvertex メッセージは、ここでのシェイプで使われる点の座標値を含んでいます。2つの座標値しか与えられない場合、これらは x と y として解釈されます。3つの座標値が与えられると、3番目の値は z 座標として解釈されます。glend メッセージは jit.gl.sketch に対し、シェイプの定義が終了したことを伝えます。もし必要であれば、ここで次のシェイプ(あるいは他のコマンドの実行)へ移ることができます。

結果として、このパッチのステップ1では、オブジェクトをリセットし、色を緑に設定して、3つの頂点を互いに結ぶ図形の輪郭を描くよう指示していることになります。これらのメッセージは(reset メッセージを除いて)、jit.gl.sketch のコマンドリストを形成し、その結果は jit.pwindow に表示されたイメージになります。

描画プリミティブについての追加

ubumenu オブジェクトを選び、"two"にセットして下さい。bpatcher に現れたメッセージボックスをクリックして下さい。

輪郭のみの三角形が消えて、塗りつぶされた三角形が表示されるはずです。


緑色に塗りつぶされた三角形

メッセージボックスのコマンドリストは、最初のものと非常によく似ています。

reset,
glcolor 0 1 0 1,
glbegin triangles,
glvertex -0.5 -0.5,
glvertex 0 0.5,
glvertex 0.5 -0.5,
glend

もう一度オブジェクトをリセットし、色(緑)の定義を行って、3つの頂点によってオブジェクトを描画しています。ただ一つの違いは、glbegin メッセージのアーギュメントとして指定される描画プリミティブです。この例では、描画プリミティブとして triangles を使用しています。これは、jit.gl.sketch に3つの頂点を三角形として解釈するよう指示します。前のステップでは jit.gl.sketch に図形の輪郭を描画させたのに対し、ここではポリゴンを生成するよう指示しています。結果として、3つの頂点の内部が指定された glcolor (緑色)で塗りつぶされています。

OpenGLが認識する描画プリミティブは10種類あります。これは、結果として jit.gl.renderjit.gl.sketch といったオブジェクトにも適用されます。その10種類とは、points、lines、line_strip、line_loop、triangles、triangles_strip(tri_stripと略記されます)、triangle_fan(tri_fanと略記されます)、quads、quad_strip、polygonです。これらのプリミティブはそれぞれ、一連の頂点を結ぶためのアルゴリズムを指定します。「チュートリアル37:覆いの下のジオメトリ」、およびOpenGL"RedBook"のTable2-2とFigure2-7には、各々に関する説明と例があり、それらの一般的な用法について記述されています。

・チュートリアルパッチの ubumenu オブジェクトを "three"にセットして、bpatcher に現れるメッセージボックスをクリックして下さい。緑一色の三角形に変わって、レインボーカラーの面を持った三角形が表示されるはずです。


異なった色の頂点からなるシェイプ

このコマンドリストでは、三角形の各頂点に対し glcolor コマンドを組み込んでいます。

reset,
glbegin triangles,
glcolor 1 0 0 1,
glvertex -0.5 -0.5,
glcolor 0 1 0 1,
glvertex 0 0.5,
glcolor 0 0 1 1,
glvertex 0.5 -0.5,
glend

この結果、jit.gl.sketch オブジェクトは3つの頂点に対してそれぞれ赤、青、緑をセットし、内部を3つの色の間でなめらかに移行するカラーグラデーションによって充填します。git.gl.sketch smooth_shading アトリビュートが(このチュートリアルパッチの jit.gl.sketch オブジェクトのように) 1 にセットされている場合に、この機能が有効になります

・チュートリアルパッチの ubumenu オブジェクトを"four"にセットして下さい。bpatcher の中の ubumenu を "fill" にセットして下さい。jit.pwindow にはレインボーカラーの面を持った四角形が表示されます。ubumenu を"outline"にセットして下さい。今度は、同じ形のレインボーカラーのアウトライン(輪郭線)だけが表示され、同様に対角線も表示されます。


連結された三角形で構成される四角形、充填されたものとそうでないもの

bpatcher のこのセクションでは、描画プリミティブがより複雑なシェイプを作る場合にどのように働くかを見ることができます。ここでは、コマンドリストを glpolygonmode コマンドから始めていて、jit.gl.sketch に対し、ポリゴンの内部全体を充填するか、アウトラインのままにしておくかを指示しています。アウトライン表示の場合、どのように頂点が連結されるかについての定義の概略がよくわかるようになっています。 glpoligonmonde への最初のアーギュメントは、シェイプの正面について指定するか、背面について指定するか、あるいはその両方について指定するか(ここで用いている front_and_back) を定義します。第2のアーギュメントはシェイプの面が充填されるか( fill )、輪郭線のままにしておくか ( line ) を定義します。JitterのOpenGLオブジェクトの poly_mode アトリビュートを使っても同様な定義ができます。

リセットを行い、どのようにシェイプを描画するか(充填するか、輪郭線だけか)を決定した後、シェイプに関する記述を与えます。

glbegin tri_strip,
glcolor 1 0 0 1,
glvertex -0.5 -0.5,
glcolor 0 1 0 1,
glvertex -0.5 0.5,
glcolor 0 0 1 1,
glvertex 0.5 -0.5,
glcolor 1 1 1 1,
glvertex 0.5 0.5,
glend

前の例での三角形と同様、各 glvertex に対して(この例では、赤、緑、青、白を4つの四角形の4つの点に対して)glcolor を与えます。glbegin のアーギュメントとして使われている tri_strip という描画プリミティブは、jit.gl.sketch に対してシェイプを一連の三角形の連続として描画するよう指定します。これは、三角形の後ろ2つの頂点を再利用して次の三角形を描画するものです。従って、tri_strip プリミティブを使用した場合、6個の頂点A、B、C、D、E、F から成るポリゴンであれば4つの三角形、ABC、CBD、CDE、EDFが描かれることになります。(順番付けの方法は、三角形がすべて同じ方向に描かれることを保証します)。このコードでは、四角形として表示される、連結されて充填された2つの三角形が描画されます。

回転、変形、およびスケーリング(拡大、縮小)

・チュートリアルパッチの ubumenu を"five"にセットして下さい。bpatcher のナンバーボックスをゆっくり0から360まで上げてみて下さい。前の例で示された、レインボーカラーに充填された四角形が再び現れ、時計と反対方向に回転します。


オブジェクトに対してマトリックスの回転が加えられます

頂点座標および色の指定を含むシェイプの定義にだけでなく、これらの図形をオブジェクトとして操作するように、jit.gl.sketch に対して指示することができます。これにより、図形を動かしたりスケーリング(拡大、縮小)することが可能になります。このコマンドリストでは、若干のコマンドを追加することにより、その設定を行っています。

reset,
glmatrixmode modelview,
glpushmatrix,
glrotate $1 0 0 1,

すべてをリセットした後、jit.gl.sketch に対し glmatrixmode メッセージを送り、modelview というマトリックスを定義するために、遠近法的な操作を行う可能性があることを伝えています。これによって、オブジェクトに対する回転、変形、スケーリングを実行することが可能になります。glpushmatix メッセージはカレント(現時点)の modelview マトリックスをスタックにコピーし、それを後で戻すことを可能にします。これによって、複雑なオブジェクトを描画するために、ネスト(入れ子)による変形を作ることができます。例えば、それぞれが前のポリゴンに対して相対的に回転しているような一連のポリゴンを描くことができます。このようにして、他のシェイプのグループとの関係で回転しながら、お互い同士は同じ位置関係を持つシェイプのシーケンスを生成することができます。この処理のためのスタックの使用法は、シェイプの頂点座標として単純な表面としての座標を用いながら、レンダラに対し回転を計算するよう指示することができるため、モデリングに大変役立ちます。glrotate コマンドは、それに続く x, y ,zベクトルをあらわす3つの値によって、回転の度数を指定します。ここではオブジェクトを z 軸について回転(シェイプをスクリーンの x-y 平面上で回転)させています。

回転させた後に、前の例と同様なコマンドリストを続けます。シェイプの指定を行った後、glpopmatrix コマンドによって jit.gl.sketch オブジェクトを前の回転状態に戻し、コマンドリストを完了させています。この後にコマンドリストにつけ加えられる新しいコマンドは、すでに適用されている回転ベクトルではなく、オリジナルの回転ベクトルを用います。

ubumenu を"six"に設定し、bpatcher の中のpak オブジェクトに連結されたナンバーボックスオブジェクトを操作して下さい。ここでは、3つの軸すべてについて四角形の回転を行うことができます。加えて、回転状態を示すガイドとなる単位ベクトルを表す線が描かれます。


ローテーションマトリックスは複数のオブジェクト(四角形と3つのベクトル)に対して適用されます

ここでのコマンドリストは、新しい modelviewl マトリックスを設定し、連続した3回の回転を実行します。

reset,
glmatrixmode modelview,
glpushmatrix,
glrotate $1 1 0 0,
glrotate $2 0 1 0,
glrotate $3 0 0 1,

これによって、パッチのナンバーボックスオブジェクトの値に基づき、x 軸、y 軸、z 軸の順にシェイプを回転させることができます。glpopmatrix を送ってオリジナルの方向に戻す前に、この回転に使用するための4つのオブジェクトを生成しています。四角形が描画された後、それぞれ2つの頂点から成る3本の線を生成していますが、これは、プレーンと同じ軸に沿った方向を持ち、それぞれ異なる色をつけられています。

glcolor 1 0 0 1, glbegin lines, glvertex 0 0 0, glvertex 1 0 0,
glend,
glcolor 0 1 0 1, glbegin lines, glvertex 0 0 0, glvertex 0 1 0,
glend,
glcolor 0 0 1 1, glbegin lines, glvertex 0 0 0, glvertex 0 0 1,
glend,
glpopmatrix

lines という描画プリミティブは、単純にシェイプのすべての頂点をつなげるものです。(line_loop と違って、最後の頂点を最初のものとつなげることはしません)。これらのオブジェクト(そして、四角形)はすべて同 じ modelview マトリックスの中にあるため、同様な回転を共有しているという点に注意して下さい。

ubumenu を"seven"にセットし、bpatcherの中のナンバーボックスオブジェクトを操作して下さい。

色つきの四角形は空間のx軸およびy軸方向へ動くことができます。


このシェイプに対して移動マトリックスが適用されています

イメージの回転に加え、modelview マトリックスはイメージの移動に適用することができます。これによって、オブジェクトの頂点を( 0 , 0 ) を中心として中央に置くよう指定し、空間の好きな場所にオブジェクトを移動させることができます。コマンドリストの gltranslate メッセージは、アーギュメントとして x と y のオフセットを取り、これを移動されるシェイプのすべての頂点に対して適用することで、この機能を実現します。

ubumenuを"eight"に設定し、bpatcherのナンバーボックスオブジェクトを操作して下さい。

色つきの四角形は両軸に対して拡大、縮小されます。


オブジェクトはスケーリング(拡大、縮小)によって変形されます。

1つまたは複数のシェイプに対する回転、移動が可能だったように、glscale メッセージによって、拡大、縮小をコントロールすることも可能です。シェイプの頂点は glscale メッセージのアーギュメントによって(x 軸、y 軸、およびオプションとして z 軸のスケーリング係数を指定することにより)乗じられます。

glrotate、gltranslate、glscale の各コマンドを jit.gl.sketch にどのような順序で送るかは重要なことです。それらは、影響を受けるオブジェクトの最終的な状態を作るために、順番に、累積的に実行されるからです。例えば、頂点座標(0.5, 1)がある場合、この頂点を (0.2 ,0.2)移動して、(1.5, 1.5)でスケーリングすると、最終的な頂点は(1.6, 1.7)になります(訳注:1.05と1.8では?)が、この順序を逆にして操作すると、最終的な頂点は(0.95,1.7)になります。

まとめ

jit.gl.sketch オブジェクトは、パワフルなOpenGL APIへのアクセスを提供し、Maxパッチ内でOpenGLコマンドリストを定義、実行することを可能にします。glbegin と glendメッセージに囲まれ、glvertex メッセージによって指定された頂点のリストはオブジェクトのシェイプ(形状)を指定するために使用できます。glbegin コマンドはそのアーギュメントとして描画プリミティブを取りますが、これらは頂点が連結され、充填されるためのアルゴリズムを定義します。glpolygonmode コマンドを使ってシェイプの構造の輪郭を示すことができます。また gclolr メッセージを使うことにより、頂点、またはシェイプ全体の色を指定することができます。アーギュメント modelview を持った glmatrixbiew コマンドを送ることにより、定義されたシェイプの回転、移動、スケーリング(拡大、縮小)を実行することができます。glrotate、gltranslate、,glscaleコマンドを使用することにより、ビューポート変換を指定することができます。glpushmatrix および glpopmatrix コマンドによって、これらの移動のスタックを定義することができます。これによって、シェイプの回転、位置、サイズをそれぞれ独立に、またはOpenGLコマンドのシーケンス内のネストされたグループとして変更することができます。