Pd は音だけでなく画像(静止画・動画)を扱うことも得意としています.ここでは,GEM という画像処理パッケージを使って,画像処理(とくに下図のような3次元グラフィクス)の基礎を学んでいきます.(GEM は Pd-extended に組み込まれていますので,別途インストールする必要はありません.)
- このページで紹介するおもなパッチ:pack3.zip
GEM (Graphics Environment for Multimedia) は,Mark Danks によって開発され,現在は IOhannes m zmölnig によってメンテナンスされている,Pd のための画像処理パッケージ(プラグイン)です.コンピュータグラフィクスの標準的な API である OpenGL の主な機能を Pd からアクセスできるようになっています.
下にあげた簡単なパッチで GEM の基本的な働きを説明しましょう.パッチの左側に,画像表示ウィンドウ [gemwin] があります.[create[ を押すと,GEM という名前のウィンドウ(おそらく真っ黒)が開きます.続いて [1[ を押すことで描画が開始されます.([0[ で描画を停止.[destroy[ で GEM ウィンドウを閉じます.)
描画が開始されると,パッチの右側にある [gemhead] から特殊なメッセージが一定間隔で出力されます.このメッセージは,描画コンテクスト(位置・角度・色など)を表わすものです.これを受け取った [colorRGB 1 0.5 0.5] は,描画コンテクストの色項目を薄赤色に変更して出力します.この描画コンテクストの流れる先が描画オブジェクト [square 1.5] で,下図のように,サイズ 1.5 の正方形を(デフォルト位置の)原点に描画します.(「サイズ」の単位は後述します.)
[gemwin] に create を送ると GEM ウィンドウが開き,さらに 1 を送ることで描画が開始されます.描画が開始されると,毎フレームごと(デフォルトでは 50ms ごと)に [gemhead] から描画コンテクストが出力されます.この描画コンテクストを順次加工していく流れをつくり,その中でさまざまなグラフィクス要素を描画していくことが,GEM による映像制作となります.なお,Pd で生成できる GEM ウィンドウは1つだけです.
上のパッチで [create, 1[ を押せば,GEM ウィンドウが開き,描画が開始されます.毎フレームごとに [gemhead] から描画コンテクストが出力され,前景色として薄赤色が設定され,続いて原点を中心に,数値ボックスに与えられた角度(単位は deg)だけ回転させた「座標系」に,正方形を描画しています.数値ボックスをマウスドラッグしてみてください.
[gemwin] で GEM ウィンドウを生成するとき,よく使う設定項目をまとめておきます.(照明や投影法の設定については後述します.)
- color R G B: 背景色を (R, G, B) に設定する.各成分は 0〜1 の値をとる.初期設定は黒=(0, 0, 0).
- frame フレーム数: 1秒間に描画するフレーム数を設定する.初期設定は 20.(つまり 50ms ごとに描画.)
- dimen 幅 高さ: GEM ウィンドウのサイズを設定する.単位は画面のピクセル数.デフォルトは 500 × 500.GEM ウィンドウを開く前に設定すること.
- offset 横位置 縦位置: GEM ウィンドウの(左上角)の画面位置を設定する.単位は画面のピクセル数で,画面左上角を (0, 0) とする.GEM ウィンドウを開く前に設定すること.
- title 名前: GEM ウィンドウのタイトルバーに名前を設定する.GEM ウィンドウを開く前に設定すること.
- FSAA 整数値: アンチエイリアシング(輪郭のギザギザを緩和すること)を設定する.初期値は 0(オフ)で,整数値 2, 4, 8 を与えることでオンとなる.たとえば 2 の場合,縦横 2 倍の大きさの画面で内部的に描画し,それを元の大きさに(2×2=4 ピクセルごとに平均化して)戻すようになる.GEM ウィンドウを開く前に設定すること.計算量が増えるので注意.
- reset: GEM ウィンドウの設定をデフォルト状態に戻す.(GEM ウィンドウを開く前に設定が必要な項目については,つぎにウィンドウが開かれたときに有効となる.)
描画コンテクストには,色(デフォルトは白=(1, 1, 1))・拡大率(デフォルトは各軸等倍=(1, 1, 1))・姿勢(デフォルトは正立=(0, 0, 0))・位置(デフォルトは原点=(0, 0, 0))などの各パラメタが含まれます.これらパラメタへの操作を積み重ねることで,描画オブジェクトを配置する「場」をつくります.また,パラメタへの操作の流れを分岐させ,複数の描画オブジェクトの間に相対的な関係(たとえば太陽・惑星・衛星のような従属関係)を与えることができます.
上のパッチにあるように,描画コンテクストへの操作を分岐させ,その先に異なる座標変換を積み重ねていく場合は,それぞれの支流の先頭に [separator] を配置します.[separator] よりも下流域は,他の支流での座標変換から影響を受けなくなります.3つの数値ボックスの値を増減させて,3つの正方形がどのような位置関係に描画されるのかを確かめてみてください.
このパッチにおける描画オブジェクトの位置関係は,下図とあわせて,つぎのように説明できます.まず (1) GEM ウィンドウの中央を原点とする座標系をイメージしてください.横軸が X 軸,縦軸が Y 軸となり,Z 軸はその交点を通る手前向きの垂直軸となります.(2) [rotateXYZ] に Z=20 を与えることで,この座標系を Z 軸を中心に(XY 平面上で)20deg 回転させた,新しい座標系を得ます.上段左側の [separator] 以下では,この新しい座標系で (0.8, 0.8), (0.8, −0.8), (−0.8, −0.8), (−0.8, 0.8) を頂点とする正方形を薄赤色で描画します.上段右側の [separator] 以下では,(3) [translateXYZ] に X=2.5 を与えることで,この座標系を X 方向に 2.5 だけ平行移動させた新しい座標系を得ます.さらに,(4) この座標系を Z 軸まわりに 30deg 回転させた,新しい座標系を得ます.下段左側の [separator] 以下では,この座標系の中心にサイズ 0.4 の正方形を薄緑色で描画します.下段右側の [separator] 以下では,(5) この座標系を X 方向に 1 だけ平行移動させ,さらに (6) Z 軸まわりに 40deg 回転させた新しい座標系を得て,その中央にサイズ 0.2 の正方形を薄青色で描画します.
このように,座標系を平行移動させたり回転させたり,あるいは拡大・縮小させることで,新しい座標系をつくり,そこに描画オブジェクトを配置したり,さらに別の座標系を派生させることが,GEM(そして OpenGL)における画像生成の基本プロセスとなります.
接続線を流れる描画コンテクストは,実際には,描画位置・角度・色といった GEM の内部データへのポインタです.[gemhead] は,フレーム (50ms) ごとに白紙(デフォルト状態)の描画コンテクストを GEM 内部に生成し,それへのポインタを出力します.[separate] は,入力された描画コンテクストの中で座標系のデータを一時保存し,それ以降の処理が終わった後で,一時保存した部分を元の描画コンテクストに戻します.
いままでのパッチはすべて3次元空間に描画オブジェクトを配置していました.gem-test3.pd をわずかに改造した下のパッチで,これを確かめてみます.上段中央にある新しい数値ボックスは,出発点となる座標軸を Y 軸回りに回転させる角度を与えるものです.軸上でプラスの方向に進むネジの回転方向がプラスの角度となります.
このパッチで,Y 軸まわりに 50deg だけ回転させると,下図のような結果が得られます.デフォルト状態では,視点は (0, 0, 4) の位置にあり,視線は原点 (0, 0, 0) を向き,Y軸方向が上になるように透視投影 (perspective projection) されます.もちろん視点の位置や視線の向きは自由に変えることもできます.この3次元空間の中で,[square] などの描画オブジェクトは,すべて XY 平面上(Z=0)に配置されていました.(薄赤色の正方形の中心が原点 (0, 0, 0) となっています.)
つぎに,[square]を厚みをもった描画オブジェクトに置き換えてみます.[cube S] は各軸それぞれに −S〜S の範囲をとる立方体です.
上のパッチによって下図のようなグラフィック表示が得られます.画面中央の薄赤色の立方体は1面しか見せていませんが,他の2つは3面を見せています. パッチ上段左側にある数値ボックスを操作して,全体を Y 軸まわりに回転させてみてください.
上の例では,斜めから見た立方体がその3面あるいは2面を見せていますが,どの面も同じ色・明るさで表示されているので,やや不自然に見えます.これは,まだ照明 (lighting) の機能をオンにしていないためです.照明への応答をオンにするには,[gemwin] に {lighting 1} を送ります.また,照明となる光源を入れる必要もあります.下のパッチでは,無限遠からの平行光線を発生させる [world_light] を導入しています.デフォルトでは (0, 0, 1) が光の進む方向ですが,ここではそれを X 軸まわりに −30deg,続いて Y 軸まわりに 15deg だけ回転させています.およそ,手前側の右斜め上からの光です.
パッチ左上側の [toggle] で,照明機能をオンにしてください.3つの立方体が,手前側の右斜め上からの光を受けて,その各面の明度を変化させているのがわかります.照明には,無限遠の [world_right] のほかに,空間内の1点に置かれた点光源の [light] があります.いずれも {debug 1} を与えることで,光源の方向または位置を表示できます.[trigger] を使うことで,照明をつけてから描画するようにしています.
上のパッチで,[cube] を [sphere] に置き換えてみてください.球が配置されます.デフォルトでは表面が粗いので,たとえば [sphere 0.8 32] のように,分割数(円を多角形で近似するときの頂点数)を引数に追加するとよいでしょう.
2011年5月の時点での GEM 最新版 (0.92.3) には,円錐 (cone) と円柱 (cylinder) の照明に対する応答(明度計算)にバグがあり,自然な陰影がつきません.このバグは次のリリースで修正される予定です.それまでは,直前に [scaleXYZ -1 -1 -1] を入れることで補正してください.
描画コンテクストに操作 (Manips: manipulations) を加え,そこに描画オブジェクト (Geos: geometrical objects) を配置することが,GEM(そして OpenGL)におけるグラフィクス生成の基本的な手順です.ここでは,描画コンテクストの操作 (Manips) について解説していきます.(なお,以下の一覧のなかで括弧に入れられた引数は省略できます.省略した場合はデフォルト値が使われます.いつでも入力端子から上書きできます.)
描画コンテクストの操作には,座標変換と色変換があります.まず座標変換について,参考パッチ gem-coord.pd を使って,以下の操作 (Manips) を解説します.座標変換を積み重ね,必要に応じて [separator] によって分岐させることで,描画オブジェクトの位置や姿勢を決めていきます.
-
[rotateXYZ (AX AY AZ)]
座標系を X 軸まわりに AX だけ回転させ,つぎに Y 軸まわりに AY だけ回転させ,さらに Z 軸まわりに AZ だけ回転させます.いずれも単位は度 (deg) で,軸上でプラスの方向に進むネジの回転方向がプラスの角度となります.AX, AY, AZ は引数として与えるか,コールド入力端子から与えます.デフォルト状態は AX=0, AY=0, AZ=0 です.
左下の図は,X 軸(赤)まわりに 30deg の回転 (AX=30) を与えた場合(つまり [rotateXYZ 30 0 0] の場合)を図示したものです.同様に,中央の図は Y 軸(緑)まわりの 30deg 回転を,右の図は Z 軸(青)まわりの 30deg 回転を図示したものです.
複数の軸に回転角度を与えた場合は,X, Y, Z 軸の順に,順次回転させていきます.左下の図は [rotateXYZ 30 30 0] の場合で,まず [rotateXYZ 30 0 0] を適用し,得られた座標系の中で [rotateXYZ 0 30 0] を適用しています.同様に,中央の図は [rotateXYZ 0 30 30] の場合,右の図は [rotateXYZ 30 0 30] の場合を示しています.
-
[translateXYZ (BX BY BZ)]
座標系を X 軸方向に BX だけ,Y 軸方向にBY だけ,Z 軸方向に BZ だけ平行移動させます.デフォルト状態は,BX=0, BY=0, BZ=0 です.左下の図は [translateXYZ 0.2 0.2 0.2] の場合,右下の図は [translateXYZ -0.2 -0.2 -0.2] の場合を図示したものです.
-
[scaleXYZ (SX SY SZ)]
座標系を X 軸方向に SX 倍に,Y 軸方向に SY 倍に,Z 軸方向に SZ 倍に拡大あるいは縮小させます.デフォルト状態は,SX=1, SY=1, SZ=1 です.左下の図は [scaleXYZ 1.2 1.2 1.2](つまり等方向に 1.2 倍に拡大)の場合,中央の図は [scaleXYZ 0.8 1 1.2] の場合,右の図は [scaleXYZ -0.8 0.8 0.8](つまり X 軸方向に反転させ,等方向に 0.8 倍に縮小)の場合を示したものです.
-
[rotate ((AV) VX VY VZ)]
回転軸 (0, 0, 0)−(VX, VY, VZ) のまわりに AV だけ座標系を回線させます.回転の単位は度 (deg) です.第2入力端子に AV を,第3入力端子にベクトル {VX VY VZ} を与えることもできます.左下の図は [rotate 30 1 1 1] の場合,右下の図は [rotate -45 1 1 1] の場合を図示したものです.白い矢印が回転軸 (0, 0, 0)−(1, 1, 1) を表わしています.
-
[translate ((F) VX VY VZ)]
座標系を X 軸方向に F × VX だけ,Y 軸方向に F × VY だけ,Z 軸方向に F × VZ だけ平行移動させます.これらパラメタを([rotate] と同じように)入力端子から与えることもできます.左下の図は [translate 0.5 1 1 1] の場合,右下の図は [translate -1 1 1 1] の場合を図示したものです.白い矢印がベクトル (1, 1, 1) を表わしています.新しい座標系の原点は,このベクトル上にあります.
-
[scale ((F) SX SY SZ)]
座標系を X 軸方向に F × SX 倍に,Y 軸方向に F × SY 倍に,Z 軸方向に F × SZ 倍に拡大あるいは縮小させます.これらパラメタを([rotate] と同じように)入力端子から与えることもできます.左下の図は [scale 0.8 1 1 1] の場合,右下の図は [scale 0.5 3 1 2] の場合を図示したものです.
座標変換の順序には注意が必要です.連続する平行移動は順序を変えても結果は変わりませんし,1つの平行移動にまとめることもできます.一方,回転と回転,あるいは回転と平行移動は,順序を変えると結果も変わります.
左上の図は [rotateXYZ 0 30 0] を適用してから [translateXYZ 1 0 0] を適用した場合,右上の図はこれらを逆の順序で適用した場合を図示したものです.両者の違いをよく確かめてください.
つぎに色と照明について説明します.GEM(OpenGL)における物体表面の「色」は,以下にあげるいくつかの反射特性によって照明光が反射された光が足し合わされたものになります.この反射特性によって,物体の色だけでなく,質感(マット・光沢など)も与えられます.まず,反射特性の操作を,いくつかの参考パッチ(下図)を使って解説します.ピンク色の部分が,反射特性の操作に関係する部分です.
パッチを開いたら,最上段にあるメッセージボックスをクリックします.これで初期設定された GEM ウィンドウが現われ,2つの [teapot](描画オブジェクトのひとつ)が白いシルエットで表示されます.つぎにパッチ左側にある [toggle] で,照明機能をオンにしてください.これで [teapot] が薄赤色の立体として見えるようになります.パッチ上段中央の2つの数値ボックスで,どの角度から見るかを調節してください.(以下の例では,それぞれ 15, 0 を与えています.)
なお,以下の一覧のなかで括弧に入れられた引数は省略できます.省略した場合は,入力端子から設定します.未設定の場合はデフォルト値(多くの場合 1)が使われます.また A と表記した引数(あるいは入力端子)は「アルファ値」という不透明度を表わすものです.これについては後述します.
-
[diffuseRGB (R G B (A))]
最も基本的な物体色の設定がこの [diffuseRGB] です.物体表面の散乱反射の特性を設定することで,マットな色を与えます.照明の光(色)は,その方向に応じた強さで物体表面に照射されますが,この照射光は,散乱反射ベクトル (R, G, B) と掛け合わされた後,全方向一様に散乱反射します.前出の [colorRGB] と置き換えても同様の効果が得られます.
上のパッチ(部分)では,同一の散乱反射特性(薄赤色)を与えた [teapot] が2つ並んだ表示結果(下図)が得られます.照明は,右手前上方の無限遠から平行光線(白色)です.[teapot] の形状がよくわかります.照明の当たらない部分は,完全な黒となり,黒い背景に溶け込んでいます.左右の [teapot] で黒い陰の部分の大きさが異なるのは,視点との位置関係によるものです.
-
[ambientRGB (R G B (A))]
照明の当たらない部分の色を与えるのが [ambientRGB] です.物体表面の周辺反射の特性を設定します.宇宙空間のような周囲に何もないところに置かれた物体は,照明が全く当たらない部分の色が黒 (0, 0, 0) になりますが,通常の環境では,照明光が他の物体や空気によって散乱されて,本来ならば照明が当たらない部分にも弱い光が届きます.この現象を近似するために,[ambientRGB] によって周辺反射特性を設定します.照射の強さや物体表面の方向とは無関係に,周辺反射ベクトル (R, G, B) の光を全方向一様に放射します.通常は (0.2, 0.2, 0.2) 程度の小さな値を与えます.大きくすると平面的になります.
上のパッチ(部分)では,左側の [teapot] に (0.5, 0.5, 0.5) の周辺反射ベクトルを与えています.表示結果(下図)を見ると,左側の [teapot] は,右側と比べて,全体的な明るさを増しています.照明の当たらない部分([teapot] の左側面)を比べてみると,照明の当たらない部分の輪郭もかすかに見えています.これが周辺反射の効果です.
-
[specularRGB (R G B (A))]
光沢のある質感(つや・てかり)を与えるのが,鏡面反射 [specularRGB] です.通常は,[shininess] といっしょに使います.物体表面の方向に応じた強さで当たった照明光は,鏡面反射ベクトル (R, G, B) と掛け合わされた後,入射角と等しい反射角の方向にフレネル反射します.実際には同時に散乱も起こるため,完全な鏡になるのではなく,物体表面に照明が白いスポット状に反射する感じです.このとき [shininess] に与える値(0〜128)によってスポットの大きさを絞り込みます.
上のパッチ(部分)では,左側の [teapot] に鏡面反射ベクトル (0.5, 0.5, 0.5) を与え,[shininess 60] を設定しています.表示結果(下図)を見ると,右側の [teapot] はマットなままで素焼き風ですが,鏡面反射を与えた左側は釉薬のかかった瀬戸物風になっています.
-
[emissionRGB (R G B (A))]
自ら発光している質感を与えます.発光ベクトル R G B が,物体表面からの反射光(上記3つの和)に加算されます.空間内に置かれた光源(電球など)や蛍光色の物体を表現する場合に使います.
下図は左側の [teapot] に発光ベクトル (0.4, 0.4, 0.4) を与えたときの様子です.あまり自然な感じがしませんが,自ら発光しているように見えなくはないです.
-
[diffuse (R G B (A))]
[ambient (R G B (A))]
[specular (R G B (A))]
[emission (R G B (A))]上で説明した4つの操作とそれぞれ同じ効果をもちますが,右側の入力端子からリスト {R G B (A)} で反射ベクトルあるいは発光ベクトルを設定します.
座標系の操作は [separator] によってその効果の範囲を切り分けることができました.一方,色の操作は [separator] によって切り分けられません.gemhead から出力される描画コンテクストが流れる順序で色変換が適用され,別の支流(順序的に後になるもの)にもその効果が波及します.基本的に,支流ごとにすべての反射特性を設定しなおす必要があります.
支流ごとに反射特性を設定する以外に,複数の [gemhead] を使うことでも,この問題に対処できます.[gemhead] ごとにデフォルト状態の描画コンテクストが用意されるため,色変換・座標変換の有効範囲が切り分けられるのです.
照明について説明します.すでに「色や質感の操作」のところで照明を使っていました.ここでは,GEM で利用できる2種類の照明について,いくつかの参考パッチ(下図)を使って解説します.ピンク色の部分が,照明の操作に関係する部分です.
パッチを開いたら,最上段にあるメッセージボックスをクリックします.これで初期設定された GEM ウィンドウが現われ,2つの [teapot] が白いシルエットで表示されます.つぎにパッチ左側にある [toggle] で,照明機能をオンにしてください.これで,薄赤色と薄青色の [teapot] が立体として見えるようになります.パッチ上段中央の2つの数値ボックスで,どの角度から見るかを調節してください.(以下の例では,それぞれ 15, 0 を与えています.)
-
[world_light (N)]
[world_light] は無限遠にある照明です.太陽のように平行光線を放ちます.デフォルトでは白色光 (1, 1, 1) で,点 (0, 0, 1) から原点に向かう方向に進みます.光源色は右側の入力端子からリスト {R G B} によって設定できます.また放射方向は [rotateXYZ] などによって回転させることができます.(光源は無限遠にあるので,平行移動は意味をもちません.) N は照明の番号で,GEM では最大 8 個まで照明を配置することができます.
上のパッチ(部分)では,デフォルト状態から X 軸まわりに −30deg だけ回転させた [world_light] を使っています.これは,手前上方から原点(2つの [teapot] の中央)に向かう照明光です.下図のように2つの [teapot] が照明を浴びて光沢を見せています.[metro] をオンにすると,この [world_light] が Y 軸まわりに回転していきます.照明の向きによって物体の見え方が変わる様子を観察してください.(上のパッチで,まず Y 軸まわりに回転させ,つぎに X 軸まわりに -30deg 回転させていることに注意してください.)
-
[light (N)]
[light] は点光源です.配置された位置から,全方向一様に光を放射します.デフォルトでは白色光 (1, 1, 1) で,原点に配置されます.光源色は右側の入力端子からリスト {R G B} によって設定できます.また位置は [translateXYZ] などによって変えることができます.N は照明の番号で,GEM では最大 8 個まで照明を配置することができます.
上のパッチ(部分)では,デフォルト状態(原点)から Y 軸方向に 2 だけ移動させた [light] を使っています.下図のように,2つの [teapot] が,それらの中央上方付近に配置された [light] によって照らし出されています.[metro] をオンにすると,この [light] が X 軸と平行に移動します.照明の位置によって物体の見え方が変わる様子を観察してください.
描画コンテクスト(座標系や色・照明など)を設定したら,そこに描画オブジェクト (Geos: geometrical objects) を配置することで,グラフィクス表示が得られます.ここでは,よく使う描画オブジェクト (Geos) とその使い方を紹介します.
立体オブジェクトは,現在有効な描画コンテクストにおける原点に配置されます.たとえば,[cube 1] であれば,原点を中心に,上下前後左右に 1 の拡がり(つまり 2×2×2 の大きさ)をもつ立方体が配置されます.ここでは,よく使う立体オブジェクトについて説明していきます.
-
[cube (Size)]
立方体を原点に配置します.デフォルトでは Size=1 のとき,X, Y, Z 軸それぞれに −1〜1 の範囲を占める立方体となります.Size は引数あるいは第2入力端子から与えます.第1入力端子に {draw line} を与えるとワイヤフレーム表示となり, {width 2} でワイヤの太さを 2 ピクセルに設定できます.元の立体表示に戻すには {draw default} を与えます.
-
[cuboid (SX SY SZ)]
直方体を原点に配置します.デフォルトでは 幅 SX=1, 高さ SY=1, 奥行 SZ=0(厚みのない正方形)となります.3つの入力端子から SX, SY, SZ を与えることができます.
-
[sphere (Size (Seg))]
原点に球を配置します.デフォルトでは Size=1 が半径となり,Seg=10 が分割数(円を多角形で近似するときの頂点数)となります.これらの値は引数あるいは入力端子から設定することができます.
-
[cone (Size (Seg))]
原点に円錐を配置します.中心軸が Z 軸上にあり,半径 Size の底面が Z=−Size の位置に,頂点が Z=Size の位置にきます.デフォルトでは Size=1,また分割数 Seg=10 となります.これらの値は引数あるいは入力端子から設定することができます.なお,ここでは底面をもつ「円錐」と書きましたが,実際には底面は描画されず,円錐面のみが描画されます.(現在の GEM には,[cone] の照明への応答にバグがあります.正しい陰影をつけるには,直前に [scaleXYZ -1 -1 -1] を入れて補正してください.)
-
[cylinder (Size (Seg))]
原点に円筒を配置します.中心軸が Z 軸上にあり,半径 Size の底面が Z=−Size と Z=Size の位置にきます.デフォルトでは Size=1,また分割数 Seg=10 となります.これらの値は引数あるいは入力端子から設定することができます.なお,ここでは底面をもつ「円筒」と書きましたが,実際には底面は描画されず,円筒面のみが描画されます.(現在の GEM には,[cylinder] の照明への応答にバグがあります.正しい陰影をつけるには,直前に [scaleXYZ -1 -1 -1] を入れて補正してください.)
-
[teapot (Size (Seg))]
原点に「ティーポット」を配置します.Size は大きなの目安(胴体部分の半径)で,デフォルトでは 1 です.分割数 Seg とともに,引数あるいは入力端子から設定することができます.
平面オブジェクトや線オブジェクトは,現在の座標系の原点に配置されます.たとえば,[square] であれば,原点を中心といて,XY 平面上(Z=0)に配置されます.3次元空間内に配置された平面であることに注意してください.ここでは,よく使う平面・線オブジェクトについて説明していきます.
-
[square (Size)]
XY 平面 (Z=0) の原点に正方形を配置します.X, Y 軸上それぞれに −Size〜Size の範囲を占める正方形となります.デフォルトでは Size=1 です.Size は引数あるいは第2入力端子から与えます.第1入力端子に {draw line} を与えるとワイヤフレーム表示となり, {width 2} でワイヤの太さを 2 ピクセルに設定できます.元の面表示に戻すには {draw default} を与えます.
-
[colorSquare (Size)]
[square] と同じく正方形ですが,各頂点に色を与えることで,色のグラデーションが表面上に得られます.各頂点の色は,第3〜6入力端子(左下・右下・右上・左上の各頂点に対応)にリスト {R G B} で与えます.
-
[rectangle (W H)]
XY 平面 (Z=0) の原点に長方形を配置します.X 軸上に −W〜W, Y 軸上に −H〜H の範囲を占める長方形となります.デフォルトでは W=1, H=1 です.W, H は引数あるいは入力端子から与えます.その他については [square] と同じですが,{draw default} の代りに {draw fill} を使ってください.
-
[triangle (Size)]
XY 平面 (Z=0) の原点に二等辺三角形を配置します.Y=−Size の直線上で,X=−Size〜Size の線分が底辺となり,Y 軸上で Y=Size の点が頂点となります.その他については [square] と同じです.
-
[primTri]
XY 平面 (Z=0) 上に三角形を配置します.第2〜4入力端子に3つの頂点の座標をリスト {X Y Z} で与えます.第5〜7入力端子にそれぞれの頂点の色をリスト {R G B} で与えます.[colorSquare] と同じような,色のグラデーションが得られます.
-
[polygon N]
XY 平面 (Z=0) 上に N 角形を配置します.引数(必須)として N を与えると,第1入力端子(描画コンテクスト用)以外に N 個の入力端子がつくられます.ここに頂点座標をリスト {X Y Z} で与えてください.
-
[circle (Size)]
XY 平面 (Z=0) の原点に円盤を配置します.Size は半径で,デフォルトは 1 です.分割数は 100(固定)となります.その他は [square] と同じです.
-
[disk (Outer (Seg (Inner)))]
XY 平面 (Z=0) の原点にドーナツ盤を配置します.Outer は外側の半径で,デフォルトは 1 です.Inner は内側(穴)の半径で,デフォルトは 0 です.Seg は分割数で,デフォルトでは 10 となっています.
-
[text3d (Text)]
XY 平面 (Z=0) の原点に文字列を表示します.現在のところ英数字しか表示できませんが,フォントの選択などが可能です.詳しくは Help をご覧ください.
-
[curve N]
ベジエ曲線を配置します.おそらく「線」を扱う唯一の描画オブジェクトです.引数(必須)として与える N は「制御点」の数で,第1入力端子(描画コンテクスト用)以外に N 個の入力端子が現われます.それぞれに制御点 Pi の座標をリスト {Xi Yi Zi} として入力します.N=2 とすることで直線を引くことができます.
第1入力端子に,たとえば {width 2} を送ることで,線の太さを 2 ピクセルにすることができます.(この太さは画面上の太さであり,視点との距離によって3次元的に変わることはありません.) また第1入力端子に,たとえば {draw point} を送ることで,描画スタイルを点列に変更することもできます.詳しくは [curve] の Help を参照してください.
3次元空間上に配置された描画オブジェクト G は,視点 E からスクリーン S に投影することで,GEM ウィンドウ上に表示されます.いわゆる透視投影 (perspective projection) とよばれる投影法です.
デフォルト状態では,視点 E は (0, 0, 4) の位置にあります.E から注視点 (0, 0, 0) に向かう直線(X=0, Y=0)が視線となります.この視線に垂直で,E から視線方向に 1 だけ離れた平面(Z=3)が S となります.Y 軸の正方向が S の上方向となります.
視点を (X, Y, Z) に移動するには,[gemwin] に {view X Y Z} を与えます.たとえば,デフォルトの視点 (0, 0, 4) を (0, 0, 8) に移動すると,下図(左 → 右)のように,原点に配置した描画オブジェクトは遠くに(小さく・弱い遠近感で)見えるようになります.使用したパッチを下にあげておきます.
{view X Y Z} による視点移動は平行移動となるため,視線方向は変化しません.たとえば,デフォルト状態から {view 1 0 4} を与えると,注視点は (0, 0, 0) から (1, 0, 0) に移ります.左下図は視点を (1, 0, 4) に,右下図は (1, 0, 8) に移した場合を表わしています.[cube] の位置だけでなく,各面の見え方も微妙に変わっています.
{view ...} による視点の設定は,一般には,以下の 10 項目からなるメッセージを [gemwin] に送ることで実行します.いつでも変更可能です.デフォルト状態は {view 0 0 4 0 0 0 0 1 0} となっています.
- セレクタ: view
- 視点の位置: XE, YE, ZE (デフォルト 0, 0, 4)
- 視線の向き(注視点の位置): XG, YG, ZG (デフォルト 0, 0, 0)
- 視野の上方向(ベクトル): XU, YU, ZU (デフォルト 0, 1, 0)
視点の位置だけを変える場合は {view, XE, YE, ZE} を送ればよいです.また,{view, XE, YE, ZE, Ayaw} あるいは {view, XE, YE, ZE, Ayaw, Apit} のように設定することもできます.Ayaw は水平方向(右へ)の偏角 (deg),Apit は垂直方向(上へ)の仰角 (deg) です.
GEM(そして OpenGL)には,上下左右のほかに,前後にも視野の境界があります.下図は,GEM における視野を「視錐台 (frustum)」として表わしたものです.left, right, bottom, top のデフォルト値は -1, 1, -1, 1 です.また,near, far のデフォルト値は 1, 20 となっています.この視錐台の内部にある描画オブジェクト(あるいはその一部)のみが GEM ウィンドウに表示されます.
この視錐台の形をデフォルト状態から変えるには,{perspec left right bottom top near far} のように,perspec に続いて各パラメタを連ねたメッセージを [gemwin] に与えます.下のパッチで,[view 0 0 4[ と [perspec -1 1 -1 1 3 10[ を押し,数値ボックスを(シフトを押しながらドラッグすることで)操作して,[cube] を奥側や手前側に動かしてみてください.奥側の限界は Z=−6 の位置,手前側の限界(スクリーン)は Z=1 の位置となります.
左下図は [cube] を Z=−6.5 に配置した場合で,その先端部分だけが表示されています.右下図は Z=0 に配置した場合で,スクリーン(Z=1)で切断された [cube] の内側が見えています.(いずれも極端な例です.ふつうは十分な視野範囲を設定します.)
この視錐台の形によって,遠近感を調節することができます.ちょうどマクロ撮影が大きな遠近感を与え,望遠撮影が遠近感を弱めるのと同じ原理です.たとえば,下のパッチでは,視点からスクリーンまでの距離と,視点から描画オブジェクトまでの距離を,1 : 2 に保ったまま増減させることで,遠近感の強弱を調節しています.[view 0 0 0[ を押してから,数値ボックスを(およそ −2〜−20 の範囲で)操作してみてください.
左下図は,視点からスクリーンまでの距離が 2, 視点から [cube] までの距離が 4 の場合で,遠近感が強く出ています.右下図は,視点からスクリーンまでの距離が 8 で,視点から [cube] までの距離が 16 の場合で,ほぼ遠近感のない(平行投影に近い)表示となっています.
GEM ウィンドウの大きさを設定するには,ウィンドウを開く前に,横のピクセル数 W, 縦のピクセル数 H を {dimen W H} というメッセージに入れて [gemwin] に与えます.下のパッチは,250×150 ピクセルおよび 150×250 ピクセルの GEM ウィンドウに,同じ条件で [cube] を描画します.
生成された GEM ウィンドウの下端・上端は,視錐台前面(スクリーン S)の bottom・top に対応しますが,左端・右端に対応する left・right の値は自動的に再設定されます.つまり,縦方向を優先して,描画オブジェクトが 1 : 1 の縦横比で表示されるように,視錐台の幅が自動調整されるようになっています.
GEM ウィンドウ生成後に,手動で {perspec ...} を設定すると,まず bottom・top がウィンドウの上端・下端と対応づけられてから,(bottom − top) : (right − left) の縦横比で描画オブジェクトが表示されるように,視錐台の幅が調整されます.多くの場合,縦横比が 1 : 1 の描画オブジェクトを表示することになるので,つぎのような手順で {dimen ...} や {perspec ...} を設定すればよいでしょう.
- 利用したい GEM ウィンドウの大きさを {dimen W H} で設定し,GEM ウィンドウを生成する.
- GEM ウィンドウの下端・上端に対応する視錐台前面(スクリーン S)上の Y 座標を bottom・top とし,同じ値(あるいは同じ間隔をもつ値)を left・right として,{perspec ...} を設定する.
GEM ウィンドウからキーボードの入力を読み取ることができます.[gemkeyboard] は押されたキーの key code を数値で出力します.ASCII コードではないので,注意してください.より詳しいキー入力情報が必要な場合は,[gemkeyname] を使うとよいでしょう.キーに対応したシンボルと,キーの状態(up=1, down=0)を出力します.(いずれも,GEM ウィンドウが選択されているときに,キー入力が読み取られます.)
また,[gemmouse] を使うことで,マウスの入力を読み取ることもできます.マウスイベント(ポインタの動き・ボタンの操作)が発生すると,GEM ウィンドウ内側の左上端を (0, 0) として,マウスポインタの位置を X 座標・Y 座標に分けて出力し,またボタン(左・中・右)の状態変化も出力します.(GEM ウィンドウが選択されているときに,マウスイベントが読み取られます.)
GEM ウィンドウのフルスクリーン表示については「Pure Data 小ネタ集」を参照してください.