unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls,
BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes, LCLType;
const
CubeSize = 600;
type
TVec3 = record
x, y, z: Single;
end;
{ TForm1 }
TForm1 = class(TForm)
BGRAVirtualScreen1: TBGRAVirtualScreen;
Timer1: TTimer;
procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure Timer1Timer(Sender: TObject);
private
public
end;
var
Form1: TForm1;
AngleX, AngleY, AngleZ: Single;
CubePoints: array[0..7] of TVec3 = (
(x:-1; y:-1; z:-1), (x:1; y:-1; z:-1),
(x:1; y:1; z:-1), (x:-1; y:1; z:-1),
(x:-1; y:-1; z:1), (x:1; y:-1; z:1),
(x:1; y:1; z:1), (x:-1; y:1; z:1)
);
implementation
{$R *.lfm}
procedure DrawCube(Bitmap: TBGRABitmap; AngleX, AngleY, AngleZ: Single);
const
Edges: array[0..11, 0..1] of Integer = (
(0,1), (1,2), (2,3), (3,0),
(4,5), (5,6), (6,7), (7,4),
(0,4), (1,5), (2,6), (3,7)
);
var
i: Integer;
Rotated: array[0..7] of TVec3;
Projected: array[0..7] of TPoint;
cx, cy: Integer;
x1, y1, z1: Single;
p1, p2: TPoint;
begin
cx := Bitmap.Width div 2;
cy := Bitmap.Height div 2;
for i := 0 to 7 do
begin
x1 := CubePoints[i].x;
y1 := CubePoints[i].y;
z1 := CubePoints[i].z;
// Rotation X
Rotated[i].y := y1 * cos(AngleX) - z1 * sin(AngleX);
Rotated[i].z := y1 * sin(AngleX) + z1 * cos(AngleX);
y1 := Rotated[i].y;
z1 := Rotated[i].z;
// Rotation Y
Rotated[i].x := x1 * cos(AngleY) + z1 * sin(AngleY);
Rotated[i].z := -x1 * sin(AngleY) + z1 * cos(AngleY);
x1 := Rotated[i].x;
z1 := Rotated[i].z;
// Rotation Z
Rotated[i].x := x1 * cos(AngleZ) - y1 * sin(AngleZ);
Rotated[i].y := x1 * sin(AngleZ) + y1 * cos(AngleZ);
// Projection
Projected[i].X := Round(cx + (Rotated[i].x * CubeSize) / (Rotated[i].z + 5));
Projected[i].Y := Round(cy + (Rotated[i].y * CubeSize) / (Rotated[i].z + 5));
end;
for i := 0 to 11 do
begin
p1 := Projected[Edges[i][0]];
p2 := Projected[Edges[i][1]];
// Bitmap.DrawLineAntialias(p1.X, p1.Y, p2.X, p2.Y, BGRA(255, 255, 255), 6);
Bitmap.DrawLine(p1.X, p1.Y, p2.X, p2.Y, BGRA(255, 255, 255),false);
Bitmap.DrawLine(4+p2.X, 4+p2.Y, p1.X+4, p1.Y+4, BGRA(255, 0, 0),false);
end;
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled := True;
Timer1.Interval := 15*2; // Amiga500 68000 vector rotation speed in 1986 !
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
);
begin
case Key of
VK_LEFT: AngleY -= 0.03;
VK_RIGHT: AngleY += 0.03;
VK_UP: AngleX -= 0.03;
VK_DOWN: AngleX += 0.03;
end;
BGRAVirtualScreen1.RedrawBitmap;
end;
procedure TForm1.BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
begin
DrawCube(Bitmap, AngleX, AngleY, AngleZ);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
//AngleX += 0.020;
//AngleY += 0.030;
AngleZ += 0.030;
BGRAVirtualScreen1.RedrawBitmap;
end;
end.