使用 Java AWT/Swing 實現一個可滑鼠拖曳旋轉的 3D 立方體,包含面填充著色、背面剔除(隱藏面消除)、透視投影與即時重繪。代碼結構清晰,適合學習 3D 圖形學基礎與 Java 形繪製機制。
Gr3d1m:基礎框架視窗,處理滑鼠事件、座標變換、線框繪製Gr3d4a:繼承基礎類,覆寫繪製方法實現面填充與背面剔除Cube:資料類,定義立方體 6 個面的 3D 頂點座標(此處省略,假設已定義)
// 旋轉角度轉弧度
final double RAD = Math.PI / 180.0;
double a = angX * RAD, b = angY * RAD;
double sinA = Math.sin(a), sinB = Math.sin(b);
double cosA = Math.cos(a), cosB = Math.cos(b);
// 每個頂點旋轉變換
for (int i = 0; i < len; i++) {
double x1 = x[i] * cosB + z[i] * sinB;
double z0 = -x[i] * sinB + z[i] * cosB;
double y1 = y[i] * cosA - z0 * sinA;
// 投影至 2D 螢幕座標
xx[i] = xp + (int) Math.rint(x1);
yy[i] = yp - (int) Math.rint(y1);
// 保留旋轉後 3D 座標供背面剔除使用
xw[i] = x1; yw[i] = y1;
}
// 計算面法線向量 Z 分量(投影平面為 XY)
// 頂點順序需符合右手定則(逆時針為正面)
double Hvec(double[] x, double[] y) {
// 三角形面外積公式簡化:x0(y1-y2) + x1(y2-y0) + x2(y0-y1)
return x[0]*(y[1]-y[2]) + x[1]*(y[2]-y[0]) + x[2]*(y[0]-y[1]);
}
// 繪製前檢查
if (Hvec(xw, yw) > 0) { // 法線指向觀察者(正面)
g.setColor(color);
g.fillPolygon(xx, yy, len); // 填充多邊形
}
// 實作 MouseListener, MouseMotionListener
public void mousePressed(MouseEvent e) { doX = e.getX(); doY = e.getY(); }
public void mouseDragged(MouseEvent e) {
angX += e.getY() - doY; // 垂直拖曳 → X 軸旋轉
angY += e.getX() - doX; // 水平拖曳 → Y 軸旋轉
doX = e.getX(); doY = e.getY();
repaint(); // 觸發重繪
}
// 其餘事件方法留空...
public void paint(Graphics g) {
delDeaw(g); // 擦除背景
for (int i = 0; i < data.x.length; i++) {
drawPG(g, data.x[i], data.y[i], data.z[i], 150, 150, Col[i]);
}
// 顯示當前旋轉角度
g.setColor(Color.YELLOW);
g.drawString("X=" + angX%360 + " Y=" + angY%360, 10, getSize().height-30);
}
private void delDeaw(Graphics g) {
Insets insets = getInsets();
g.setColor(new Color(128,128,255)); // 背景色
g.fillRect(insets.left, insets.top, 350, 350);
}
javac Gr3d1m.java Gr3d4a.java Cube.java
java Gr3d4a
滑鼠拖曳視窗即可旋轉立方體,角度即時顯示於左下角。