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
オブジェクトへ頂点座標を設定するが必要になります。
GeometryArray
javax.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.java1 // 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
パッケージに追加されることになるだろう、と言われています。
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 }
このプログラムの実行結果は次のようになります。
(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
である、という点だけです。
実行結果は次のようになります。
すべてのポリゴンがデフォルトの色である白色なので
ポリゴンの境界がわかりにくいですが、
LineStripArray
で描画された折れ線の間に
三角形ポリゴンが描画されています。
各ポリゴンの頂点指定の順序はすべて同じになります。(このサンプルではすべて反時計回り。つまり、すべてのポリゴンは“表面”となる)
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
を生成しています。
このプログラムの実行結果は次のようになります。
頂点配列は次のようになっています。
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()
する例によって言葉で説明してもわかりにくいので、具体例を見ていただこうと思います。
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
のサンプルと同じです。
このプログラムの実行結果は次のようになります。
見ていただいて分かるように、PointArray
のサンプルと全く同様です。
INdexedPointArray
のメリットとは何でしょうか?
PointArray
と比べて特にメリットはありませんが、強いて言えば次の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)で全体の形状がよくわかるようにするため回転を与えています。
このプログラムの実行結果は次のようになります。
「頂点を共有する複数の独立した線分」を描画するには
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)で回転を与えています。
このプログラムの実行結果は次のようになります。
任意の形状のポリゴンを形成するとき、
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)で回転を与えています。
このプログラムの実行結果は次のようになります。
四角形ポリゴンを複数描画するときは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 (連続した線分、ポリゴンの集合) の頂点の個数を要素とした配列です。
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
の例と同じものを描画していますが、複数の折れ線を使っているところが異ります。
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)で回転を与えています。
このプログラムの実行結果は次のようになります。
使用方法は比較的面倒ですが、大量のデータを使って形状を定義するときに便利です。
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)で回転を与えています。
このプログラムの実行結果は次のようになります。
扇型の三角形ポリゴン集合は、最初の頂点を中心にするので、赤色の頂点を中心に色がスムースに広がっているのが分かると思います。
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