如何在JavaFX中将轴(三重轴)设置在屏幕上的固定位置?
如何在
JavaFX中将轴(三重轴)设置在屏幕上的固定位置?我目前正在开发一个应用程序,我想在屏幕上的固定位置(即左下角)显示轴(三重轴).我希望轴的旋转应该与主要对象同步.不应将缩放和平移操作应用于轴.
但是我在屏幕上的特定位置显示轴时遇到一些困难. 我已经使用screenToLocal方法获取场景中的固定位置,但它只返回Point2D对象,这对设置3D翻译值没有帮助. 你能帮我解决这个问题吗? 基于此example的源代码如下: 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,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); 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,0); mesh.getTexCoords().addAll(0,0); for(int i=1;i<=divisions;i++) { mesh.getFaces().addAll( 0,i+1,i,//COunter clock wise divisions+2,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,Rotate.X_AXIS); final Rotate ry = new Rotate(0,Rotate.Y_AXIS); final Rotate rz = new Rotate(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); 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); } } 在上面的代码中,首先我将屏幕的左下角平移了轴,但是在旋转主对象(即BOX和SPHERE)之后,轴也被平移.我想要围绕它们自己的原点旋转主对象和轴. 如果我尝试放大(更改了摄像机Z位置),那么I轴位置也会相对于屏幕发生变化. 在上面的例子中,我想在屏幕的左下角显示我的轴,并且轴的旋转应该与主对象同步. 解决方法
此变化使轴保持原点,将框移动到 P = (size / 2,-size / 2,-size / 2) 相对于轴,并将相机朝向屏幕中心的底部平移.取消注释对camera.setTranslateX()的调用以向左平移.移动鼠标会使组围绕轴的原点旋转.按shift键绕z旋转,然后用鼠标滚轮移动相机. 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 https://stackoverflow.com/a/37734966/230513 * @see https://stackoverflow.com/a/37714700/230513 * @see https://stackoverflow.com/a/37685167/230513 * @see https://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,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,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); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |