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
Shape3Dはjavax.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 の使用方法は次のようになります。
Shape3D オブジェクトの生成setGeometry() メソッドで、Shape3D に GeometryArray オブジェクトをセットするaddChild() メソッドで、親となる Group ノードに Shape3D を追加する2.ついては、Shape3Dのコンストラクターで行う方法もあります。
Shape3Dのコンストラクターは次の通りです。
public Shape3D()
public Shape3D(Geometry geometry) // 物体の幾何学的形状
public Shape3D(Geometry geometry, // 物体の幾何学的形状
Appearance appearance) // 物体の外観上の属性 (色、透明度など)
また、2に先立って、
GeometryArray オブジェクトを生成するGeometryArray オブジェクトへ頂点座標を設定するが必要になります。
GeometryArrayjavax.media.j3d.GeometryArray は、物体の幾何学的形状を定義します。
javax.media.j3d.GeometryArray は abstract クラスであり、実際にはそのサブクラスが使用されます。
クラス継承
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 の使用方法は次のようになります。
GeometryArray オブジェクトを生成する。GeometryArray.COORDINATES を設定するsetCoordinates() メソッドで頂点配列をセットする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の最後の d は double 型であることを表します。
javax.vecmath.Point3f は float 型で座標を定義します。
クラス継承
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ピクセルです。

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オブジェクトの生成を行っています。
このプログラムの実行結果は次のようになります。

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と変わりありません。
このプログラムの実行結果は次のようになります。

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と変わりありません。
このプログラムの実行結果は次のようになります。

結論から言うとありません。
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パッケージに追加されることになるだろう、と言われています。
GeometryStripArrayPointArray, 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 (連続した頂点配列) の個数」を要素とする配列です。これについては具体例が無いとわかりにくいと思うので、後に詳しく説明します。
LineStripArrayjavax.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 }
このプログラムの実行結果は次のようになります。

(1)で頂点配列を要素数=15で初期化し、(2)で各頂点に座標をセットしています。
(3)で個々の折れ線の頂点数を格納するint型の配列変数stripVertextCountsを初期化しています。
この配列の要素数は2です。つまり、折れ線の数は2つということになります。
この配列の各要素はそれぞれ8、7です。つまり、最初の折れ線の頂点数は8、2番目の折れ線の頂点数は7ということになります。
(4)の8つの頂点座標が最初の折れ線、(5)の7つの頂点座標が2番目の折れ線の頂点座標として使用されます。
(6)のLineStripArray生成のときに、コンストラクターの3番目の引数としてstripVertexCountsを渡しています。
setCoordinates()による頂点配列のセットや、Shape3Dオブジェクトの生成は今までと同様です。
TriangleStripArrayjavax.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である、という点だけです。
実行結果は次のようになります。

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

各ポリゴンの頂点指定の順序はすべて同じになります。(このサンプルではすべて反時計回り。つまり、すべてのポリゴンは“表面”となる)
TriangleFanArrayjavax.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を生成しています。
このプログラムの実行結果は次のようになります。

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

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では、点、線分、ポリゴンに色を指定できます。
このために必要なのは以下の手順です。
GeometryArrayのコンストラクターで COLOR_3 または COLOR_4 を指定する。(2番目の引数の int vertexFormat)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 (青)
Color3fはTuple3fのサブクラスです。Tuple3fはfloat型のprotectedフィールドx, y, zを持っています。
Tuple3fのサブクラスには、ほかにVector3f, Point3fなどがあります。
Color3fでは、x, y, z はそれぞれ赤、緑、青の3色を表します。
x, y ,z に RGB カラー値を代入/使用することを強制しているわけではありません。RGB以外のカラー値 (HSBなど) を代入/使用してもかまいません。GeometryArrayのsetColor(), 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 (不透明度)
Colo4f は Tuple4f のサブクラスです。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 です。
w は 0.0f=透明、1.0f=不透明 です。
x, y, z, w のデフォルト値は 0.0f です。
GeometryArray の setColor(), 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.COORDINATES と GeometryArray.COLOR_3 を OR 演算したものを指定しています。
(2)で赤と青の Color3f オブジェクトを生成しています。
(3)でsetColor() メソッドで各頂点の色を設定しています。最初のポリゴンの頂点にはすべて赤、2番目のポリゴンの頂点にはすべて青を設定しています。
setColor()メソッドの引数は次の通りです。
public final void setColor(int index, // 頂点のindex
Color3f color) // 頂点に設定する色
このプログラムの実行結果は次のようになります。

各ポリゴンの頂点には同じ色が設定してあるので、赤と青のポリゴンが表示されています。
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)で メソッドを使って複数の頂点に色を設定しています。
(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() メソッドを使って複数の頂点に色を設定しています。
このプログラムの実行結果は次のようになります。

各頂点に設定された色が、きれいな中間色として補間されているのがわかると思います。
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 の使用方法は次のような手順になります。
IndexedGeometryArry を生成するsetCoordinates() メソッドを使って頂点配列を設定するsetCoordinateIndices() メソッドを使って頂点 index を設定するIndexedGeometryArray を引数に Shape3D を生成するShape3D をシーン・グラフに addChild() する例によって言葉で説明してもわかりにくいので、具体例を見ていただこうと思います。
IndexedPointArrayjavax.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 のサンプルと同じです。
このプログラムの実行結果は次のようになります。

見ていただいて分かるように、PointArray のサンプルと全く同様です。
INdexedPointArray のメリットとは何でしょうか?
PointArrayと比べて特にメリットはありませんが、強いて言えば次の2点です。
IndexedLineArrayjavax.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)で全体の形状がよくわかるようにするため回転を与えています。
このプログラムの実行結果は次のようになります。

「頂点を共有する複数の独立した線分」を描画するには
IndexedLineArray が便利です。
IndexedTriangleArrayjavax.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)で回転を与えています。
このプログラムの実行結果は次のようになります。

任意の形状のポリゴンを形成するとき、
IndexedTriangelArrayはたいへん便利に使えます。
IndexedQuadArrayIndexedQuadArray は、複数の独立した四角形ポリゴンを描画します。ポリゴンと頂点は、頂点配列の 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)で回転を与えています。
このプログラムの実行結果は次のようになります。

四角形ポリゴンを複数描画するときはIndexedQuadArray
を使うと便利です。
IndexedGeometryStripArrayIndexedGeometryArray のサブクラスは独立した点、線分、ポリゴンを描画しましたが、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 (連続した線分、ポリゴンの集合) の頂点の個数を要素とした配列です。
IndexedGeometryStripArray と GeometryStripArray を比べると、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)で回転を与えています。
このプログラムの実行結果は次のようになります。

IndexedLineArray の例と同じものを描画していますが、複数の折れ線を使っているところが異ります。
IndexedTriangleStripArrayjavax.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)で回転を与えています。
このプログラムの実行結果は次のようになります。

使用方法は比較的面倒ですが、大量のデータを使って形状を定義するときに便利です。
IndexedTriangleFanArrayjavax.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)で回転を与えています。
このプログラムの実行結果は次のようになります。

扇型の三角形ポリゴン集合は、最初の頂点を中心にするので、赤色の頂点を中心に色がスムースに広がっているのが分かると思います。
GeometryArrayのまとめGeometryArray で点、線分、三角形/四角形ポリゴンを描画できるGeometryStripArray で折れ線、連続した三角形ポリゴン、連続した扇型の三角形ポリゴンを描画できるIndexedGeometryArray で、頂点 index を指定して点、線分、三角形/四角形ポリゴンを描画できるIndexedGeometryStripArray で、頂点 index を指定して折れ線、連続した三角形ポリゴン、連続した扇型の三角形ポリゴンを描画できる今までに説明して来た 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