JavaFX Cameraの扱いかた
JavaFXでは表示するための視点の位置や方向をCameraで設定します。
カメラからみた映像がSceneに表示されます。
CameraはLigthなどとともにGroupに登録しますが、Sceneにも登録する必要があります。
簡単なプログラム
下のプログラムは単純な
カメラ
楽天 設定例です。
6面体とLightとCameraをSceneに置いて、6面体を表示しています。
カメラの視線方向はZ軸方向です。
デフォルトでは6面体とカメラが同じ位置なので、カメラをZ方向に-50移動させ、6面体が視界に入るようにしています。
サンプルプログラム
package tomojavalib.fx;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.LightBase;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
/**単純なJavaFX楽天 プログラム
*カメラの移動、回転
* */
public class App15 extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Scene scene = make3dScene();
stage.setScene(scene);
//タイトルの表示
stage.setTitle("カメラ試験");
stage.show();
}
private Scene make3dScene(){
Group group = new Group();
//箱を置く
Box box = new Box( 10 , 10 , 10 );
group.getChildren().add( box );
// カメラを置く
PerspectiveCamera camera = new PerspectiveCamera( true );
//方向と位置
Translate cameratranslate = new Translate(0,0,-50);
camera.getTransforms().add( cameratranslate );
//点光源を置く
LightBase light = new PointLight();
light.setTranslateX( 30.0 );
light.setTranslateY( -30.0 );
light.setTranslateZ( -30.0 );
group.getChildren().add( light );
//Sceneの設定
Scene s3d = new Scene(group, 320, 240);
s3d.setFill(Color.ALICEBLUE);
s3d.setCamera( camera );
return s3d;
}
}
カメラの回転と平行移動
下記はカメラをX方向に15度、Y方向に15度回転したのち、Z方向へ‐50平行移動するものです。
Translate cameratranslate = new Translate(0,0,-50);
Rotate camerarotateX = new Rotate( 15 , new Point3D( 1 , 0 , 0 ) );
Rotate camerarotateY = new Rotate( 15 , new Point3D( 0 , 1 , 0 ) );
camera.getTransforms().add( camerarotateX );
camera.getTransforms().add( camerarotateY );
camera.getTransforms().add( cameratranslate );
実行結果はこんな感じになります。
回転移動と平行移動の順番が重要で、順序が変わると見え方も変わります。
Translate cameratranslate = new Translate(0,0,-50);
Rotate camerarotateX = new Rotate( 15 , new Point3D( 1 , 0 , 0 ) );
Rotate camerarotateY = new Rotate( 15 , new Point3D( 0 , 1 , 0 ) );
camera.getTransforms().add( cameratranslate );
camera.getTransforms().add( camerarotateX );
camera.getTransforms().add( camerarotateY );
上のように平行移動後に回転移動をすると、6面体が視界の中心からずれてしまいます。
この理由は、カメラの移動がカメラ自身のローカル座標に従って行われるためです。
下図の左が移動後回転、右が回転後移動です。
表示対象を常に視解の中心に置く方法
座標a,b,cにある物を視界の中心におさめたい場合、Cameraを下記の順に移動させます。
1、座標a,b,c,へ平行移動
2、見たい角度へ回転移動
3、Z軸マイナス方向へ平行移動
下のサンプルプログラムでは、カメラを6面体と同じ位置に平行移動させたのち、回転移動、Z方向平行移動をしています。
実行結果
サンプルプログラム
package tomojavalib.fx;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.LightBase;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
/**単純な
Java
楽天 FXプログラム
*カメラの移動、回転
* */
public class App15 extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Scene scene = make3dScene();
stage.setScene(scene);
//タイトルの表示
stage.setTitle("カメラ試験");
stage.show();
}
private Scene make3dScene(){
Group group = new Group();
//箱を置く
Box box = new Box( 10 , 10 , 10 );
Translate boxtranslate = new Translate(100,100,100);
box.getTransforms().add( boxtranslate );
group.getChildren().add( box );
// カメラを置く
PerspectiveCamera camera = new PerspectiveCamera( true );
//方向と位置
Translate cameratranslate = new Translate(0,0,-50);
Rotate camerarotateX = new Rotate( 45 , new Point3D( 1 , 0 , 0 ) );
Rotate camerarotateY = new Rotate( 45 , new Point3D( 0 , 1 , 0 ) );
camera.getTransforms().add( boxtranslate );
camera.getTransforms().add( camerarotateX );
camera.getTransforms().add( camerarotateY );
camera.getTransforms().add( cameratranslate );
//点光源を置く
LightBase light = new PointLight();
light.setTranslateX( 30.0 );
light.setTranslateY( -30.0 );
light.setTranslateZ( -30.0 );
group.getChildren().add( light );
//Sceneの設定
Scene s3d = new Scene(group, 320, 240);
s3d.setFill(Color.ALICEBLUE);
s3d.setCamera( camera );
return s3d;
}
}
カメラの視野角と表示範囲
カメラは自分の座標系を持っており、Z軸方向が視線の中心になります。
見える角度は、
camera.setFieldOfView( 30. );
で設定します。この場合30度になります。
また、カメラから一定の距離以上、以下の範囲を表示しないことができます。
camera.setFarClip( 50. );
camera.setNearClip( 45. );
上の場合では距離50以上と45以下は表示されません
実行するとこうなります。
可視範囲を3Dで描くと下図のようになります。四角錐を輪切りにしたような形状の内側が可視範囲。
カメラの設定後に位置と方向を変える
回転と平行移動に順序があるなら、一度カメラを設置してから動かすのは大変だなあと思ったのですが...
下記のようにCameraにaddしておいたTranslateやRotateをあとから変更することで移動できました。
camerarotateX.setAngle( 15. );
camerarotateY.setAngle( 15. );
cameratranslate.setZ( -100. );
実行結果
左は追記前で、X,Y方向に45度回転、距離50。右は追記後で、X,Y方向に15度回転、距離100にしています。
サンプルプログラム
下記のように追記しましたが、マウスイベントに組み込めばマウスで視点を操作できるようになります。
(こちら)
package tomojavalib.fx;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.LightBase;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
/**単純なJavaFXプログラム
*カメラの移動、回転
* */
public class App15 extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Scene scene = make3dScene();
stage.setScene(scene);
//タイトルの表示
stage.setTitle("カメラ試験");
stage.show();
}
private Scene make3dScene(){
Group group = new Group();
//箱を置く
Box box = new Box( 10 , 10 , 10 );
Translate boxtranslate = new Translate(100,100,100);
box.getTransforms().add( boxtranslate );
group.getChildren().add( box );
// カメラを置く
PerspectiveCamera camera = new PerspectiveCamera( true );
//方向と位置
Translate cameratranslate = new Translate(0,0,-50);
Rotate camerarotateX = new Rotate( 45 , new Point3D( 1 , 0 , 0 ) );
Rotate camerarotateY = new Rotate( 45 , new Point3D( 0 , 1 , 0 ) );
camera.getTransforms().add( boxtranslate );
camera.getTransforms().add( camerarotateX );
camera.getTransforms().add( camerarotateY );
camera.getTransforms().add( cameratranslate );
//視界の角度
camera.setFieldOfView( 30. );
//可視距離の設定
//camera.setFarClip( 50. );
//camera.setNearClip( 45. );
group.getChildren().add( camera );
//点光源を置く
LightBase light = new PointLight();
light.setTranslateX( 30.0 );
light.setTranslateY( -30.0 );
light.setTranslateZ( -30.0 );
group.getChildren().add( light );
//Sceneの設定
Scene s3d = new Scene(group, 320, 240);
s3d.setFill(Color.ALICEBLUE);
s3d.setCamera( camera );
//カメラの向きと位置を変更
camerarotateX.setAngle( 15. );
camerarotateY.setAngle( 15. );
cameratranslate.setZ( -100. );
return s3d;
}
}
最終更新日: 2017-03-06 12:35:47