unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls,OpenGL;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormResize(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    hrc:HGLRC; // Дописать строчку "hrc:HGLRC" в раздел "private"
    DC : HDC;  // И еще одну строчку (Device Context)
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  anglex,anglez, angley, st, bi, bj: integer;
  filled, stop: boolean;
  r, rr: real;
  a, b, x, y, z: real;
implementation

{$R *.DFM}

procedure SetDCPixelFormat (hdc : HDC);     // Это процедура задания формата пикселей
var pfd : TPixelFormatDescriptor;           // Ее нужно полностью написать самому
    nPixelFormat : Integer;
begin
 FillChar (pfd, SizeOf (pfd), 0);
 // Следующие строки разрешают рисование в окне, включают поддержку видеокартой режима
 // OpenGL и включают двойную буферизацию (чтобы изображение не моргало)
 pfd.dwFlags  := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
 nPixelFormat := ChoosePixelFormat (hdc, @pfd);
 SetPixelFormat (hdc, nPixelFormat, @pfd);
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  InvalidateRect(Handle,nil,False); // Перерисовать экран (вызвать процедуру FormPaint)
end;

procedure TForm1.FormPaint(Sender: TObject);
var i, j, k:integer;
begin
  glViewPort(0,0,ClientWidth,ClientHeight); // Указываем, какая часть экрана будет
           // использоваться для отображения "картинки" OpenGL (сейчас - весь экран)
  glClearColor(0.0,0.5,0.2,1);  // Задаем цвет очистки экрана (как яркости RGB, от 0 до 1)
  glClear(GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT);    // Очищаем буфер цвета и Z-буфер
  glEnable(GL_DEPTH_TEST);              // Включаем режим отслеживания глубины объектов
  glLoadIdentity;
  glRotatef(anglez,0,0,1);
  glRotatef(anglex,1,0,0);
  glRotatef(angley,0,1,0);
  // Сюда и пишем, собственно, программу рисования изображения средствами OpenGL
  glColor3f(1,0,0);
         // Задать цвет следующих вершин
  if filled then
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
  else
    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

case st of
1:
begin
  glBegin(GL_TRIANGLE_FAN);
  glVertex3f(0,0,0);
  for i:= 0 to 40 do
   begin
   glVertex3f(sin((i/40)*2*PI),cos((i/40)*2*PI),0);
   end;
  glEnd;
  glBegin(GL_TRIANGLE_FAN);
  glVertex3f(0,0,0.5);
  for i:= 0 to 40 do
   begin
   glVertex3f(sin(i/40*2*PI),cos(i/40*2*PI),0);
   end;
  glEnd;
end;
2:
begin
glBegin(GL_TRIANGLE_FAN);
  glVertex3f(0,0,0);
  for i:= 0 to 40 do
   begin
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,0);
   end;
  glEnd;
glBegin(GL_TRIANGLE_FAN);
  glVertex3f(0,0,0.5);
  for i:= 0 to 40 do
   begin
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,0.5);
   end;
  glEnd;
glColor3f(1,0,0);
glBegin(GL_QUADS);
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,0.5);
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,0);
  for i:= 0 to 40 do
   begin
   if i mod 2 = 0 then
    begin a:= 0; b:= 0.5; end
   else
    begin
    a:= 0.5; b:= 0;
    end;
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,a);
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,b);
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,a);
   glVertex3f(sin(i/40*2*PI)*0.5,cos(i/40*2*PI)*0.5,b);
   end;
  glEnd;
end;
3:
 begin
 r:= 0.4;
 bi:= 20;
 bj:= 20;
for i:= 0 to bi do
 begin
   glBegin(GL_QUAD_STRIP);
   glColor3f(1,0,0);
   for j:= 0 to bj do
    begin
      glVertex3f(r*sin( i   /bi*PI)*cos(j/bj*2*PI),r*sin(j/bj*2*PI)*sin( i   /bi*PI),r*cos( i   /bi*PI));
      glVertex3f(r*sin((i+1)/bi*PI)*cos(j/bj*2*PI),r*sin(j/bj*2*PI)*sin((i+1)/bi*PI),r*cos((i+1)/bi*PI));
    end;
    glEnd;
 end;
 end;
4:
 begin
 r:= 0.1;
 rr:= 0.8;
 for i:= 0 to 20 do
  begin
  glBegin(GL_QUAD_STRIP);
   for j:= 0 to 20 do
    begin
     glVertex3f((rr+r*cos(j/20*2*PI))*cos(i/20*2*PI),sin((j/20)*2*PI)*r,(rr+r*cos(j/20*2*PI))*sin(i/20*2*PI));
     glVertex3f((rr+r*cos(j/20*2*PI))*cos((i+1)/20*2*PI),sin((j/20)*2*PI)*r,(rr+r*cos(j/20*2*PI))*sin((i+1)/20*2*PI));
    end;
  glEnd;
  end;
 end;
end;
  SwapBuffers(DC);           // Меняем местами буферы (для более гладкой анимации)
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  case Key of
    #27: Close;
    'q': anglez:=anglez+5;
    'w': anglez:=anglez-5;
    'a': anglex:=anglex+5;
    'd': anglex:=anglex-5;
    'y': angley:= angley + 5;
    'c': begin st:= st + 1; if st = 6 then st:= 1; end;
    ' ': filled:=not filled;
    's': stop:= not stop;
  end;
  InvalidateRect(Handle,nil,False); // Перерисовать экран (вызвать процедуру FormPaint)
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DC := GetDC (Handle);                   // Получили контекст устройства
  SetDCPixelFormat(DC);                   // Установили формат пикселей
  hrc := wglCreateContext(DC);            // Создали указатель на контекст окна формы
  wglMakeCurrent(DC, hrc);                // Сделали форму текущим устройством рисования
  randomize;
  anglez:=0;
  anglex:=0;
  st:= 1;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if stop = false then
  begin
  anglez:=anglez+1;
  anglex:=anglex+1;
  angley:=angley+1;
  end;
  InvalidateRect(Handle,nil,False); // Если необходимо перерисовывать окно по таймеру
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(0, 0);
  wglDeleteContext(hrc);  // Удалить указатель на контекст окна формы
  ReleaseDC (Handle, DC);
  DeleteDC (DC);
end;


end.


