Java 如何正确渲染三维图形
我试图在Java 如何正确渲染三维图形,java,javafx-8,javafx-3d,Java,Javafx 8,Javafx 3d,我试图在javafx中制作一个rubiks立方体,结果得到了一个非常糟糕的模型,如本文所示。我给出了这方面的源代码,我使用了RectangleBuilder类来创建矩形并在3d中进行转换。为了修复图形,我还尝试构建了使用TriangleMesh类的矩形,并在添加材质后,在3d中对其进行了转换,最终再次生成同样糟糕的图形。为什么会发生这种情况以及如何消除它 import javafx.scene.transform.Rotate; import javafx.scene.PerspectiveCa
javafx
中制作一个rubiks立方体,结果得到了一个非常糟糕的模型,如本文所示。我给出了这方面的源代码,我使用了RectangleBuilder
类来创建矩形并在3d中进行转换。为了修复图形,我还尝试构建了使用TriangleMesh
类的矩形,并在添加材质后,在3d中对其进行了转换,最终再次生成同样糟糕的图形。为什么会发生这种情况以及如何消除它
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
}
导入javafx.scene.transform.Rotate;
导入javafx.scene.PerspectiveCamera;
导入javafx.scene.transform.Translate;
导入javafx.application.application;
导入javafx.scene.Group;
导入javafx.scene.scene;
导入javafx.stage.stage;
导入javafx.animation.animation;
导入javafx.animation.KeyFrame;
导入javafx.animation.KeyValue;
导入javafx.animation.Timeline;
导入javafx.event.EventHandler;
导入javafx.scene.Group;
导入javafx.scene.Node;
导入javafx.scene.sceneatialiasing;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.RectangleBuilder;
导入javafx.scene.transform.Rotate;
导入javafx.util.Duration;
公共类NewFXMain1扩展了应用程序{
公共类多维数据集扩展组{
最终旋转rx=新旋转(0,旋转X_轴);
最终旋转ry=新旋转(0,旋转Y_轴);
最终旋转rz=新旋转(0,旋转Z_轴);
公共立方体(双尺寸、彩色背面、彩色底部、彩色右侧、彩色左侧、彩色顶部、彩色前部、双阴影){
getTransforms().addAll(rz、ry、rx);
getChildren().addAll(
RectangleBuilder.create()//背面
.宽度(尺寸).高度(尺寸)
.填充(背衬颜色(0.0,1.0,(1-0.5*阴影),1.0))
.translateX(-0.5*尺寸)
.translateY(-0.5*尺寸)
.translateZ(0.5*尺寸)
.平滑(真实)
.笔划(颜色.黑色)
.build(),
RectangleBuilder.create()//底面
.宽度(尺寸).高度(尺寸)
.填充(底部衍生颜色(0.0,1.0,(1-0.4*阴影),1.0))
.translateX(-0.5*尺寸)
.translateY(0)
.旋转轴(旋转X_轴)
.旋转(90)
.平滑(真实)
.笔划(颜色.黑色)
.build(),
RectangleBuilder.create()//右面
.宽度(尺寸).高度(尺寸)
.填充(右侧的衍生色(0.0,1.0,(1-0.3*阴影),1.0))
.translateX(-1*尺寸)
.translateY(-0.5*尺寸)
.旋转轴(旋转Y_轴)
.旋转(90)
.平滑(真实)
.笔划(颜色.黑色)
.build(),
RectangleBuilder.create()//左侧面
.宽度(尺寸).高度(尺寸)
.填充(左德里维科颜色(0.0,1.0,(1-0.2*阴影),1.0))
.translateX(0)
.translateY(-0.5*尺寸)
.旋转轴(旋转Y_轴)
.旋转(90)
.平滑(真实)
.笔划(颜色.黑色)
.build(),
RectangleBuilder.create()//顶面
.宽度(尺寸).高度(尺寸)
填充(顶部衍生颜色(0.0,1.0,(1-0.1*阴影),1.0))
.translateX(-0.5*尺寸)
.translateY(-1*大小)
.旋转轴(旋转X_轴)
.旋转(90)
.平滑(真实)
.笔划(颜色.黑色)
.build(),
RectangleBuilder.create()//正面
.宽度(尺寸).高度(尺寸)
.加油(前)
.translateX(-0.5*尺寸)
.translateY(-0.5*尺寸)
.translateZ(-0.5*尺寸)
.平滑(真实)
.笔划(颜色.黑色)
.build()
);
}
}
透视摄影机=新透视摄影机(真);
@覆盖公共无效开始(阶段primaryStage)引发异常{
组根=新组();
场景场景=新场景(根,600600,真);
摄像头。setNearClip(0.00001);
摄像机.setFarClip(10000000.0);
camera.getTransforms().addAll(
新旋转(0,旋转Y_轴),
新旋转(0,旋转X_轴),
新翻译(0,0,-1000));
场景。设置摄像机(摄像机);
立方体c1=新立方体(50,Color.BLUE.darker(),Color.BLUE.darker(),Color.ORANGE.darker(),Color.BLUE.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c1.setTranslateX(100);
立方体c2=新立方体(50,Color.GREEN.darker(),Color.GREEN.darker(),Color.GREEN.darker(),Color.YELLOW.darker(),Color.BLUE.darker(),Color.RED.darker(),1);
c2.setTranslateX(50);
立方体c3=新立方体(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);
立方体c4=新立方体(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);
立方体c5=新立方体(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);
立方体c6=新立方体(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);
立方体c7=新立方体(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);
立方体c8=新立方体(50,Color.CYAN.brighter(),Color.GREEN)。
camera.setNearClip(0.00001);
camera.setFarClip(10000000.0);
camera.setNearClip(0.1);
camera.setFarClip(10000.0);
Box cube = new Box();
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(new Image(getClass().getResource("cubeNet.png").toExternalForm()));
cube.setMaterial(material);
CuboidMesh cube = new CuboidMesh();
cube.setTextureModeImage(getClass().getResource("cubeNet.png").toExternalForm());
public static final int RED = 0;
public static final int GREEN = 1;
public static final int BLUE = 2;
public static final int YELLOW = 3;
public static final int ORANGE = 4;
public static final int WHITE = 5;
public static final int GRAY = 6;
public static final float X_RED = 0.5f / 7f;
public static final float X_GREEN = 1.5f / 7f;
public static final float X_BLUE = 2.5f / 7f;
public static final float X_YELLOW = 3.5f / 7f;
public static final float X_ORANGE = 4.5f / 7f;
public static final float X_WHITE = 5.5f / 7f;
public static final float X_GRAY = 6.5f / 7f;
private TriangleMesh createCube(int[] face) {
TriangleMesh m = new TriangleMesh();
m.getPoints().addAll(
0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f
);
m.getTexCoords().addAll(
X_RED, 0.5f,
X_GREEN, 0.5f,
X_BLUE, 0.5f,
X_YELLOW, 0.5f,
X_ORANGE, 0.5f,
X_WHITE, 0.5f,
X_GRAY, 0.5f
);
m.getFaces().addAll(
2, face[0], 3, face[0], 6, face[0], // F
3, face[0], 7, face[0], 6, face[0],
0, face[1], 1, face[1], 2, face[1], // R
2, face[1], 1, face[1], 3, face[1],
1, face[2], 5, face[2], 3, face[2], // U
5, face[2], 7, face[2], 3, face[2],
0, face[3], 4, face[3], 1, face[3], // B
4, face[3], 5, face[3], 1, face[3],
4, face[4], 6, face[4], 5, face[4], // L
6, face[4], 7, face[4], 5, face[4],
0, face[5], 2, face[5], 4, face[5], // D
2, face[5], 6, face[5], 4, face[5]
);
return m;
}
int[] p = new int[]{BLUE, GRAY, GRAY, GRAY, ORANGE, WHITE};
MeshView meshP = new MeshView();
meshP.setMesh(createCube(p));
PhongMaterial mat = new PhongMaterial();
mat.setDiffuseMap(new Image(getClass().getResourceAsStream("palette.png")));
meshP.setMaterial(mat);