如何正确渲染3D图形 [英] How to render 3D graphics properly

查看:106
本文介绍了如何正确渲染3D图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆