ともさんのHP >プロブラミング >JavaFX >MeshViewの扱いかた

JavaFX MeshViewの扱いかた

MeshViewはJavaFXの3次元モデルを表示するためのオブジェクトです。
たくさんの3角形を定義してテクスチャを貼りつけ、様々な形状を表示させることができます。
JavaFXMeshView

広告


Meshの定義手順

MeshViewを定義する前に、まずTriangleMeshを作ります。メッシュには3つのデータを入れます。
3角形を構成する3次元点(points)、貼りつける画像を切り取るための2次元点(TexCoords)、三角形を構成する点(Faces)

pointsの設定

pointsは、floatの配列とし、各点のx,y,z値を順に入れます。下のような4点を格納する場合、
4点

 double x = 5.;
 double y = 5.;
 double z = 0.;
 Point3D[] point = new Point3D[4];
 point[0] =new Point3D( -x , -y , z );
 point[1] =new Point3D( -x ,  y , z );
 point[2] =new Point3D(  x ,  y , z );
 point[3] =new Point3D(  x , -y , z );

下のように格納します。

 float[] points = new float[ point.length*3 ];
 int i=0;
 for(int ii=0;ii<point.length;ii++){
  points[i] = (float)point[ii].getX();i++;
  points[i] = (float)point[ii].getY();i++;
  points[i] = (float)point[ii].getZ();i++;
 }

TexCoordsの設定

TexCoordsもfloatの配列ですが、2次元の点、x,yの値を順に入れてゆきます。
pointsの点と同じ数だけの点を定義するので、配列の長さは2/3になります。
JavaFXテクスチャ画像の座標

座標の値は、上のように貼りつける画像の左上を0,0、右下を1,1とします。0~1の範囲を外れると、画像をタイル状に並べて延長した画像がはめ込まれます。
pointsのx,y座標を取り出して、最大座標を1、最小を0となるように調整して定義すると、下記のようになります。

 float[] texCoords = new float[ point.length*2 ];
 i=0;
 for(int ii=0;ii<point.length;ii++){
  texCoords[i] = (float)((point[ii].getX()+x)/x/2);i++;
  texCoords[i] = (float)((point[ii].getY()+y)/y/2);i++;
 }

Facesの設定

先に定義した2組の点を使って三角形を定義します。三角形は3つの点の配列番号を順に並べて定義します。
点の順番は、逆時計回りに並べると、向かっている側の面が表となります。
JavaFXFacesの定義

上のように3角形を2つ定義して、向かい側を表にする場合、{0,1,2, 2,3,0}とします。
また、テクスチャを貼る点の方も同時に設定します。Pointsの番号、TexCoordsの番号の順で交互に設定します。
points、TexCoordsの同じ配列番号を設定する場合は、{0,0,1,1,2,2, 2,2,3,3,0,0}
intの配列で、下記のように書きます。

 int[] faces = {0,0,1,1,2,2,2,2,3,3,0,0};

TriangleMeshの定義

定義した3つをTriangleMeshに格納すれば2つの3角形で構成されるTriangleMeshを定義できます。

 double x = 5.;
 double y = 5.;
 double z = 0.;
 Point3D[] point = new Point3D[4];
 point[0] =new Point3D( -x , -y , z );
 point[1] =new Point3D( -x ,  y , z );
 point[2] =new Point3D(  x ,  y , z );
 point[3] =new Point3D(  x , -y , z );
 float[] points = new float[ point.length*3 ];
 int i=0;
 for(int ii=0;ii<point.length;ii++){
  points[i] = (float)point[ii].getX();i++;
  points[i] = (float)point[ii].getY();i++;
  points[i] = (float)point[ii].getZ();i++;
 }
 float[] texCoords = new float[ point.length*2 ];
 i=0;
 for(int ii=0;ii<point.length;ii++){
  texCoords[i] = (float)((point[ii].getX()+x)/x/2);i++;
  texCoords[i] = (float)((point[ii].getY()+y)/y/2);i++;
 }
 i=0;
 int[] faces = {0,0,1,1,2,2,2,2,3,3,0,0};
 TriangleMesh mesh = new TriangleMesh();
 mesh.getPoints().addAll( points );
 mesh.getTexCoords().addAll( texCoords );
 mesh.getFaces().addAll( faces );

広告


MeshViewの定義

定義したTriangleMeshをMeshViewに格納します。 画像を貼りつけなくても表示できますが、画像を貼りつける場合はPhongMaterialを作って追加します。

 MeshView meshView  = new MeshView();
 meshView.setMesh( mesh );
 meshView.setDrawMode( DrawMode.FILL );
 PhongMaterial material = new PhongMaterial();
 Image img = new Image("file:d:/work/java/maru.png");
 material.setDiffuseMap( img );
 meshView.setMaterial(material);


JavaFXMeshViewを表示するサンプルプログラム

作ったMeshViewを表示するプルグラムです。
実行結果
JavaFXMeshView

package tomojavalib.fx;

import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.*;
import javafx.scene.transform.*;
import javafx.stage.Stage;

/**単純なJavaFX楽天 プログラム
 *メッシュの作成
 * */
public class App17 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();
 //メッシュを置く
 this.makeMesh( group );
 //カメラを置く
 PerspectiveCamera camera = new PerspectiveCamera( true );
 // カメラ 楽天 方向と位置
 Translate cameratranslate = new Translate(0,0,-50);
 //Rotate camerarotateX = new Rotate( 30 , new Point3D( 1 , 0 , 0 ) );
 //Rotate camerarotateY = new Rotate( 30 , new Point3D( 0 , 1 , 0 ) );
 //camera.getTransforms().add( camerarotateX );
 //camera.getTransforms().add( camerarotateY );
 camera.getTransforms().add( cameratranslate ); 
 //視界の角度
 camera.setFieldOfView( 30. );
 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 );
return s3d;
}

/**meshViewを作成してグループに追加する*/
private void makeMesh( Group group ){
 double x = 5.;
 double y = 5.;
 double z = 0.;
 Point3D[] point = new Point3D[4];
 point[0] =new Point3D( -x , -y , z );
 point[1] =new Point3D( -x ,  y , z );
 point[2] =new Point3D(  x ,  y , z );
 point[3] =new Point3D(  x , -y , z );
 float[] points = new float[ point.length*3 ];
 int i=0;
 for(int ii=0;ii<point.length;ii++){
  points[i] = (float)point[ii].getX();i++;
  points[i] = (float)point[ii].getY();i++;
  points[i] = (float)point[ii].getZ();i++;
 }
 float[] texCoords = new float[ point.length*2 ];
 i=0;
 for(int ii=0;ii<point.length;ii++){
  texCoords[i] = (float)((point[ii].getX()+x)/x/2);i++;
  texCoords[i] = (float)((point[ii].getY()+y)/y/2);i++;
 }
 //i=0;
 int[] faces = {0,0,1,1,2,2,2,2,3,3,0,0};
 TriangleMesh mesh = new TriangleMesh();
 mesh.getPoints().addAll( points );
 mesh.getTexCoords().addAll( texCoords );
 mesh.getFaces().addAll( faces );
 MeshView meshView  = new MeshView();
 meshView.setMesh( mesh );
 meshView.setDrawMode( DrawMode.FILL );
 PhongMaterial material = new PhongMaterial();
 Image img = new Image("file:d:/work/java/maru2.png");
 material.setDiffuseMap( img );
 meshView.setMaterial(material);
 group.getChildren().add( meshView );
return;
}
}


テクスチャーの歪み対策

貼りつける画像と作成するメッシュの形状が異なる場合、画像が歪んでしまいます。
下の例では、長方形の画像を正方形のメッシュに貼りつけたため、円が楕円になってしまいました。
テクスチャ貼り付け画像 JavaFXメッシュ


正方形の画像を正方形のMeshViewに貼りつければ歪むことはありません。
サンプルプログラムのようにMeshを平面で作る場合であれば、Meshのx,y座標を縮尺してTexCoordsの座標とし、正方形の画像をあてはめれば、歪みを無くすことができます。
テクスチャ貼り付け画像 JavaFXMesh


繰り返し形状

TexCoordsの座標が0~1の範囲になければ、画像をタイル状に並べた表示となるので、市松模様や水玉模様など、同じ形が並ぶテクスチャーを作る場合、1つの模様の画像を用意するだけで済みます。

 変更前
  texCoords[i] = (float)((point[ii].getX()+x)/x/2.);i++;
  texCoords[i] = (float)((point[ii].getY()+y)/y/2.);i++;
 変更後
  texCoords[i] = (float)((point[ii].getX()+x)/2.);i++;
  texCoords[i] = (float)((point[ii].getY()+y)/2.);i++;

実行結果
変更前
JavaFXMesh

変更後
水玉模様

最終更新日: 2017-03-08 08:10:57

ともさんのHP >プロブラミング >JavaFX >MeshViewの扱いかた

広告
新着ページ

AIを利用し、衣服のデザイン画から型紙を制作する方法  
2つのアパレル3D技術でひらくオーダーメイド生産の手法  
【洋裁型紙】前後身頃の肩の傾きは何故前身頃の方が傾いているのか  
電子追尾式天体写真撮影法  
日本ミツバチ巣箱の種類  
ドラフター(製図台)でソーイング  
日本ミツバチが逃亡  
カメさんの箱庭  
天体用デジタルカメラの構造と天体写真  
Javaで静止画像(Jpeg)を動画(Mov)に変換  
USBカメラをJAVAで制御  

他のサイト

3D-CAD
洋裁CAD

いいねなど

 RSS 

Author: Tomoyuki Ito

このサイトの文章・写真の無断転載を禁じます