105 lines
3.3 KiB
Ada
105 lines
3.3 KiB
Ada
with Ada.Numerics.Elementary_Functions;
|
|
|
|
with SDL.Video.Windows.Makers;
|
|
with SDL.Video.Renderers.Makers;
|
|
with SDL.Events.Events;
|
|
|
|
procedure Rotating_Cube is
|
|
|
|
Width : constant := 500;
|
|
Height : constant := 500;
|
|
Offset : constant := 500.0 / 2.0;
|
|
|
|
Window : SDL.Video.Windows.Window;
|
|
Renderer : SDL.Video.Renderers.Renderer;
|
|
Event : SDL.Events.Events.Events;
|
|
Quit : Boolean := False;
|
|
|
|
type Node_Id is new Natural;
|
|
type Point_3D is record X, Y, Z : Float; end record;
|
|
type Edge_Type is record A, B : Node_Id; end record;
|
|
|
|
Nodes : array (Node_Id range <>) of Point_3D :=
|
|
((-100.0, -100.0, -100.0), (-100.0, -100.0, 100.0), (-100.0, 100.0, -100.0),
|
|
(-100.0, 100.0, 100.0), (100.0, -100.0, -100.0), (100.0, -100.0, 100.0),
|
|
(100.0, 100.0, -100.0), (100.0, 100.0, 100.0));
|
|
Edges : constant array (Positive range <>) of Edge_Type :=
|
|
((0, 1), (1, 3), (3, 2), (2, 0), (4, 5), (5, 7),
|
|
(7, 6), (6, 4), (0, 4), (1, 5), (2, 6), (3, 7));
|
|
|
|
use Ada.Numerics.Elementary_Functions;
|
|
|
|
procedure Rotate_Cube (AngleX, AngleY : in Float) is
|
|
SinX : constant Float := Sin (AngleX);
|
|
CosX : constant Float := Cos (AngleX);
|
|
SinY : constant Float := Sin (AngleY);
|
|
CosY : constant Float := Cos (AngleY);
|
|
X, Y, Z : Float;
|
|
begin
|
|
for Node of Nodes loop
|
|
X := Node.X;
|
|
Y := Node.Y;
|
|
Z := Node.Z;
|
|
Node.X := X * CosX - Z * SinX;
|
|
Node.Z := Z * CosX + X * SinX;
|
|
Z := Node.Z;
|
|
Node.Y := Y * CosY - Z * SinY;
|
|
Node.Z := Z * CosY + Y * SinY;
|
|
end loop;
|
|
end Rotate_Cube;
|
|
|
|
function Poll_Quit return Boolean is
|
|
use type SDL.Events.Event_Types;
|
|
begin
|
|
while SDL.Events.Events.Poll (Event) loop
|
|
if Event.Common.Event_Type = SDL.Events.Quit then
|
|
return True;
|
|
end if;
|
|
end loop;
|
|
return False;
|
|
end Poll_Quit;
|
|
|
|
procedure Draw_Cube (Quit : out Boolean) is
|
|
use SDL.C;
|
|
Pi : constant := Ada.Numerics.Pi;
|
|
Xy1, Xy2 : Point_3D;
|
|
begin
|
|
Rotate_Cube (Pi / 4.0, Arctan (Sqrt (2.0)));
|
|
for Frame in 0 .. 359 loop
|
|
Renderer.Set_Draw_Colour ((0, 0, 0, 255));
|
|
Renderer.Fill (Rectangle => (0, 0, Width, Height));
|
|
|
|
Renderer.Set_Draw_Colour ((0, 220, 0, 255));
|
|
for Edge of Edges loop
|
|
Xy1 := Nodes (Edge.A);
|
|
Xy2 := Nodes (Edge.B);
|
|
Renderer.Draw (Line => ((int (Xy1.X + Offset), int (Xy1.Y + Offset)),
|
|
(int (Xy2.X + Offset), int (Xy2.Y + Offset))));
|
|
end loop;
|
|
Rotate_Cube (Pi / 180.0, 0.0);
|
|
Window.Update_Surface;
|
|
Quit := Poll_Quit;
|
|
exit when Quit;
|
|
delay 0.020;
|
|
end loop;
|
|
end Draw_Cube;
|
|
|
|
begin
|
|
if not SDL.Initialise (Flags => SDL.Enable_Screen) then
|
|
return;
|
|
end if;
|
|
|
|
SDL.Video.Windows.Makers.Create (Win => Window,
|
|
Title => "Rotating cube",
|
|
Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
|
|
Size => SDL.Positive_Sizes'(Width, Height),
|
|
Flags => 0);
|
|
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
|
|
|
|
while not Quit loop
|
|
Draw_Cube (Quit);
|
|
end loop;
|
|
|
|
Window.Finalize;
|
|
SDL.Finalise;
|
|
end Rotating_Cube;
|