如何正确渲染3D图形 [英] How to render 3D graphics properly
问题描述
我试图在 javafx
中创建一个rubiks多维数据集,结果是一个非常糟糕的模型,如下所示图片。我给出了我的代码源代码,我使用 RectangleBuilder
类来创建矩形并在3d中进行转换。为了修复图形,我还试图构建使用 TriangleMesh
类的矩形,并在向它们添加材料后,将它们转换为3d,再次以相同的坏图形结束。为什么会发生这种情况以及如何摆脱它?
I was trying to make a rubiks cube in javafx
an ended up with a very bad model as given in this Image. I am giving my source for code for this, where I have used RectangleBuilder
class to create rectangles and transformed in 3d. To fix the graphics i had also tried to build the rectangles used TriangleMesh
class and after adding materials to them, transformed them in 3d to end up again in the same bad graphics. Why does this occur and how to get rid of it ?
import javafx.scene.transform.Rotate;
import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Translate;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.SceneAntialiasing;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.RectangleBuilder;
import javafx.scene.transform.Rotate;
import javafx.util.Duration;
public class NewFXMain1 extends Application {
public class Cube extends Group {
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 Cube(double size, Color back,Color bottom,Color right,Color left,Color top,Color front, double shade) {
getTransforms().addAll(rz, ry, rx);
getChildren().addAll(
RectangleBuilder.create() // back face
.width(size).height(size)
.fill(back.deriveColor(0.0, 1.0, (1 - 0.5*shade), 1.0))
.translateX(-0.5*size)
.translateY(-0.5*size)
.translateZ(0.5*size)
.smooth(true)
.stroke(Color.BLACK)
.build(),
RectangleBuilder.create() // bottom face
.width(size).height(size)
.fill(bottom.deriveColor(0.0, 1.0, (1 - 0.4*shade), 1.0))
.translateX(-0.5*size)
.translateY(0)
.rotationAxis(Rotate.X_AXIS)
.rotate(90)
.smooth(true)
.stroke(Color.BLACK)
.build(),
RectangleBuilder.create() // right face
.width(size).height(size)
.fill(right.deriveColor(0.0, 1.0, (1 - 0.3*shade), 1.0))
.translateX(-1*size)
.translateY(-0.5*size)
.rotationAxis(Rotate.Y_AXIS)
.rotate(90)
.smooth(true)
.stroke(Color.BLACK)
.build(),
RectangleBuilder.create() // left face
.width(size).height(size)
.fill(left.deriveColor(0.0, 1.0, (1 - 0.2*shade), 1.0))
.translateX(0)
.translateY(-0.5*size)
.rotationAxis(Rotate.Y_AXIS)
.rotate(90)
.smooth(true)
.stroke(Color.BLACK)
.build(),
RectangleBuilder.create() // top face
.width(size).height(size)
.fill(top.deriveColor(0.0, 1.0, (1 - 0.1*shade), 1.0))
.translateX(-0.5*size)
.translateY(-1*size)
.rotationAxis(Rotate.X_AXIS)
.rotate(90)
.smooth(true)
.stroke(Color.BLACK)
.build(),
RectangleBuilder.create() // front face
.width(size).height(size)
.fill(front)
.translateX(-0.5*size)
.translateY(-0.5*size)
.translateZ(-0.5*size)
.smooth(true)
.stroke(Color.BLACK)
.build()
);
}
}
PerspectiveCamera camera = new PerspectiveCamera(true);
@Override public void start(Stage primaryStage) throws Exception {
Group root = new Group();
Scene scene=new Scene(root,600,600,true);
camera.setNearClip(0.00001);
camera.setFarClip(10000000.0);
camera.getTransforms().addAll (
new Rotate(0, Rotate.Y_AXIS),
new Rotate(0, Rotate.X_AXIS),
new Translate(0, 0, -1000));
scene.setCamera(camera);
Cube c1 = new Cube(50,Color.BLUE.darker(),Color.BLUE.darker(),Color.ORANGE.darker(),Color.BLUE.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c1.setTranslateX(100);
Cube c2 = new Cube(50,Color.GREEN.darker(),Color.GREEN.darker(),Color.GREEN.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c2.setTranslateX(50);
Cube c3 = new Cube(50,Color.CYAN.brighter(),Color.GREEN.darker(),Color.GREEN.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c3.setTranslateX(50);
c3.setTranslateZ(50);
Cube c4 = new Cube(50,Color.CYAN.brighter(),Color.GREEN.darker(),Color.ORANGE.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c4.setTranslateX(100);
c4.setTranslateZ(50);
Cube c5 = new Cube(50,Color.BLUE.darker(),Color.GREEN.darker(),Color.ORANGE.darker(),Color.BLUE.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c5.setTranslateX(100);
c5.setTranslateY(50);
Cube c6 = new Cube(50,Color.GREEN.darker(),Color.GREEN.darker(),Color.GREEN.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c6.setTranslateX(50);
c6.setTranslateY(50);
Cube c7 = new Cube(50,Color.CYAN.brighter(),Color.GREEN.darker(),Color.GREEN.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c7.setTranslateX(50);
c7.setTranslateZ(50);
c7.setTranslateY(50);
Cube c8 = new Cube(50,Color.CYAN.brighter(),Color.GREEN.darker(),Color.ORANGE.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c8.setTranslateX(100);
c8.setTranslateZ(50);
c8.setTranslateY(50);
handleMouse(scene,root);
Group k=new Group(c1,c2,c3,c4,c5,c6,c7,c8);
k.setTranslateZ(70);
root.getChildren().addAll(k);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
private static final double CONTROL_MULTIPLIER = 0.1;
private static final double SHIFT_MULTIPLIER = 10.0;
private static final double MOUSE_SPEED = 0.1;
private static final double ROTATION_SPEED = 2.0;
double mousePosX,mousePosY,mouseOldX,mouseOldY,mouseDeltaX,mouseDeltaY;
private void handleMouse(Scene scene, final Node root) {
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent me) {
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
mouseOldX = me.getSceneX();
mouseOldY = me.getSceneY();
}
});
scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent me) {
mouseOldX = mousePosX;
mouseOldY = mousePosY;
mousePosX = me.getSceneX();
mousePosY = me.getSceneY();
mouseDeltaX = (mousePosX - mouseOldX);
mouseDeltaY = (mousePosY - mouseOldY);
double modifier = 1.0;
if (me.isControlDown()) {
modifier = CONTROL_MULTIPLIER;
}
if (me.isShiftDown()) {
modifier = SHIFT_MULTIPLIER;
}
if (me.isPrimaryButtonDown()) {
camera.setRotationAxis(Rotate.Y_AXIS);camera.setRotate(camera.getRotate() -
mouseDeltaX*modifier*ROTATION_SPEED); //
camera.setRotationAxis(Rotate.X_AXIS);camera.setRotate(camera.getRotate() +
mouseDeltaY*modifier*ROTATION_SPEED); // -
}
else if (me.isSecondaryButtonDown()) {
double z = camera.getTranslateZ();
double newZ = z + mouseDeltaX*MOUSE_SPEED*modifier;
camera.setTranslateZ(newZ);
}
}
}); // setOnMouseDragged
} //handleMouse
}
推荐答案
编辑:
这里最初给出的渲染工件的原因是错误的,建议的解决方案可能不是适当*。有关详细信息,请参阅修订历史记录。实际的解决方案要简单得多。如有任何不便,请致歉。
The reason for the rendering artifacts that was originally given here was wrong, and the proposed solution may not be appropriate*. Details can be found in the Revision History. The actual solution is far simpler. Apologies for any inconveniences.
渲染工件的原因是你的相机剪裁平面相距太远。您正在设置
The reason for the rendering artifacts is that your camera clip planes are too far apart. You are setting
camera.setNearClip(0.00001);
camera.setFarClip(10000000.0);
这远远超出了普通Z缓冲区中明显可以表示的范围。将这些行更改为
which is far beyond what can sensibly be represented in a normal Z-buffer. Changing these lines to
camera.setNearClip(0.1);
camera.setFarClip(10000.0);
将修复渲染错误。
* 原始解决方案建议对几个 Mesh
实例中的框进行建模。这具有以下优点:它允许定义法线并因此实现逼真的外观3D效果,但需要更多的努力。有关真正的3D解决方案,请参阅修订历史记录。
* The original solution suggested to model the boxes from several Mesh
instances. This has the advantage that it allows defining normals and thus to achieve a "realistic" looking 3D effect, but involves a bit more effort. See the Revision History for the "real 3D" solution.
这篇关于如何正确渲染3D图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!