unit DrawCubeBoxUnit; interface uses Winapi.Windows, Winapi.MMSystem, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Forms, Vcl.ExtCtrls; type TForm1 = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure FormPaint(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClick(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} type // 頂点座標格納用 TMyPoint3D = record x, y, Z: Double; end; // 辺情報格納用 TEdge = record P1, P2: Integer; end; var ang_x: Double; ang_y: Double; prevTime: DWORD; vertexs: TArray; edges: TArray; procedure AddVertex(x, y, Z: Double); var i: Integer; begin i := Length(vertexs); SetLength(vertexs, i + 1); vertexs[i].x := x; vertexs[i].y := y; vertexs[i].Z := Z; end; procedure AddEdge(P1, P2: Integer); var i: Integer; begin i := Length(edges); SetLength(edges, i + 1); edges[i].P1 := P1; edges[i].P2 := P2; end; procedure TForm1.FormClick(Sender: TObject); begin Application.Terminate; end; procedure TForm1.FormCreate(Sender: TObject); const FULLSCR_ENABLE: Boolean = False; begin // タイマーの精度を1msに変更 timeBeginPeriod(1); prevTime := timeGetTime; if FULLSCR_ENABLE then begin // フルスクリーン表示を設定 self.BorderStyle := bsNone; self.Left := 0; self.Top := 0; self.Width := Screen.Width; self.Height := Screen.Height; // 最前面表示 self.FormStyle := fsStayOnTop; end; self.DoubleBuffered := True; Timer1.Interval := 15; // 頂点を定義 AddVertex(-50, -50, -50); // 0 AddVertex(50, -50, -50); // 1 AddVertex(50, 50, -50); // 2 AddVertex(-50, 50, -50); // 3 AddVertex(-50, -50, 50); // 4 AddVertex(50, -50, 50); // 5 AddVertex(50, 50, 50); // 6 AddVertex(-50, 50, 50); // 7 // 辺を定義 AddEdge(0, 1); AddEdge(1, 2); AddEdge(2, 3); AddEdge(3, 0); AddEdge(4, 5); AddEdge(5, 6); AddEdge(6, 7); AddEdge(7, 4); AddEdge(0, 4); AddEdge(1, 5); AddEdge(2, 6); AddEdge(3, 7); end; procedure TForm1.FormDestroy(Sender: TObject); begin // タイマーの精度を元に戻す timeEndPeriod(1); vertexs := nil; edges := nil; end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin Application.Terminate; end; procedure TForm1.Timer1Timer(Sender: TObject); begin // 描画を要求 self.Invalidate; end; procedure TForm1.FormPaint(Sender: TObject); var i: Integer; v: Integer; x, y, Z, x1, y1, z1, x2, y2, z2: Double; sX, cX, sY, cY: Double; pnts: TArray; scale: Double; count: Integer; t: DWORD; dt: Double; begin // 経過時間(単位は秒)を取得 t := timeGetTime; dt := (t - prevTime) / 1000.0; prevTime := t; ang_x := ang_x + 0.5 * dt; ang_y := ang_y + 1.5 * dt; count := Length(vertexs); if count = 0 then Exit; sX := Sin(ang_x); cX := Cos(ang_x); sY := Sin(ang_y); cY := Cos(ang_y); SetLength(pnts, count); scale := self.ClientHeight / 300; for i := 0 to count - 1 do begin x := vertexs[i].x; y := vertexs[i].y; Z := vertexs[i].Z; // rotate x y1 := y * cX - Z * sX; z1 := y * sX + Z * cX; x1 := x; // rotate y x2 := x1 * cY + z1 * sY; z2 := -x1 * sY + z1 * cY; y2 := y1; pnts[i].x := Round(scale * ((x2 * 300) / (z2 + 200)) + ClientWidth / 2); pnts[i].y := Round(scale * ((y2 * 300) / (z2 + 200)) + ClientHeight / 2); end; // 背景を消去 Canvas.Brush.Color := clBlack; Canvas.FillRect(ClientRect); // 線を描画 for v := 10 downto 1 do begin Canvas.Pen.Color := RGB(Round(128 / v), Round(255 / v), Round(128 / v)); Canvas.Pen.Width := v * 3; for i := 0 to Length(edges) - 1 do begin Canvas.MoveTo(pnts[edges[i].P1].x, pnts[edges[i].P1].y); Canvas.LineTo(pnts[edges[i].P2].x, pnts[edges[i].P2].y); end; end; end; end.