Рендеринг куба из треугольников дает странные углы поворота - PullRequest
1 голос
/ 08 марта 2019

Я установил простой 3D-рендеринг в Java, который позволяет проецировать 3D-куб на заданную 2D-панель. Теперь я на шаге, когда я хотел бы повернуть этот куб, чтобы продемонстрировать 3D. Однако, как только я добавлю к нему вращение, углы, которые образуют треугольники, больше не «синхронизируются», и я получаю странные перекрывающиеся вершины.

Two vertices of the cube

Это делается с использованием только двух вершин, чтобы ясно показать проблему. Я не уверен, как это исправить.

Пока это мой код.

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;
}

1 Ответ

1 голос
/ 08 марта 2019
for (triangle t : meshCube.tris) {
    …
    fTheta += 0.1f * 1.0f;

У вас есть новый угол камеры для каждого треугольника.Переместите расчет вашей матрицы за пределы цикла.

...