JavaFX中2D鼠标坐标转3D坐标的实现异常问题排查
JavaFX SubScene中2D鼠标转3D坐标的CameraHelper.pickProjectPlane问题
我要做一个简易3D三角形创建器,需要把SubScene上的2D鼠标点击位置转换成3D坐标。试了内部类CameraHelper.pickProjectPlane(camera, x, y)方法,但转出来的坐标值太大,没法在点击位置正确渲染Box。测试发现把fixedEyeAtCameraZero设为false时Z值正常,但这会搞坏整个相机的原有实现——文档明确说移动相机时这个参数得设为true。
问题原因
CameraHelper是内部类,它的pickProjectPlane方法计算坐标时默认基于主Scene的空间,完全忽略了SubScene的视口缩放、位置偏移这些因素,直接用就会出现坐标缩放异常。- 当
fixedEyeAtCameraZero=true时,相机坐标系统以自身为原点,这时候转换坐标必须结合SubScene的投影矩阵和视图矩阵做修正,不然就会算出离谱的坐标值。
解决方案
1. 先把鼠标坐标转成SubScene局部坐标
鼠标事件的坐标是相对于主Scene的,得先转成SubScene的局部坐标:
Point2D subSceneMouse = subScene.sceneToLocal(event.getSceneX(), event.getSceneY());
2. 手动计算3D坐标(替代内部的CameraHelper方法)
直接利用相机的投影矩阵和视图矩阵,结合SubScene的尺寸手动转换,不用依赖内部类:
private Point3D convertMouseTo3D(SubScene subScene, Camera camera, double x, double y) { double width = subScene.getWidth(); double height = subScene.getHeight(); // 把鼠标坐标转成标准化设备坐标(NDC),范围[-1,1] double ndcX = (x / width) * 2 - 1; double ndcY = 1 - (y / height) * 2; // JavaFX的Y轴向下,得翻转一下 // 获取相机的投影矩阵和视图矩阵 Matrix4d projMatrix = new Matrix4d(camera.getProjectionMatrix()); Matrix4d viewMatrix = new Matrix4d(camera.getViewMatrix()); // 计算逆矩阵:投影逆矩阵 × 视图逆矩阵 Matrix4d invProjView = projMatrix.invert().multiply(viewMatrix.invert()); // NDC坐标转成齐次坐标,Z设为0(对应投影平面),W=1 Point4d ndcPoint = new Point4d(ndcX, ndcY, 0, 1); // 用逆矩阵转成世界坐标 Point4d worldPoint = invProjView.transform(ndcPoint); // 齐次坐标转3D坐标(除以W分量) return new Point3D(worldPoint.getX()/worldPoint.getW(), worldPoint.getY()/worldPoint.getW(), worldPoint.getZ()/worldPoint.getW()); }
3. 保留fixedEyeAtCameraZero=true的正确配置
不用改这个参数,用上面的手动转换方法就能得到正确的3D坐标,同时相机的移动逻辑也不会受影响。
测试代码
在鼠标点击事件里这么用:
subScene.setOnMouseClicked(event -> { Point2D localMouse = subScene.sceneToLocal(event.getSceneX(), event.getSceneY()); Point3D worldPos = convertMouseTo3D(subScene, camera, localMouse.getX(), localMouse.getY()); Box box = new Box(10,10,10); box.setTranslateX(worldPos.getX()); box.setTranslateY(worldPos.getY()); box.setTranslateZ(worldPos.getZ()); subScene.getRoot().getChildren().add(box); });
内容的提问来源于stack exchange,提问作者Suic
相关产品推荐
相关产品推荐

