我在 youtube 上关注 javidx9 的关于制作 3D 图形引擎的教程(我是在 java 中做的,而不是 C++,但我非常接近他的步骤),我正处于我们移动立方体的地方远离“相机”以便更好地看到它(35:49,如果你好奇的话),但是一旦我添加了相关的代码行并运行它,什么都没有出现。当我把它们拿走时,它又回来了,我不知道发生了什么。代码如下,对不起,它有点长而且可能写得不好(使用 Graphics2D 进行显示):
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
static Frame frame;
static double FOV = Math.PI / 2;
static int w = 400;
static int h = 400;
static double a = h / w;
static double f = 1 / Math.tan(FOV / 2);
static double zFar = 1000;
static double zNear = 0.1;
static double q = zFar / (zFar - zNear);
static double[][] matProj = new double[4][4];
public static void main(String[] args) {
frame = new Frame();
}
static void draw() {
Mesh cubeMesh = new Mesh();
//south
cubeMesh.addTri(0, 0, 0, 0, 1, 0, 1, 1, 0);
cubeMesh.addTri(0, 0, 0, 1, 1, 0, 1, 0, 0);
//east
cubeMesh.addTri(1, 0, 0, 1, 1, 0, 1, 1, 1);
cubeMesh.addTri(1, 0, 0, 1, 1, 1, 1, 0, 1);
//north
cubeMesh.addTri(1, 0, 1, 1, 1, 1, 0, 1, 1);
cubeMesh.addTri(1, 0, 1, 0, 1, 1, 0, 0, 1);
//west
cubeMesh.addTri(0, 0, 1, 0, 1, 1, 0, 1, 0);
cubeMesh.addTri(0, 0, 1, 0, 1, 0, 0, 0, 0);
//top
cubeMesh.addTri(0, 1, 0, 0, 1, 1, 1, 1, 1);
cubeMesh.addTri(0, 1, 0, 1, 1, 1, 1, 1, 0);
//bottom
cubeMesh.addTri(1, 0, 1, 0, 0, 1, 0, 0, 0);
cubeMesh.addTri(1, 0, 1, 0, 0, 0, 1, 0, 0);
matProj[0][0] = a * f;
matProj[1][1] = f;
matProj[2][2] = q;
matProj[3][2] = -1 * q * zNear;
matProj[2][3] = 1;
matProj[3][3] = 0;
frame.graphics.g2D.setColor(Color.WHITE);
frame.graphics.g2D.setStroke(new BasicStroke(2));
for(TrianglePoints i : cubeMesh.triangles) {
TrianglePoints translated = i;
translated.p1[2] = i.p1[2] + 3; //when I comment out these lines, it works, but then of course the cube isn't translated
translated.p2[2] = i.p2[2] + 3;
translated.p3[2] = i.p3[2] + 3;
int[] xPoints = {(int) MultiplyMatrixVector(translated.p1, matProj)[0], (int) MultiplyMatrixVector(translated.p2, matProj)[0], (int) MultiplyMatrixVector(translated.p3, matProj)[0]};
int[] yPoints = {(int) MultiplyMatrixVector(translated.p1, matProj)[1], (int) MultiplyMatrixVector(translated.p2, matProj)[1], (int) MultiplyMatrixVector(translated.p3, matProj)[1]};
for(int j = 0; j < xPoints.length; j++) {
xPoints[j] += 1;
xPoints[j] *= (0.5 * w);
yPoints[j] += 1;
yPoints[j] *= (0.5 * w);
}
frame.graphics.g2D.drawPolygon(xPoints, yPoints, 3);
}
}
private static double[] MultiplyMatrixVector(double[] i, double[][] m) {
double[] o = new double[3];
o[0] = i[0] * m[0][0] + i[1] * m[1][0] + i[2] * m[2][0] + m[3][0];
o[1] = i[0] * m[0][1] + i[1] * m[1][1] + i[2] * m[2][1] + m[3][1];
o[2] = i[0] * m[0][2] + i[1] * m[1][2] + i[2] * m[2][2] + m[3][2];
double w = i[0] * m[0][3] + i[1] * m[1][3] + i[2] * m[2][3] + m[3][3];
if(w != 0) { //I think this might be where the issue is, when I translate it w won't be 0, but I don't know how that would make it not work, I have to divide by w here.
o[0] /= w;
o[1] /= w;
o[2] /= w;
}
return o;
}
}
class Frame extends JFrame {
private static final long serialVersionUID = 1L;
GraphicsC graphics = new GraphicsC();
Frame(){
this.setSize(Main.w, Main.h);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(graphics);
this.setVisible(true);
}
}
class GraphicsC extends JPanel {
private static final long serialVersionUID = 1L;
Graphics2D g2D;
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g2D = (Graphics2D) g;
Main.draw();
}
}
class TrianglePoints {
double[] p1 = new double[3];
double[] p2 = new double[3];
double[] p3 = new double[3];
TrianglePoints(double[] p1, double[] p2, double[] p3) {
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
}
}
class Mesh {
List<TrianglePoints> triangles = new ArrayList<TrianglePoints>();
void addTri(double a, double b, double c, double d, double e, double f, double g, double h, double i) {
double[] p1 = {a, b, c};
double[] p2 = {d, e, f};
double[] p3 = {g, h, i};
triangles.add(new TrianglePoints(p1, p2, p3));
}
}