JavaFX 8 Z 缓冲区问题
JavaFX 8 Z-buffer issue
我的问题是 JavaFX 3D 中的 Z-Buffer,它在我的机器上似乎无法正常工作。
我知道问题:
Overlapping shapes
和
但是我确实启用了 Z-Buffer,并且节点仍然按照它们添加到场景图中的顺序进行渲染。
也许我缺少一些依赖项或其他什么?
我正在post编写代码,希望有人能帮助我。我正在创建一个过渡,在椭圆路径上围绕另一个节点移动节点。
提前致谢!
public class OrbitExp extends Application {
Group root = new Group();
Scene scene = new Scene(root, 800, 600, true, SceneAntialiasing.BALANCED);
PerspectiveCamera camera = new PerspectiveCamera();
@Override
public void start(Stage primaryStage) {
root.setDepthTest(DepthTest.ENABLE);
//Tried to set Depthtest explicitly. Assumed maybe it did not inherit:S
System.out.println(
"3D supported? " +
Platform.isSupported(ConditionalFeature.SCENE3D)
); // returns true
System.out.println("root z-buffer: " + root.getDepthTest());
initCamera();
Box
box1 = new Box(50,50,50),
box2 = new Box(10,10,10);
root.setTranslateX(scene.getWidth()/2);
root.setTranslateY(scene.getHeight()/2);
PhongMaterial
pmat = new PhongMaterial(Color.BLUE),
pmat2 = new PhongMaterial(Color.RED);
box1.setMaterial(pmat);
box2.setMaterial(pmat2);
scene.setFill(Color.LIGHTGREEN);
root.getChildren().addAll(box1,box2);
SequentialTransition sqt = orbit(box1, box2, 40, 40, Duration.seconds(3), 360);
sqt.play();
scene.setOnMouseClicked(click->{
Node node = (Node)(click.getPickResult().getIntersectedNode());
System.out.println("Tx: "+node.getTranslateX());
System.out.println("Ty: "+node.getTranslateY());
System.out.println("Tz: "+node.getTranslateZ());
});
// just for debugging, but coords does seem to be alright
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void initCamera() {
camera.setTranslateZ(-50);
camera.setTranslateY(20);
camera.setFarClip(5000);
camera.setNearClip(0);
scene.setCamera(camera);
}
SequentialTransition orbit(Node node1, Node node2,double a, double b, Duration totalDuration, int N) {
SequentialTransition sqt = new SequentialTransition();
Duration dur = new Duration(totalDuration.toMillis()*(1.0d/N));
node2.setTranslateX(a+node1.getTranslateX());
node2.setTranslateZ(node1.getTranslateZ());
for (int i = 1; i < N; i++) {
TranslateTransition tt = new TranslateTransition(dur, node2);
double
angle = i*(360.0d/N),
toX = (Math.cos(Math.toRadians(angle))*a)+node1.getTranslateX(),
toZ = (Math.sin(Math.toRadians(angle))*b)+node1.getTranslateZ();
tt.setToX(toX);
tt.setToZ(toZ);
tt.setInterpolator(Interpolator.LINEAR);
sqt.getChildren().add(tt);
System.out.println("angle = " + angle + "\nangle in rads: " + Math.toRadians(angle) + "\ntoX = " + toX + "\ntoZ = " + toZ);
}
sqt.setCycleCount(Timeline.INDEFINITE);
return sqt;
}
}
顺便说一下,这是我的第一个 post:)
如果您使用矩形检查 link 上的代码,深度缓冲区工作正常。
更改矩形以使用 3D 框同样有效。
问题是你如何定义一个盒子相对于另一个盒子的旋转,所以不要像你那样使用 RotateTransition
或 TranslateTransition
的 SequentialTransition
,我对红色框应用 Rotate
变换,在蓝色框的中心设置一个轴心,并使用 AnimationTimer
修改旋转角度以创建 'orbit' 效果.
您甚至可以在大框(自 8u60 起)上使用透明度来查看下方的小框。
private final Group shapes = new Group();
private long lastTimerCall;
private AnimationTimer timeline;
@Override
public void start(Stage stage) throws Exception {
Scene scene = new Scene(createRotatingShapes(), 400, 300,
true, SceneAntialiasing.BALANCED);
scene.setFill(Color.LIGHTGREEN);
final PerspectiveCamera camera = new PerspectiveCamera();
camera.setRotationAxis(Rotate.X_AXIS);
camera.setRotate(10);
camera.setTranslateZ(200);
scene.setCamera(camera);
stage.setScene(scene);
stage.show();
}
private Group createRotatingShapes() {
final Box box1 = new Box(50, 50, 50);
// Transparency in box1: last node of the group
box1.setMaterial(new PhongMaterial(Color.web("#0000FF80")));
box1.setTranslateZ(50);
final Box box2 = new Box(10, 10, 10);
box2.setMaterial(new PhongMaterial(Color.RED));
box2.setTranslateZ(-50);
shapes.getChildren().addAll(box2, box1);
shapes.setTranslateX(200);
shapes.setTranslateY(150);
rotateAroundYAxis(box2);
return shapes;
}
private int count = 0;
private void rotateAroundYAxis(Node node) {
Rotate r = new Rotate(0, 0, 0, 100, Rotate.Y_AXIS);
node.getTransforms().add(r);
lastTimerCall = System.nanoTime();
timeline = new AnimationTimer() {
@Override public void handle(long now) {
if (now > lastTimerCall + 100_000_000l) {
r.setAngle((count++)%360);
}
}
};
timeline.start();
}
@Override
public void stop() {
timeline.stop();
}
箱子前:
蓝框后面:
编辑
如果您查看 nearClip
的 Camera JavaDoc:
Specifies the distance from the eye of the near clipping plane of
this Camera in the eye coordinate space.
Objects closer to the eye than nearClip are not drawn.
nearClip is specified as a value greater than zero. A value less
than or equal to zero is treated as a very small positive number.
(粗体是我的)
所以你的代码的问题是这一行:
camera.setNearClip(0);
只需将其更改为:
camera.setNearClip(0.01);
它会如您所愿地工作。
我的问题是 JavaFX 3D 中的 Z-Buffer,它在我的机器上似乎无法正常工作。
我知道问题:
Overlapping shapes
和
但是我确实启用了 Z-Buffer,并且节点仍然按照它们添加到场景图中的顺序进行渲染。
也许我缺少一些依赖项或其他什么?
我正在post编写代码,希望有人能帮助我。我正在创建一个过渡,在椭圆路径上围绕另一个节点移动节点。
提前致谢!
public class OrbitExp extends Application {
Group root = new Group();
Scene scene = new Scene(root, 800, 600, true, SceneAntialiasing.BALANCED);
PerspectiveCamera camera = new PerspectiveCamera();
@Override
public void start(Stage primaryStage) {
root.setDepthTest(DepthTest.ENABLE);
//Tried to set Depthtest explicitly. Assumed maybe it did not inherit:S
System.out.println(
"3D supported? " +
Platform.isSupported(ConditionalFeature.SCENE3D)
); // returns true
System.out.println("root z-buffer: " + root.getDepthTest());
initCamera();
Box
box1 = new Box(50,50,50),
box2 = new Box(10,10,10);
root.setTranslateX(scene.getWidth()/2);
root.setTranslateY(scene.getHeight()/2);
PhongMaterial
pmat = new PhongMaterial(Color.BLUE),
pmat2 = new PhongMaterial(Color.RED);
box1.setMaterial(pmat);
box2.setMaterial(pmat2);
scene.setFill(Color.LIGHTGREEN);
root.getChildren().addAll(box1,box2);
SequentialTransition sqt = orbit(box1, box2, 40, 40, Duration.seconds(3), 360);
sqt.play();
scene.setOnMouseClicked(click->{
Node node = (Node)(click.getPickResult().getIntersectedNode());
System.out.println("Tx: "+node.getTranslateX());
System.out.println("Ty: "+node.getTranslateY());
System.out.println("Tz: "+node.getTranslateZ());
});
// just for debugging, but coords does seem to be alright
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void initCamera() {
camera.setTranslateZ(-50);
camera.setTranslateY(20);
camera.setFarClip(5000);
camera.setNearClip(0);
scene.setCamera(camera);
}
SequentialTransition orbit(Node node1, Node node2,double a, double b, Duration totalDuration, int N) {
SequentialTransition sqt = new SequentialTransition();
Duration dur = new Duration(totalDuration.toMillis()*(1.0d/N));
node2.setTranslateX(a+node1.getTranslateX());
node2.setTranslateZ(node1.getTranslateZ());
for (int i = 1; i < N; i++) {
TranslateTransition tt = new TranslateTransition(dur, node2);
double
angle = i*(360.0d/N),
toX = (Math.cos(Math.toRadians(angle))*a)+node1.getTranslateX(),
toZ = (Math.sin(Math.toRadians(angle))*b)+node1.getTranslateZ();
tt.setToX(toX);
tt.setToZ(toZ);
tt.setInterpolator(Interpolator.LINEAR);
sqt.getChildren().add(tt);
System.out.println("angle = " + angle + "\nangle in rads: " + Math.toRadians(angle) + "\ntoX = " + toX + "\ntoZ = " + toZ);
}
sqt.setCycleCount(Timeline.INDEFINITE);
return sqt;
}
}
顺便说一下,这是我的第一个 post:)
如果您使用矩形检查 link 上的代码,深度缓冲区工作正常。
更改矩形以使用 3D 框同样有效。
问题是你如何定义一个盒子相对于另一个盒子的旋转,所以不要像你那样使用 RotateTransition
或 TranslateTransition
的 SequentialTransition
,我对红色框应用 Rotate
变换,在蓝色框的中心设置一个轴心,并使用 AnimationTimer
修改旋转角度以创建 'orbit' 效果.
您甚至可以在大框(自 8u60 起)上使用透明度来查看下方的小框。
private final Group shapes = new Group();
private long lastTimerCall;
private AnimationTimer timeline;
@Override
public void start(Stage stage) throws Exception {
Scene scene = new Scene(createRotatingShapes(), 400, 300,
true, SceneAntialiasing.BALANCED);
scene.setFill(Color.LIGHTGREEN);
final PerspectiveCamera camera = new PerspectiveCamera();
camera.setRotationAxis(Rotate.X_AXIS);
camera.setRotate(10);
camera.setTranslateZ(200);
scene.setCamera(camera);
stage.setScene(scene);
stage.show();
}
private Group createRotatingShapes() {
final Box box1 = new Box(50, 50, 50);
// Transparency in box1: last node of the group
box1.setMaterial(new PhongMaterial(Color.web("#0000FF80")));
box1.setTranslateZ(50);
final Box box2 = new Box(10, 10, 10);
box2.setMaterial(new PhongMaterial(Color.RED));
box2.setTranslateZ(-50);
shapes.getChildren().addAll(box2, box1);
shapes.setTranslateX(200);
shapes.setTranslateY(150);
rotateAroundYAxis(box2);
return shapes;
}
private int count = 0;
private void rotateAroundYAxis(Node node) {
Rotate r = new Rotate(0, 0, 0, 100, Rotate.Y_AXIS);
node.getTransforms().add(r);
lastTimerCall = System.nanoTime();
timeline = new AnimationTimer() {
@Override public void handle(long now) {
if (now > lastTimerCall + 100_000_000l) {
r.setAngle((count++)%360);
}
}
};
timeline.start();
}
@Override
public void stop() {
timeline.stop();
}
箱子前:
蓝框后面:
编辑
如果您查看 nearClip
的 Camera JavaDoc:
Specifies the distance from the eye of the near clipping plane of this Camera in the eye coordinate space. Objects closer to the eye than nearClip are not drawn. nearClip is specified as a value greater than zero. A value less than or equal to zero is treated as a very small positive number.
(粗体是我的)
所以你的代码的问题是这一行:
camera.setNearClip(0);
只需将其更改为:
camera.setNearClip(0.01);
它会如您所愿地工作。