使用 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 的变换
1 和 2: 我不明白这部分,就像描绘立方体的直线和顶点一样
绘制 1 和 2 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);
解决问题...
我正在尝试将这个 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 的变换
1 和 2: 我不明白这部分,就像描绘立方体的直线和顶点一样
绘制 1 和 2 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);
解决问题...