General about the project: I am trying to program my own 3D engine in java, but I have some issues with programming the camera right. What I have already programmed is a window and the 3d objects that can be displayed, rotate and do everything they need to. But as soon as I try to add a perspective to the camera (Perspective projection) something goes wrong and the object is not displayed right anymore.
Exact problem: The problem is that when the object rotates one of the points gets streched and the object is disformed. For example one point turns towards the camera and suddenly the tetraeda is out of shape:
This is how it looks without the perspective projection:
Here is the code of the two classes that calculate the displayed vectors: Calculates everything:
package Math;
import Objects.Triangle;
import Objects.Vector;
public class CalcView {
// Updates all the meshes one by one
public Triangle[] updateMesh(Triangle[] m, Camera cam, double time) {
// I don't want to change the actual position of the object in the world, but only the displayed one
Triangle[] nm = new Triangle[m.length];
// Goes through all the meshes
for (int i = 0; i < m.length; i++) {
Triangle t = new Triangle(new Vector[3]);
// This first changes the triangle by the wanted rotation in the axis
// It's needed so that we don't just see one side of the object
for (int j = 0; j < t.vectors.length; j++) {
Rotate r = new Rotate();
r.calcRotation(time);
t.vectors[j] = vecMatToVec(m[i].vectors[j], r.rX); // X-Axis
t.vectors[j] = vecMatToVec(t.vectors[j], r.rY); // Y-Axis
t.vectors[j] = vecMatToVec(t.vectors[j], r.rZ); // Z-Axis
}
// After the object is rotated it's also moved by the camera position
// I want to add a perspective projection matrix as well, but it doesn't work quite well yet
for (int j = 0; j < t.vectors.length; j++) {
//t.vectors[j] = cam.mProjToVec(t.vectors[j], cam.projMatrix);
t.vectors[j] = moveVecByVec(t.vectors[j], cam.posCam);
}
nm[i] = t;
}
//printVectors(nm);
return nm;
}
// This method moves a vector by another vector
// Mostly needed to move the object by the position of the camera
public static Vector moveVecByVec(Vector or, Vector mul) {
Vector v = new Vector(0, 0, 0);
for (int i = 0; i < or.vec.length; i++) v.vec[i] = or.vec[i] + mul.vec[i];
return v;
}
// This is just a matrix-vector multiplication, which outputs a vector
public Vector vecMatToVec(Vector i, double[][] m) {
Vector v = new Vector(0, 0,0);
for (int j = 0; j < 3; j++) v.vec[j] = i.vec[0] * m[0][j] + i.vec[1] * m[1][j] + i.vec[2] * m[2][j];
return v;
}
// That's the same as in the meshes, but still only needed for debugging
public void printVectors(Triangle[] t) {
for (int i = 0; i < t.length; i++) {
System.out.println("Triangle: " + i);
for (int j = 0; j < 3; j++) {
System.out.println(
"XYZ: " + t[i].vectors[j].vec[0] + " " + t[i].vectors[j].vec[1]+ " " + t[i].vectors[j].vec[2]);
}
System.out.println(" ");
}
}
}
And here is the camera:
package Math;
import Objects.Vector;
public class Camera {
public double[][] projMatrix;
public Vector posCam;
// Screen width and height, used for the ratio
public int sWidth = 690;
public int sHeight = 690;
public double r = sWidth / sHeight; // = r
// Some settings of the camera
public double dNear = 0.01;
public double dFar = 100;
public double fov = 90;
public Camera() {
// Sets the position of the camera in space
// The starting object should be in the middle, so everything is moved by half the screen
// The middle of the screen marks the origin (0 | 0)
posCam = new Vector(sWidth / 2, sHeight / 2, 0);
setProjection();
}
// This a perspective projection matrix, which is used to simulate the view of a camera
// Some things here are wrong and I still need to correct them
public void setProjection() {
double s = (1 / Math.tan(Math.toRadians(fov / 2)));
double range = dNear - dFar;
projMatrix = new double[][] {
{1 / (s * r), 0, 0, 0},
{0, 1 / s, 0, 0},
{0, 0, -range / range, 2 * dFar * dNear / range},
{0, 0, 1, 0}
};
}
// This method is used to update the meshes and their view relative to the camera
public Vector mProjToVec(Vector i, double[][] m) {
Vector v = new Vector(0, 0,0);
for (int j = 0; j < 3; j++) v.vec[j] = i.vec[0] * m[0][j] + i.vec[1] * m[1][j] + i.vec[2] * m[2][j] + m[3][j];
double w = i.vec[0] * m[0][3] + i.vec[1] * m[1][3] + i.vec[2] * m[2][3] + m[3][3];
if (w != 0) {
v.vec[0] /= w;
v.vec[1] /= w;
v.vec[2] /= w;
}
return v;
}
}
I think the issue has something to do with the z-axis and the location of the camera, but I am not sure and don't know how to fix it.
If you need the rest of the code from the project: (The code from these two classes need to be updates though, as it's not updated yet)