Я установил простой 3D-рендеринг в Java, который позволяет проецировать 3D-куб на заданную 2D-панель. Теперь я на шаге, когда я хотел бы повернуть этот куб, чтобы продемонстрировать 3D. Однако, как только я добавлю к нему вращение, углы, которые образуют треугольники, больше не «синхронизируются», и я получаю странные перекрывающиеся вершины.
Это делается с использованием только двух вершин, чтобы ясно показать проблему.
Я не уверен, как это исправить.
Пока это мой код.
meshCube = new mesh();
proj.m[0][0]= fAspectRatio *fFovRad;
proj.m[1][1]= fFovRad;
proj.m[2][2]= fFar / (fFar-fNear);
proj.m[3][2]=(-fFar*fNear)/(fFar-fNear);
proj.m[2][3]=1.0f;
proj.m[3][3] = 0.0f;
// SOUTH
meshCube.tris.add(new triangle(new vector(0.0f,0.0f,0.0f), new vector(0.0f,1.0f,0.0f), new vector(1.0f,1.0f,0.0f)));
meshCube.tris.add(new triangle(new vector(0.0f,0.0f,0.0f), new vector(1.0f,1.0f,0.0f), new vector(1.0f,0.0f,0.0f)));
// EAST
meshCube.tris.add(new triangle(new vector(1.0f,0.0f,0.0f), new vector(1.0f,1.0f,0.0f), new vector(1.0f,1.0f,1.0f)));
meshCube.tris.add(new triangle(new vector(1.0f,0.0f,0.0f), new vector(1.0f,1.0f,1.0f), new vector(1.0f,0.0f,1.0f)));
/*
// NORTH
meshCube.tris.add(new triangle(new vector(1.0f,0.0f,1.0f), new vector(1.0f,1.0f,1.0f), new vector(0.0f,1.0f,1.0f)));
meshCube.tris.add(new triangle(new vector(1.0f,0.0f,1.0f), new vector(0.0f,1.0f,1.0f), new vector(0.0f,0.0f,1.0f)));
// WEST
meshCube.tris.add(new triangle(new vector(0.0f,0.0f,1.0f), new vector(0.0f,1.0f,1.0f), new vector(0.0f,1.0f,0.0f)));
meshCube.tris.add(new triangle(new vector(0.0f,0.0f,1.0f), new vector(0.0f,1.0f,0.0f), new vector(0.0f,0.0f,0.0f)));
// TOP
meshCube.tris.add(new triangle(new vector(0.0f,1.0f,0.0f), new vector(0.0f,1.0f,1.0f), new vector(1.0f,1.0f,1.0f)));
meshCube.tris.add(new triangle(new vector(0.0f,1.0f,0.0f), new vector(1.0f,1.0f,1.0f), new vector(1.0f,1.0f,0.0f)));
// BOTTOM
meshCube.tris.add(new triangle(new vector(1.0f,0.0f,1.0f), new vector(0.0f,0.0f,1.0f), new vector(0.0f,0.0f,0.0f)));
meshCube.tris.add(new triangle(new vector(1.0f,0.0f,1.0f), new vector(0.0f,0.0f,0.0f), new vector(1.0f,0.0f,0.0f)));*/
JPanel renderPanel = new JPanel() {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setColor(Color.WHITE);
for (triangle t : meshCube.tris) {
triangle triRotatedZ = new triangle(t.p[0],t.p[1],t.p[2]);
long finish = System.nanoTime();
long timeElapsed = finish - start;
fTheta += 0.1f * 1.0f; //This should really be fTheta += 1.0f * timeElapsed; but doesn't seem to work that way.
System.out.println(fTheta);
mat4x4 matRotZ = new mat4x4();
mat4x4 matRotX = new mat4x4();
matRotZ.m[0][0] = (float)Math.cos(fTheta);
matRotZ.m[0][1] = (float)Math.sin(fTheta);
matRotZ.m[1][0] = (float)-Math.sin(fTheta);
matRotZ.m[1][1] = (float)Math.cos(fTheta);
matRotZ.m[2][2] = 1;
matRotZ.m[3][3] = 1;
matRotX.m[0][0] = 1;
matRotX.m[1][1] = (float)Math.cos((fTheta*0.5f));
matRotX.m[1][2] = (float)Math.sin((fTheta*0.5f));
matRotX.m[2][1] = (float)-Math.sin((fTheta*0.5f));
matRotX.m[2][2] = (float)Math.cos((fTheta*0.5f));
matRotX.m[3][3] = 1;
triRotatedZ.p[0] = multiplyMatrixVector(t.p[0],matRotZ);
triRotatedZ.p[1] = multiplyMatrixVector(t.p[1],matRotZ);
triRotatedZ.p[2] = multiplyMatrixVector(t.p[2],matRotZ);
triangle triRotatedZX = new triangle(triRotatedZ.p[0],triRotatedZ.p[1],triRotatedZ.p[2]);
triRotatedZX.p[0] = multiplyMatrixVector(triRotatedZ.p[0],matRotX);
triRotatedZX.p[1] = multiplyMatrixVector(triRotatedZ.p[1],matRotX);
triRotatedZX.p[2] = multiplyMatrixVector(triRotatedZ.p[2],matRotX);
triangle triTranslated = new triangle(triRotatedZX.p[0],triRotatedZX.p[1],triRotatedZX.p[2]);
triTranslated.p[0].z = triRotatedZX.p[0].z + 3.0f;
triTranslated.p[1].z = triRotatedZX.p[1].z + 3.0f;
triTranslated.p[2].z = triRotatedZX.p[2].z + 3.0f;
triangle triProjected = new triangle(triTranslated.p[0],triTranslated.p[1],triTranslated.p[2]);
triProjected.p[0] = multiplyMatrixVector(triTranslated.p[0],proj);
triProjected.p[1] = multiplyMatrixVector(triTranslated.p[1],proj);
triProjected.p[2] = multiplyMatrixVector(triTranslated.p[2],proj);
// Scale into view
triProjected.p[0].x += 1.0f;
triProjected.p[0].y += 1.0f;
triProjected.p[1].x += 1.0f;
triProjected.p[1].y += 1.0f;
triProjected.p[2].x += 1.0f;
triProjected.p[2].y += 1.0f;
triProjected.p[0].x *= 0.5f * 500.0f;
triProjected.p[0].y *= 0.5f * 500.0f;
triProjected.p[1].x *= 0.5f * 500.0f;
triProjected.p[1].y *= 0.5f * 500.0f;
triProjected.p[2].x *= 0.5f * 500.0f;
triProjected.p[2].y *= 0.5f * 500.0f;
Path2D path = new Path2D.Double();
path.moveTo(triProjected.p[0].x, triProjected.p[0].y);
path.lineTo(triProjected.p[1].x, triProjected.p[1].y);
path.lineTo(triProjected.p[2].x, triProjected.p[2].y);
path.closePath();
g2.draw(path);
}
}
};
Код для умножения матриц:
public static vector multiplyMatrixVector(vector in, mat4x4 m){
vector out = new vector(0,0,0);
out.x = in.x * m.m[0][0] + in.y * m.m[1][0] + in.z * m.m[2][0] + m.m[3][0];
out.y = in.x * m.m[0][1] + in.y * m.m[1][1] + in.z * m.m[2][1] + m.m[3][1];
out.z = in.x * m.m[0][2] + in.y * m.m[1][2] + in.z * m.m[2][2] + m.m[3][2];
float w = in.x * m.m[0][3] + in.y * m.m[1][3] + in.z * m.m[2][3] + m.m[3][3];
if(w!=0.0f) {
out.x /= w;
out.y /= w;
out.z /= w;
return out;
}
System.out.println("W is 0.");
return out;
}