I'm following javidx9's tutorial on youtube about making a 3D graphics engine (I'm doing it in java, rather than C++, but I'm pretty closely following his steps), and I'm at the point where we move the cube away from the 'camera' to better see it (35:49, if you're curious), but as soon as I add the relevant lines of code and run it, nothing shows up. When I take them away, it comes back, and I have no idea what's happening. Code is below, sorry it's kind of long and probably poorly written (using Graphics2D for display):
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));
}
}
I highly suspect your issue to be that in C++, doing (timestamp)
will in fact make a copy of the triangle, whereas your code merely gets a reference, therefore your triangles drift away at pace of 3 units per render, likely vanishing out of view before you could see anything.