トップページ > Java3D入門 > 視点移動(3)
//******************************************************************************
//マウスのドラッグで視点移動を行うCanvas3D拡張クラス“Canvas3D_ViewChange”
//
//Canvas3Dを継承
//MouseMotionLisenerを実装
//
//コンストラクタの引数はカメラの距離とマウス感度
//さらに,コンストラクタの引数にはGraphicsConfigurationが必要(Canvas3Dと同じ仕様)
//
//フィールドとして,SimpleUniverse,ViewingPlatformを持つ
//
//球座標を使用
//動径の長さ一定,マウスのX移動はφ,マウスのY移動はθに対応
//動径の長さは“camera_distance”,初期角度は“theta”と“phi”で調節
//マウス感度は“sensitivity”で調節
//******************************************************************************
//全般のためのインポート
import java.awt.*;
import java.awt.event.*;
//Java3D関係のインポート
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
public class Canvas3D_ViewChange extends Canvas3D
{
//=============================================================================
//クラスのフィールド
//マウスの動きに対する感度
float sensitivity;
//動径の長さ(座標中心と視点との距離)
float camera_distance;
//新規取得するマウスのx,y座標
int new_x, new_y;
//前に取得したマウスのx,y座標
int pre_x, pre_y;
//SimpleUniverseをフィールドとしてもっておく。
SimpleUniverse universe;
//視点の座標変換のためのグループ
TransformGroup Camera;
//視点(カメラ)の座標
float camera_x, camera_y, camera_z, camera_xz, camera_xy, camera_yz = 0;
//極座標のパラメータ
float phi = 0;//(float)Math.PI;
float theta = (float)Math.PI/3;
//座標変換クラス
Transform3D Transform_camera_pos; //カメラの位置
Transform3D Transform_camera_phi; //phiに関する回転
Transform3D Transform_camera_theta; //thetaに関する回転
//3次元ベクトル(カメラの位置用)
Vector3f Vector_camera_pos;
//=============================================================================
//コンストラクタ
public Canvas3D_ViewChange(float Distance, float Sensitivity, GraphicsConfiguration config)
{
//親クラスのコンストラクタを呼ぶ. 引数はGraphicsConfiuration.
super(config);
//カメラの原点からの距離を設定
camera_distance = Distance;
//マウス感度を調節
sensitivity = Sensitivity;
//空のSimpleUniverseを生成
universe = new SimpleUniverse(this);
//============================================================================
//視点(カメラ)について設定
//============================================================================
//------------------------------------------------------------------
//カメラ全般の初期設定
//SimpleUniverseが生成したViewingPlatformを取得
ViewingPlatform vp = universe.getViewingPlatform();
//ViewingPlatformの座標変換グループとして,“Camera”を割り当てる
Camera = vp.getViewPlatformTransform();
//------------------------------------------------------------------
//カメラの位置に関する初期設定
//theta関係の計算(球座標→直交座標)
camera_y = camera_distance * (float)Math.sin(theta);
camera_xz = camera_distance * (float)Math.cos(theta);
//phi関係の計算(球座標→直交座標)
camera_x = camera_xz * (float)Math.sin(phi);
camera_z = camera_xz * (float)Math.cos(phi);
//カメラの位置ベクトルを用意
Vector_camera_pos = new Vector3f(camera_x, camera_y, camera_z);
//カメラ位置の座標変換クラスを用意
Transform_camera_pos = new Transform3D();
//初期位置設定ための座標変換を用意する。
Transform_camera_pos.setTranslation(Vector_camera_pos);
//------------------------------------------------------------------
//カメラの向きに関する初期設定
//カメラの向きの座標変換クラスを用意
Transform_camera_phi = new Transform3D();
Transform_camera_theta = new Transform3D();
//カメラの向きの初期設定
Transform_camera_theta.rotX(-theta);
Transform_camera_phi.rotY(phi);
//------------------------------------------------------------------
//以上の設定をカメラに反映
//合成する
Transform_camera_theta.mul(Transform_camera_phi);
Transform_camera_pos.mul(Transform_camera_theta);
//座標変換実行
Camera.setTransform(Transform_camera_pos);
//============================================================================
//マウスの設定
//============================================================================
//マウス入力用のクラス,mouse_classをインスタンス化
mouse_ViewChange mouse = new mouse_ViewChange();
//このフレームにマウス入力クラスを登録
addMouseMotionListener(mouse);
}
//*****************************************************************************
//mouse_ViewChange:マウス入力用のクラス
//*****************************************************************************
class mouse_ViewChange implements MouseMotionListener
{
//============================================================================
//マウスが動いた時に呼ばれるメソッド
//============================================================================
public void mouseMoved(MouseEvent event)
{
//常にマウス座標を更新しておく
pre_x = event.getX();
pre_y = event.getY();
}
//============================================================================
//マウスがドラッグされた時に呼ばれるメソッド
//============================================================================
public void mouseDragged(MouseEvent event)
{
//現在のx座標を取得
new_x = event.getX();
new_y = event.getY();
//thetaとphiの値を更新
theta -= sensitivity*(new_y - pre_y);
phi += sensitivity*(new_x - pre_x);
//===========================================================================
//極座標を直交座標へ直す
//theta関係の計算(球座標→直交座標)
camera_y = camera_distance * (float)Math.sin(theta);
camera_xz = camera_distance * (float)Math.cos(theta);
//phi関係の計算(球座標→直交座標)
camera_x = camera_xz * (float)Math.sin(phi);
camera_z = camera_xz * (float)Math.cos(phi);
//===========================================================================
//座標変換クラスを用意する
//カメラの位置ベクトルを作る
Vector_camera_pos.x = camera_x;
Vector_camera_pos.y = camera_y;
Vector_camera_pos.z = camera_z;
//座標変換クラスを初期化(重要!)
Transform_camera_pos.setIdentity();
//平行移動の座標変換を用意
Transform_camera_pos.setTranslation(Vector_camera_pos);
//回転の座標変換を用意
Transform_camera_theta.rotX(-theta);
Transform_camera_phi.rotY(phi);
//===========================================================================
//カメラの座標変換実行
//合成する
Transform_camera_phi.mul(Transform_camera_theta);
Transform_camera_pos.mul(Transform_camera_phi);
//座標変換実行
Camera.setTransform(Transform_camera_pos);
//===========================================================================
//マウス座標を更新しておく
pre_x = event.getX();
pre_y = event.getY();
}
}
//mouse_ViewChangeここまで
//*****************************************************************************
}
//******************************************************************************
//Canvas3Dクラスのテスト “ViewChange_test.java”
//
//カラーキューブを表示させてマウスドラッグで視点移動
//******************************************************************************
//Swing関係のインポート
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
//Java3D関係のインポート
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
public class ViewChange_test
{
public static void main(String args[])
{
//============================================================================
//まずは、基礎フレームの設定。
//============================================================================
//メイン・ウィンドウ作成
JFrame frame = new JFrame();
//ウィンドウのサイズ設定
frame.setSize(400,400);
//ウィンドウのタイトル設定
frame.setTitle("ViewChange_test");
//ウィンドウを閉じる動作の登録
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//コンテントペインを作成
JPanel cp = new JPanel();
//コンテントペイン上のレイアウトは全て手動で行う
cp.setLayout(null);
//フレームに、コンテントペインを登録
frame.add(cp);
//============================================================================
//次にJava3D関係の設定。
//============================================================================
//現在使用している画面の、ハードウェア情報を取得する
GraphicsConfiguration g_config = SimpleUniverse.getPreferredConfiguration();
//Cnavas3D_ViewChangeクラスを用意する(距離は3, マウス感度は0.01)
Canvas3D_ViewChange canvas = new Canvas3D_ViewChange(3.0f, 0.01f, g_config);
//3D表示領域の大きさを設定。今回はウィンドウいっぱいに表示する
canvas.setBounds(0,0,400,400);
//コンテントペインにCanvas3Dを登録
cp.add(canvas);
//============================================================================
//3D空間を構築していきます
//============================================================================
//Canvas3DクラスのSimpleUniverseを利用。
SimpleUniverse universe = canvas.universe;
//オブジェクトの「枝」を1つ作る
BranchGroup group1 = new BranchGroup();
//「カラーキューブ」を1つ生成
ColorCube cube = new ColorCube(0.4f);
//座標変換クラスを生成
TransformGroup transform_group1 = new TransformGroup();
//座標変換の書き換えを許可
transform_group1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
//カラーキューブを座標変換クラスに登録
transform_group1.addChild(cube);
//座標変換内容
Transform3D transform1 = new Transform3D();
//「枝」に座標変換クラスを登録
group1.addChild(transform_group1);
//仮想空間に「枝」を登録(これは最後に・・・!)
universe.addBranchGraph(group1);
//ウィンドウを可視化
frame.setVisible(true);
}
}
またカラーキューブを回転させるだけなのですが。。。 今回は直観的に見やすい動きだと思います。動いているのは自分の「目線」です。