使用 Java AWT 在 2D Canvas 上渲染 3D 对象

Rendering 3D objects on 2D Canvas using Java AWT

我正在尝试将这个 JS code 移植到 Java 上,因为我厌倦了为我的 2D Java 游戏编写原型,我想将我的游戏制作成 3D,然后我遇到了这个奇怪的渲染错误,我认为我的数学或逻辑不对...

示例数据:

Cube: x = 79.78739, y = 102.75975, z = -42.678993

1: x = 31.787392, y = 54.75975, z = -90.67899
2: x = 127.78739, y = 54.75975, z = -90.67899

1 Project: x = 359.64944, y = 339.39612
2 Project: x = 358.59076, y = 339.39612

1: x = 127.78739, y = 54.75975, z = -90.67899
2: x = 127.78739, y = 150.75975, z = -90.67899

1 Project: x = 358.59076, y = 339.39612
2 Project: x = 358.59076, y = 338.33743

1: x = 127.78739, y = 150.75975, z = -90.67899
2: x = 31.787392, y = 150.75975, z = -90.67899

1 Project: x = 358.59076, y = 338.33743
2 Project: x = 359.64944, y = 338.33743

1: x = 31.787392, y = 150.75975, z = -90.67899
2: x = 31.787392, y = 54.75975, z = -90.67899

1 Project: x = 359.64944, y = 338.33743
2 Project: x = 359.64944, y = 339.39612

1: x = 31.787392, y = 150.75975, z = -90.67899
2: x = 31.787392, y = 150.75975, z = 5.321007

1 Project: x = 359.64944, y = 338.33743
2 Project: x = 365.97394, y = 368.33295

1: x = 127.78739, y = 150.75975, z = -90.67899
2: x = 127.78739, y = 150.75975, z = 5.321007

1 Project: x = 358.59076, y = 338.33743
2 Project: x = 384.01562, y = 368.33295

1: x = 31.787392, y = 54.75975, z = -90.67899
2: x = 31.787392, y = 54.75975, z = 5.321007

1 Project: x = 359.64944, y = 339.39612
2 Project: x = 365.97394, y = 350.29123

1: x = 127.78739, y = 54.75975, z = -90.67899
2: x = 127.78739, y = 54.75975, z = 5.321007

1 Project: x = 358.59076, y = 339.39612
2 Project: x = 384.01562, y = 350.29123

1: x = 31.787392, y = 150.75975, z = 5.321007
2: x = 127.78739, y = 150.75975, z = 5.321007

1 Project: x = 365.97394, y = 368.33295
2 Project: x = 384.01562, y = 368.33295

1: x = 31.787392, y = 150.75975, z = 5.321007
2: x = 31.787392, y = 54.75975, z = 5.321007

1 Project: x = 365.97394, y = 368.33295
2 Project: x = 365.97394, y = 350.29123

1: x = 127.78739, y = 150.75975, z = 5.321007
2: x = 127.78739, y = 54.75975, z = 5.321007

1 Project: x = 384.01562, y = 368.33295
2 Project: x = 384.01562, y = 350.29123

1: x = 31.787392, y = 54.75975, z = 5.321007
2: x = 127.78739, y = 54.75975, z = 5.321007

1 Project: x = 365.97394, y = 350.29123
2 Project: x = 384.01562, y = 350.29123

图例:

立方体: 实际的立方体,具有 x、y、z 的变换

12: 我不明白这部分,就像描绘立方体的直线和顶点一样

绘制 12 returns 这个:

1 Project and 2 Project: 我认为要画的线(1 Project是起点,2 Project是终点端点)

绘制 1 项目2 项目 returns 这个:

代码:

public class JavaTestClassForWhosebug {
    // dimension
    public static int WIDTH = 720, HEIGHT = 1360/2;
    // 3D stuff
    float PROJECTION_CENTER_X = WIDTH / 2f;
    float PROJECTION_CENTER_Y = HEIGHT / 2f;
    float FIELD_OF_VIEW = WIDTH * 0.8f;
    // cube const
    int[][] CUBE_LINES = {{0, 1}, {1, 3}, {3, 2}, {2, 0}, {2, 6}, {3, 7}, {0, 4}, {1, 5}, {6, 7}, {6, 4}, {7, 5}, {4, 5}};
    int[][] CUBE_VERTICES = {{-1, -1, -1}, {1, -1, -1}, {-1, 1, -1}, {1, 1, -1}, {-1, -1, 1}, {1, -1, 1}, {-1, 1, 1}, {1, 1, 1}};

    class Cube {
        public float x, y, z, radius;

        public Cube(){
            x = (float)((Math.random() - 0.5) * WIDTH);
            y = (float)((Math.random() - 0.5) * WIDTH);
            z = (float)((Math.random() - 0.5) * WIDTH);
            radius = (float)(Math.floor(Math.random() * 100 + 10));
        }

        class v {
            public float x;
            public float y;
            public float z;

            public v(float x, float y, float z){
                this.x = x;
                this.y = y;
                this.z = z;
            }
        }

        public void tick(){}

        public v project(float x, float y, float z){
            float scaleProjected = FIELD_OF_VIEW / (FIELD_OF_VIEW * z);
            float xProjected = (x * scaleProjected) + PROJECTION_CENTER_X;
            float yProjected = (y * scaleProjected) + PROJECTION_CENTER_Y;

            return new v(xProjected, yProjected, scaleProjected);
        }
        public void render(Graphics g){
            if (z < - FIELD_OF_VIEW + radius)
                return;

            System.out.println("Cube: x = " + x + ", y = " + y + ", z = " + z + "\n");

            for (int i = 0; i < CUBE_LINES.length; i++){

                v v1 = new v(x + (radius * CUBE_VERTICES[CUBE_LINES[i][0]][0]),
                             y + (radius * CUBE_VERTICES[CUBE_LINES[i][0]][1]),
                             z + (radius * CUBE_VERTICES[CUBE_LINES[i][0]][2]));

                v v2 = new v(x + (radius * CUBE_VERTICES[CUBE_LINES[i][1]][0]),
                             y + (radius * CUBE_VERTICES[CUBE_LINES[i][1]][1]),
                             z + (radius * CUBE_VERTICES[CUBE_LINES[i][1]][2]));

                System.out.println("1: x = " + v1.x + ", y = " + v1.y + ", z = " + v1.z);
                System.out.println("2: x = " + v2.x + ", y = " + v2.y + ", z = " + v2.z + "\n");

                v v1Project = project(v1.x, v1.y, v1.z);
                v v2Project = project(v2.x, v2.y, v2.z);

                System.out.println("1 Project: x = " + v1Project.x + ", y = " + v1Project.y);
                System.out.println("2 Project: x = " + v2Project.x + ", y = " + v2Project.y + "\n");

                g.setColor(Color.GREEN);
                g.drawLine((int)v1Project.x, (int)v1Project.y, (int)v2Project.x, (int)v2Project.y);
            }
        }
    }
}

改变

float scaleProjected = FIELD_OF_VIEW / (FIELD_OF_VIEW * z);

float scaleProjected = FIELD_OF_VIEW / (FIELD_OF_VIEW + z);

解决问题...