物体を定義する(Shape3D)

これまでは描画テストのために、あらかじめ形状が定義されたcom.sun.j3d.utils.geometry.ColorCubeなどを使ってきました。
自分で物体の形状を定義するにはどうしたらよいでしょうか。

このために用意されているのがjavax.media.j3d.Shape3Dクラスです。

クラス継承

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.Node
              |
              +--javax.media.j3d.Leaf
                    |
                    +--javax.media.j3d.Shape3D

クラス宣言

public class Shape3D
extends Leaf

Shape3Djavax.media.j3d.Leafのサブクラスです。
LeafノードなのでaddChild()メソッドを持ちません。
つまり、Java 3Dのシーン・グラフの中で他のノードの“親”になることはできません。

Shape3DクラスにはsetGeometry(javax.media.j3d.Geometry)というメソッドがあります。
javax.media.j3d.Geometryオブジェクトをセットすることで物体の形状を定義することができます。

クラス継承

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Geometry

クラス宣言

public abstract class Geometry
extends NodeComponent

通常はGeometryのサブクラスであるjavax.media.j3d.GeometryArrayの、さらにサブクラスである次のようなクラスを使います。

javax.media.j3d.PointArray // 点
javax.media.j3d.LineArray // 直線
javax.media.j3d.TriangleArray // 三角形ポリゴン
javax.media.j3d.QuadArray // 四角形ポリゴン

Shape3D の使用方法は次のようになります。

  1. Shape3D オブジェクトの生成
  2. setGeometry() メソッドで、Shape3DGeometryArray オブジェクトをセットする
  3. addChild() メソッドで、親となる Group ノードに Shape3D を追加する

2.ついては、Shape3Dのコンストラクターで行う方法もあります。

Shape3Dのコンストラクターは次の通りです。

public Shape3D()

public Shape3D(Geometry geometry)    // 物体の幾何学的形状

public Shape3D(Geometry geometry,    // 物体の幾何学的形状
               Appearance appearance) // 物体の外観上の属性 (色、透明度など)

また、2に先立って、

  1. GeometryArray オブジェクトを生成する
  2. GeometryArray オブジェクトへ頂点座標を設定する

が必要になります。

GeometryArray

javax.media.j3d.GeometryArray は、物体の幾何学的形状を定義します。

javax.media.j3d.GeometryArrayabstract クラスであり、実際にはそのサブクラスが使用されます。

クラス継承

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Geometry
                    |
                    +--javax.media.j3d.GeometryArray
                          |
                          |--javax.media.j3d.PointArray
                          |
                          |--javax.media.j3d.LineArray
                          |
                          |--javax.media.j3d.TriangleArray
                          |
                          +--javax.media.j3d.QuadArray

クラス宣言

public abstract class GeometryArray
extends Geometry

GeometryArray の使用方法は次のようになります。

  1. 頂点座標の配列を用意する
  2. GeometryArray オブジェクトを生成する。
    コンストラクターの最初の引数には頂点配列の要素数、
    2番目の引数には GeometryArray.COORDINATES を設定する
  3. setCoordinates() メソッドで頂点配列をセットする
  4. setGeometry() メソッドで、Shape3D オブジェクトに GeometryArray をセットする

■■GeometryArray のコンストラクター

GeometryArray のコンストラクターは次の通りです。

public GeometryArray(int vertexCount,  // 頂点数
                     int vertexFormat) // 頂点指定の形式

最初の引数 int vertexCount は頂点座標の要素数です。

物体の形状を決定するためには、三次元空間上での物体の各点の座標 (x, y, z) が必要です。各点の座標は通常ポリゴンの頂点の座標であるため、「頂点座標」という言葉が良く使われます。

2番目の引数 int vertexFormat には次の定数を指定します。

public static final int COORDINATES           // 頂点座標を使用する
public static final int NORMALS               // 頂点法線ベクトルを使用する
public static final int COLOR_3               // 頂点に色を使用する (RGBで指定)
public static final int COLOR_4               // 頂点に色を使用する (RGBと不透明度で指定)
public static final int TEXTURE_COORDINATE_2  // 二次元テクスチャー座標を使用する
public static final int TEXTURE_COORDINATE_3  // 三次元テクスチャー座標を使用する

COORDINATESは通常必ず指定します。後の定数を使用する場合は | (OR演算子) で OR をとって指定します。

■■頂点座標の配列 (javax.vecmath.Point3d, Point3f クラス)

GeometryArray で頂点座標は javax.vecmath.Point3d または javax.vecmath.Point3f の配列として定義します。

javax.vecmath.Point3dは三次元空間上の座標を定義するオブジェクトです。

クラス継承

java.lang.Object
  |
  +--javax.vecmath.Tuple3d
        |
        +--javax.vecmath.Point3d

クラス宣言

public class Point3d
extends Tuple3d
implements java.io.Serializable

Point3dは次のようなコンストラクターを持ちます。

public Point3d(double x, // X 座標
               double y, // Y 座標
               double z) // Z 座標

Point3dの最後の ddouble 型であることを表します。

javax.vecmath.Point3ffloat 型で座標を定義します。

クラス継承

java.lang.Object
  |
  +--javax.vecmath.Tuple3f
        |
        +--javax.vecmath.Point3f

クラス宣言

public class Point3f
extends Tuple3f
implements java.io.Serializable

Point3fは次のようなコンストラクターを持ちます。

public Point3f(float x, // X 座標
               float y, // Y 座標
               float z) // Z 座標

頂点座標は、double または float の配列としても定義することができます。

頂点座標が double または float の配列のとき、 配列の要素数は3の倍数になります。( { x0, y0, z0, x1, y1, z1, ... } という並びになる )

■[コラム]javax.vecmathパッケージについて

Java 3Dは次の3つのパッケージで構成されています。

javax.media.j3d Java 3Dのコアパッケージ
com.sun.j3d Sunのユーティリティーパッケージ
javax.vecmath ベクトル数学ライブラリー

Java 3Dの主要なクラスはjavax.media.j3d パッケージにまとめられています。

補助的なクラスや実装例などはcom.sun.j3d パッケージにまとめられています。

3DCGに必須の座標やベクトル、行列などのクラスは Java 3Dのコアパッケージから独立しています。 これがjavax.vecmathパッケージです。
javax.media.j3dパッケージは Java Sound APIなどと同じJava Media APIに属していますが、 javax.vecmathパッケージはJava Media APIとは 独立しています。3DCGだけでなく、 一般的なベクトル/行列演算の用途にも使用できます。

javax.vecmathパッケージとその数学的背景については 付録の「javax.vecmathパッケージ詳説」に詳しく解説されています。 ぜひ参照してください。

■■頂点座標のセット (setCoordinates() メソッド)

GeometryArray にはこの頂点座標の配列をセットするための setCoordinates() メソッドを持ちます。

public final void setCoordinates(int index,            // セットを開始する頂点インデックス
                                 Point3d[] coordinate) // 頂点座標の配列

public final void setCoordinates(int index,            // セットを開始する頂点インデックス
                                 Point3f[] coordinate) // 頂点座標の配列

public final void setCoordinates(int index,           // セットを開始する頂点インデックス
                                 double[] coordinate) // 頂点座標の配列
                                                      // (x0, y0, z0, x1, y1, z1, ...)

public final void setCoordinates(int index,           // セットを開始する頂点インデックス
                                 float[] coordinate)  // 頂点座標の配列
                                                      // (x0, y0, z0, x1, y1, z1, ...)

これから、点、線分、三角形ポリゴン、四角形ポリゴンそれぞれのコーディングについて見ていきましょう。

■■点の描画(PointArray)

javax.media.j3d.PointArrayは画面上に点を描画します。


クラス宣言

public class PointArray
extends GeometryArray

コンストラクター

public PointArray(int vertexCount,      // 頂点数
                  int vertexFormat)     // 頂点指定の形式

public PointArray(int vertexCount,      // 頂点数        
                  int vertexFormat,     // 頂点指定の形式
                  int texCoordSetCount, // 指定する頂点の数
                  int[] texCoordSetMap) // 指定する頂点 index の配列
Shape3DTest.java
 1  // Java 3Dテスト用アプレット
 2  // Shape3DTest.java
 3  //   Copyright (c) 1999 ENDO Yasuyuki
 4  //                      mailto:yasuyuki@javaopen.org
 5  //                      http://www.javaopen.org/j3dbook/index.html
 6  
 7  import java.applet.*;
 8  import java.awt.*;
 9  import javax.media.j3d.*;
10  import javax.vecmath.*;
11  import com.sun.j3d.utils.applet.MainFrame;
12  import com.sun.j3d.utils.universe.SimpleUniverse;
13  
14  public class Shape3DTest extends Applet {
15    public Shape3DTest() {
16      GraphicsConfiguration config =
17        SimpleUniverse.getPreferredConfiguration();
18      Canvas3D canvas = new Canvas3D(config);
19      this.setLayout(new BorderLayout());
20      this.add(canvas, BorderLayout.CENTER);
21  
22      SimpleUniverse universe = new SimpleUniverse(canvas);
23      universe.getViewingPlatform().setNominalViewingTransform();
24  
25      BranchGroup scene = createSceneGraph();
26  
27      universe.addBranchGraph(scene);
28    }
29  
30    private BranchGroup createSceneGraph() {
31      BranchGroup root = new BranchGroup();
32  
33      Point3d[] vertices = new Point3d[3];...........(1)
34      
35      vertices[0] = new Point3d(-0.4, -0.8, 0.0);─┐
36      vertices[1] = new Point3d(0.5, -0.4, 0.0);   ├(2)
37      vertices[2] = new Point3d(-0.6, 0.7, 0.0); ─┘   
38      
39      PointArray geometry =
          new PointArray(vertices.length, GeometryArray.COORDINATES);...(3)
40      geometry.setCoordinates(0, vertices);...........................(4)
41      
42      Shape3D shape = new Shape3D(geometry);..........................(5)
43      
44      root.addChild(shape);
45  
46      return root;
47    }

(1)でPoint3dの配列変数を要素数=3で初期化しています。

(2)でX, Y, Z座標を与えてPoint3dオブジェクトを生成し、配列の各要素に代入しています。

(3)で頂点数とGeometryArray.COORDINATES定数を与えてPointArrayオブジェクトを生成しています。

(4)ではsetCoordinates()メソッドを使ってPointArrayに頂点配列をセットしています。setCoordinates()の最初の引数は、セットを開始する頂点のindexです。ここではゼロなので、先頭要素 (いちばんはじめの頂点) からセットを開始します。

(このサンプルではやっていませんが、途中の頂点からセットすることも可能です。
また setCoordinate() メソッドを使うと、特定の頂点をひとつだけセットすることができます)

(5)でPointArrayを与えてShape3Dオブジェクトを生成しています。

このプログラムの実行結果は次のようになります。画面上に白い点が3つ描画されているのがわかるでしょうか。

PointArrayでの、点の大きさのデフォルト値は1ピクセルです。

Shape3DTest1.gif

■■線の描画(LineArray)

javax.media.j3d.LineArrayは複数の独立した線分を描画します。


クラス宣言

public class LineArray
extends GeometryArray

コンストラクター

public LineArray(int vertexCount,      // 頂点数                   
                 int vertexFormat)     // 頂点指定の形式           
					                           
public LineArray(int vertexCount,      // 頂点数                   
                 int vertexFormat,     // 頂点指定の形式           
                 int texCoordSetCount, // 指定する頂点の数         
                 int[] texCoordSetMap) // 指定する頂点 index の配列
Shape3DTest.java (一部)

30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[6];...(1)
34     
35     vertices[0] = new Point3d(-0.7, -0.1, 0.0);─┐   
36     vertices[1] = new Point3d(-0.3, -0.7, 0.0);  │
37     vertices[2] = new Point3d(0.2, -0.7, 0.0);   ├(2)   
38     vertices[3] = new Point3d(0.8, 0.0, 0.0);    │
39     vertices[4] = new Point3d(0.6, 0.4, 0.0);    │
40     vertices[5] = new Point3d(-0.6, 0.6, 0.0); ─┘
41     
42     LineArray geometry =
         new LineArray(vertices.length, GeometryArray.COORDINATES);...(3)
43     geometry.setCoordinates(0, vertices);..........................(4)
44     
45     Shape3D shape = new Shape3D(geometry);.........................(5)
46     
47     root.addChild(shape);
48 
49     return root;
50   }

(1)でPonit3dの頂点配列を要素数=6で初期化しています。
LineArrayの頂点配列の要素数は、必ず2の倍数でなければいけません。線分の[始点-終点]のペアを必要とするためです。

2の倍数でない場合には、LineArrayのコンストラクターでjava.lang.IllegalArgumentExceptionが発生します。

(2)でX, Y, Z座標を与えてPoint3dオブジェクトを生成し、頂点配列の各要素を初期化しています。先に述べた通り、頂点配列は[始点、終点、始点、終点、...]という並びになります。

(3)でLineArrayオブジェクト生成、(4)で頂点配列のセット、(5)でShape3Dオブジェクトの生成を行っています。

このプログラムの実行結果は次のようになります。

Shape3DTest2.gif

■■三角形ポリゴンの描画(TriangleArray)

javax.media.j3d.TriangleArrayは複数の独立した三角形ポリゴンを描画します。

(「ポリゴン」というのは「多角形」という意味なので、「三角形ポリゴン」 とか「四角形ポリゴン」というのは本来おかしな表現です。 ですが、他に呼び方が無いのでこの表現を使用します)


クラス宣言

public class TriangleArray
extends GeometryArray

コンストラクター

public TriangleArray(int vertexCount,      // 頂点数                   
                     int vertexFormat)     // 頂点指定の形式           
					                               
public TriangleArray(int vertexCount,      // 頂点数                   
                     int vertexFormat,     // 頂点指定の形式           
                     int texCoordSetCount, // 指定する頂点の数         
                     int[] texCoordSetMap) // 指定する頂点 index の配列
Shape3DTest.java (一部)

30    private BranchGroup createSceneGraph() {
31      BranchGroup root = new BranchGroup();
32  
33      Point3d[] vertices = new Point3d[6];...(1)
34      
35      vertices[0] = new Point3d(-0.9, 0.0, 0.0); ─┐──┐
36      vertices[1] = new Point3d(-0.6, -0.4, 0.0);  ├(3) │
37      vertices[2] = new Point3d(-0.2, 0.3, 0.0); ─┘    ├(2)
38      vertices[3] = new Point3d(0.1, 0.0, 0.0);  ─┐    │
39      vertices[4] = new Point3d(0.3, -0.4, 0.0);   ├(4) │
40      vertices[5] = new Point3d(0.6, 0.1, 0.0);  ─┘──┘   
41      
42      TriangleArray geometry =
43        new TriangleArray(vertices.length, GeometryArray.COORDINATES);
44      geometry.setCoordinates(0, vertices);
45      
46      Shape3D shape = new Shape3D(geometry);
47      
48      root.addChild(shape);
49  
50      return root;
51    }

(1)で頂点配列を初期化しています。頂点配列の要素数は、必ず3の倍数である必要があります。三角形ポリゴンを形成するためには3頂点が必要となるためです。

(2)で各頂点の座標を設定しています。ここで注意することは次の点です。

「3頂点は、視点から見て必ず反時計回りの順序で設定しなければならない」

(3)で設定した3頂点も、(4)で指定した3頂点も、視点から見て反時計回り(左回り)になる順序にしています。

デフォルトではポリゴンの“裏面”は描画されません
ポリゴンの“裏表”は、視点から見た頂点の並びで決定されます。反時計回り(左回り)が“表面”、時計回り(右回り)が“裏面”です。

TrinangleArrayのコンストラクターでは、頂点数が3の倍数でない場合java.lang.IllegalArgumentExceptionが発生します。

setCoordinates()メソッドでの頂点配列設定、Shape3D生成はPointArray, LineArrayと変わりありません。

このプログラムの実行結果は次のようになります。

Shape3DTest3.gif

■■四角形ポリゴンの描画(QuadArray)

javax.media.j3d.QuadArrayは四角形ポリゴンを描画します。


クラス宣言

public class QuadArray
extends GeometryArray

コンストラクター

public QuadArray(int vertexCount,      // 頂点数                   
                 int vertexFormat)     // 頂点指定の形式           
					                           
public QuadArray(int vertexCount,      // 頂点数                   
                 int vertexFormat,     // 頂点指定の形式           
                 int texCoordSetCount, // 指定する頂点の数         
                 int[] texCoordSetMap) // 指定する頂点 index の配列
Shape3DTest.java (一部)

30    private BranchGroup createSceneGraph() {
31      BranchGroup root = new BranchGroup();
32  
33      Point3d[] vertices = new Point3d[8];...(1)
34      
35      vertices[0] = new Point3d(-0.9, 0.0, 0.0); ─┐
36      vertices[1] = new Point3d(-0.6, -0.4, 0.0);  ├(2)
37      vertices[2] = new Point3d(-0.2, 0.3, 0.0);   │
38      vertices[3] = new Point3d(-0.5, 0.5, 0.0); ─┘ 
39      vertices[4] = new Point3d(0.1, 0.0, 0.0);  ─┐
40      vertices[5] = new Point3d(0.3, -0.4, 0.0);   ├(3)
41      vertices[6] = new Point3d(0.6, 0.1, 0.0);    │
42      vertices[7] = new Point3d(0.2, 0.3, 0.0);  ─┘
43      
44      QuadArray geometry =
45        new QuadArray(vertices.length, GeometryArray.COORDINATES);
46      geometry.setCoordinates(0, vertices);
47      
48      Shape3D shape = new Shape3D(geometry);
49      
50      root.addChild(shape);
51  
52      return root;
53    }

(1)で頂点配列を初期化しています。QuadArrayの頂点配列の要素数は必ず4の倍数でなければなりません。四角形ポリゴンを形成するためです。

また、三角形ポリゴンと同様、頂点の並びは視点から見て反時計回りでなければなりません。

(2)で指定した4頂点も、(3)で指定した4頂点も、反時計回りにしてあります。

QuadArrayのコンストラクターでは、頂点数が4の倍数でない場合java.lang.IllegalArgumentExceptionが発生します。

setCoordinates()メソッドでの頂点配列設定、Shape3Dの生成は今まで紹介した他のGeometryArrayと変わりありません。

このプログラムの実行結果は次のようになります。

Shape3DTest4.gif

■曲線や曲面は無いのか?

結論から言うとありません。

Java 3Dで描画できるのは点、直線、ポリゴンのみです。

曲面を描画したい場合は、複数のポリゴンに分割して描画する必要があります。

Java 3Dの下位APIとして実際に描画を担当しているOpenGLは、NURBS (Not Uniform Rational B-Spline) 曲線や曲面を描画できるAPIを持っていますが、Java 3DからそのAPIを使うための手段は今のところありません。

今後Java 3DにNURBS曲線、曲面の描画APIが追加される可能性もあります。 ただし追加されるとしても、javax.media.j3dパッケージではなくcom.sun.j3d.utilsパッケージに追加されることになるだろう、と言われています。

GeometryStripArray

PointArray, LineArray, TriangleArray, QuadArrayはそれぞれ独立した点、線分、多角形を定義するオブジェクトでしたが、連続した線、多角形を定義するためのオブジェクトもあります。javax.media.j3d.GeometryStripArrayです。

クラス継承

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Geometry
                    |
                    +--javax.media.j3d.GeometryArray
                          |
                          +--javax.media.j3d.GeometryStripArray
                                |
                                |--javax.media.j3d.LineStripArray     // 折れ線
                                |
                                |--javax.media.j3d.TriangleStripArray // つながった三角形ポリゴン
                                |
                                +--javax.media.j3d.TriangleFanArray   // 扇型の三角形ポリゴン

クラス宣言

public abstract class GeometryStripArray
extends GeometryArray

GeometryStripArrayは抽象クラス(abstract クラス)なので、実際にはそのサブクラスであるLineStripArray, TriangleStripArray, TriangleFanArrayを使用します。

GeometryStrinpArrayは次のようなコンストラクターを持っています。

public GeometryStripArray(int vertexCount,         // 頂点数
                          int vertexFormat,        // 頂点指定の形式
                          int[] stripVertexCounts) // 個々のstripの頂点数

頂点数 (int vertexCount)、頂点指定の形式 (int vertexFormat) は GeometryArray と同様です。

3番目の引数 int[] stripVertexCounts は、「個々の strip (連続した頂点配列) の個数」を要素とする配列です。これについては具体例が無いとわかりにくいと思うので、後に詳しく説明します。

■■LineStripArray

javax.media.j3d.LineStripArrayは折れ線を複数描画します。


クラス宣言

public class LineStripArray
extends GeometryStripArray

コンストラクター


public LineStripArray(int vertexCount,         // 頂点数
                      int vertexFormat,        // 頂点指定の形式
                      int[] stripVertexCounts) // (stripごとの頂点数)の配列
						  
public LineStripArray(int vertexCount,         // 頂点数
                      int vertexFormat,        // 頂点指定の形式
                      int texCoordSetCount,    // 指定する頂点の数
                      int[] texCoordSetMap,    // 指定する頂点 index の配列
                      int[] stripVertexCounts) // (stripごとの頂点数)の配列

次のサンプルは、2つの折れ線を描画します。頂点数はそれぞれ8、7です。

Shape3DTest.java (一部)

30    private BranchGroup createSceneGraph() {
31      BranchGroup root = new BranchGroup();
32  
33      Point3d[] vertices = new Point3d[15];...(1)
34      
35      vertices[0] = new Point3d(-0.9, -0.6, 0.0);─┐──┐   
36      vertices[1] = new Point3d(-0.5, -0.8, 0.0);  │    │   
37      vertices[2] = new Point3d(-0.5, -0.4, 0.0)); │    │
38      vertices[3] = new Point3d(0.0, -0.6, 0.0);   ├(3) │
39      vertices[4] = new Point3d(0.0, -0.2, 0.0);   │    │
40      vertices[5] = new Point3d(0.4, -0.3, 0.0);   │    │
41      vertices[6] = new Point3d(0.5, 0.1, 0.0);    │    │
42      vertices[7] = new Point3d(0.8, 0.0, 0.0);  ─┘    ├(2)
43      vertices[8] = new Point3d(-0.8, 0.2, 0.0); ─┐    │  
44      vertices[9] = new Point3d(-0.6, 0.0, 0.0);   │    │  
45      vertices[10] = new Point3d(-0.6, 0.5, 0.0)   │    │
46      vertices[11] = new Point3d(-0.3, 0.3, 0.0);  ├(4) │
47      vertices[12] = new Point3d(-0.2, 0.6, 0.0);  │    │
48      vertices[13] = new Point3d(0.1, 0.5, 0.0);   │    │
49      vertices[14] = new Point3d(0.0, 0.8, 0.0); ─┘──┘
50      
51      int[] stripVertexCounts = { 8, 7 };...(3)
52      
53      LineStripArray geometry = new LineStripArray(
54        vertices.length, GeometryArray.COORDINATES, stripVertexCounts);...(6)
55      geometry.setCoordinates(0, vertices);
56      
57      Shape3D shape = new Shape3D(geometry);
58      
59      root.addChild(shape);
60  
61      return root;
62    }

このプログラムの実行結果は次のようになります。

Shape3DTest5.gif

(1)で頂点配列を要素数=15で初期化し、(2)で各頂点に座標をセットしています。

(3)で個々の折れ線の頂点数を格納するint型の配列変数stripVertextCountsを初期化しています。

この配列の要素数は2です。つまり、折れ線の数は2つということになります。

この配列の各要素はそれぞれ8、7です。つまり、最初の折れ線の頂点数は8、2番目の折れ線の頂点数は7ということになります。

(4)の8つの頂点座標が最初の折れ線、(5)の7つの頂点座標が2番目の折れ線の頂点座標として使用されます。

(6)のLineStripArray生成のときに、コンストラクターの3番目の引数としてstripVertexCountsを渡しています。

setCoordinates()による頂点配列のセットや、Shape3Dオブジェクトの生成は今までと同様です。

■■TriangleStripArray

javax.media.j3d.TriangleStripArrayは「辺を共有する連続した三角形ポリゴンの集合」を複数描画します。


クラス宣言

public class TriangleStripArray
extends GeometryStripArray

コンストラクター

public TriangleStripArray(int vertexCount,         // 頂点数                   
                          int vertexFormat,        // 頂点指定の形式           
                          int[] stripVertexCounts) // (stripごとの頂点数)の配列
						                               
public TriangleStripArray(int vertexCount,         // 頂点数                   
                          int vertexFormat,        // 頂点指定の形式           
                          int texCoordSetCount,    // 指定する頂点の数         
                          int[] texCoordSetMap,    // 指定する頂点 index の配列
                          int[] stripVertexCounts) // (stripごとの頂点数)の配列

次のサンプルではポリゴン集合を2つ描画します。

Shape3DTest.java (一部)

30    private BranchGroup createSceneGraph() {
31      BranchGroup root = new BranchGroup();
32  
33      Point3d[] vertices = new Point3d[15];
34      
35      vertices[0] = new Point3d(-0.9, -0.6, 0.0); ──────┐
36      vertices[1] = new Point3d(-0.5, -0.8, 0.0);             │
37      vertices[2] = new Point3d(-0.5, -0.4, 0.0);             │
38      vertices[3] = new Point3d(0.0, -0.6, 0.0);              │
39      vertices[4] = new Point3d(0.0, -0.2, 0.0);              │
40      vertices[5] = new Point3d(0.4, -0.3, 0.0);              │
41      vertices[6] = new Point3d(0.5, 0.1, 0.0);               │
42      vertices[7] = new Point3d(0.8, 0.0, 0.0);               │
43      vertices[8] = new Point3d(-0.8, 0.2, 0.0);              ├(1)
44      vertices[9] = new Point3d(-0.6, 0.0, 0.0);              │
45      vertices[10] = new Point3d(-0.6, 0.5, 0.0);             │
46      vertices[11] = new Point3d(-0.3, 0.3, 0.0);             │
47      vertices[12] = new Point3d(-0.2, 0.6, 0.0);             │
48      vertices[13] = new Point3d(0.1, 0.5, 0.0);              │
49      vertices[14] = new Point3d(0.0, 0.8, 0.0);              │
50                                                              │
51      int[] stripVertexCounts = { 8, 7 };...(2)   ──────┘
52      
53      TriangleStripArray geometry = new TriangleStripArray(
54        vertices.length, GeometryArray.COORDINATES, stripVertexCounts);...(3)
55      geometry.setCoordinates(0, vertices);
56      
57      Shape3D shape = new Shape3D(geometry);
58      
59      root.addChild(shape);
60  
61      return root;
62    }

(1)はLineStripArrayのサンプルと全く同じ頂点配列を使用しています。(2)のstripVertexCountsも要素数=2、各要素は{ 8, 7 }LineStripArrayのときと全く同様です。

違いは(3)で生成するのがLineStripArrayではなくTriangleStripArrayである、という点だけです。

実行結果は次のようになります。

Shape3DTest6.gif

すべてのポリゴンがデフォルトの色である白色なので ポリゴンの境界がわかりにくいですが、 LineStripArrayで描画された折れ線の間に 三角形ポリゴンが描画されています。

TriangleStripArray.gif

各ポリゴンの頂点指定の順序はすべて同じになります。(このサンプルではすべて反時計回り。つまり、すべてのポリゴンは“表面”となる)

註:
Java 3D API Specification に上記のように明確に書いてあるわけではありませんが、 Java 3D 1.1.2 Win32 (OpenGL 1.1), Java 3D 1.1 Linux (Mesa 3.0)での実行結果では すべてのポリゴンが"表"になりました。つまり、頂点指定の順序が同じです。

■■TriangleFanArray

javax.media.j3d.TriangleFanArrayは「辺を共有する連続した扇形の三角形ポリゴンの集合」を複数描画します。


クラス宣言

public class TriangleFanArray
extends GeometryStripArray

コンストラクター

public TriangleFanArray(int vertexCount,         // 頂点数                   
                        int vertexFormat,        // 頂点指定の形式           
                        int[] stripVertexCounts) // (stripごとの頂点数)の配列
						                             
public TriangleFanArray(int vertexCount,         // 頂点数                   
                        int vertexFormat,        // 頂点指定の形式           
                        int texCoordSetCount,    // 指定する頂点の数         
                        int[] texCoordSetMap,    // 指定する頂点 index の配列
                        int[] stripVertexCounts) // (stripごとの頂点数)の配列
Shape3DTest.java (一部)

30    private BranchGroup createSceneGraph() {
31      BranchGroup root = new BranchGroup();
32  
33      Point3d[] vertices = new Point3d[15]; ──────┐   
34                                                      │   
35      vertices[0] = new Point3d(-0.4, -0.2, 0.0);     │   
36      vertices[1] = new Point3d(0.0, -0.3, 0.0);      │   
37      vertices[2] = new Point3d(0.1, 0.0, 0.0);       │   
38      vertices[3] = new Point3d(-0.1, 0.3, 0.0);      │   
39      vertices[4] = new Point3d(-0.6, 0.2, 0.0);      │   
40      vertices[5] = new Point3d(-0.9, 0.0, 0.0);      │   
41      vertices[6] = new Point3d(-0.8, -0.5, 0.0);     ├(1)
42      vertices[7] = new Point3d(0.4, 0.5, 0.0);       │
43      vertices[8] = new Point3d(0.1, 0.5, 0.0);       │
44      vertices[9] = new Point3d(0.4, 0.3, 0.0);       │
45      vertices[10] = new Point3d(0.6, 0.5, 0.0);      │
46      vertices[11] = new Point3d(0.5, 0.8, 0.0);      │
47      vertices[12] = new Point3d(0.3, 0.8, 0.0);      │
48      vertices[13] = new Point3d(0.2, 0.7, 0.0);      │
49      vertices[14] = new Point3d(0.2, 0.6, 0.0);───┘
50      
51      int[] stripVertexCounts = { 7, 8 };...(2)
52      
53      TriangleFanArray geometry = new TriangleFanArray(
54        vertices.length, GeometryArray.COORDINATES, stripVertexCounts);...(3)
55      geometry.setCoordinates(0, vertices);
56      
57      Shape3D shape = new Shape3D(geometry);
58      
59      root.addChild(shape);
60  
61      return root;
62    }

(1)で頂点配列を初期化、座標設定しています。

(2)でstripVertextCounts{ 7, 8 }で初期化しています。

(3)でTriangleFanArrayを生成しています。

このプログラムの実行結果は次のようになります。

Shape3DTest7.gif

頂点配列は次のようになっています。

TriangleFanArray.gif

TriangleFanArrayは、各頂点配列の先頭要素の頂点 (ここでは V0、V7) を中心に、三角形ポリゴンを扇形に形成します。

TriangleStripArrayと同様に、各ポリゴンの頂点指定の順序はすべて同じになります。(このサンプルではすべて反時計回り。つまり、すべてのポリゴンは“表面”となる)

註:
TriangleStripArrayのときと同様に、Java 3D API Specification に上記のように明確に書いてあるわけではありませんが、Java 3D 1.1.2 Win32 (OpenGL 1.1), Java 3D 1.1 Linux (Mesa 3.0) での実行結果ではすべてのポリゴンが“表面”になりました。つまり、頂点指定の順序が同じです。

GeometryArrayでの色指定の方法

GeometryArrayでは、点、線分、ポリゴンに色を指定できます。

このために必要なのは以下の手順です。

  1. GeometryArrayのコンストラクターで COLOR_3 または COLOR_4 を指定する。(2番目の引数の int vertexFormat)
  2. setColor() または setColors() メソッドで各頂点に色を指定する

COLOR_3 を指定したとき、RGB で色を設定できます。RGB は red、green、blue の3色です。

COLOR_4 を指定したとき、RGBA で色を設定できます。RGBA は red、green、blue の3色のほかに、4番目の要素として透明度 alpha を持ちます。

javax.vecmathパッケージには、RGB, RGBA のためのクラス Color3f, Color4f があります。

■■javax.vecmath.Color3fクラス

javax.vecmath.Color3fはRGBカラーを定義します。

クラス継承

java.lang.Object
  |
  +--javax.vecmath.Tuple3f
        |
        +--javax.vecmath.Color3f

クラス宣言

public class Color3f
extends Tuple3f
implements java.io.Serializable

Color3fは次のようなコンストラクターを持ちます。

public Color3f(float x, // red   (赤)
               float y, // green (緑)
               float z) // blue  (青)

Color3fTuple3fのサブクラスです。Tuple3ffloat型のprotectedフィールドx, y, zを持っています。

Tuple3fのサブクラスには、ほかにVector3f, Point3fなどがあります。

Color3fでは、x, y, z はそれぞれ赤、緑、青の3色を表します。

註:
Java 3D API Specificationx, y ,z に RGB カラー値を代入/使用することを強制しているわけではありません。RGB以外のカラー値 (HSBなど) を代入/使用してもかまいません。
しかしながら、GeometryArraysetColor(), setColors()メソッドでは x, y, z は RGB になります。
このため、ここでは「x, y, z は RGB である」と説明しています。

x, y ,z の取り得る範囲は 0.0f〜1.0f です。

x, y ,z のデフォルト値は 0.0f です。

x, y ,z すべてが 0.0f なら黒、すべてが 1.0f なら白です。

■■javax.vecmath.Color4fクラス

javax.vecmath.Color4fはRGBAカラーを定義します。

RGBAは、red (赤), green (緑), bule (青), alpha (透明度) の4つの要素から成り立っています。

クラス継承

java.lang.Object
  |
  +--javax.vecmath.Tuple4f
        |
        +--javax.vecmath.Color4f

クラス宣言

public class Color4f
extends Tuple4f
implements java.io.Serializable

Color4f は次のようなコンストラクターを持ちます。

Color4f のコンストラクター (一部)
public Color4f(float x, // red   (赤)
               float y, // green (緑)
               float z, // blue  (青)
               float w) // alpha (不透明度)

Colo4fTuple4f のサブクラスです。Tuple4f は float 型の procected フィールド x, y, z, w を持っています。

Color3f と同様に、x, y, z はそれぞれ red (赤), green (緑), blue (青) の3色を表します。

w は alpha (不透明度) を表します。w の取り得る値の範囲は、x, y, z と同様に 0.0f〜1.0f です。

w0.0f=透明1.0f=不透明 です。

x, y, z, w のデフォルト値は 0.0f です。

■■色の指定-ポリゴンの頂点に同じ色を指定する

GeometryArraysetColor(), setColors() メソッドによる色指定は、各頂点に対して適用されます。

ColorTest.java (一部)

30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[6];
34     
35     vertices[0] = new Point3d(-0.9, 0.0, 0.0);
36     vertices[1] = new Point3d(-0.6, -0.4, 0.0);
37     vertices[2] = new Point3d(-0.2, 0.3, 0.0);
38     vertices[3] = new Point3d(0.1, 0.0, 0.0);
39     vertices[4] = new Point3d(0.3, -0.4, 0.0);
40     vertices[5] = new Point3d(0.6, 0.1, 0.0);
41     
42     TriangleArray geometry = new TriangleArray(
43       vertices.length, GeometryArray.COORDINATES | GeometryArray.COLOR_3);...(1)
44     geometry.setCoordinates(0, vertices);
45     Color3f red = new Color3f(1.0f, 0.0f, 0.0f); ─┬(2)
46     Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);─┘
47     geometry.setColor(0, red); ─┐
48     geometry.setColor(1, red);   │
49     geometry.setColor(2, red);   ├(3)
50     geometry.setColor(3, blue);  │
51     geometry.setColor(4, blue);  │
52     geometry.setColor(5, blue);─┘
53     
54     Shape3D shape = new Shape3D(geometry);
55     
56     root.addChild(shape);
57 
58     return root;
59   }

(1)で TriangleArray を生成しています。このとき、コンストラクターの2番目の引数 int vertexFormat には、GeometryArray.COORDINATESGeometryArray.COLOR_3 を OR 演算したものを指定しています。

(2)で赤と青の Color3f オブジェクトを生成しています。

(3)でsetColor() メソッドで各頂点の色を設定しています。最初のポリゴンの頂点にはすべて赤、2番目のポリゴンの頂点にはすべて青を設定しています。

setColor()メソッドの引数は次の通りです。

public final void setColor(int index,      // 頂点のindex
                           Color3f color) // 頂点に設定する色

このプログラムの実行結果は次のようになります。

ColorTest1.gif

各ポリゴンの頂点には同じ色が設定してあるので、赤と青のポリゴンが表示されています。

setColor()メソッドは一つの頂点に色を設定するメソッドですが、GeometryArray には複数の頂点にまとめて色を設定できる setColors() メソッドもあります。

public final void setColors(int index,        // 設定を開始する頂点のindex
                            Color3b[] colors) // 色の配列

setColors() メソッドの例を次に示します。

ColorTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[6];
34     
35     vertices[0] = new Point3d(-0.9, 0.0, 0.0);
36     vertices[1] = new Point3d(-0.6, -0.4, 0.0);
37     vertices[2] = new Point3d(-0.2, 0.3, 0.0);
38     vertices[3] = new Point3d(0.1, 0.0, 0.0);
39     vertices[4] = new Point3d(0.3, -0.4, 0.0);
40     vertices[5] = new Point3d(0.6, 0.1, 0.0);
41     
42     TriangleArray geometry = new TriangleArray(
43       vertices.length, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
44     geometry.setCoordinates(0, vertices);
45     Color3f red = new Color3f(1.0f, 0.0f, 0.0f); 
46     Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);
47     Color3f[] colors1 = { red, red, red };   ─┬(1)
48     Color3f[] colors2 = { blue, blue, blue };─┘
49     geometry.setColors(0, colors1);.............(2)
50     geometry.setColors(3, colors2);.............(3)
51     
52     Shape3D shape = new Shape3D(geometry);
53     
54     root.addChild(shape);
55 
56     return root;
57   }
58 

上に示した以外の部分は、setColor() メソッドのサンプルと全く同じです。

(1)で Color3f の配列を確保し初期化しています。この例では要素数=3で、各要素をすべて同じ色にしてあります。

(2)〜(3)で setColors() メソッドを使って複数の頂点に色を設定しています。

(2)では頂点index=0、つまり頂点配列の先頭要素から設定を開始しています。配列 colors1 は要素数=3なので、先頭要素を含んだ3頂点の色が赤に設定されます。

(3)では頂点index=3 の頂点から設定を開始し、index=3 の頂点を含んだ3頂点を青に設定しています。

このプログラムの実行結果は、setColor()のサンプルと全く同じです。

■■色の指定-各頂点に別々の色を指定する

これまで、ポリゴンの頂点全てに同じ色を設定して来ましたが、各頂点に別々の色を設定したらどうなるでしょうか。

ColorTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[6];
34     
35     vertices[0] = new Point3d(-0.9, 0.0, 0.0);
36     vertices[1] = new Point3d(-0.6, -0.4, 0.0);
37     vertices[2] = new Point3d(-0.2, 0.3, 0.0);
38     vertices[3] = new Point3d(0.1, 0.0, 0.0);
39     vertices[4] = new Point3d(0.3, -0.4, 0.0);
40     vertices[5] = new Point3d(0.6, 0.1, 0.0);
41     
42     TriangleArray geometry = new TriangleArray(
43       vertices.length, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
44     geometry.setCoordinates(0, vertices);
45 
46     Color3f[] colors = { new Color3f(0.0f, 0.0f, 1.0f),   // blue  ─┐
47                          new Color3f(1.0f, 0.0f, 0.0f),   // red     │
48                          new Color3f(0.0f, 1.0f, 0.0f),   // green   ├(1)
49                          new Color3f(1.0f, 1.0f, 0.0f),   // yellow  │
50                          new Color3f(1.0f, 0.0f, 1.0f),   // magente │
51                          new Color3f(0.0f, 1.0f, 1.0f) }; // cya   ─┘
52     geometry.setColors(0, colors);.....................................(2)
53     
54     Shape3D shape = new Shape3D(geometry);
55     
56     root.addChild(shape);
57 
58     return root;
59   }

(1)で要素数=6 の Color3f の配列を確保し、配列の各要素すべてに別々の色を代入して初期化しています。

(2)で setColors() メソッドを使って複数の頂点に色を設定しています。

このプログラムの実行結果は次のようになります。

ColorTest3.gif

各頂点に設定された色が、きれいな中間色として補間されているのがわかると思います。

IndexedGeometryArray

いままで紹介して来た javax.media.j3d.GeometryArray のサブクラスでは、同じ頂点を共有している線分、ポリゴンがある場合でも頂点数と同じ数の頂点座標 (頂点配列) を必要とします。

実際には同じ頂点を共有するケースの方が多いかも知れません。

こういう場合のために、頂点座標の配列をまず用意し、線分、ポリゴン形成のための頂点指定はその配列の index で指定するという方法が考えられます。このためのクラスが javax.media.j3d.IndexedGeometryArray とそのサブクラスです。

クラス継承

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Geometry
                    |
                    +--javax.media.j3d.GeometryArray
                          |
                          +--javax.media.j3d.IndexedGeometryArray
                                |
                                |--javax.media.j3d.IndexedPointArray    // 点
                                |
                                |--javax.media.j3d.IndexedLineArray     // 独立した線分
                                |
                                |--javax.media.j3d.IndexedTriangleArray // 独立した三角形ポリゴン
                                |
                                +--javax.media.j3d.IndexedQuadArray     // 独立した四角形ポリゴン

クラス宣言

public abstract class IndexedGeometryArray
extends GeometryArray

IndexedGeometryArray は抽象クラス (abstract クラス) なので、実際にはそのサブクラスである IndexedPointArra, IndexedLineArray, IndexedTriangleArray, IndexedQuadArray が使用されます。

IndexedGeometryArray は次のようなコンストラクターを持ちます。

public IndexedGeometryArray(int vertexCount,  // 頂点数
                            int vertexFormat, // 頂点指定の形式
                            int indexCount)   // 頂点 index の数

最初の引数の頂点数ですが、「線分またはポリゴンの頂点数の総数」よりも少ないことがあり得ます。

2番目の引数は GeometryArray と同じです。

3番目の引数は頂点 index の数です。これは「点/線分/ポリゴンの頂点数の総数」と同じ数になります。

IndexedGeometryArray の使用方法は次のような手順になります。

  1. 頂点配列を用意する
  2. 頂点indexの配列を用意する
  3. 頂点数、頂点指定形式、頂点indexの数を引数にIndexedGeometryArry を生成する
  4. setCoordinates() メソッドを使って頂点配列を設定する
  5. setCoordinateIndices() メソッドを使って頂点 index を設定する
  6. IndexedGeometryArray を引数に Shape3D を生成する
  7. Shape3D をシーン・グラフに addChild() する

例によって言葉で説明してもわかりにくいので、具体例を見ていただこうと思います。

■■IndexedPointArray

javax.media.j3d.IndexedPointArray は、画面上に点を描画します。PointArray と同じです。


クラス宣言

public class IndexedPointArray
extends IndexedGeometryArray

コンストラクター

public IndexedPointArray(int vertexCount,      // 頂点数                   
                         int vertexFormat,     // 頂点指定の形式           
                         int indexCount)       // 頂点 index 配列の要素数
						                           
public IndexedPointArray(int vertexCount,      // 頂点数                   
                         int vertexFormat,     // 頂点指定の形式           
                         int texCoordSetCount, // 指定する頂点の数         
                         int[] texCoordSetMap, // 指定する頂点 index の配列
                         int indexCount)       // 頂点 index 配列の要素数
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[3];        ─┐
34     						     │
35     vertices[0] = new Point3d(-0.6, 0.7, 0.0);    ├(1)
36     vertices[1] = new Point3d(-0.4, -0.8, 0.0);   │
37     vertices[2] = new Point3d(0.5, -0.4, 0.0);    │
38     						   ─┘
39     int[] indices = { 2, 0, 1 };....................(2)
40     
41     IndexedPointArray geometry =
42       new IndexedPointArray(vertices.length, GeometryArray.COORDINATES, indices.length);...(3)
43     geometry.setCoordinates(0, vertices);........(4)
44     geometry.setCoordinateIndices(0, indices);...(5)
45     
46     Shape3D shape = new Shape3D(geometry);
47     
48     root.addChild(shape);
49 
50     return root;
51   }

(1)で要素数=3 の頂点配列を確保、初期化しています。この座標は PointArray のサンプルと同じですが、順序は変えてあります。

(2)で要素数=3 のint 型の配列を確保、初期化しています。この配列の各要素は、頂点配列の index (配列の添え字) です。

(3)で IndexedPointArray オブジェクトを生成しています。 コンストラクターの3番目の引数は「頂点 index の配列の要素数」です。ここでは頂点数と同じ 3 です。

(4)で setCoordinates() メソッドを使って頂点配列を設定しています。

(5)で setCoordinateInices() メソッドを使って、頂点 index の配列を設定しています。

これ以外の部分は PintArray のサンプルと同じです。

このプログラムの実行結果は次のようになります。

Shape3DTest8.gif

見ていただいて分かるように、PointArray のサンプルと全く同様です。

INdexedPointArray のメリットとは何でしょうか?

PointArrayと比べて特にメリットはありませんが、強いて言えば次の2点です。

  1. 頂点配列とは違う順序で点を描画できる
  2. 頂点配列とは違う個数の点を描画できる (ただし、[ 点の数 ≦ 頂点配列の要素数 ] )

■■IndexedLineArray

javax.media.j3d.IndexedLineArray は、複数の独立した線分を描画します。線分の端点 (始点、終点) は、頂点配列の index で指定します。

クラス宣言

public class IndexedLineArray
extends IndexedGeometryArray

コンストラクター

public IndexedLineArray(int vertexCount,      // 頂点数                   
                        int vertexFormat,     // 頂点指定の形式           
                        int indexCount)       // 頂点 index 配列の要素数  
						                          
public IndexedLineArray(int vertexCount,      // 頂点数                   
                        int vertexFormat,     // 頂点指定の形式           
                        int texCoordSetCount, // 指定する頂点の数         
                        int[] texCoordSetMap, // 指定する頂点 index の配列
                        int indexCount)       // 頂点 index 配列の要素数  
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[8];        ─┐
34     						     │
35     vertices[0] = new Point3d(-0.5, 0.5, 0.5);    │  
36     vertices[1] = new Point3d(-0.5, -0.5, 0.5);   │
37     vertices[2] = new Point3d(0.5, -0.5, 0.5);    ├(1)  
38     vertices[3] = new Point3d(0.5, 0.5, 0.5);     │
39     vertices[4] = new Point3d(-0.5, 0.5, -0.5);   │
40     vertices[5] = new Point3d(-0.5, -0.5, -0.5);  │
41     vertices[6] = new Point3d(0.5, -0.5, -0.5);   │
42     vertices[7] = new Point3d(0.5, 0.5, -0.5);  ─┘
43     
44     int[] indices = { 0, 1,  ─┐
45                       1, 2,    │
46                       2, 3,    │
47                       3, 0,    │
48                       0, 4,    │
49                       1, 5,    ├(2)
50                       2, 6,    │
51                       3, 7,    │
52                       4, 5,    │
53                       5, 6,    │
54                       6, 7,    │
55                       7, 4 };─┘
56     
57     IndexedLineArray geometry =
58       new IndexedLineArray(vertices.length, GeometryArray.COORDINATES, indices.length);...(3)
59     geometry.setCoordinates(0, vertices);........(4)
60     geometry.setCoordinateIndices(0, indices);...(5)
61     
62     Shape3D shape = new Shape3D(geometry);
63     
64     Transform3D t3d = new Transform3D();                 ─┐
65     t3d.setRotation(                                       ├(6)
66       new AxisAngle4d(0.57, 0.57, -0.57, Math.PI / 4.0));  │
67     TransformGroup trans = new TransformGroup(t3d);      ─┘
68     
69     trans.addChild(shape);
70     
71     root.addChild(trans);
72 
73     return root;
74   }

(1)で頂点配列を確保、初期化しています。これは、原点を中心とし、辺の長さが 1.0 の立方体の頂点になっています。要素数=8 です。

(2)で頂点 index の配列を確保、初期化しています。 この頂点 index の配列で、各線分の端点 (始点、終点) を指定します。線分の端点 (始点、終点) を指定するので、頂点 index の配列要素数は必ず 2 の倍数になります。

(3)で IndexedLineArray を生成しています。3番目の引数に、頂点 index の数を指定しています。

(4)で setCoordinates() メソッドで頂点配列を設定しています。設定を開始する頂点はゼロ、つまり先頭から設定を開始します。

(5)で setCoordinateIndices() メソッドで頂点 index の配列を設定しています。設定を開始する頂点 index はゼロ、つまり先頭要素から設定を開始します。

(6)で全体の形状がよくわかるようにするため回転を与えています。

このプログラムの実行結果は次のようになります。

Shape3DTest9.gif

「頂点を共有する複数の独立した線分」を描画するには IndexedLineArray が便利です。

■■IndexedTriangleArray

javax.media.j3d.IndexedTriangleArray は、複数の独立した三角形ポリゴンを描画します。ポリゴンの頂点は頂点配列の index で指定します。


クラス宣言

public class IndexedTriangleArray
extends IndexedGeometryArray

コンストラクター

public IndexedTriangleArray(int vertexCount,      // 頂点数                   
                            int vertexFormat,     // 頂点指定の形式           
                            int indexCount)       // 頂点 index 配列の要素数  
						                              
public IndexedTriangleArray(int vertexCount,      // 頂点数                   
                            int vertexFormat,     // 頂点指定の形式           
                            int texCoordSetCount, // 指定する頂点の数         
                            int[] texCoordSetMap, // 指定する頂点 index の配列
                            int indexCount)       // 頂点 index 配列の要素数  
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[8];
34     
35     vertices[0] = new Point3d(-0.5, 0.5, 0.5);  ─┐
36     vertices[1] = new Point3d(-0.5, -0.5, 0.5);   │
37     vertices[2] = new Point3d(0.5, -0.5, 0.5);    │
38     vertices[3] = new Point3d(0.5, 0.5, 0.5);     ├(1)
39     vertices[4] = new Point3d(-0.5, 0.5, -0.5);   │ 
40     vertices[5] = new Point3d(-0.5, -0.5, -0.5);  │
41     vertices[6] = new Point3d(0.5, -0.5, -0.5);   │
42     vertices[7] = new Point3d(0.5, 0.5, -0.5);  ─┘
43
44     int[] indices = { 0, 1, 2,    ─┐
45                       0, 2, 3,      │
46                       4, 5, 1,      │
47                       4, 1, 0,      │
48                       4, 0, 3,      │
49                       4, 3, 7,      ├(2)
50                       3, 2, 6,      │
51                       3, 6, 7,      │
52                       7, 6, 5,      │
53                       7, 5, 4,      │
54                       1, 5, 6,      │
55                       1, 6, 2 };  ─┘
56 
57     Color3f[] colors = { new Color3f(1.0f, 0.0f, 0.0f),    // red       ─┐
58                          new Color3f(0.0f, 1.0f, 0.0f),    // green       │
59                          new Color3f(0.0f, 0.0f, 1.0f),    // blue	     ├(3)
60                          new Color3f(0.0f, 1.0f, 1.0f),    // cyan	     │
61                          new Color3f(1.0f, 0.0f, 1.0f),    // magenta     │
62                          new Color3f(1.0f, 1.0f, 0.0f) };  // yellow	   ─┘
63 
64     int[] colorIndices = { 0, 0, 0,   // red       ─┐
65                            1, 1, 1,   // green       │
66                            2, 2, 2,   // blue        │
67                            3, 3, 3,   // cyan        │
68                            4, 4, 4,   // magenta     │
69                            5, 5, 5,   // yellow      ├(4)
70                            0, 0, 0,   // red         │
71                            1, 1, 1,   // green       │
72                            2, 2, 2,   // blue        │
73                            3, 3, 3,   // cyan        │
74                            4, 4, 4,   // magenta     │
75                            5, 5, 5 }; // yellow    ─┘
76     
77     IndexedTriangleArray geometry =
78       new IndexedTriangleArray( vertices.length,
79                                 GeometryArray.COORDINATES | GeometryArray.COLOR_3,
80                                 indices.length);...(5)
81     geometry.setCoordinates(0, vertices);..........(6)
82     geometry.setCoordinateIndices(0, indices);.....(7)
83     geometry.setColors(0, colors);.................(8)
84     geometry.setColorIndices(0, colorIndices);.....(9)
85     
86     Shape3D shape = new Shape3D(geometry);
87     
88     Transform3D t3d = new Transform3D();                 ─┐
89     t3d.setRotation(					      ├(10)
90       new AxisAngle4d(0.57, 0.57, -0.57, Math.PI / 4.0));  │
91     TransformGroup trans = new TransformGroup(t3d);	    ─┘
92     
93     trans.addChild(shape);
94     
95     root.addChild(trans);
96 
97     return root;
98   }

(1)で確保、初期化している頂点配列は、IndexedLineArray のサンプルと同じものです。原点を中心に、辺の長さが 1.0 の立方体の頂点です。

(2)で頂点 index の配列を確保、初期化しています。この配列で、三角形ポリゴンの頂点を指定します。頂点 index の配列要素数は必ず 3 の倍数になります。

この頂点 index で指定する各ポリゴンの頂点の順序は、視点から見てかならず反時計回りになるようにする必要があります。

各ポリゴンに色を指定してわかりやすくする目的で、(3)で色の配列を確保、初期化しています。

(4)で色の配列の index を確保、初期化しています。各三角形ポリゴンの3つの頂点に同じ色を適用しています。

(5)で IndexedTraingleArray を生成しています。

頂点に色を指定するので、2番目の引数に GeometryArray.COLOR_3 を指定しています。

3番目の引数には、頂点 index の配列要素数を指定しています。

(6)で secCoordinates() メソッドで頂点配列を設定しています。設定を開始する頂点はゼロ、つまり先頭から設定を開始します。

(7)ではCODE>setCoordinateIndices() メソッドで頂点 index の配列を設定しています。設定を開始する index はゼロ、つまり先頭から設定を開始します。

(8)では setColors() メソッドで色の配列を設定しています。設定を開始するのはゼロ、つまり先頭からです。

(9)では setColorIndices() メソッドで色の配列の index を設定しています。この設定によって各ポリゴンの頂点に色が設定されます。(頂点配列に対して色を設定するわけではありません。頂点 index の配列、つまり実際のポリゴンの各頂点に色を設定します)

(10)で回転を与えています。

このプログラムの実行結果は次のようになります。

Shape3DTest10.gif

任意の形状のポリゴンを形成するとき、 IndexedTriangelArrayはたいへん便利に使えます。

■■IndexedQuadArray

IndexedQuadArray は、複数の独立した四角形ポリゴンを描画します。ポリゴンと頂点は、頂点配列の index で指定します。


クラス宣言

public class IndexedQuadArray
extends IndexedGeometryArray

コンストラクター

public IndexedQuadArray(int vertexCount,      // 頂点数                   
                        int vertexFormat,     // 頂点指定の形式           
                        int indexCount)       // 頂点 index 配列の要素数  
						                          
public IndexedQuadArray(int vertexCount,      // 頂点数                   
                        int vertexFormat,     // 頂点指定の形式           
                        int texCoordSetCount, // 指定する頂点の数         
                        int[] texCoordSetMap, // 指定する頂点 index の配列
                        int indexCount)       // 頂点 index 配列の要素数  
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[8];
34     
35     vertices[0] = new Point3d(-0.5, 0.5, 0.5);
36     vertices[1] = new Point3d(-0.5, -0.5, 0.5);
37     vertices[2] = new Point3d(0.5, -0.5, 0.5);
38     vertices[3] = new Point3d(0.5, 0.5, 0.5);
39     vertices[4] = new Point3d(-0.5, 0.5, -0.5);
40     vertices[5] = new Point3d(-0.5, -0.5, -0.5);
41     vertices[6] = new Point3d(0.5, -0.5, -0.5);
42     vertices[7] = new Point3d(0.5, 0.5, -0.5);
43     
44     int[] indices = { 0, 1, 2, 3,   ─┐
45                       4, 5, 1, 0,     │
46                       4, 0, 3, 7,     ├(1)
47                       3, 2, 6, 7,     │
48                       7, 6, 5, 4,     │
49                       1, 5, 6, 2 }; ─┘
50 			 		    
51     Color3f[] colors = { new Color3f(1.0f, 0.0f, 0.0f),   // red     ─┐
52                          new Color3f(0.0f, 1.0f, 0.0f),   // green     │
53                          new Color3f(0.0f, 0.0f, 1.0f),   // blue      ├(2)
54                          new Color3f(0.0f, 1.0f, 1.0f),   // cyan      │
55                          new Color3f(1.0f, 0.0f, 1.0f),   // magenta	  │
56                          new Color3f(1.0f, 1.0f, 0.0f) }; // yellow  ─┘
57 
58     int[] colorIndices = { 0, 0, 0, 0,   // red    ─┐
59                            1, 1, 1, 1,   // green    │
60                            2, 2, 2, 2,   // blue     ├(3)
61                            3, 3, 3, 3,   // cyan     │
62                            4, 4, 4, 4,   // magenta  │
63                            5, 5, 5, 5 }; // yellow ─┘
64     
65     IndexedQuadArray geometry =
66       new IndexedQuadArray( vertices.length, 
67                             GeometryArray.COORDINATES | GeometryArray.COLOR_3,
68                             indices.length);.........(4)
69     geometry.setCoordinates(0, vertices);      ─┐
70     geometry.setCoordinateIndices(0, indices);   ├(5)
71     geometry.setColors(0, colors);               │
72     geometry.setColorIndices(0, colorIndices); ─┘
73     
74     Shape3D shape = new Shape3D(geometry);
75     
76     Transform3D t3d = new Transform3D();                 ─┐
77     t3d.setRotation(					      ├(6)
78       new AxisAngle4d(0.57, 0.57, -0.57, Math.PI / 4.0));  │
79     TransformGroup trans = new TransformGroup(t3d);	    ─┘
80     
81     trans.addChild(shape);
82     
83     root.addChild(trans);
84 
85     return root;
86   }

(1)で頂点 index の配列を確保、初期化しています。この配列で、四角形ポリゴンの各頂点を設定します。それぞれのポリゴンの頂点の順序は、視点から見て反時計回りになっている必要があります。四角形ポリゴンの頂点を指定するので、頂点 index の数は必ず 4の倍数である必要があります。

(2)で色の配列を確保、初期化しています。

(3)で色の配列の index を確保、初期化しています。ここでは、それぞれの四角形ポリゴンの4つの頂点に同じ色を適用しています。

(4)で IndexedQuadArray を生成しています。引数の意味は IndexedLineArray, IndexedTriangleArray と同じです。

(5)で setCoordinates(), setCoordinateIndices(), setColors(), setColorIndices() メソッドを使って頂点配列、頂点 index、色の配列、色の配列の index を設定しています。

(6)で回転を与えています。

このプログラムの実行結果は次のようになります。

Shape3DTest11.gif

四角形ポリゴンを複数描画するときはIndexedQuadArray を使うと便利です。

IndexedGeometryStripArray

IndexedGeometryArray のサブクラスは独立した点、線分、ポリゴンを描画しましたが、javax.media.j3d.IndexedGeometryStripArray のサブクラスは折れ線、辺を共有する連続した三角形、辺を共有する扇型の三角形などを描画します。

ポリゴンの頂点は、頂点 index で指定します。

クラス継承

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Geometry
                    |
                    +--javax.media.j3d.GeometryArray
                          |
                          +--javax.media.j3d.IndexedGeometryArray
                                |
                                +--javax.media.j3d.IndexedGeometryStripArray
                                      |
                                      |--javax.media.j3d.IndexedLineStripArray     // 折れ線
                                      |
                                      |--javax.media.j3d.IndexedTriangleStripArray // 連続した三角形ポリゴン
                                      | 
                                      +--javax.media.j3d.IndexedTriangleFanArray   // 連続した扇型の三角形ポリゴン

クラス宣言

public abstract class IndexedGeometryStripArray
extends IndexedGeometryArray

IndexedGeometryStripArray は次のようなコンストラクターを持ちます。

 
public IndexedGeometryStripArray(int vertexCount,        // 頂点数
                                 int vertexFormat,       // 頂点指定の形式
                                 int indexCount,         // 頂点 index の数
                                 int[] stripIndexCounts) // (stripごとのindex数)の配列

最初から3番目までの引数は IndexedGeometryArray と同じです。

4番目の引数は、「個々の strip (連続した線分、ポリゴンの集合) の頂点の個数を要素とした配列です。

IndexedGeometryStripArrayGeometryStripArray を比べると、strip の頂点を頂点 index で指定するのか、それとも頂点配列そのもので指定するのか、という点が異なります。

■■IndexedLineStripArray


クラス宣言

public class IndexedLineStripArray
extends IndexedGeometryStripArray

コンストラクター

public IndexedLineStripArray(int vertexCount,        // 頂点数
                             int vertexFormat,       // 頂点指定の形式
                             int indexCount,         // 頂点 index 配列の要素数
                             int[] stripIndexCounts) // (stripごとのindex数)の配列
							
public IndexedLineStripArray(int vertexCount,        // 頂点数
                             int vertexFormat,       // 頂点指定の形式
                             int texCoordSetCount,   // 指定する頂点の数
                             int[] texCoordSetMap,   // 指定する頂点 index の配列
                             int indexCount,         // 頂点 index 配列の要素数
                             int[] stripIndexCounts) // (stripごとのindex数)の配列
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[8];
34     
35     vertices[0] = new Point3d(-0.5, 0.5, 0.5);
36     vertices[1] = new Point3d(-0.5, -0.5, 0.5);
37     vertices[2] = new Point3d(0.5, -0.5, 0.5);
38     vertices[3] = new Point3d(0.5, 0.5, 0.5);
39     vertices[4] = new Point3d(-0.5, 0.5, -0.5);
40     vertices[5] = new Point3d(-0.5, -0.5, -0.5);
41     vertices[6] = new Point3d(0.5, -0.5, -0.5);
42     vertices[7] = new Point3d(0.5, 0.5, -0.5);
43     
44     int[] indices = { 0, 1, 2, 3, 0,┐
45                       0, 4, 5, 1,   │
46                       5, 6, 7, 4,   ├(1)
47                       2, 6,         │
48                       3, 7 };       ┘
49     
50     int[] lineStripCounts = { 5, 4, 4, 2, 2 };...(2)
51     
52     IndexedLineStripArray geometry = new IndexedLineStripArray(
53       vertices.length, GeometryArray.COORDINATES, indices.length, lineStripCounts);...(3)
54     geometry.setCoordinates(0, vertices);........(4)
55     geometry.setCoordinateIndices(0, indices);...(5)
56     
57     Shape3D shape = new Shape3D(geometry);
58     
59     Transform3D t3d = new Transform3D();                 ─┐
60     t3d.setRotation(					      ├(6)
61       new AxisAngle4d(0.57, 0.57, -0.57, Math.PI / 4.0));  │
62     TransformGroup trans = new TransformGroup(t3d);	    ─┘
63     
64     trans.addChild(shape);
65     
66     root.addChild(trans);
67 
68     return root;
69   }

(1)で頂点 index の配列を確保、初期化しています。頂点配列を「一筆書き」のように頂点指定して、5本の折れ線の頂点を指定しています。

(2)で「それぞれの折れ線の頂点の個数」を要素とした配列を確保、初期化しています。

(3)で IndexedLineStripArray を生成しています。3番目の引数は頂点 index の総数、4番目の引数は「それぞれの折れ線の個数」を要素とした配列です。

(4)で setCoordinates()、(5)で setCoordinateIndices() メソッドを使って頂点配列、頂点 index を設定しています。

(6)で回転を与えています。

このプログラムの実行結果は次のようになります。

Shape3DTest12.gif

IndexedLineArray の例と同じものを描画していますが、複数の折れ線を使っているところが異ります。

■■IndexedTriangleStripArray

javax.media.j3d.IndexedTriangleStripArray は「辺を共有する連続した三角形ポリゴンの集合」を複数描画します。各ポリゴン集合の頂点は頂点 index で指定します。


クラス宣言

public class IndexedTriangleStripArray
extends IndexedGeometryStripArray

コンストラクター

public IndexedTriangleStripArray(int vertexCount,        // 頂点数                    
                                 int vertexFormat,       // 頂点指定の形式            
                                 int indexCount,         // 頂点 index 配列の要素数   
                                 int[] stripIndexCounts) // (stripごとのindex数)の配列
							                              
public IndexedTriangleStripArray(int vertexCount,        // 頂点数                    
                                 int vertexFormat,       // 頂点指定の形式            
                                 int texCoordSetCount,   // 指定する頂点の数          
                                 int[] texCoordSetMap,   // 指定する頂点 index の配列 
                                 int indexCount,         // 頂点 index 配列の要素数   
                                 int[] stripIndexCounts) // (stripごとのindex数)の配列
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[8];
34     
35     vertices[0] = new Point3d(-0.5, 0.5, 0.5);
36     vertices[1] = new Point3d(-0.5, -0.5, 0.5);
37     vertices[2] = new Point3d(0.5, -0.5, 0.5);
38     vertices[3] = new Point3d(0.5, 0.5, 0.5);
39     vertices[4] = new Point3d(-0.5, 0.5, -0.5);
40     vertices[5] = new Point3d(-0.5, -0.5, -0.5);
41     vertices[6] = new Point3d(0.5, -0.5, -0.5);
42     vertices[7] = new Point3d(0.5, 0.5, -0.5);
43     
44     int[] indices = { 0, 1, 2, 3, 0,  ┐
45                       4, 5, 1, 0, 4,  │
46                       4, 0, 3, 7, 4,  ├(1)
47                       3, 2, 6, 7, 3,  │
48                       7, 6, 5, 4, 7,  │
49                       1, 5, 6, 2, 1 };┘
50     
51     int[] triangleStripCounts = { 5, 5, 5, 5, 5, 5 };...(2)
52     
53     Color3f[] colors = { new Color3f(1.0f, 0.0f, 0.0f),   // red     ┐
54                          new Color3f(0.0f, 1.0f, 0.0f),   // green   │
55                          new Color3f(0.0f, 0.0f, 1.0f),   // blue    ├(3)
56                          new Color3f(0.0f, 1.0f, 1.0f),   // cyan    │
57                          new Color3f(1.0f, 0.0f, 1.0f),   // magenta │
58                          new Color3f(1.0f, 1.0f, 0.0f) }; // yellow  ┘  
59 
60     int[] colorIndices = { 0, 1, 2, 3, 4, 5,  // r, g, b, c, m, y, ┐
61                            0, 1, 2, 3, 4, 5,                       │
62                            0, 1, 2, 3, 4, 5,                       ├(4)
63                            0, 1, 2, 3, 4, 5,                       │
64                            0, 1, 2, 3, 4, 5 };                     ┘
65
66     IndexedTriangleStripArray geometry = new IndexedTriangleStripArray(
67        vertices.length,
68        GeometryArray.COORDINATES | GeometryArray.COLOR_3,
69        indices.length, triangleStripCounts);......................(5)
70     geometry.setCoordinates(0, vertices);       ┐
71     geometry.setCoordinateIndices(0, indices);  ├(6)
72     geometry.setColors(0, colors);              │
73     geometry.setColorIndices(0, colorIndices);  ┘
74     
75     Shape3D shape = new Shape3D(geometry);
76     
77     Transform3D t3d = new Transform3D();                 ─┐
78     t3d.setRotation(					      ├(7)
79       new AxisAngle4d(0.57, 0.57, -0.57, Math.PI / 4.0));  │
80     TransformGroup trans = new TransformGroup(t3d);	    ─┘
81     
82     trans.addChild(shape);
83     
84     root.addChild(trans);
85 
86     return root;
87   }

(1)で頂点 index の配列を確保、初期化しています。この例では、6個の三角形ポリゴン集合の頂点 index を指定しています。

(2)で「ひとつの三角形ポリゴン集合の頂点数」を要素とする配列を確保、初期化しています。

(3)で色の配列を確保、初期化しています。

(4)で色の配列の index を確保、初期化しています。ここでは、各頂点に別々の色を適用しています。

(5)で IndexedTriangleStripArray を生成しています。引数の意味は IndexedLineStripArray と変わりありません。

(6)で setCoordinates(), setCoordinateIndices(), setColors(), setColorIndices() メソッドを使って頂点配列、頂点 index、色の配列、色の配列の index を設定しています。

(7)で回転を与えています。

このプログラムの実行結果は次のようになります。

Shape3DTest13.gif

使用方法は比較的面倒ですが、大量のデータを使って形状を定義するときに便利です。

■■IndexedTriangleFanArray

javax.media.j3d.IndexedTriangleFanArray は、「辺を共有する扇型の連続した三角形ポリゴン集合」を複数描画します。ポリゴン集合の頂点は頂点 index で指定します。


クラス宣言

public class IndexedTriangleFanArray
extends IndexedGeometryStripArray

コンストラクター

public IndexedTriangleFanArray(int vertexCount,        // 頂点数                    
                               int vertexFormat,       // 頂点指定の形式            
                               int indexCount,         // 頂点 index 配列の要素数   
                               int[] stripIndexCounts) // (stripごとのindex数)の配列
							                            
public IndexedTriangleFanArray(int vertexCount,        // 頂点数                    
                               int vertexFormat,       // 頂点指定の形式            
                               int texCoordSetCount,   // 指定する頂点の数          
                               int[] texCoordSetMap,   // 指定する頂点 index の配列 
                               int indexCount,         // 頂点 index 配列の要素数   
                               int[] stripIndexCounts) // (stripごとのindex数)の配列
Shape3DTest.java (一部)
30   private BranchGroup createSceneGraph() {
31     BranchGroup root = new BranchGroup();
32 
33     Point3d[] vertices = new Point3d[8];
34     
35     vertices[0] = new Point3d(-0.5, 0.5, 0.5);
36     vertices[1] = new Point3d(-0.5, -0.5, 0.5);
37     vertices[2] = new Point3d(0.5, -0.5, 0.5);
38     vertices[3] = new Point3d(0.5, 0.5, 0.5);
39     vertices[4] = new Point3d(-0.5, 0.5, -0.5);
40     vertices[5] = new Point3d(-0.5, -0.5, -0.5);
41     vertices[6] = new Point3d(0.5, -0.5, -0.5);
42     vertices[7] = new Point3d(0.5, 0.5, -0.5);
43     
44     int[] indices = { 0, 4, 5, 1, 2, 3, 7, 4,  ┬(1)
45                       6, 2, 1, 5, 4, 7, 3, 2 };┘
46     
47     int[] triangleStripCounts = { 8, 8 };........(2)
48     
49     Color3f[] colors = { new Color3f(1.0f, 0.0f, 0.0f),   // red     ┐
50                          new Color3f(0.0f, 1.0f, 0.0f),   // green   │
51                          new Color3f(0.0f, 0.0f, 1.0f),   // blue    ├(3)
52                          new Color3f(0.0f, 1.0f, 1.0f),   // cyan    │
53                          new Color3f(1.0f, 0.0f, 1.0f),   // magenta │
54                          new Color3f(1.0f, 1.0f, 0.0f) }; // yellow  ┘
55 
56     int[] colorIndices = { 0, 1, 2, 3, 4, 5, 0, 1,   // r, g, b, c, m, y, r, g,
57                            2, 3, 4, 5, 0, 1, 2, 3 }; // b, c, m, y, r, g, b, c ...(4)
58 
59     IndexedTriangleFanArray geometry = new IndexedTriangleFanArray(
60        vertices.length,
61        GeometryArray.COORDINATES | GeometryArray.COLOR_3,
62        indices.length, triangleStripCounts); ...............(5)
63     geometry.setCoordinates(0, vertices);      ┐
64     geometry.setCoordinateIndices(0, indices); ├(6)
65     geometry.setColors(0, colors);             │
66     geometry.setColorIndices(0, colorIndices); ┘
67     
68     Shape3D shape = new Shape3D(geometry);
69     
70     Transform3D t3d = new Transform3D();                  ─┐
71     t3d.setRotation(					       ├(7)
72       new AxisAngle4d(0.57, 0.57, -0.57, Math.PI / 4.0));   │
73     TransformGroup trans = new TransformGroup(t3d);	     ─┘
74     
75     trans.addChild(shape);
76     
77     root.addChild(trans);
78 
79     return root;
80   }

(1)頂点 index の配列を確保、初期化しています。いままでのサンプルの中で最も少ない頂点数で立方体を定義している点に注目してください。

(2)で2つの「連続した扇型の三角形ポリゴン集合」の頂点数を要素とした配列を確保、初期化しています。

(3)で色の配列を確保、初期化し、(4)で色の配列の index を確保、初期化しています。ここでは各頂点に別々の色を適用しています。

(5)で IndexedTriangleFanArray を生成しています。引数は今まで説明した IndexedGeometryStripArray のサブクラスと変わりありません。

(6)でsetCoordinates(), setCoordinateIndices(), setColors(), setColorIndices() メソッドを使って頂点配列、頂点 index、色の配列、色の配列の index を設定しています。

(7)で回転を与えています。

このプログラムの実行結果は次のようになります。

Shape3DTest14.gif

扇型の三角形ポリゴン集合は、最初の頂点を中心にするので、赤色の頂点を中心に色がスムースに広がっているのが分かると思います。

GeometryArrayのまとめ

  1. GeometryArray で点、線分、三角形/四角形ポリゴンを描画できる
  2. GeometryStripArray で折れ線、連続した三角形ポリゴン、連続した扇型の三角形ポリゴンを描画できる
  3. IndexedGeometryArray で、頂点 index を指定して点、線分、三角形/四角形ポリゴンを描画できる
  4. IndexedGeometryStripArray で、頂点 index を指定して折れ線、連続した三角形ポリゴン、連続した扇型の三角形ポリゴンを描画できる
  5. 頂点には色を指定できる。色は頂点と頂点の間でスムースに補間される

今までに説明して来た GeometryArray のサブクラスは次のような継承関係になります。

java.lang.Object
  |
  +--javax.media.j3d.SceneGraphObject
        |
        +--javax.media.j3d.NodeComponent
              |
              +--javax.media.j3d.Geometry
                    |
                    +--javax.media.j3d.GeometryArray
                          |
                          |--javax.media.j3d.PointArray
                          |
                          |--javax.media.j3d.LineArray
                          |
                          |--javax.media.j3d.TriangleArray
                          |
                          |--javax.media.j3d.QuadArray
                          |
                          |--javax.media.j3d.GeometryStripArray
                          |     |
                          |     |--javax.media.j3d.LineStripArray
                          |     |
                          |     |--javax.media.j3d.TriangleStripArray
                          |     |
                          |     +--javax.media.j3d.TtiangleFanArray
                          |
                          +--javax.media.j3d.IndexedGeometryArray
                                |
                                |--javax.media.j3d.IndexedPointArray
                                |
                                |--javax.media.j3d.IndexedLineArray
                                |
                                |--javax.media.j3d.IndexedTriangleArray
                                |
                                |--javax.media.j3d.IndexedQuadArray
                                |
                                +--javax.media.j3d.IndexedGeometryStripArray
                                      |
                                      |--javax.media.j3d.IndexedLineStripArray
                                      |
                                      |--javax.media.j3d.IndexedTriangleStripArray
                                      |
                                      +--javax.media.j3d.IndexedTriangleFanArray