實作一個可透過滑鼠拖曳旋轉的 3D 線框立方體。使用簡單的 3D 旋轉矩陣 (X/Y 軸旋轉) 將 3D 座標投影至 2D 平面,繪製 6 個面的多邊形。滑鼠事件監聽器根據位移量更新旋轉角度並觸發重繪。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Gr3d1m extends JFrame
implements MouseListener, MouseMotionListener {
int dragX, dragY, angX = 30, angY = 30;
CubeData data = new CubeData();
Color[] colors = {Color.gray, Color.cyan, Color.green, Color.red,
Color.white, Color.orange, Color.magenta, Color.pink};
public static void main(String[] args) { new Gr3d1m(); }
public Gr3d1m() {
setTitle("3D Cube Wireframe");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
addMouseListener(this); addMouseMotionListener(this);
setBackground(new Color(128, 128, 255));
setSize(350, 350);
setVisible(true);
}
public void mousePressed(MouseEvent e) { dragX = e.getX(); dragY = e.getY(); }
public void mouseDragged(MouseEvent e) {
angX += e.getY() - dragY;
angY += e.getX() - dragX;
dragX = e.getX(); dragY = e.getY();
repaint();
}
// 其他 MouseListener/MouseMotionListener 方法留空
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void paint(Graphics g) {
clear(g);
for (int i = 0; i < data.x.length; i++) {
drawFace(g, data.x[i], data.y[i], data.z[i], 150, 150, colors[i]);
}
g.setColor(Color.YELLOW);
g.drawString("X=" + (angX%360) + " Y=" + (angY%360), 10, getSize().height-30);
}
void clear(Graphics g) {
Insets in = getInsets();
g.setColor(new Color(128, 128, 255));
g.fillRect(in.left, in.top, 350, 350);
}
void drawFace(Graphics g, double[] x, double[] y, double[] z,
int cx, int cy, Color c) {
double radX = Math.toRadians(angX), radY = Math.toRadians(angY);
double sinX = Math.sin(radX), cosX = Math.cos(radX);
double sinY = Math.sin(radY), cosY = Math.cos(radY);
int n = x.length;
int[] xs = new int[n], ys = new int[n];
for (int i = 0; i < n; i++) {
double x1 = x[i]*cosY + z[i]*sinY;
double z1 = -x[i]*sinY + z[i]*cosY;
double y1 = y[i]*cosX - z1*sinX;
xs[i] = cx + (int)Math.round(x1);
ys[i] = cy - (int)Math.round(y1);
}
g.setColor(c);
g.drawPolygon(xs, ys, n);
}
}
class CubeData {
double[][] x = new double[6][4];
double[][] y = new double[6][4];
double[][] z = new double[6][4];
CubeData() {
// 定義立方體 6 個面的 4 個頂點 (省略詳細座標)
}
}
教學重點: