忍者ブログ

軽Lab

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

Home > > JavaFX 3D シェイプ・メッシュ

JavaFX 3D シェイプ・メッシュ

×

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

Home > > JavaFX 3D シェイプ・メッシュ

- ランダム記事 -
- PR -

コメント

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

Home > JavaFX入門 > JavaFX 3D シェイプ・メッシュ

JavaFX 3D シェイプ・メッシュ

今回はJavaFX上の3Dオブジェクトである3Dシェイプとメッシュを見ていく。マテリアル(色・テクスチャ)の設定については、次回の記事にて扱う。

■ 3Dオブジェクトのクラス一覧

 JavaFXで利用可能な3Dオブジェクト・クラスの一覧は以下の通りである。注意点としてメッシュ以外の位置指定は、すべて重心位置で設定することである。

3Dオブジェクト クラス 内容
立方体、直方体 Box 縦・横・奥行を持つ直方体を出力する
Sphere 半径を指定して球を出力する
円柱 Cylinder 半径と高さを指定して、球を出力する
メッシュ MeshView 複数の頂点を面でつなげた立体を出力する。3Dモデルの出力などで利用する。

■ メッシュの構築

 JavaFXでのメッシュ構築は以下の手順で実行する。

  

 ①頂点の定義
  必要な頂点を(x,y,z)座標で指定して作成する。作成した頂点には番号を付与し、
  後で参照できるようにする。

 ②面の作成
  ①で作成した頂点の番号を3つ指定して、1つの面(三角形)を作成する。
  頂点の指定順序で面に裏表を設定する。裏表の設定方法は以下の通り。

    

  例えば、面を( v1 , v2 , v3 )の3つの頂点で作成することを考える。
  3つの頂点をカメラ位置から見た場合、半時計周りの順番で定義されている側が表となり、
  逆に、時計回りの順番で定義されている側が裏となる。

■ カリングの設定 / setCullFace関数

 カリング処理(Culling)とは、3Dオブジェクトの面の片面(裏か表)を描画しない仕組みである。3Dレンダリングで物体を描画する際に面の裏・表は別々に描画される。しかし、球のように面の裏側が見えない物体(球の表面はすべて表面)の場合、裏面を描写しなくても問題がない場合が多い。裏面を描画しないことで描画処理量が単純に1/2になるため、ようにすることで、見た目は変わらずに描画処理を軽くすることができる。もちろん、平面のような裏・表両面を描画する必要がある3Dオブジェクトではカリングしないよう設定する必要がある。

定数 内容
CullFace.NONE 裏・表の両方を描画する
CullFace.BACK 表面を描画し、裏面を描画しない。デフォルト値
CullFace.FRONT 表面を描画せず、裏面を描画する


■ 描画モデルの設定 / setDrawMode関数

 描画モデルでは、3Dオブジェクトを描画する際に面を表示するか、枠線のみ表示するかを設定できる。

定数 内容
DrawMode.FILL 面を塗りつぶす。デフォルト値
DrawMode.LINE 面を塗りつぶさず、輪郭線のみ描画する

■ サンプルプログラム

 以下に3Dオブジェクトの表示と、カリング・描画モデルの設定方法を示すサンプルコードを示す。サンプルでは6つの3Dオブジェクトを作成しているが、カリングにより1つの3Dオブジェクトが描画されていない。

◇サンプルコード
package application_fx;

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.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.Cylinder;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.Sphere;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;

public class TestShape3D extends Application
{
    public static void main(String[] args)
    { launch( args );}
    
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // ルートノードの作成
        Group       root        = create3DGroup();
        
        // カメラを設定
        Camera      camera      = new PerspectiveCamera( true );
        camera.getTransforms().add( new Rotate( 30 , 0 , 0 , 0 , new Point3D( -1 , -1 , 0 ) ) );
        camera.getTransforms().add( new Translate( 0.0 , 0.0 , -30 ) );
        root.getChildren().add( camera );
        
        // 照明を設定
        LightBase   light       = new PointLight();
        light.setTranslateX( 0.0 );
        light.setTranslateY( -20.0 );
        light.setTranslateZ( -30.0 );
        root.getChildren().add( light );
        
        // 3D用のーンを作成
        Scene   scene           = new Scene( root , 500 , 500 , true );
        scene.setFill( Color.BLACK );
        scene.setCamera( camera );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
        
    }
    
    /**
     * 3Dオブジェクトのグループを作成する
     * @return
     */
    public Group create3DGroup()
    {
        // シーングラフのルートを作成
        Group       root        = new Group();
        
        // BOXを作成
        Box         box         = new Box();
        box.setWidth( 4 );
        box.setHeight( 4 );
        box.setDepth( 4 );
        box.setTranslateX( -5 );
        box.setTranslateY( -3 );
        root.getChildren().add( box );
        
        // 球の作成
        Sphere      sphere      = new Sphere();
        sphere.setRadius( 2 );
        sphere.setTranslateX( 0 );
        sphere.setTranslateY( -3 );
        root.getChildren().add( sphere );
        
        // 円柱の作成
        Cylinder    cylinder    = new Cylinder();
        cylinder.setRadius( 2 );
        cylinder.setHeight( 4 );
        cylinder.setTranslateX( 5 );
        cylinder.setTranslateY( -3 );
        root.getChildren().add( cylinder );
        
        // メッシュの作成
        // 【頂点座標】
        // p0┏━┓p3
        //   ┃\┃
        // p1┗━┛p2
        TriangleMesh    mesh        = new TriangleMesh();
        float[]         points      = { -2      ,-2     ,0      ,   // p0
                                        -2      ,2      ,0      ,   // p1
                                        2       ,2      ,0      ,   // p2
                                        2       ,-2     ,0      };  // p3
        float[]         texCoords   = { 0 , 0 };
        int[]           faces       = { 0 , 0 , 1 , 0 , 2 , 0,
                                        2 , 0 , 3 , 0 , 0 , 0 };
        mesh.getPoints().addAll( points );
        mesh.getTexCoords().addAll( texCoords );
        mesh.getFaces().addAll( faces );
        
        // メッシュビュー1(左)を作成
        MeshView        meshView1    = new MeshView();
        meshView1.setMesh( mesh );
        meshView1.setTranslateX( -5 );
        meshView1.setTranslateY( 4 );
        meshView1.setDrawMode( DrawMode.FILL );
        root.getChildren().add( meshView1 );
        
        // メッシュビュー2(中央)を作成
        MeshView        meshView2    = new MeshView();
        meshView2.setMesh( mesh );
        meshView2.setTranslateY( 4 );
        meshView2.setDrawMode( DrawMode.LINE );
        root.getChildren().add( meshView2 );

        // メッシュビュー3(右)を作成
        MeshView        meshView3    = new MeshView();
        meshView3.setMesh( mesh );
        meshView3.setTranslateX( 5 );
        meshView3.setTranslateY( 4 );
        meshView3.setDrawMode( DrawMode.FILL );
        meshView3.setCullFace( CullFace.FRONT );
        root.getChildren().add( meshView3 );
        
        
        return root;
    }

}
◇実行結果
 
◇解説

  1. 直方体の作成時には、幅(x座標)・高さ(y座標)・奥行(z座標)を指定する(68行目~73行目)。3Dオブジェクトもシーングラフへ追加することで自動的に描画される(74行目)。ただし、2Dと3Dのオブジェクトは同じシーン内に表示できず、3Dシーンではシーン作成時にシーンバッファを有効にする必要がある(48行目)。
  2. 球と円柱も、直方体と同様に作成後にシーングラフに追加する(77行目~89行目)。直方体も球も円柱も、作成直後は物体の重心が座標(0,0,0)にくるように配置される。このため、setTranslate○○関数で物体位置を移動させている。
  3. メッシュの描画は『メッシュの作成』と『メッシュの出力』の2段階に分かれる。メッシュの作成では、頂点と面を指定してジオメトリデータを作成する(96行目~106行目)。頂点の宣言では、(x,y,z)座標を示す小数をfloat型の1次元配列に格納していく。ここでは、1つめの頂点座標は(-2,-2,0)を表し、2つめの頂点座標は(-2,2,0)を表す(97行目~100行目)。今回はテクスチャを用いないため、ダミーデータを設定している(101行目)。面の作成では、1つの面の作成に、3頂点の番号と3テクスチャの番号を指定している。ここでは、(頂点,テクスチャ)=(0,0) , (1,0) , (2,0)の3つの組で1つの面を構築している(102行目)。
  4. メッシュの出力では、作成したメッシュデータを表示するためのビューを作成・登録する(109行目~130行目)。画像の出力と同様、1つのメッシュの出力を別々のビューに設定可能である。
  5. 3Dオブジェクトの描画モード設定では、面の出力(上図の左下)と線の出力(上図の下中央)が指定できる(113行目、120行目)。
  6. カリング設定で表面の描画を省略するようにすると、出力されなくなる(129行目)。もちろん、カメラ位置を裏側に移動させると裏面は描画されている。

■ 参照

  1. JavaDoc - クラスShape3D
  2. JavaDoc - クラスTriangleMesh
Home > JavaFX入門 > JavaFX 3D シェイプ・メッシュ

- ランダム記事 -
- PR -

コメント

プロフィール

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

PR