JavaFX TriangleMeshを生成するClass
平面で四角形のJavaFX TriangleMeshを生成するサンプルプログラムの紹介です。
アニメーションのしかたを紹介する他のページで使っています。
このページではClassの構造を紹介します。
TriangleMeshの作り方はこちらを参照ください。
こんな3Dオブジェクトができます。
応用でこんな形にも変形できます。
MeshViewを作成するClass、FlatMesh
コンストラクタ FlatMesh(double px,double py, int x,int y,double s) で、X方向にpx間隔でx-1分割、Y方向にpy間隔でy-1分割、z座標0の四角で平坦なTriangleMeshを定義します。
このあと、getTriangleMesh()で、生成されたTriangleMeshを受け取ることができます。
アニメーションをするときには、TriangleMeshを構成する点pを取り出して座標を変えます。
TriangleMesh作成の手順
まず点と三角形のClassを用意します。
Point3CtはPoint3Dを拡張したもので、点番号を追加しています。
package tomojavalib.fx;
import javafx.geometry.Point3D;
public class Point3Dt extends Point3D {
public int no =0;
public Point3Dt(double x, double y, double z,int i) {
super(x, y, z);
no = I;
}
}
Triangleは三角形を構成する3つのPoint3Dtを格納します。
package tomojavalib.fx;
public class Triangle {
public Point3Dt[] p = new Point3Dt[3];
public Triangle( Point3Dt p1 , Point3Dt p2 , Point3Dt p3 ){
p[0]=p1; p[1]=p2;p[2]=p3;
}
}
点を格子状に並べて作ります。3角形は、3つの点を定義することで配置します。
点は x * y 個
三角形は( x-1 )*( y-1 ) * 2 個作り、下の図のように並べます。
点
三角形
三角形に点を割り当てるには、下の図のように半時計まわりに3点を割り当てます。反時計回りだと、三角形に貼りつけられる面のの表が正面側になります。
図では三角形番号40と81を構成する番号を赤字で示しています。
また、3角点は、構成点pのシャローコピー(Shallow Copy)で作っておきます。こうすると、構成点を変えるだけで三角形の3点も変更することができます。
n =0;
for(int ii=0;ii<y-1;ii++){
for(int i=0;i<x-1;i++){
int p1 = x*ii+I;
int p3 = p1+1;
int p2 = x*(ii+1)+I;
t[n] = new Triangle( p[p1] , p[p2] , p[p3] );
n++;
p1 = x*ii+i+1;
p2 = x*(ii+1)+I;
p3 = p2+1;
t[n] = new Triangle( p[p1] , p[p2] , p[p3] );
n++;
}
}
TriangleMesh構成データの作成
TriangleMeshを作るには、構成点の3次元座標を入れるPoints、テクスチャ貼り付けの2次元座標を入れるTexCoords、三角形を構成する点番号を入れるFacesの三つが必要です。
Pointは3次元点pの座標をそのまま入れます。
TexCoordsにはpのz座標を除いたものに、コンストラクタで入力したスケールを掛けたものを入れます。
Facesには、Point3Dtの番号をしめすnoを入れてゆきます。
平面で四角形のTriangleMeshを生成するサンプルプログラム
出来たコードが以下です。
package tomojavalib.fx;
import javafx.scene.shape.TriangleMesh;
/**平面、四角形のTriangleMeshを作成するclass*/
public class FlatMesh {
public Triangle[] t = null;
public Point3Dt[] p = null;
private double scale = 1.;
/**
* 新規メッシュの作成
*/
public FlatMesh(double px,double py, int x,int y,double s){
scale =s;
//点と3角形の準備
int nos = (int)( x * y );
p = new Point3Dt[ nos ];
nos =(int)( x-1 )*( y-1 ) * 2;
t = new Triangle[ nos ];
//点を作成
int n =0;
for(int ii=0;ii<y;ii++){
for(int i=0;i<x;i++){
double ax = px*i ;
double ay = py*ii ;
p[n] = new Point3Dt( ax , ay , 0. , n );
n++;
}
}
//三角形を生成
n =0;
for(int ii=0;ii<y-1;ii++){
for(int i=0;i<x-1;i++){
int p1 = x*ii+I;
int p3 = p1+1;
int p2 = x*(ii+1)+I;
t[n] = new Triangle( p[p1] , p[p2] , p[p3] );
n++;
p1 = x*ii+i+1;
p2 = x*(ii+1)+I;
p3 = p2+1;
t[n] = new Triangle( p[p1] , p[p2] , p[p3] );
n++;
}
}
return;
}
/**3角形の構成情報を返す*/
public int[] getFaces(){
int[] faces = new int[ t.length *3*2 ];
int ii=0;
for(int i=0;i<t.length;i++){
faces[ii] = t[i].p[0].no;ii++;
faces[ii] = t[i].p[0].no;ii++;
faces[ii] = t[i].p[1].no;ii++;
faces[ii] = t[i].p[1].no;ii++;
faces[ii] = t[i].p[2].no;ii++;
faces[ii] = t[i].p[2].no;ii++;
}
return faces;
}
/**テクスチャ用の座標を返す*/
public float[] getTexCoords(){
float[] texCoords = new float[ p.length*2 ];
int i=0;
for(int ii=0;ii<p.length;ii++){
texCoords[i] = (float)( p[ii].getX() * scale );i++;
texCoords[i] = (float)( p[ii].getY() * scale );i++;
}
return texCoords;
}
/**構成する3次元点を返す*/
public float[] getPoints(){
float[] points = new float[ p.length*3 ];
int pi=0;
for(int ii=0;ii<p.length;ii++){
points[pi] =(float)this.p[ii].getX(); pi++;
points[pi] =(float)this.p[ii].getY(); pi++;
points[pi] =(float)this.p[ii].getZ(); pi++;
}
return points;
}
/**TriangleMeshを返す*/
public TriangleMesh getTriangleMesh(){
TriangleMesh mesh = new TriangleMesh();
mesh.getPoints().addAll( this.getPoints() );
mesh.getTexCoords().addAll( this.getTexCoords() );
mesh.getFaces().addAll( this.getFaces() );
return mesh;
}
}
メッシュを表示するためのサンプルプログラム
下は生成したメッシュを表示するコードです。
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.Box;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.*;
import javafx.stage.Stage;
/**単純なJavaFX楽天 プログラム
*フラットメッシュを作成して表示
* */
public class App18 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();
//メッシュを置く
FlatMesh fm = new FlatMesh( 5 , 5 , 20 , 20 , .01 );
MeshView meshView = new MeshView();
meshView.setMesh( fm.getTriangleMesh() );
meshView.setDrawMode( DrawMode.FILL);
PhongMaterial material = new PhongMaterial();
Image img = new Image("file:d:/work/java/2.png");
material.setDiffuseMap( img );
meshView.setMaterial(material);
meshView.setCullFace(CullFace.NONE);
group.getChildren().add( meshView );
// カメラを置く
PerspectiveCamera camera = new PerspectiveCamera( true );
//方向と位置
Translate cameratranslate = new Translate(50,50,-550);
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.setFarClip( 1000. );
//視界の角度
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;
}
}
応用
点の座標を定義するさいに三角関数を使うなどすれば、円筒や壺型のメッシュを作ることができます。
この場合、テクスチャの座標がおかしくなってしまうので、別途作成する必要があります。
double ax = Math.sin( (i/(double)x)*2.*Math.PI )*Math.cos( (ii/(double)y)*.5*Math.PI )*50.;
double az = Math.cos( (i/(double)x)*2.*Math.PI )*Math.cos( (ii/(double)y)*.5*Math.PI )*50.;
double ay = ii*5;
p[n] = new Point3Dt( ax , ay , az , n );
最終更新日: 2017-03-10 17:52:28