忍者ブログ

軽Lab

 Javaを中心とした、プログラミング関係のナレッジベース

Home > > JavaFX SceneGraph(全体像)

JavaFX SceneGraph(全体像)

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

Home > > JavaFX SceneGraph(全体像)

- ランダム記事 -

コメント

ただいまコメントを受けつけておりません。

Home > JavaFX入門 > JavaFX SceneGraph(全体像)

JavaFX SceneGraph(全体像)

Stage, Sceneはパッケージだが、JavaDocを見てもSceneGraphというパッケージは存在しない。どうやら、Scene.Nodeクラスを継承したクラスがSceneGraphと呼ばれている模様。今回は、SceneGraphの全体像を見ていく。

■ SceneGraph( Scene.Nodeクラス )の基本


Scene Graphには多くのクラスが属しているが、すべてのクラスについて以下のルールが適用される。

データ構造の制約
各ノードは1つ以上の親を持てない。もし、親を新しく設定した場合、かつての親との関係はリセットされる。木構造内にループが発生するような操作は無視され、例外が発生する。

ID
ノードにはID(String型)が設定でき、lookup(String)でノードの呼び出しができる。IDは一意になるようにプログラマが設定する。

座標系
画面左上が(x,y)=(0,0)。右に行くほどx座標の値が、下に行くほどy座標の値が増える。3Dの場合、z軸は画面に垂直方向に伸び、奥に置くほどz座標の値が増える。座標は整数(Integer)でなく浮動小数点数(float)で指定する。

座標変換
平行移動・回転・拡大縮小・せん断(shearing)が可能。

その他
シェイプのバウンディングボックスは、外枠を含めた大きさとなる。外枠に太さが設定されている場合、デフォルトではシェイプの内外にそれぞれ外枠の太さの半分の厚みが追加される。
また、各ノードはstyleClassを持ち、CSSと同様の内容を保持している。


■ SceneGraphに属するクラス

SceneGraphはクラス数が多いため、すべて列挙することはできないが代表的なものを上げると以下のように分類できる。すべてScene.Nodeクラスを継承しているため、どのようなクラスがあるか知りたい場合にはJava DocのScene.Nodeクラスからたどっていけばよい。

分類
(type)
基底クラス
(base class)
主要な具象クラス
(main concrete class)
内容
(content)
一般 Parent Group
Button
Label
GridPane
PieChartなど
子ノードを保持できるクラス。
レイアウト・コンテナやチャート(グラフ)、UIコントロールなどが該当する。
SubScene SubScene シーンの中に別のシーンを表示するためのクラス。
2Dと3Dは1つのシーン内で同時に描画できないため、
SubSceneを使ってシーンを分ける。
2D Canvas Canvas Swingと同じような描画関数が使えるクラス。
GraphicsContextを用いた描画を行う。
Shape Line
Circle
Polygon
Rectangle
Textなど
2次元シェイプを出力するクラス。
ImageView ImageView 画像を出力するクラス。
MediaView MediaView メディアを出力するクラス。
SwingNode SwingNode SwingコンテンツをJavaFXに埋め込むために使うクラス
3D Shape3D Box
Cylinder
MeshView
Sphereなど
3次元シェイプを出力するクラス。
Camera  ParallelCamera
PerspectiveCamera
3Dカメラを表すクラス。
LightBase AmbientLight
PointLight
3D照明を表すクラス。

Scene Graphは名前を見ただけで大体どのようなものかわかると思われる。
利用の際に注意すべき点は、『2Dオブジェクトと3Dオブジェクトは、1つのシーン内で併用できない』という点である。利用しようとしているクラスが2D/3Dのどちらに分類されるかはプログラマが意識する必要がある。ただしSubSceneクラスを利用することで、1つのウィンドウ内に2Dと3Dの併用が可能となる。

Scene Graphを用いたサンプルプログラムを以下に示す。サンプルでは3Dオブジェクトである立方体と、2Dオブジェクトであるメッセージを同時に出力している。

◇サンプルプログラムの実行結果
 

◇サンプルプログラム
package application_fx;

import java.io.File;

import javafx.application.Application;
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.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class TestSceneGraph extends Application {

    public static void main(String[] args)
    {
        launch( args );
    }
    
    /** 
     * 【シーングラフの構成】
     * 
     *  root
     *  ┣ sg3D
     *  ┃ ┣ box
     *  ┃ ┃ ┗material
     *  ┃ ┣ camera
     *  ┃ ┗ light
     *  ┃
     *  ┗ sg2D
     *   ┣ rect
     *   ┣ circle
     *   ┣ image
     *   ┗ text
     * 
     */
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // 3Dシーンを作成
        SubScene sg3D = create3DScene();
        
        // 2Dシーンを作成
        SubScene sg2D = create2DScene();
                
        // シーングラフを構成
        Pane   root   = new Pane();
        root.getChildren().add( sg3D );
        root.getChildren().add( sg2D );
        sg2D.relocate( 10 , sg3D.getHeight() - sg2D.getHeight() - 10 );
        
        // シーンを作成
        Scene scene = new Scene( root );
    
        // ステージの作成
        primaryStage.setScene( scene );
        primaryStage.setTitle( "Scene Graphのテスト" );
        primaryStage.show();
        
    }

    /**
     * 3Dシーンを作成
     * @return
     */
    private SubScene create3DScene()
    {
        // 3Dシーングラフのルートを作成
        Group       sg3D        = new Group();
        
        // 立方体を追加
        Box         box         = new Box( 10 , 10 , 10 );
        box.setRotationAxis( new Point3D( 1.0 , 1.0 , 1.0 ) );
        box.setRotate( 30.0 );
        sg3D.getChildren().add( box );
        
        // 立方体の色を設定
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor( Color.AZURE );
        box.setMaterial( material );
        
        // カメラ設定
        Camera      camera      = new PerspectiveCamera( true );
        camera.setTranslateZ( -30.0 );
        sg3D.getChildren().add( camera );
        
        // 照明設定(スポットライト)
        LightBase   light       = new PointLight();
        light.setTranslateX(  20.0 );
        light.setTranslateY( -20.0 );
        light.setTranslateZ( -30.0 );
        sg3D.getChildren().add( light );
        
        // シーンを作成
        SubScene    subscene    = new SubScene( sg3D , 400 , 400 );
        subscene.setFill(Color.BLACK);
        subscene.setCamera( camera );
        
        return subscene;
                
    }
    
    /**
     * 2Dシーンを作成
     * @return
     */
    private SubScene create2DScene()
    {
        // 2Dシーングラフのルートを作成
        Pane        sg2D    = new Pane();
        
        // 長方形を追加
        Rectangle   rect    = new Rectangle( 200 , 50 );
        rect.setArcHeight( 10 );
        rect.setArcWidth( 10 );
        rect.setFill( Color.GREENYELLOW );
        rect.setOpacity( 0.75 );
        sg2D.getChildren().add( rect );
        
        // 円を追加
        Circle      circle  = new Circle( 17.5 );
        circle.setLayoutX( 25.0 );
        circle.setLayoutY( 25.0 );
        circle.setFill( Color.WHITE );
        sg2D.getChildren().add( circle );
                
        // 画像を追加
        ImageView   image   = new ImageView();
        Image       img     = new Image( new File("img/cursor.png").toURI().toString() );
        image.setImage( img );
        image.setSmooth( true );
        image.setPreserveRatio( true );
        image.setFitWidth( 30 );
        image.setLayoutX( 10.0 );
        image.setLayoutY( 10.0 );
        sg2D.getChildren().add( image );        
        
        // テキストを追加
        Text        text    = new Text();
        text.setText( "JavaFX 8からはテキストの自動改行(折り返し)機能が追加されています。" );
        text.setFont( new Font( 12 ) );
        text.setFill( Color.BLACK );
        text.setWrappingWidth( 140 );
        text.setLayoutX( 50.0 );
        text.setLayoutY( 15.0 );
        sg2D.getChildren().add( text );
        
        // シーンを作成
        SubScene   subscene   = new SubScene( sg2D , rect.getWidth() , rect.getHeight() );
        
        return subscene;
        
    }

}

ソースコードの解説は以下の通り。今回は各々のScene Graphノードについて詳細に説明はせず、プログラムの骨格について解説する。

  1. create3DScene関数(79行目~)では、3Dオブジェクトを表示するサブシーンを作成している。関数内ではサブシーンのルート・ノードであるsd3Dオブジェクトに作成した3Dオブジェクトを追加している。
  2. create2DScene関数(120行目~)では、2Dオブジェクトを表示するサブシーンを作成している。関数内ではサブシーンのルート・ノードであるsd2Dオブジェクトに作成した2Dオブジェクトを追加している。
  3. Start関数(51行目~)では、事前に作成した3Dオブジェクトと2Dオブジェクトを1つのシーンにまとめ、ウィンドウ表示している。

Scene Graphの各クラスについて、詳細な使い方はまた別の記事にて確認する。


■ 参照

  1. JavaDoc - Class Node
- PR -
Home > JavaFX入門 > JavaFX SceneGraph(全体像)

- ランダム記事 -

コメント

ただいまコメントを受けつけておりません。

QRコード

プロフィール

管理者:
連絡はContactよりお願いします。

PR