トップページ > Java3D入門 > Java3Dの座標変換(5)
通常、座標変換は1種類だけ適用されることは少なく、複数の座標変換を同時に行いたい場面が出てきます。 移動+回転や、回転+回転など、同時に複数の座標変換を行う場合はそれぞれの座標変換を合成した 「合成変換」を使います。
合成変換のためにはTransform3Dクラスに用意されたメソッドを使います。 合成変換のためのメソッドには数種類ありますが、今回は最も簡単な合成変換用のメソッドを紹介します。
mul(Transform3D t1)“mul”というのは“multiply”(マルチプライ:かけ算する)の略です。2つの座標変換を合成する作業は、 座標変換に用いる行列をかけ算することと同じです。 つまり、mul()メソッドとは2つの行列の積を取るメソッドだと考えることができます。 (座標変換と行列の話は、後で詳しく扱います) たとえば、“transform1”と“transform2”という2つのTransform3Dクラスのオブジェクトがあったとします。
“transform1.mul(transform2)”と書いた場合、transform1とtransform2を合成した 座標変換行列が“transform1”に格納されます。
“transform1 = transform1 * transform2”という感じです。(実際はこう書けません)
そして、2つの座標変換を合成した場合、図形オブジェクトに作用する順序を考える必要があります。 上のように“transform1.mul(transform2)”とした上で、“setTransform(transform1)”を実行すると、 上図のように図形オブジェクトに作用します。先に図形オブジェクトに作用するのは数式で書いた場合に 後ろ側であり、より図形オブジェクトに近い“transform2”となります。 「結局2つの座標変換を作用させるんだから、順序なんて関係無いでしょ」と思ってしまいがちです。 そこは、実際にテストプログラムで試してみてください。 テストプログラムの最後でtransform1とtransform2の合成変換を行っています。 そこの順序を入れ替えると、表示される図形が変化します。
//******************************************************************************
//Java3D Mul_test
//合成変換のテスト(回転を2つ合成)
//******************************************************************************
//==============================================================================
//インポート・ファイル
import javax.media.j3d.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.Box;
import javax.vecmath.*;
import java.awt.*;
import javax.swing.*;
//==============================================================================
//メイン・クラス
public class Mul_test
{
//=============================================================================
//メイン・メソッド
public static void main(String[] args)
{
Mul_test test = new Mul_test();
}
//=============================================================================
//コンストラクタ
public Mul_test()
{
//============================================================================
//まずは、基礎フレームの設定。
//============================================================================
JFrame frame = new JFrame();
frame.setSize(250,250);
frame.setTitle("Mul_test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel cp = new JPanel();
cp.setLayout(null);
frame.add(cp);
//============================================================================
//次にJava3D関係の設定。
//============================================================================
GraphicsConfiguration g_config = SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(g_config);
canvas.setBounds(0,0,250,250);
cp.add(canvas);
//============================================================================
//空のSimpleUniverseを生成。
//============================================================================
SimpleUniverse universe = new SimpleUniverse(canvas);
frame.setVisible(true);
//============================================================================
//視点の設定
//============================================================================
ViewingPlatform camera = universe.getViewingPlatform();
camera.setNominalViewingTransform();
//============================================================================
//ライトの設定
//============================================================================
Color3f light_color = new Color3f(1.3f,1.3f,1.3f);
Vector3f light_direction = new Vector3f(0.2f,-0.3f,-1.0f);
DirectionalLight light = new DirectionalLight(light_color,light_direction);
BoundingSphere bounds = new BoundingSphere();
light.setInfluencingBounds(bounds);
BranchGroup group2 = new BranchGroup();
group2.addChild(light);
universe.addBranchGraph(group2);
//============================================================================
//Boxを作る
//============================================================================
Appearance appearance = new Appearance();
Material material = new Material();
material.setDiffuseColor(0.9f,0.75f,0.75f);
appearance.setMaterial(material);
Box box = new Box(0.3f,0.3f,0.3f,appearance);
//============================================================================
//BoxをTransfomrGroupに追加。さらにTransformGroupをBranchGroupへ登録。
//============================================================================
BranchGroup group1 = new BranchGroup();
TransformGroup transform_group = new TransformGroup();
transform_group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
transform_group.addChild(box);
group1.addChild(transform_group);
universe.addBranchGraph(group1);
//============================================================================
//回転の座標変換を2つ、合成します。
//============================================================================
//Transform3Dを生成
Transform3D transform1 = new Transform3D();
Transform3D transform2 = new Transform3D();
//Transform3Dに座標変換の内容を登録。
//X軸周りに30度回転。
//Y軸周りに45度回転。
transform1.rotX(Math.PI/6);
transform2.rotY(Math.PI/4);
//2つの座標変換を合成します。
//transform1 = transform1 * transform2
//先に作用するのはtransform2の方です。
transform1.mul(transform2);
//TransformGroupにTransform3Dを登録。
transform_group.setTransform(transform1);
}
}
//ソースコードここまで。
//******************************************************************************
今回も、ソースコード中に書いたコメントの通りです。 特殊なことはやっていません。 今回の座標変換は、先にY軸周りに45度回転して、あとからX軸中心に30度回転させています。