トップページ > Java3D入門 > Javaのマウス入力(4)
ここではマウスをドラッグすると図形が動くプログラムを作ります。 前回と同様に,JFrameクラスを継承した枠組みをつくり,それをメインクラス(メインメソッド)で インスタンス化することにします。
主となる“cube_dragg_frame”はJFrameクラスを継承しているのでフレームのような扱いになります。 また,MouseMotionListenerを実装し,前ページと同様に “mouseDragged()”メソッド内で処理を記述します。 今回はカラーキューブを回転させる座標変換をmouseDragged()内で処理しています。
//******************************************************************************
//立法体を表示し,マウスドラッグを受け付けるフレーム“cube_dragg_frame”
//
//JFrameを継承
//MouseListenerとMouseMotionLisenerとMouseWheelListenerを実装
//
//フレームとマウス座標を表示するラベルを1つにまとめたクラス
//(カメラの位置と角度に注意)
//******************************************************************************
//フレーム関係のインポート
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 cube_dragg_frame extends JFrame
{
//=============================================================================
//クラスのフィールド
//新規取得するx,y座標
int new_x, new_y;
//前に取得したx,y座標
int pre_x, pre_y;
//仮想空間全体
SimpleUniverse universe;
//オブジェクトのためのグループ
BranchGroup group1;
//オブジェクトの座標変換のためのグループ
TransformGroup transform_group1;
//オブジェクトの座標変換のためのクラス
Transform3D Transform_Rot_x;
Transform3D Transform_Rot_y;
//回転角を管理
double rot_x = 0;
double rot_y = 0;
//前回の回転角を保持
double pre_rot_x = 0;
double pre_rot_y = 0;
//=============================================================================
//コンストラクタ(引数はタイトルとフレームの寸法)
public cube_dragg_frame(String title, int x_size, int y_size)
{
//============================================================================
//ウィンドウ全般の設定
//============================================================================
//サイズ設定
setSize(x_size, y_size);
//タイトル設定
setTitle(title);
//ウィンドウを閉じる動作の登録
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//============================================================================
//コンテントペインの設定
//============================================================================
//コンテントペインを作成
JPanel cp = new JPanel();
//コンテントペインのレイアウトは手動
cp.setLayout(null);
//フレームにコンテントペインを登録
setContentPane(cp);
//============================================================================
//次にJava3D関係の設定。
//============================================================================
//現在使用している画面の、ハードウェア情報を取得する
GraphicsConfiguration g_config = SimpleUniverse.getPreferredConfiguration();
//3Dグラフィクスを表示する領域となる
Canvas3D canvas = new Canvas3D(g_config);
//3D表示領域の大きさを設定。今回はウィンドウいっぱいに表示する
canvas.setBounds(0,0,400,400);
//コンテントペインにCanvas3Dを登録
cp.add(canvas);
//============================================================================
//3D空間を構築していきます
//============================================================================
//仮想空間のインスタンスを生成。表示先としてcanvasを指定。
universe = new SimpleUniverse(canvas);
//オブジェクトの「枝」を1つ作る
group1 = new BranchGroup();
//「カラーキューブ」を1つ生成
ColorCube cube = new ColorCube(0.4f);
//座標変換クラスを生成
transform_group1 = new TransformGroup();
//座標変換の書き換えを許可
transform_group1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
//カラーキューブを座標変換クラスに登録
transform_group1.addChild(cube);
//座標変換内容を扱うためのクラス
Transform_Rot_x = new Transform3D();
Transform_Rot_y = new Transform3D();
//「枝」に座標変換クラスを登録
group1.addChild(transform_group1);
//仮想空間に「枝」を登録(これは最後に・・・!)
universe.addBranchGraph(group1);
//============================================================================
//視点について設定
//============================================================================
//視点についてのハードウェア情報を取得。
ViewingPlatform vp = universe.getViewingPlatform();
//視点のための座標変換クラスを用意
TransformGroup Camera = vp.getViewPlatformTransform();
//カメラの位置ベクトル
Transform3D view_pos = new Transform3D();
//カメラの位置を決める
Vector3f pos_vec = new Vector3f(0.0f,0.0f,2.8f);
//カメラの位置について、座標変換実行
view_pos.setTranslation(pos_vec);
//カメラの向きを示すベクトル
Transform3D view_dir = new Transform3D();
Transform3D view_dir2 = new Transform3D();
//カメラの向きを決める
view_dir.rotY(Math.PI/4);
view_dir2.rotX(-Math.PI/4 + 0.1f);
view_dir.mul(view_dir2);
//カメラの位置およびカメラの向きを統合
//view_pos.mul(view_dir2);
//カメラの位置情報を登録
Camera.setTransform(view_pos);
//============================================================================
//マウスの設定
//============================================================================
//マウス入力用のクラス,mouse_classをインスタンス化
mouse_class mouse = new mouse_class();
//このフレームにマウス入力クラスを登録
canvas.addMouseMotionListener(mouse);
}
//*****************************************************************************
//mouse_class:マウス入力用のクラス
//*****************************************************************************
class mouse_class 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();
//今回動いた分の回転角 + 前回までの回転角(なめらかに回転させるため)
rot_x = (new_x - pre_x)/(50* Math.PI) + pre_rot_x;
rot_y = (new_y - pre_y)/(50* Math.PI) + pre_rot_y;
//横方向のマウスの動きはY軸中心の回転
Transform_Rot_x.rotY(rot_x);
//縦方向のマウスの動きはX軸中心の回転
Transform_Rot_y.rotX(rot_y);
//2つの座標変換を合成
Transform_Rot_x.mul(Transform_Rot_y);
//座標変換を登録
transform_group1.setTransform(Transform_Rot_x);
//回転角情報を更新
pre_rot_x = rot_x;
pre_rot_y = rot_y;
//回転角が2πをこえたらリセット(オーバーフロー防止)
if(pre_rot_x > 2*Math.PI)
{
pre_rot_x %= 2*Math.PI;
}
if(pre_rot_y > 2*Math.PI)
{
pre_rot_y %= 2*Math.PI;
}
//マウス座標を更新しておく
pre_x = event.getX();
pre_y = event.getY();
}
}
}
//******************************************************************************
//“mouse_test3.java”
//マウス入力クラスのための、テストプログラム(3)
//マウスをドラッグすると立方体が回転
//******************************************************************************
public class mouse_test3
{
//=============================================================================
//メインメソッド
public static void main(String[] args)
{
//mouse_dragg_frame クラスをインスタンス化
cube_dragg_frame frame = new cube_dragg_frame("mouse test3", 400, 400);
//フレームを可視化
frame.setVisible(true);
}
}
それでは,両方をコンパイルして,“mouse_test3.java”を実行します。 とりあえずマウスでドラッグするとカラーキューブが動きます。
しかし,この動きは直観的ではないような気がします。 下図のように,カラーキューブを横へ向けた状態でマウスを上下にドラッグすると, カラーキューブは面内(Z軸中心で)回転してしまいます。
本来ならば,上のような状態でマウスを上下へ動かすとカラーキューブが画面奥を向いたり,こっち側を向いたりしてほしいところです。このようになってしまうのは,「カラーキューブを回転させている」からです。 おそらく,キューブ自体を動かすよりも「自分の目線を動かす」ほうがキューブの各面を見る時に自然な印象になると思います。そんなわけで,次は「視点移動」を扱います。