Japanese | English | Korean

Samples


M3G でのプリミティブの描画は、各ポリゴンの頂点を設定することにより実現されます。各頂点は座標値、色、法線やテクスチャ座標といった情報を持ちます。これらの情報をここでは「頂点属性」と呼びます。 また、ポイントスプライトと呼ばれる画面に対し常に正面を向くプリミティブの描画も可能です。 以下にサンプルを交えた描画の解説を行います。


1. ポリゴンの描画

ここではもっとも単純なポリゴンの描画について解説します。

1.1. 頂点属性の設定

まず、頂点属性を設定していきます。頂点属性の設定には VertexArray クラスを用います。 VertexArray クラスは頂点属性を表す整数ベクトルの配列です。

VertexArray クラスを利用するにはVertexArray クラスに 「 頂点数、各頂点が持つ要素数、各要素のサイズ 」 を指定しインスタンスを生成します。その後、 VertexArray.set () メソッドに 「 配列中における先頭頂点のインデックス、頂点数、頂点属性コピー元の整数配列 」 を指定することで頂点属性を設定します。 VertexArray.set () メソッドには整数配列として short 型の配列を取るものと、 byte 型の配列を取るものがあります。

/* プリミティブ用頂点情報設定 */
/* Triangle */
short [] triVert = {  0, 10, 0,    -6,    0, 0,     6,     0, 0,         // 上表面
             -6,  0,  0,     0, -10, 0,     6,     0, 0,        // 下表面
             -6,  0,  0,     6,    0, 0,     0,  -10, 0 } ;     // 下裏面

VertexArray triVertArray = new VertexArray (
( triVert.length / 3 ), 3, 2 );
triVertArray.set ( 0, ( triVert.length / 3 ), triVert );

byte[] triNorm = {  0, 0, 127,     0, 0, 127,     0, 0, 127,
             0, 0, 127,     0, 0, 127,     0, 0, 127,
             0, 0, 127,     0, 0, 127,     0, 0, 127 } ;

VertexArray triNormArray = new VertexArray (
( triNorm.length / 3 ), 3, 1 );
triNormArray.set ( 0, ( triNorm.length / 3 ) , triNorm );

byte [] triColor = {  127,     0, 0,      127,     0,     0,      127,     0,     0,
     0, 127, 0,          0,     0, 127,          0, 127,     0,
     0, 127, 0,          0, 127,     0,          0,     0, 127 } ;

VertexArray triColorArray = new VertexArray (
( triColor.length / 3 ), 3, 1 );
triColorArray.set ( 0, ( triColor.length / 3 ), triColor );

( 中略 )

/* Quads */
short [] qdsVert = { -10, 10, 0,     -30,   10, 0,     -10, -10, 0,     -30, -10, 0,      // 表面
  -10, 10, 0,     -10, -10, 0,     -30,   10, 0,     -30, -10, 0 } ;   // 裏面

VertexArray qdsVertArray = new VertexArray (
( qdsVert.length / 3 ), 3, 2 );
qdsVertArray.set ( 0, ( qdsVert.length / 3 ), qdsVert );

byte [] qdsNorm = { 0, 0, 127,     0, 0, 127,     0, 0, 127,     0, 0, 127,
  0, 0, 127,     0, 0, 127,     0, 0, 127,     0, 0, 127 } ;

VertexArray qdsNormArray = new VertexArray (
( qdsNorm.length / 3 ), 3, 1 );
qdsNormArray.set ( 0, ( qdsNorm.length / 3 ), qdsNorm );
short [] qdsTexcoord = { 255, 0,         0,    0,     255, 255,     0, 255,
         255, 0,     255, 255,        0,     0,     0, 255 } ;

VertexArray qdsTexArray = new VertexArray ( ( qdsTexcoord.length / 2 ), 2, 2 );
qdsTexArray.set ( 0, ( qdsTexcoord.length / 2 ), qdsTexcoord );

このとき、頂点座標、法線ベクトル、テクスチャ座標は各要素が short 型でも byte 型でも問題ありませんが、色情報に関しては必ず byte 型による指定を行わなければなりません。

VertexArray クラスへの設定が終わった後、これらの VertexArray クラスを VertexBuffer クラスに登録します。 VertexBuffer クラスは頂点属性の配列を保持します。同一の VertexBuffer に対し、頂点属性のうち頂点座標配列、色情報配列、法線ベクトル配列の3種はそれぞれ1つまでしか登録できません。テクスチャ座標配列に関してはゼロから実装がサポートするテクスチャ単位数まで登録することができます。それぞれの頂点属性配列の設定には、VertexBuffer.setPositions (), VertexBuffer.setNormals (), VertexBuffer.setColors (), VertexBuffer.setTexCoords () メソッドを使用します。

/**
  * 頂点属性
  * private VertexBuffer triVertexBuffer;
  * private VertexBuffer qdsVertexBuffer;
  *
  */

triVertexBuffer = new VertexBuffer ();
triVertexBuffer.setPositions ( triVertArray, 1.f, null );
triVertexBuffer.setNormals ( triNormArray );
triVertexBuffer.setColors ( triColorArray );

( 中略 )

qdsVertexBuffer = new VertexBuffer ();
qdsVertexBuffer.setPositions ( qdsVertArray, 1.f, null );
qdsVertexBuffer.setNormals ( qdsNormArray );
qdsVertexBuffer.setTexCoords ( 0, qdsTexArray, ( 1.f / 256.f ), null );

なお、頂点座標、テクスチャ座標、法線ベクトルは 4D の同次座標として解釈されます。このとき、頂点座標とテクスチャ座標において4つ目の成分は暗黙的に「1」に、法線ベクトルでは「0」とされます。これは、頂点座標とテクスチャ座標は 3D のある一点として解釈され、法線ベクトルは 3D ベクトルとして解釈されることを意味しています。 2D テクスチャ座標の場合、3つ目の成分は暗黙的に「0」とされます。

1.2. 三角形ストリップの設定

先ほど設定した頂点属性の配列だけではポリゴンの描画を行うことはできません。描画を行うためには、これら頂点属性から生成された三角形ストリップの配列を設定する必要があります。これには TriangleStripArray クラスを使用します。三角形ストリップ配列のインデックスは明示的、または暗黙的に指定することができます。なお、このインデックスは描画対象となる頂点配列の各頂点に対応するインデックスです。

明示的な指定を行う場合、 TriangleStripArray クラスに指定された頂点配列の先頭3頂点によって最初の三角形が形成されます。次の三角形は前の3頂点のうち先頭を除く、2頂点と新しく追加された1頂点により形成されます。たとえば頂点 ( 0, 1, 2, 3, 4 ) が設定されているときに、ストリップ S = ( 2, 0, 1, 4 ) は頂点 ( 2, 0, 1 ) により形成される三角形と頂点 ( 0, 1, 4 ) により形成される三角形の2つの三角形を形成します。このとき TriangleStripArray クラスのコンストラクタには頂点配列と各ストリップ長を表す配列を設定します。

暗黙的に指定する場合、 TriangleStripArray クラスには最初のストリップの先頭インデックスのみが指定されます。後続の頂点インデックスは前のインデックスに「1」を加算して求められます。先頭インデックスが 10 で、ストリップ長が 3 と 4 の場合、次のようなストリップとして解釈されます : S1 = ( 10, 11, 12 ), S2 = ( 13, 14, 15, 16 ) 。このとき TriangleStripArray クラスのコンストラクタには先頭ストリップの先頭頂点が持つインデックスと各ストリップ長を表す配列を設定します。

このサンプルでは暗黙的な指定により三角形ストリップを設定します。

/**
  * private IndexBuffer triIndexBuffer ;
  * private IndexBuffer qdsIndexBuffer ;
  * IndexBuffer クラスは TriangleStripArray クラスのスーパークラス
  * ここでは三角形を3つと
  * 三角形2つを組み合わせて四角形を2つ形成している。
  *
  */

int [] triStripLen = { 3, 3, 3 } ;
triIndexBuffer = new TriangleStripArray ( 0, triStripLen );

( 中略 )

int [] qdsStripLen = { 4, 4 } ;
qdsIndexBuffer = new TriangleStripArray ( 0, qdsStripLen );

1.3. 外観の設定

次にポリゴンの外観や材質に関する要素群を設定します。外観の設定には Appearance クラスを使用します。 Appearance クラスのオブジェクトを新規に作成するとその要素の初期値はすべて null となっています。レンダリングの際にひとつ以上の要素が null であっても問題はありません。しかし、 Appearance オブジェクトそのものを null にした場合、ポリゴンのレンダリングは無効となり、描画が行われません。そのため、 Appearance の設定は必須です。

このサンプルでは Material クラスを使用して光源からの光を反射するように設定しています。なお、 Appearance クラスに対する Material オブジェクトの設定は Appearance.setMaterial () メソッドを使用します。

/**
  * private Appearance myAppearance ;
  * private Appearance texAppearance ;
  * private Material myMaterial ;
  *
  */

/* Appearance */
myAppearance.setMaterial ( myMaterial );

texAppearance.setTexture ( 0, texture );
texAppearance.setMaterial ( myMaterial );

myMaterial.setVertexColorTrackingEnable ( true );
myMaterial.setColor ( Material.SPECULAR, 0xFFFFFFFF );
myMaterial.setShininess ( 100.f );

なお、ポリゴンに対しテクスチャを貼り付ける場合 Texture2D クラスを使用します。Texture2D クラスのオブジェクトは PNG 形式の画像ファイルから読み込んだ Image2D オブジェクトを引数に指定してコンストラクタを呼び出すことで生成できます。

1.4. 描画の設定

最後に実際の描画を行います。描画を行うためには他の 3D オブジェクト同様、 Graphics3D.render () メソッドを使用します。このとき、 render() メソッドに渡す引数は VertexBuffer, IndexBuffer ( 実体は TriangleStripArray ), Appearance, Transform の各オブジェクトです。なおこのとき、 Transform オブジェクトとして null を渡すことができますが、これは変換行列として恒等変換が渡されたことを意味します。

/**
  * Graphics3D g3d ;
  * Transform primTrans ;
  * g3d は描画対象となる Graphics3D オブジェクト
  * primTrans はプリミティブ全体への変換行列
  *
  */

g3d.render ( triVertexBuffer, triIndexBuffer, myAppearance, primTrans );
g3d.render ( qdsVertexBuffer, qdsIndexBuffer, texAppearance, primTrans );

render() メソッドの引数には、注意が必要です。
Appearance オブジェクトにTexture2D オブジェクトが関連付けられている場合、必ずVertexBufferオブジェクトにテクスチャの座標を指定してください。





2. ポイントスプライトの描画

ここではプリミティブの中でも、特にポイントスプライトと呼ばれるものについて解説します。 ポイントスプライトとは前述の通り、常に画面方向を向いて描画されるプリミティブのことです。 M3G でポイントスプライトを扱うためには Sprite3D クラスを使用します。

2.1. Sprite3D オブジェクトの生成

Sprite3D オブジェクトの生成にはコンストラクタ Sprite3D ( boolean scaled, Image2D image, Appearance appearance ) を使用します。引数 scaled は Sprite3D オブジェクトの拡大縮小の有効無効を表し、引数 image はポイントスプライトに貼り付けるためのテクスチャを表し、引数 appearance はポイントスプライトの外観を表します。テクスチャや外観は常に変更可能ですが、拡大縮小の有無については生成時の一度しか設定ができません。

以下のサンプルでは引数 scaled に true を指定しているため、 Sprite3D オブジェクトの拡大縮小が有効となっています。

/**
  * private Image2D texImage ;
  * private Appearance myAppearance ;
  * texImage は PNG ファイルから取得した Image2D オブジェクト
  *
  */

/* Sprite3D */
sprite = new Sprite3D ( true, texImage, myAppearance );

2.2. テクスチャ座標の設定

次に、 Sprite3D オブジェクトに貼り付けるテクスチャに関する設定を行います。オブジェクトに貼り付けるために取得した外部ファイルのどの部分を使用するかは Sprite3D.setCrop () メソッドによって設定できます。引数には使用範囲の左上角の座標と範囲の幅と高さを指定します。

sprite.setCrop ( 0, 0, 256, 256 );

2.3. Sprite3D オブジェクトの描画

描画には Graphics3D.render () メソッドを使用します。このとき、 Sprite3D オブジェクト以外の引数として Transform オブジェクトを渡します。

/**
  * private float [] sprPosition = new float [ 3 ] ;
  * private float sprSclae ;
  *
  */

sprPosition [ 0 ] = 18.f ;
sprPosition [ 1 ] = 0.f ;
sprPosition [ 2 ] = 0.f ;
sprScale = 20.f;

sprPos.postTranslate( sprPosition [ 0 ] , sprPosition [ 1 ] , sprPosition [ 2 ] );
sprPos.postScale ( sprScale, sprScale, sprScale );

( 中略 )

g3d.render ( sprite, sprPos );



環境光源+表面

直接光源+表面

環境光源+裏面

直接光源+裏面