设置在屏幕上的固定位置

设置在屏幕上的固定位置

本文介绍了如何在JavaFX中将轴(三重轴)设置在屏幕上的固定位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在JavaFX中将轴(三重轴)设置在屏幕上的固定位置?我目前正在开发一个应用程序,我想在屏幕上的固定位置(即左下角)显示轴(三重轴)。我想要旋转轴应该与主要对象同步。缩放和平移操作不应该应用于轴。



但是我在屏幕上的特定位置显示轴时遇到一些困难。



我使用screenToLocal方法获取场景中的固定位置,但它只返回Point2D对象,这对设置3D翻译值没有帮助。



你能不能请给我解决这个问题的方法吗?



基于此的源代码

  import javafx.application.Application; 
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

/ **
* @see http://stackoverflow.com/a/37734966/230513
* @see http://stackoverflow.com/a/37714700/ 230513
* @see http://stackoverflow.com/a/37685167/230513
* @see http://stackoverflow.com/a/37370840/230513
* /
公共类TriadBox扩展Application {

private static final SIZE = 300;
private final内容content = Content.create(SIZE);

private static final class Content {

private static final double WIDTH = 3;
private final Group group = new Group();
private final旋转rx = new旋转(0,Rotate.X_AXIS);
private final旋转ry = new Rotate(0,Rotate.Y_AXIS);
private final旋转rz = new旋转(0,旋转.Z_AXIS);
私人决赛Box xAxis;
私人决赛Box yAxis;
私人决赛Box zAxis;
私人决赛盒子;

private static内容创建(双倍大小){
内容c =新内容(大小);
c.group.getChildren()。addAll(c.box,c.xAxis,c.yAxis,c.zAxis);
c.group.getTransforms()。addAll(c.rz,c.ry,c.rx);
返回c;
}

私人内容(双倍大小){
xAxis = createBox(size * 2,WIDTH,WIDTH);
yAxis = createBox(WIDTH,size * 2,WIDTH);
zAxis = createBox(WIDTH,WIDTH,size * 2);
双边= 3 *尺寸/ 4;
box = new Box(边缘,边缘,边缘);
box.setMaterial(new PhongMaterial(Color.CORAL));
box.setTranslateX(size / 2);
box.setTranslateY(-size / 2);
box.setTranslateZ(-size / 2);
}

私人Box createBox(双w,双h,双d){
方框b =新方框(w,h,d);
b.setMaterial(new PhongMaterial(Color.AQUA));
返回b;
}
}

@Override
public void start(Stage primaryStage)抛出异常{
primaryStage.setTitle(JavaFX 3D);
场景场景=新场景(content.group,SIZE * 2,SIZE * 2,true);
primaryStage.setScene(scene);
scene.setFill(Color.BLACK);
scene.setOnMouseMoved((final MouseEvent e) - > {
if(e.isShiftDown()){
content.rz.setAngle(e.getSceneX()* 360 / scene。 getWidth());
} else {
content.rx.setAngle(e.getSceneY()* 360 / scene.getHeight());
content.ry.setAngle(e.getSceneX ()* 360 / scene.getWidth());
}
});
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setFarClip(SIZE * 6);
//camera.setTranslateX(SIZE / 2);
camera.setTranslateY(-SIZE / 2);
camera.setTranslateZ(-4.5 * SIZE);
scene.setCamera(相机);
scene.setOnScroll((final ScrollEvent e) - > {
camera.setTranslateZ(camera.getTranslateZ()+ e.getDeltaY());
});
primaryStage.show();
}

public static void main(String [] args){
launch(args);
}
}


How to set axis (triad) at fixed position on screen in JavaFX? I am currently developing one application in which I want to show axis (triad) at fixed position on my screen (i.e. bottom-left corner). I want rotation of axis should be in sync with the main object. Zoom and Translate operation should not be applied to axis.

But I am facing some difficulties to show axis at specific position on screen.

I have used screenToLocal method to get fixed position in scene but it only returns Point2D object which is not helpful to set 3D translate values.

Can you please give me solution for this problem?

Source code based on this example is as below:

import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.geometry.BoundingBox;
    import javafx.geometry.Bounds;
    import javafx.geometry.Point2D;
    import javafx.geometry.Point3D;
    import javafx.scene.DepthTest;
    import javafx.scene.Group;
    import javafx.scene.PerspectiveCamera;
    import javafx.scene.Scene;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.input.ScrollEvent;
    import javafx.scene.paint.Color;
    import javafx.scene.paint.Material;
    import javafx.scene.paint.PhongMaterial;
    import javafx.scene.shape.Box;
    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.Transform;
    import javafx.scene.transform.Translate;
    import javafx.stage.Stage;


    public class TrafoTest extends Application {
        final Group root = new Group();
        Group axis = new Group();
        final XformWorld world = new XformWorld();
        final PerspectiveCamera camera = new PerspectiveCamera(true);
        final XformCamera cameraXform = new XformCamera();
        final XformCamera cameraXform2 = new XformCamera();
        final XformCamera cameraXform3 = new XformCamera();
        private static final double CAMERA_INITIAL_DISTANCE = -1000;
        private static final double CAMERA_NEAR_CLIP = 0.1;
        private static final double CAMERA_FAR_CLIP = 10000.0;
        private static final double MOUSE_SPEED = 1;
        private static final double ROTATION_SPEED = 4.0;
        private static final double TRACK_SPEED = 0.02;
        double mousePosX, mousePosY, mouseOldX, mouseOldY, mouseDeltaX, mouseDeltaY;
        double mouseFactorX, mouseFactorY;
        Stage stage;


        @Override
        public void start(Stage primaryStage) {
            root.getChildren().add(world);
            root.setDepthTest(DepthTest.ENABLE);
            buildCamera();
            buildBodySystem();
            Scene scene = new Scene(root, 800, 600, true);
            scene.setFill(Color.GREY);
            handleMouse(scene);
            this.stage = primaryStage;
            primaryStage.setTitle("TrafoTest");
            primaryStage.setScene(scene);
            primaryStage.show();
            scene.setCamera(camera);

            mouseFactorX = 180.0 / scene.getWidth();
            mouseFactorY = 180.0 / scene.getHeight();
        }

        private void buildCamera() {
            root.getChildren().add(cameraXform);
            cameraXform.getChildren().add(cameraXform2);
            cameraXform2.getChildren().add(cameraXform3);
            cameraXform3.getChildren().add(camera);
            camera.setNearClip(CAMERA_NEAR_CLIP);
            camera.setFarClip(CAMERA_FAR_CLIP);
            camera.setTranslateZ(CAMERA_INITIAL_DISTANCE);
        }

        private void buildBodySystem() {
            PhongMaterial whiteMaterial = new PhongMaterial();
            whiteMaterial.setDiffuseColor(Color.WHITE);
            whiteMaterial.setSpecularColor(Color.LIGHTBLUE);
            Box box = new Box(400, 200, 100);
            box.setMaterial(whiteMaterial);
            box.setDrawMode(DrawMode.LINE);
            PhongMaterial redMaterial = new PhongMaterial();
            redMaterial.setDiffuseColor(Color.DARKRED);
            redMaterial.setSpecularColor(Color.RED);
            Sphere sphere = new Sphere(5);
            sphere.setMaterial(redMaterial);
            sphere.setTranslateX(200.0);
            sphere.setTranslateY(-100.0);
            sphere.setTranslateZ(-50.0);
            axis = drawReferenceFrame();
            world.getChildren().addAll(axis);
            world.getChildren().add(box);
            world.getChildren().addAll(sphere);
        }

        private void handleMouse(Scene scene) {
            scene.setOnMousePressed((MouseEvent me) -> {
                mousePosX = me.getSceneX();
                mousePosY = me.getSceneY();
                mouseOldX = me.getSceneX();
                mouseOldY = me.getSceneY();
            });
            scene.setOnMouseDragged((MouseEvent me) -> {
                mouseOldX = mousePosX;
                mouseOldY = mousePosY;
                mousePosX = me.getSceneX();
                mousePosY = me.getSceneY();
                mouseDeltaX = (mousePosX - mouseOldX);
                mouseDeltaY = (mousePosY - mouseOldY);
                if (me.isPrimaryButtonDown()) {
                    cameraXform.ry(mouseDeltaX * 180.0 / scene.getWidth());
                    cameraXform.rx(-mouseDeltaY * 180.0 / scene.getHeight());

                    BoundingBox point = (BoundingBox) root.screenToLocal(new BoundingBox(root.getLayoutX()+350, root.getLayoutY()+650, 0, 0,0, 20));
                    System.out.println(point);

                    axis.setTranslateX(point.getMinX());
                    axis.setTranslateY(point.getMinY());
                    axis.setTranslateZ(point.getMinZ());
                } else if (me.isSecondaryButtonDown()) {
                    cameraXform2.setTx((cameraXform2.t.getX() + (-mouseDeltaX)*MOUSE_SPEED*TRACK_SPEED));
                    cameraXform2.setTy((cameraXform2.t.getY() + (-mouseDeltaY)*MOUSE_SPEED*TRACK_SPEED));

                    camera.setTranslateZ(camera.getTranslateZ() + mouseDeltaY);
                }
            });

            scene.setOnScroll(new EventHandler<ScrollEvent>() {

                @Override
                public void handle(ScrollEvent event) {
                    double z = cameraXform3.getTranslateZ();
                    double newZ = z - event.getDeltaY() * MOUSE_SPEED * 0.05;
                    cameraXform3.setTranslateZ(newZ);
                }

            });
        }

        public static void main(String[] args) {
            launch(args);
        }


        private  Group drawReferenceFrame(){
            Group G1= new Group();

            Cylinder CX = new  Cylinder(2,25);
            Cylinder CY = new  Cylinder(2,25);
            Cylinder CZ = new  Cylinder(2,25);
            Sphere S = new Sphere(4);



            Material mat =new PhongMaterial(Color.WHITE);
            PhongMaterial Xmat = new PhongMaterial();
            Xmat.setDiffuseColor(Color.GREEN);
            PhongMaterial Ymat = new PhongMaterial();
            Ymat.setDiffuseColor(Color.BLUE);
            PhongMaterial Zmat = new PhongMaterial();
            Zmat.setDiffuseColor(Color.RED);

            S.setMaterial(Zmat);
            CY.setMaterial(mat);
    //      CY.setRotationAxis(Rotate.X_AXIS);

    //      CY.setRotate(90);
            CY.setTranslateY(-12.5);

            CX.setMaterial(mat);
            CX.setTranslateX(15);
            CX.setRotationAxis(Rotate.Z_AXIS);

            CX.setRotate(90);

            CZ.setMaterial(mat);
            CZ.setRotationAxis(Rotate.X_AXIS);
            CZ.setRotate(90);
            CZ.setTranslateZ(-12.5);
            G1.getChildren().addAll(CX,CY,CZ,S);

            TriangleMesh coneMeshY = createCone(3.5f, 7.5f);
            TriangleMesh coneMeshX = createCone(3.5f, 7.5f);
            TriangleMesh coneMeshZ = createCone(3.5f, 7.5f);
            MeshView yCone = new MeshView(coneMeshY);
            MeshView xCone = new MeshView(coneMeshX);
            MeshView zCone = new MeshView(coneMeshZ);
            yCone.setMaterial(Ymat);
            yCone.setTranslateY(-32.5);
            yCone.setDrawMode(DrawMode.FILL);

            xCone.setMaterial(Xmat);
            xCone.setTranslateY(-3.75);
            xCone.setRotationAxis(Rotate.Z_AXIS);
            xCone.setRotate(90);
            xCone.setTranslateX(28.5);
            xCone.setDrawMode(DrawMode.FILL);

            zCone.setRotationAxis(Rotate.X_AXIS);
            zCone.setTranslateY(-3.75);
            zCone.setRotate(90);
            zCone.setTranslateZ(-28.5);
            zCone.setDrawMode(DrawMode.FILL);
            zCone.setMaterial(Zmat);

            G1.getChildren().addAll(xCone,yCone,zCone);
    //      G1.setScale(0.45);
            return G1;
        }

        private TriangleMesh createCone( float radius, float height) {
            int divisions=500;
            TriangleMesh mesh = new TriangleMesh();
            mesh.getPoints().addAll(0,0,0);
            double segment_angle = 2.0 * Math.PI / divisions;
            float x, z;
            double angle;
            double halfCount = (Math.PI / 2 - Math.PI / (divisions / 2));
            for(int i=divisions+1;--i >= 0; ) {
                angle = segment_angle * i;
                x = (float)(radius * Math.cos(angle - halfCount));
                z = (float)(radius * Math.sin(angle - halfCount));
                mesh.getPoints().addAll(x,height,z);
            }
            mesh.getPoints().addAll(0,height,0);


            mesh.getTexCoords().addAll(0,0);

            for(int i=1;i<=divisions;i++) {
                mesh.getFaces().addAll(
                    0,0,i+1,0,i,0,           //COunter clock wise
                    divisions+2,0,i,0,i+1,0   // Clock wise
                );
            }
            return mesh;
        }
    }

    class XformWorld extends Group {
        final Translate t = new Translate(0.0, 0.0, 0.0);
        final Rotate rx = new Rotate(0, 0, 0, 0, Rotate.X_AXIS);
        final Rotate ry = new Rotate(0, 0, 0, 0, Rotate.Y_AXIS);
        final Rotate rz = new Rotate(0, 0, 0, 0, Rotate.Z_AXIS);

        public XformWorld() {
            super();
            this.getTransforms().addAll(t, rx, ry, rz);
        }
    }

    class XformCamera extends Group {
        Point3D px = new Point3D(1.0, 0.0, 0.0);
        Point3D py = new Point3D(0.0, 1.0, 0.0);
        Rotate r;
        Transform tx = new Rotate();
        Translate t = new Translate();
        public XformCamera() {
            super();
        }

        public void rx(double angle) {
            r = new Rotate(angle, px);
            this.tx = tx.createConcatenation(r);
            this.getTransforms().clear();
            this.getTransforms().addAll(tx);
        }

        public void ry(double angle) {
            r = new Rotate(angle, py);
            this.tx = tx.createConcatenation(r);
            this.getTransforms().clear();
            this.getTransforms().addAll(tx);
        }

        public void setTx(double x) {
            t.setX(x);
            this.getTransforms().clear();
            this.getTransforms().addAll(t);
        }

        public void setTy(double y) {
            t.setY(y);
            this.getTransforms().clear();
            this.getTransforms().addAll(t);
        }
    }

In above code, first I have translated the axis at left-bottom corner of my screen, but after rotating the main object (ie. BOX and SPHERE), axis is also translated.I wanted to rotate main object and axis about their own origins.

If I tried to zoom in (changed camera Z position), then also I axis location changed with respect to screen.

In above cases, I wanted to display my axis at left-bottom corner of the screen and Rotation of the axis should be in sync with the main object.

解决方案

This variation leaves the axes at the origin, moves the box to

P = (size / 2, -size / 2, -size / 2)

relative to the axes, and pans the camera toward the bottom, center of the screen. Uncomment the call to camera.setTranslateX() to pan left. Moving the mouse causes the group to rotate about the axes' origin. Press to rotate about z, and use the mouse wheel to dolly the camera.

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

/**
 * @see http://stackoverflow.com/a/37734966/230513
 * @see http://stackoverflow.com/a/37714700/230513
 * @see http://stackoverflow.com/a/37685167/230513
 * @see http://stackoverflow.com/a/37370840/230513
 */
public class TriadBox extends Application {

    private static final double SIZE = 300;
    private final Content content = Content.create(SIZE);

    private static final class Content {

        private static final double WIDTH = 3;
        private final Group group = new Group();
        private final Rotate rx = new Rotate(0, Rotate.X_AXIS);
        private final Rotate ry = new Rotate(0, Rotate.Y_AXIS);
        private final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
        private final Box xAxis;
        private final Box yAxis;
        private final Box zAxis;
        private final Box box;

        private static Content create(double size) {
            Content c = new Content(size);
            c.group.getChildren().addAll(c.box, c.xAxis, c.yAxis, c.zAxis);
            c.group.getTransforms().addAll(c.rz, c.ry, c.rx);
            return c;
        }

        private Content(double size) {
            xAxis = createBox(size * 2, WIDTH, WIDTH);
            yAxis = createBox(WIDTH, size * 2, WIDTH);
            zAxis = createBox(WIDTH, WIDTH, size * 2);
            double edge = 3 * size / 4;
            box = new Box(edge, edge, edge);
            box.setMaterial(new PhongMaterial(Color.CORAL));
            box.setTranslateX(size / 2);
            box.setTranslateY(-size / 2);
            box.setTranslateZ(-size / 2);
        }

        private Box createBox(double w, double h, double d) {
            Box b = new Box(w, h, d);
            b.setMaterial(new PhongMaterial(Color.AQUA));
            return b;
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("JavaFX 3D");
        Scene scene = new Scene(content.group, SIZE * 2, SIZE * 2, true);
        primaryStage.setScene(scene);
        scene.setFill(Color.BLACK);
        scene.setOnMouseMoved((final MouseEvent e) -> {
            if (e.isShiftDown()) {
                content.rz.setAngle(e.getSceneX() * 360 / scene.getWidth());
            } else {
                content.rx.setAngle(e.getSceneY() * 360 / scene.getHeight());
                content.ry.setAngle(e.getSceneX() * 360 / scene.getWidth());
            }
        });
        PerspectiveCamera camera = new PerspectiveCamera(true);
        camera.setFarClip(SIZE * 6);
        //camera.setTranslateX(SIZE / 2);
        camera.setTranslateY(-SIZE / 2);
        camera.setTranslateZ(-4.5 * SIZE);
        scene.setCamera(camera);
        scene.setOnScroll((final ScrollEvent e) -> {
            camera.setTranslateZ(camera.getTranslateZ() + e.getDeltaY());
        });
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这篇关于如何在JavaFX中将轴(三重轴)设置在屏幕上的固定位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 04:39