CDR6275

Michio SHIRAISHI Official Site

Java3Dチュートリアル

東邦大学理学部情報科学科 白石路雄
最終更新: 2012-09-28

1. はじめに

 Java3DはJavaを利用して3次元コンピュータグラフィックスのアプリケーションを作るためのAPIです。描く物体をシーングラフと呼ばれるデータ構造にまとめて、レンダリングするのが特徴です。OpenGLをJavaから利用するためのAPIであるJOGLもありますが、Java3Dを用いるとある程度まで高度なプログラムが簡単にかけます(が、凝ったことをしようとするとOpenGLで書くしかないようにも思います)。

1.1 この文書のねらい

 Javaを学び始め、3次元コンピュータグラフィックスに関する知識はない方を対象としています。この文書ではコンピュータグラフィックスについて詳しく解説することが目的ではなく、Javaの知識を持っている方にAPIの使い方を学んでいただくことを目的としている点をご了承ください。

2. セットアップ

 JDKは1.5.0以上が必要です。こちらからダウンロードしてインストールしてください。

 Java3Dの最新版はこちらからダウンロードできます(本稿執筆時には1.5.2が最新版)が、お使いのオペレーティングシステムによってダウンロードするファイルが異なります。なお、Zip binary版とInstaller版がありますが、ここではZip binary版を利用します。

2.1 Windows 7

 ダウンロードページからj3d-1_5_2-windows-i586.zipをダウンロードし、展開してください。展開すると、j3d-jre.zipという名前のファイルがありますので、そのファイルをさらに展開します。

 binフォルダにはdllが4つ含まれています。javaプログラムを実行するのと同じディレクトリにおいて置くとよいでしょう。Eclipseを利用する場合、プロジェクトの直下に配置します。

 libフォルダにはjarファイルが3つ含まれています。これらのjarファイルを見るようにクラスパスを設定する必要があります。Eclipseを利用されている場合、プロジェクト内に適当なフォルダを作りその中にjarファイルを入れ、プロジェクトのプロパティを開き「Java Build Path→Libraries→Add JARs」を選択して追加します。

 お使いのPCのアーキテクチャによってはj3d-1_5_2-windows-amd64.zipをダウンロードする必要があるかもしれません。こちらはbin内のdllファイルが1つしかないなどの違いがありますが、上記の通り設定すれば問題ありません。

2.2 OS X 10.8

 上述のダウンロードページからj3d-1_5_2-macosx.zipをダウンロードし、展開してください。展開すると、j3d-jre.zipという名前のファイルがありますので、そのファイルをさらに展開します。

 libフォルダにはjarファイルが3つ含まれています。これらのjarファイルを見るようにクラスパスを設定する必要があります。Eclipseを利用されている場合、プロジェクト内に適当なフォルダを作りその中にjarファイルを入れ、プロジェクトのプロパティを開き「Java Build Path→Libraries→Add JARs」を選択して追加します。

2.3 東邦大学理学部情報科学科の環境におけるセットアップ

 2.1節で説明した方法でファイルを展開してください。次に、binフォルダのdllファイルとlibフォルダのjarファイルをすべて1つのフォルダにまとめていれておきます。プログラムはそのフォルダで書くようにします。また、Java3Dのプログラムをコンパイルする際には、次の設定をjcpadで行います。

  1. メニューバーから「実行→設定」を選択する
  2. 「高度な設定」タブの「以下の設定を変更する」にチェックする
  3. 「追加する環境変数」に「CLASSPATH=.;j3dcore.jar;j3dutils.jar;vecmath.jar」を追加する

3. はじめてのJava3D

 まず最初に次の画像のような赤い円錐を表示するプログラムを作ってみましょう。

Image of PrimitiveTest.java

 以下にこのプログラムを示します。実行すると、マウスをドラッグして回転させたり、右ボタンを押しながらドラッグして平行移動させたり、altキーを押しながら上下に動かしてズームしたりできます。

import java.applet.*;
import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.applet.*;
import com.sun.j3d.utils.behaviors.mouse.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;

public class PrimitiveTest extends Applet{
	private void createPrimitives(TransformGroup tg) {
		// 以下の4行によって物体の見た目を設定する
		Appearance appearance = new Appearance();
		Material material = new Material();
		material.setDiffuseColor(1.0f, 0.0f, 0.0f);
		appearance.setMaterial(material);
		
		// 円錐を作成し、tgに接続する
		Cone cone = new Cone(0.5f, 1.0f, Primitive.GENERATE_NORMALS, 100, 10, appearance);
		tg.addChild(cone);
	}
	
	public PrimitiveTest(){
		// 描画領域であるCanvas3Dを作成し、Appletウィンドウの内部に配置する
		Canvas3D canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
		this.setLayout(new BorderLayout());
		this.add(canvas3D, BorderLayout.CENTER);
		
		// SimpleUniverseを作成し、標準的な投影変換を行うように設定する
		SimpleUniverse simpleUniverse = new SimpleUniverse(canvas3D);
		simpleUniverse.getViewingPlatform().setNominalViewingTransform();
		
		// BranchGroupを作成する。このメソッドの最後でSimpleUniverseに接続する
		// 以下のプログラムではbgの下にシーングラフのノードを接続していく。
		BranchGroup bg = new BranchGroup();
		
		// 平行光源を作成し、bgに接続する
		DirectionalLight directionalLight = new DirectionalLight();
		directionalLight.setInfluencingBounds(new BoundingSphere());
		bg.addChild(directionalLight);
		
		// シーン全体の座標変換を行うTransformGroupを作成する。
		TransformGroup tg = new TransformGroup();
		
		// マウスによる操作を行うために、MouseRotateクラス、MouseTranslateクラス、および、
		// MouseZoomクラス、のインスタンスを作成し、tgに接続する
		tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		MouseRotate mouseRotate = new MouseRotate(tg);
		mouseRotate.setSchedulingBounds(new BoundingSphere());
		tg.addChild(mouseRotate);
		MouseTranslate mouseTranslate = new MouseTranslate(tg);
		mouseTranslate.setSchedulingBounds(new BoundingSphere());
		tg.addChild(mouseTranslate);
		MouseZoom mouseZoom = new MouseZoom(tg);
		mouseZoom.setSchedulingBounds(new BoundingSphere());
		tg.addChild(mouseZoom);
				
		// createPrimtivesメソッドを呼び出しtgに接続させる
		createPrimitives(tg);
		
		// tgへの接続がすべて終わったので、bgに接続する
		bg.addChild(tg);

		// SimpleUniverseにBranchGroupを接続する
		simpleUniverse.addBranchGraph(bg);
	}
	
	public static void main(String[] args){
		new MainFrame(new PrimitiveTest(), 640, 480);
	}
}

 このプログラムをアプリケーションとして実行すると、次のような処理が行われます。まず最初にmainメソッドが呼び出されます。このメソッドの中では、PrimitiveTestクラスのインスタンスを作成しているので、コンストラクタが呼び出されます。コンストラクタでは、次のような処理を行っています。

  • 描画領域の設定
  • 投影変換の設定
  • 光源の設定
  • マウス操作の設定
  • シーングラフ(後述)のベースの作成

これらの処理については、しばらくの間は「これらの処理は必要なものなのだ」と思っておいてください。

 コンストラクタの途中でcreatePrimitivesメソッドを呼び出しています。このメソッドでは、「tgというシーングラフのノードを受け取り、メソッドの内部で円錐を作成して、そのノードに円錐を接続する」ことを行っています。仮に表示したい物体を変更したいとききには、createPrimitivesメソッドを書き換えればよいことになります。

4. プリミティブ

4.1 円錐の作り方 (APIドキュメントの見方)

 PrimitiveTestでは円錐を表示しています。この円錐は次の1行で作成されています。

Cone cone = new Cone(0.5f, 1.0f, Cone.GENERATE_NORMALS, 100, 10, appearance);

 これに対応するAPIドキュメントを調べてみましょう。APIドキュメントは、こちらにあります。このページの左下の「All classes」と書かれているフレームからConeのリンクをたどってみましょう。右側に表示される説明の中に次のような項目を探してください。

Cone(float radius, float height, int primflags, int xdivision, int ydivision, Appearance ap) 

 これが先ほどのプログラムで呼び出しているコンストラクタの定義になります。ここでそれぞれの引数の説明が書かれているので、それを一つ一つ見てみましょう。

radius
円錐の半径を与える
height
円錐の高さを与える
primflags
プリミティブの種別を示すフラグで、Primitive.GENERATE_NORMALSを与えておけばよい
xdivision
Java3Dでは円錐をそのまま描くのではなく、表面を細かい多角形に分割して表示する。その際の底面の円周に沿った方向の分割数を与える
ydivison
円錐の縦方向の分割数を与える
ap
Apperanceクラスのインスタンスを与える

4.2 Java3Dで利用できるプリミティブ

 Java3Dでは次の4つのプリミティブを利用できます。

  • 円錐 (Cone)
  • 円柱 (Cylinder)
  • 球 (Sphere)
  • 直方体 (Box)

 円柱については

Cylinder(float radius, float height, int primflags, int xdivision, int ydivision, Appearance ap) 

というコンストラクタがあるので、これを円錐と同様に利用することができます。

 球については

Sphere(float radius, int primflags, int divisions, Appearance ap) 

というコンストラクタがありますので、これを利用するとよいでしょう。

 直方体については

Box(float xdim, float ydim, float zdim, int primflags, Appearance ap) 

というコンストラクタがあります。ここで、xdimはx軸方向の長さを表しますが、作成される直方体のx軸に平行な辺の長さ は-xdimからxdimまでとなりますので注意してください(すなわち、ある大きさの直方体を作成したいときには、その半分の長さを引数として与える)。

5. アピアランスとマテリアル

5.1 マテリアル

 プログラムの以下の部分を見てみましょう。

Appearance appearance = new Appearance();
Material material = new Material();
material.setDiffuseColor(1.0f, 0.0f, 0.0f);
appearance.setMaterial(material);

 この一連のプログラムではAppearanceMaterialという2つのクラスが登場しています。ここではまずMaterialクラスの説明をします。

 Materialクラスは材質を表します。物体は光源からの光を反射することで色を持ちますが、その色を設定します。

 色を設定する際には、赤(Red)、緑(Green)、および、青(Blue)の反射成分を0から1までの実数値で与えています。色を選択するには、カラーピッカーと呼ばれるウィジェットを使うのが便利です。カラーピッカーの一例がこちらにあります。ここで色を選択し、RGBのそれぞれの値を記録します。カラーピッカーの多くは各成分を0から255の整数値で表示しますので、たとえば、R:100、G:45、B:80という色をプログラムに書くには、(100/255f, 45/255f, 80/255f)とすればよいです。

 コンピュータグラフィックスでは、物体から放たれる光を次の4種類の光の和によって表現します。

拡散反射光 (Diffuse)
物体に光源から到達した光を全方向に均一に反射する成分。MaterialクラスのsetDiffuseColorメソッドで設定できる。
鏡面反射光 (Specular)
物体に光源から到達した光が、物体が鏡であったときに跳ね返る方向に強く反射する成分。MaterialクラスのsetSpecularColorメソッドで設定できる。
環境光 (Ambient)
上記の2つだけでは、光源から光が到達しない部分は真っ暗になってしまう。それを避けるために、環境中から均一に環境光と呼ばれる光で照らされていると考え、その光を反射していると考える。MaterialクラスのsetAmbientColorメソッドで設定できる。ただし、これを利用するためには、AmbientLightを設定する必要があるため、上記のプログラムに追加しても変化しません。
放射光
光源から到達する光を反射する以外にも、物体そのものが光を放っている場合もあり、それを表現するのに放射光を考える。MaterialクラスのsetEmissiveColorメソッドで設定できる。

 これらの値の組み合わせによりさまざまな材質を表現できます。ただし、第1節でも述べたように本稿ではコンピュータグラフィックスについて説明することが目的のため、詳しくは説明しません。興味のある方は、Wikipediaのページを参照してください。

5.2 アピアランス

 Materialクラスは見た目を表すAppearanceクラスと組み合わせて使用します。Appearanceクラスで設定できる項目を次に2つ挙げます。

5.2.1 透明度

 Java3Dでは次のようにすることで、物体の透明度を設定できます。ここで、0.6fは物体の透明度を示し、0.0fから1.0fまでの値で設定します。

appearance.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.NICEST, 0.6f));

5.2.2 テクスチャマッピング

 テクスチャマッピングとは物体の表面にテクスチャと呼ばれる画像を貼り付ける手法です。テクスチャマッピングを行うためには、まずテクスチャ画像を用意します(以下のサンプルコードではtoho.jpgというファイルを使用しました)。そして、Appearanceにテクスチャを設定します。また、プリミティブの作成時の種別を「Primitive.GENERATE_NORMALS」から「Primitive.GENERATE_TEXTURE_COORDS」に変更します。

import com.sun.j3d.utils.image.TextureLoader;
TextureLoader textureLoader = new TextureLoader("toho.jpg", this);
appearance.setTexture(textureLoader.getTexture());
Sphere sphere = new Sphere(0.5f, Primitive.GENERATE_TEXTURE_COORDS, 100, appearance);

 以下にテクスチャ画像と実行例を示します。

Texture Image

テクスチャ画像

Image of TextureTest.java

テクスチャマッピングを行った結果

6. 複数のプリミティブを配置する

 次に複数のプリミティブを配置することを考えます。

6.1 シーングラフ

 Java3Dでは、プリミティブやその座標変換情報などをシーングラフと呼ばれる木構造のデータで表現します。PrimitiveTest.javaでは以下に示すシーングラフとなっていました。

Original Scene Graph

 ここで単純に、2つのプリミティブを持つシーングラフを作るとすると、次のようになるでしょう。

Scene Graph

 これを実現するためのプログラムは以下のようになります。

Appearance appearance1 = new Appearance();
Material material1 = new Material();
material1.setDiffuseColor(new Color3f(1.0f, 0.0f, 0.0f));
appearance1.setMaterial(material1);
Cone cone = new Cone(0.5f, 1.0f, Primitive.GENERATE_NORMALS, 100, 10, appearance1);
tg.addChild(cone);
		
Appearance appearance2 = new Appearance();
Material material2 = new Material();
material2.setDiffuseColor(new Color3f(0.0f, 1.0f, 0.0f));
appearance2.setMaterial(material2);
Cylinder cylinder = new Cylinder(0.2f, 0.6f, Primitive.GENERATE_NORMALS, 100, 10, appearance2);
tg.addChild(cylinder);

ただし、このようなシーングラフはあまりおすすめできません。その理由は、2つの物体を異なる位置に配置したいときに困るからです。たとえば、円錐を左にずらし、円筒を右にずらしたいとします。このとき、座標変換を行う命令は、TransformGroupのインスタンスであるtgに対して行います。ここで、tgに対して、座標変換を行うように指定すると、tgの子であるノードに影響するので、円錐と円筒は同じ座標変換しかできないこととなってしまいます。

 そこで、それぞれの物体に対して座標変換を行えるようにするために、さらに以下のようにシーングラフを階層化させます。

Recommended Scene Graph

 このようなシーングラフを作るためには以下のようにします。

Appearance appearance1 = new Appearance();
Material material1 = new Material();
material1.setDiffuseColor(new Color3f(1.0f, 0.0f, 0.0f));
appearance1.setMaterial(material1);
Cone cone = new Cone(0.5f, 1.0f, Primitive.GENERATE_NORMALS, 100, 10, appearance1);
TransformGroup tg1 = new TransformGroup();	
tg1.addChild(cone);
tg.addChild(tg1);
		
Appearance appearance2 = new Appearance();
Material material2 = new Material();
material2.setDiffuseColor(new Color3f(0.0f, 1.0f, 0.0f));
appearance2.setMaterial(material2);
Cylinder cylinder = new Cylinder(0.2f, 0.6f, Primitive.GENERATE_NORMALS, 100, 10, appearance2);
TransformGroup tg2 = new TransformGroup();	
tg2.addChild(cylinder);
tg.addChild(tg2);

 このようにすることで、tg1tg2に別々の座標変換を施せるようになるため、円錐と円筒を別々の位置に配置することができます。

6.2 座標変換

 座標変換は、Transform3Dクラスのインスタンスを作成し、TransformGroupsetTransformメソッドで設定します。以下に円錐を左方向、円筒を右方向に平行移動した例を示します。
Image of TranslateTest.java

Appearance appearance1 = new Appearance();
Material material1 = new Material();
material1.setDiffuseColor(new Color3f(1.0f, 0.0f, 0.0f));
appearance1.setMaterial(material1);
Cone cone = new Cone(0.5f, 1.0f, Primitive.GENERATE_NORMALS, 100, 10, appearance1);
TransformGroup tg1 = new TransformGroup();
Transform3D transform3D1 = new Transform3D();
transform3D1.setTranslation(new Vector3f(-0.3f, 0.0f, 0.0f));
tg1.setTransform(transform3D1);
tg1.addChild(cone);
tg.addChild(tg1);
		
Appearance appearance2 = new Appearance();
Material material2 = new Material();
material2.setDiffuseColor(new Color3f(0.0f, 1.0f, 0.0f));
appearance2.setMaterial(material2);
Cylinder cylinder = new Cylinder(0.2f, 0.6f, Primitive.GENERATE_NORMALS, 100, 10, appearance2);
TransformGroup tg2 = new TransformGroup();	
Transform3D transform3D2 = new Transform3D();
transform3D2.setTranslation(new Vector3f(0.3f, 0.0f, 0.0f));
tg2.setTransform(transform3D2);
tg2.addChild(cylinder);
tg.addChild(tg2);

 座標変換には、次の3つがあります。

平行移動
TransformGroupsetTranslationメソッドにより設定します。
回転変換
回転変換を行うためには、TransformGroupsetRotationメソッドにより設定します。引数として、どの軸について回転するのか、および、その角度の2つの情報を与える必要があり、そのためにAxisAngle4fクラスを利用します。このクラスのコンストラクタは4つの引数を持ち、最初の3つの引数は回転する軸を示し(最初の引数が1.0fで、2番目・3番目の引数が0.0fの場合x軸を意味する)、4番目の引数で回転角を与えます。

transform3D.setRotation(new AxisAngle4f(1.0f, 0.0f, 0.0f, (float)Math.PI/4.0f));
拡大縮小変換
拡大縮小変換を行うためには、TransformGroupsetScaleメソッドにより設定します。引数として、x軸、y軸、z軸それぞれについての拡大率を与えます。 たとえば、x軸方向に半分にする拡大縮小変換は次のように設定します。

transform3D.setScale(new Vector3d(0.5, 1.0, 1.0));

6.3 合成変換

 6.2節で述べた座標変換は、平行移動・回転変換・拡大縮小変換のうち一つしか適用できません。たとえば、回転させて、平行移動したい、ということはそのままではできません。このような変換を行うためには、合成変換を行う必要があります。

 以下の例では、z軸周りの回転変換transform_rotとx軸方向への平行移動transform_transという2つの座標変換を作成しています。次に、transform_transmulメソッドを呼び出して2つの変換を合成しています。このようにすると、「回転変換を行ってから、平行移動する」という座標変換を表現できます。

Transform3D transform_rot = new Transform3D();
transform_rot.setRotation(new AxisAngle4f(0.0f, 0.0f, 1.0f, (float)Math.PI/4.0f));
Transform3D transform_trans = new Transform3D();
transform_trans.setTranslation(new Vector3f(0.3f, 0.0f, 0.0f));
transform_trans.mul(transform_rot);
tg.setTransform(transform_trans);

 ここで注意しなければいけないのは、合成変換を行う際には変換の順序が異なると結果が異なってしまうことがあるという点です。

7. そのほか

 本節ではいくつかのトピックについてのサンプルプログラムを挙げます。

7.1 テキスト

 2次元のテキストは次のようにして作ることができます。

TransformGroup tg = new TransformGroup();
Text2D text2D = new Text2D("Sample Text", new Color3f(0.0f, 0.0f, 1.0f), "SansSerif", 
                           30, java.awt.Font.PLAIN);
tg.addChild(text2D);

 3次元テキストは次のようにして作ることができます。

TransformGroup tg3 = new TransformGroup();	
Appearance appearance3 = new Appearance();
Material material3 = new Material();
material3.setDiffuseColor(new Color3f(0.0f, 0.0f, 1.0f));
appearance3.setMaterial(material3);
Font font = new Font("SansSerif", java.awt.Font.PLAIN, 1);
Font3D font3D = new Font3D(font, new FontExtrusion());
Text3D text3D = new Text3D(font3D, "Sample Text");
Shape3D shape3D = new Shape3D();
shape3D.setGeometry(text3D);
shape3D.setAppearance(appearance3);
tg3.addChild(shape3D);
tg.addChild(tg3);

7.2 点、線、三角形

 4つの点を配置するサンプルプログラムを示します。

// 点の配列を確保し、座標を設定する。
Point3f[] vertexCoordinates = new Point3f[4];
vertexCoordinates[0] = new Point3f(-0.1f, -0.7f, 0.2f);
vertexCoordinates[1] = new Point3f(0.5f, -0.6f, 0.0f);
vertexCoordinates[2] = new Point3f(-0.4f, 0.7f, -0.5f);
vertexCoordinates[3] = new Point3f(0.4f, 0.1f, 0.5f);
		
// PointArrayクラスのインスタンスを作成する
PointArray pointArray = new PointArray(vertexCoordinates.length, GeometryArray.COORDINATES);
pointArray.setCoordinates(0, vertexCoordinates);
		
// Shape3Dクラスのインスタンスを作成し、ジオメトリを設定する。
Shape3D shape3D = new Shape3D(pointArray);
		
// shape3Dをシーングラフに接続する。
tg.addChild(shape3D);

 4つの点を定義し、1番目と2番目の点、および、3番目と4番目の点を結ぶと2本の線分を描くことができます。以下にサンプルプログラムを示します。

// 点の配列を確保し、座標を設定する。
Point3f[] vertexCoordinates = new Point3f[4];
vertexCoordinates[0] = new Point3f(-0.1f, -0.7f, 0.2f);
vertexCoordinates[1] = new Point3f(0.5f, -0.6f, 0.0f);
vertexCoordinates[2] = new Point3f(-0.4f, 0.7f, -0.5f);
vertexCoordinates[3] = new Point3f(0.4f, 0.1f, 0.5f);
		
// 頂点の色を設定する (オプション)
Color3f[] vertexColors = new Color3f[4];
vertexColors[0] = new Color3f(1.0f, 1.0f, 1.0f); // 白 
vertexColors[1] = new Color3f(0.1f, 0.1f, 0.1f); // 黒に近い灰
vertexColors[2] = new Color3f(1.0f, 0.0f, 0.0f); // 赤
vertexColors[3] = new Color3f(0.0f, 1.0f, 0.0f); // 緑

// LineArrayクラスのインスタンスを作成する
LineArray lineArray = new LineArray(vertexCoordinates.length, 
                                    GeometryArray.COORDINATES | GeometryArray.COLOR_3);
lineArray.setCoordinates(0, vertexCoordinates);
lineArray.setColors(0, vertexColors);

// Shape3Dクラスのインスタンスを作成し、ジオメトリを設定する。
Shape3D shape3D = new Shape3D(lineArray);

// shape3Dをシーングラフに接続する。
tg.addChild(shape3D);

 点を3つ定義し、それらを結ぶと三角形を描くことができます。以下にサンプルプログラムを示します。

// 点の配列を確保し、座標を設定する。
Point3f[] vertexCoordinates = new Point3f[3];
vertexCoordinates[0] = new Point3f(-0.1f, -0.7f, 0.2f);
vertexCoordinates[1] = new Point3f(0.5f, -0.6f, 0.0f);
vertexCoordinates[2] = new Point3f(-0.4f, 0.7f, -0.5f);

// 頂点の色を設定する (オプション)
Color3f[] vertexColors = new Color3f[3];
vertexColors[0] = new Color3f(0.0f, 0.0f, 1.0f); // 青
vertexColors[1] = new Color3f(1.0f, 0.0f, 0.0f); // 赤
vertexColors[2] = new Color3f(0.0f, 1.0f, 0.0f); // 緑

// LineArrayクラスのインスタンスを作成する
TriangleArray triangleArray = new TriangleArray(vertexCoordinates.length, 
                                                GeometryArray.COORDINATES | GeometryArray.COLOR_3);
triangleArray.setCoordinates(0, vertexCoordinates);
triangleArray.setColors(0, vertexColors);

// Shape3Dクラスのインスタンスを作成し、ジオメトリを設定する。
Shape3D shape3D = new Shape3D(triangleArray);

// shape3Dをシーングラフに接続する。
tg.addChild(shape3D);

7.3 背景色

 BranchGroupにBackgroundクラスのインスタンスを設定する。

BranchGroup bg = new BranchGroup();	
// 背景色の設定
Background background = new Background(new Color3f(0.3f, 0.3f, 0.3f));
background.setApplicationBounds(new BoundingSphere());
bg.addChild(background);

8. おわりに

 以上でJava3Dのチュートリアルを終わります。アニメーションなどもできますので、ぜひ調べてみてください。