javaFX8初探(构建3D简单应用)

本章提供一个构建简单的javafX3D应用


准备:

 JDK8

 eclipse,安装有e(fx)clipse插件

创建项目

新建一个 javaFX项目,名称是MoleculeSampleApp

创建场景

创建一个分子结构的UI布局


1:创建一个Xform文件,代码如下:

[java]  view plain  copy
  1. package com.chu.shape3d;  
  2.   
  3. import javafx.scene.Group;  
  4. import javafx.scene.transform.Rotate;  
  5. import javafx.scene.transform.Scale;  
  6. import javafx.scene.transform.Translate;  
  7.   
  8. public class Xform extends Group {  
  9.   
  10.     public enum RotateOrder {  
  11.         XYZ, XZY, YXZ, YZX, ZXY, ZYX  
  12.     }  
  13.   
  14.     public Translate t = new Translate();  
  15.     public Translate p = new Translate();  
  16.     public Translate ip = new Translate();  
  17.       
  18.       
  19.     public Rotate rx = new Rotate();  
  20.     public Rotate ry = new Rotate();  
  21.     public Rotate rz = new Rotate();  
  22.       
  23.       
  24.     public Scale s = new Scale();  
  25.   
  26.     public Xform() {  
  27.         super();  
  28.         init();  
  29.         getTransforms().addAll(t, rz, ry, rx, s);  
  30.   
  31.     }  
  32.   
  33.     private void init() {  
  34.         rx.setAxis(Rotate.X_AXIS);  
  35.         ry.setAxis(Rotate.Y_AXIS);  
  36.         rz.setAxis(Rotate.Z_AXIS);  
  37.     }  
  38.   
  39.     public Xform(RotateOrder rotateOrder) {  
  40.         super();  
  41.         switch (rotateOrder) {  
  42.         case XYZ:  
  43.             getTransforms().addAll(t, p, rz, ry, rx, s, ip);  
  44.             break;  
  45.         case YXZ:  
  46.             getTransforms().addAll(t, p, rz, rx, ry, s, ip);  
  47.             break;  
  48.         case YZX:  
  49.             getTransforms().addAll(t, p, rx, rz, ry, s, ip); // For Camera  
  50.             break;  
  51.         case ZXY:  
  52.             getTransforms().addAll(t, p, ry, rx, rz, s, ip);  
  53.             break;  
  54.         case ZYX:  
  55.             getTransforms().addAll(t, p, rx, ry, rz, s, ip);  
  56.             break;  
  57.         default:  
  58.             break;  
  59.         }  
  60.   
  61.     }  
  62.   
  63.     public void setTranslate(double x, double y, double z) {  
  64.         t.setX(x);  
  65.         t.setY(y);  
  66.         t.setZ(z);  
  67.     }  
  68.   
  69.     public void setTranslate(double x, double y) {  
  70.         t.setX(x);  
  71.         t.setY(y);  
  72.     }  
  73.   
  74.     // Cannot override these methods as they are final:  
  75.     // public void setTranslateX(double x) { t.setX(x); }  
  76.     // public void setTranslateY(double y) { t.setY(y); }  
  77.     // public void setTranslateZ(double z) { t.setZ(z); }  
  78.     // Use these methods instead:  
  79.     public void setTx(double x) {  
  80.         t.setX(x);  
  81.     }  
  82.   
  83.     public void setTy(double y) {  
  84.         t.setY(y);  
  85.     }  
  86.   
  87.     public void setTz(double z) {  
  88.         t.setZ(z);  
  89.     }  
  90.   
  91.     public void setRotate(double x, double y, double z) {  
  92.         rx.setAngle(x);  
  93.         ry.setAngle(y);  
  94.         rz.setAngle(z);  
  95.     }  
  96.   
  97.     public void setRotateX(double x) {  
  98.         rx.setAngle(x);  
  99.     }  
  100.   
  101.     public void setRotateY(double y) {  
  102.         ry.setAngle(y);  
  103.     }  
  104.   
  105.     public void setRotateZ(double z) {  
  106.         rz.setAngle(z);  
  107.     }  
  108.   
  109.     public void setRy(double y) {  
  110.         ry.setAngle(y);  
  111.     }  
  112.   
  113.     public void setRz(double z) {  
  114.         rz.setAngle(z);  
  115.     }  
  116.   
  117.     public void setScale(double scaleFactor) {  
  118.         s.setX(scaleFactor);  
  119.         s.setY(scaleFactor);  
  120.         s.setZ(scaleFactor);  
  121.     }  
  122.   
  123.     // Cannot override these methods as they are final:  
  124.     // public void setScaleX(double x) { s.setX(x); }  
  125.     // public void setScaleY(double y) { s.setY(y); }  
  126.     // public void setScaleZ(double z) { s.setZ(z); }  
  127.     // Use these methods instead:  
  128.     public void setSx(double x) {  
  129.         s.setX(x);  
  130.     }  
  131.   
  132.     public void setSy(double y) {  
  133.         s.setY(y);  
  134.     }  
  135.   
  136.     public void setSz(double z) {  
  137.         s.setZ(z);  
  138.     }  
  139.   
  140.     public void setPivot(double x, double y, double z) {  
  141.         p.setX(x);  
  142.         p.setY(y);  
  143.         p.setZ(z);  
  144.         ip.setX(-x);  
  145.         ip.setY(-y);  
  146.         ip.setZ(-z);  
  147.     }  
  148.   
  149.     public void reset() {  
  150.         t.setX(0.0);  
  151.         t.setY(0.0);  
  152.         t.setZ(0.0);  
  153.         rx.setAngle(0.0);  
  154.         ry.setAngle(0.0);  
  155.         rz.setAngle(0.0);  
  156.         s.setX(1.0);  
  157.         s.setY(1.0);  
  158.         s.setZ(1.0);  
  159.         p.setX(0.0);  
  160.         p.setY(0.0);  
  161.         p.setZ(0.0);  
  162.         ip.setX(0.0);  
  163.         ip.setY(0.0);  
  164.         ip.setZ(0.0);  
  165.     }  
  166.   
  167.     public void resetTSP() {  
  168.         t.setX(0.0);  
  169.         t.setY(0.0);  
  170.         t.setZ(0.0);  
  171.         s.setX(1.0);  
  172.         s.setY(1.0);  
  173.         s.setZ(1.0);  
  174.         p.setX(0.0);  
  175.         p.setY(0.0);  
  176.         p.setZ(0.0);  
  177.         ip.setX(0.0);  
  178.         ip.setY(0.0);  
  179.         ip.setZ(0.0);  
  180.     }  
  181.   
  182.     public void debug() {  
  183.         System.out.println("t = (" + t.getX() + ", " + t.getY() + ", "  
  184.                 + t.getZ() + ")  " + "r = (" + rx.getAngle() + ", "  
  185.                 + ry.getAngle() + ", " + rz.getAngle() + ")  " + "s = ("  
  186.                 + s.getX() + ", " + s.getY() + ", " + s.getZ() + ")  "  
  187.                 + "p = (" + p.getX() + ", " + p.getY() + ", " + p.getZ()  
  188.                 + ")  " + "ip = (" + ip.getX() + ", " + ip.getY() + ", "  
  189.                 + ip.getZ() + ")");  
  190.     }  
  191. }  

这个文件包含了一个从Group类继承来的子类Xform,这个类可以用来阻止当组件的子节点改变的时候重新计算组的轴位置。Xform允许添加

自定义的变形和反转。这个文件包含了变形组件,三个翻转组件和一个范围组件。有3个翻转组件对于频繁的翻转值是有帮助的,比如改变

场。相机的角度:

2:打开MoleculeSampleApp ,为他添加以下代码:

[java]  view plain  copy
  1. public class MoleculeSampleApp extends Application {  
  2.    
  3.     final Group root = new Group();  
  4.     final Xform world = new Xform();  
  5.    
  6.     @Override  
  7.     public void start(Stage primaryStage) {  
  8.    
  9.         Scene scene = new Scene(root, 1024768true);  
  10.         scene.setFill(Color.GREY);  
  11.    
  12.         primaryStage.setTitle("Molecule Sample Application");  
  13.         primaryStage.setScene(scene);  
  14.         primaryStage.show();  
  15.    
  16.     }  
  17.    
  18.     /** 
  19.      * The main() method is ignored in correctly deployed JavaFX  
  20.      * application. main() serves only as fallback in case the  
  21.      * application can not be launched through deployment artifacts,  
  22.      * e.g., in IDEs with limited FX support. NetBeans ignores main(). 
  23.      * 
  24.      * @param args the command line arguments 
  25.      */  
  26.     public static void main(String[] args) {  
  27.         launch(args);  
  28.     }  
  29. }  


装配相机

1:

[java]  view plain  copy
  1. final Group root = new Group();  
  2.     final Xform world = new Xform();  
  3.     final PerspectiveCamera camera = new PerspectiveCamera(true);  
  4.     final Xform cameraXform = new Xform();  
  5.     final Xform cameraXform2 = new Xform();  
  6.     final Xform cameraXform3 = new Xform();  
  7.     private static final double CAMERA_INITIAL_DISTANCE = -450;  
  8.     private static final double CAMERA_INITIAL_X_ANGLE = 70.0;  
  9.     private static final double CAMERA_INITIAL_Y_ANGLE = 320.0;  
  10.     private static final double CAMERA_NEAR_CLIP = 0.1;  
  11.     private static final double CAMERA_FAR_CLIP = 10000.0;  


 

2:

[java]  view plain  copy
  1. private void buildCamera() {  
  2.         root.getChildren().add(cameraXform);  
  3.         cameraXform.getChildren().add(cameraXform2);  
  4.         cameraXform2.getChildren().add(cameraXform3);  
  5.         cameraXform3.getChildren().add(camera);  
  6.         cameraXform3.setRotateZ(180.0);  
  7.    
  8.         camera.setNearClip(CAMERA_NEAR_CLIP);  
  9.         camera.setFarClip(CAMERA_FAR_CLIP);  
  10.         camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);  
  11.         cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE);  
  12.         cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE);  
  13.     }  


 

3:

[java]  view plain  copy
  1. public void start(Stage primaryStage) {  
  2.   
  3.         buildCamera();  


4:

[java]  view plain  copy
  1. primaryStage.show();  
  2.         scene.setCamera(camera);  


 

创建轴线

每通常的惯例,x轴是红色所示,y轴所示绿色和蓝色的z轴。

1:

[java]  view plain  copy
  1. import javafx.scene.paint.PhongMaterial;  
  2. import javafx.scene.shape.Box;  

2:

[java]  view plain  copy
  1. private static final double AXIS_LENGTH = 250.0;  

3:

[java]  view plain  copy
  1. final Group root = new Group();  
  2. final Xform axisGroup = new Xform();  

4:

[java]  view plain  copy
  1. private void buildAxes() {  
  2.         final PhongMaterial redMaterial = new PhongMaterial();  
  3.         redMaterial.setDiffuseColor(Color.DARKRED);  
  4.         redMaterial.setSpecularColor(Color.RED);  
  5.    
  6.         final PhongMaterial greenMaterial = new PhongMaterial();  
  7.         greenMaterial.setDiffuseColor(Color.DARKGREEN);  
  8.         greenMaterial.setSpecularColor(Color.GREEN);  
  9.    
  10.         final PhongMaterial blueMaterial = new PhongMaterial();  
  11.         blueMaterial.setDiffuseColor(Color.DARKBLUE);  
  12.         blueMaterial.setSpecularColor(Color.BLUE);  
  13.    
  14.         final Box xAxis = new Box(AXIS_LENGTH, 11);  
  15.         final Box yAxis = new Box(1, AXIS_LENGTH, 1);  
  16.         final Box zAxis = new Box(11, AXIS_LENGTH);  
  17.           
  18.         xAxis.setMaterial(redMaterial);  
  19.         yAxis.setMaterial(greenMaterial);  
  20.         zAxis.setMaterial(blueMaterial);  
  21.    
  22.         axisGroup.getChildren().addAll(xAxis, yAxis, zAxis);  
  23.         axisGroup.setVisible(true);  
  24.         world.getChildren().addAll(axisGroup);  
  25.     }  


5:

[java]  view plain  copy
  1. root.getChildren().add(world);  
  2. buildCamera();  
  3. buildAxes();  


6:如下图:


创建分子

1:

[java]  view plain  copy
  1. final Xform axisGroup = new Xform();  
  2.  final Xform moleculeGroup = new Xform();  

2:

[java]  view plain  copy
  1. import javafx.scene.shape.Cylinder;  
  2.     import javafx.scene.shape.Sphere;  
  3.     import javafx.scene.transform.Rotate;  


3:

[java]  view plain  copy
  1. private static final double AXIS_LENGTH = 250.0;  
  2.     private static final double HYDROGEN_ANGLE = 104.5;  


4:

[java]  view plain  copy
  1. private void buildMolecule() {  
  2.    
  3.        final PhongMaterial redMaterial = new PhongMaterial();  
  4.        redMaterial.setDiffuseColor(Color.DARKRED);  
  5.        redMaterial.setSpecularColor(Color.RED);  
  6.    
  7.        final PhongMaterial whiteMaterial = new PhongMaterial();  
  8.        whiteMaterial.setDiffuseColor(Color.WHITE);  
  9.        whiteMaterial.setSpecularColor(Color.LIGHTBLUE);  
  10.    
  11.        final PhongMaterial greyMaterial = new PhongMaterial();  
  12.        greyMaterial.setDiffuseColor(Color.DARKGREY);  
  13.        greyMaterial.setSpecularColor(Color.GREY);  
  14.    
  15.        // Molecule Hierarchy  
  16.        // [*] moleculeXform  
  17.        //     [*] oxygenXform  
  18.        //         [*] oxygenSphere  
  19.        //     [*] hydrogen1SideXform  
  20.        //         [*] hydrogen1Xform  
  21.        //             [*] hydrogen1Sphere  
  22.        //         [*] bond1Cylinder  
  23.        //     [*] hydrogen2SideXform  
  24.        //         [*] hydrogen2Xform  
  25.        //             [*] hydrogen2Sphere  
  26.        //         [*] bond2Cylinder  
  27.    
  28.        Xform moleculeXform = new Xform();  
  29.        Xform oxygenXform = new Xform();  
  30.        Xform hydrogen1SideXform = new Xform();  
  31.        Xform hydrogen1Xform = new Xform();  
  32.        Xform hydrogen2SideXform = new Xform();  
  33.        Xform hydrogen2Xform = new Xform();  
  34.   
  35.       Sphere oxygenSphere = new Sphere(40.0);  
  36.       oxygenSphere.setMaterial(redMaterial);  
  37.   
  38.       Sphere hydrogen1Sphere = new Sphere(30.0);  
  39.       hydrogen1Sphere.setMaterial(whiteMaterial);  
  40.       hydrogen1Sphere.setTranslateX(0.0);  
  41.   
  42.       Sphere hydrogen2Sphere = new Sphere(30.0);  
  43.       hydrogen2Sphere.setMaterial(whiteMaterial);  
  44.       hydrogen2Sphere.setTranslateZ(0.0);  
  45.   
  46.       Cylinder bond1Cylinder = new Cylinder(5100);  
  47.       bond1Cylinder.setMaterial(greyMaterial);  
  48.       bond1Cylinder.setTranslateX(50.0);  
  49.       bond1Cylinder.setRotationAxis(Rotate.Z_AXIS);  
  50.       bond2Cylinder.setRotate(90.0);  
  51.   
  52.       Cylinder bond1Cylinder = new Cylinder(5100);  
  53.       bond2Cylinder.setMaterial(greyMaterial);  
  54.       bond2Cylinder.setTranslateX(50.0);  
  55.       bond2Cylinder.setRotationAxis(Rotate.Z_AXIS);  
  56.       bond2Cylinder.setRotate(90.0);  
  57.   
  58.       moleculeXform.getChildren().add(oxygenXform);  
  59.       moleculeXform.getChildren().add(hydrogen1SideXform);  
  60.       moleculeXform.getChildren().add(hydrogen2SideXform);  
  61.       oxygenXform.getChildren().add(oxygenSphere);  
  62.       hydrogen1SideXform.getChildren().add(hydrogen1Xform);  
  63.       hydrogen2SideXform.getChildren().add(hydrogen2Xform);  
  64.       hydrogen1Xform.getChildren().add(hydrogen1Sphere);  
  65.       hydrogen2Xform.getChildren().add(hydrogen2Sphere);  
  66.       hydrogen1SideXform.getChildren().add(bond1Cylinder);  
  67.       hydrogen2SideXform.getChildren().add(bond2Cylinder);  
  68.    
  69.       hydrogen1Xform.setTx(100.0);  
  70.       hydrogen2Xform.setTx(100.0);  
  71.       hydrogen2SideXform.setRotateY(HYDROGEN_ANGLE);  
  72.   
  73.       moleculeGroup.getChildren().add(moleculeXform);  
  74.   
  75.       world.getChildren().addAll(moleculeGroup);  
  76. }  


5:

[java]  view plain  copy
  1. buildCamera();  
  2. buildAxes();  
  3. buildMolecule();  


6:

[java]  view plain  copy
  1. axisGroup.setVisible(false);  


运行如下:


添加照相机查看控制

1:

[java]  view plain  copy
  1. private static final double CONTROL_MULTIPLIER = 0.1;      
  2. private static final double SHIFT_MULTIPLIER = 10.0;      
  3. private static final double MOUSE_SPEED = 0.1;      
  4. private static final double ROTATION_SPEED = 2.0;     
  5.  private static final double TRACK_SPEED = 0.3;  
  6.           
  7.     double mousePosX;  
  8.     double mousePosY;  
  9.     double mouseOldX;  
  10.     double mouseOldY;  
  11.     double mouseDeltaX;  
  12.     double mouseDeltaY;  

2:

[java]  view plain  copy
  1. 增加handleMouse 和 handleKeyboard方法  
  2.   
  3. private void handleMouse(Scene scene, final Node root) {  
  4.         scene.setOnMousePressed(new EventHandler<MouseEvent>() {  
  5.             @Override  
  6.             public void handle(MouseEvent me) {  
  7.                 mousePosX = me.getSceneX();  
  8.                 mousePosY = me.getSceneY();  
  9.                 mouseOldX = me.getSceneX();  
  10.                 mouseOldY = me.getSceneY();  
  11.             }  
  12.         });  
  13.         scene.setOnMouseDragged(new EventHandler<MouseEvent>() {  
  14.             @Override  
  15.             public void handle(MouseEvent me) {  
  16.                 mouseOldX = mousePosX;  
  17.                 mouseOldY = mousePosY;  
  18.                 mousePosX = me.getSceneX();  
  19.                 mousePosY = me.getSceneY();  
  20.                 mouseDeltaX = (mousePosX - mouseOldX);  
  21.                 mouseDeltaY = (mousePosY - mouseOldY);  
  22.   
  23.                 double modifier = 1.0;  
  24.   
  25.                 if (me.isControlDown()) {  
  26.                     modifier = CONTROL_MULTIPLIER;  
  27.                 }  
  28.                 if (me.isShiftDown()) {  
  29.                     modifier = SHIFT_MULTIPLIER;  
  30.                 }  
  31.                 if (me.isPrimaryButtonDown()) {  
  32.                     cameraXform.ry.setAngle(cameraXform.ry.getAngle()  
  33.                             - mouseDeltaX * MOUSE_SPEED * modifier  
  34.                             * ROTATION_SPEED);  
  35.                     cameraXform.rx.setAngle(cameraXform.rx.getAngle()  
  36.                             + mouseDeltaY * MOUSE_SPEED * modifier  
  37.                             * ROTATION_SPEED);  
  38.                 } else if (me.isSecondaryButtonDown()) {  
  39.                     double z = camera.getTranslateZ();  
  40.                     double newZ = z + mouseDeltaX * MOUSE_SPEED * modifier;  
  41.                     camera.setTranslateZ(newZ);  
  42.                 } else if (me.isMiddleButtonDown()) {  
  43.                     cameraXform2.t.setX(cameraXform2.t.getX() + mouseDeltaX  
  44.                             * MOUSE_SPEED * modifier * TRACK_SPEED);  
  45.                     cameraXform2.t.setY(cameraXform2.t.getY() + mouseDeltaY  
  46.                             * MOUSE_SPEED * modifier * TRACK_SPEED);  
  47.                 }  
  48.             }  
  49.         });  
  50.     }  
  51.   
  52.     private void handleKeyboard(Scene scene, final Node root) {  
  53.         scene.setOnKeyPressed(new EventHandler<KeyEvent>() {  
  54.             @Override  
  55.             public void handle(KeyEvent event) {  
  56.                 switch (event.getCode()) {  
  57.                 case Z:  
  58.                     cameraXform2.t.setX(0.0);  
  59.                     cameraXform2.t.setY(0.0);  
  60.                     camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);  
  61.                     cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE);  
  62.                     cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE);  
  63.                     break;  
  64.                 case X:  
  65.                     axisGroup.setVisible(!axisGroup.isVisible());  
  66.                     break;  
  67.                 case V:  
  68.                     moleculeGroup.setVisible(!moleculeGroup.isVisible());  
  69.                     break;  
  70.                 }  
  71.             }  
  72.         });  
  73.     }  


 

3:

ctrl + z :返回初始位置
ctrl + v:隐藏分子视图
ctrl+x:显示坐标

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值