VR
Virtual Reality On-line   OpenGL
Новости   |     Журнал    |    Хаkер   |     Магазин   |   Проекты
[   Вход    ]
[Kарта сайтa]
[ Download  ]
[  Конкурс  ]
[  Анекдоты ]
[  Ссылки   ]
[  Реклама  ]
[ Почтальон ]
[ О проекте ]






TopList
OpenGL+Delphi
Генерация собственных примитивов
:

Представим, что нам надо нарисовать стол. В этом случае нам надо нарисовать четыре ножки, которые выглядят как кубы. Вроде ничего сложного, но куба среди примитивов OpenGL нет. Поэтому придёться каждый куб рисовать из шести квадратов. И так четыре раза. Не легче ли один раз создать ножку и использовать её в своей проге сколько угодно? Вот именно этому мы и научимся.

Для реализации задуманного я использовал пример из июльского номера. Посмотри на рисунок 1, чтобы освежить его в памяти. Я этот пример сейчас немного изнасилую.
Logo
Рис 1. Форма

На событие OnCreate добавим вот такую конструкцию:

glNewList(1,GL_COMPILE);
  glColor3f (0.0, 1.0, 0.0);
  glBegin(GL_QUAD_STRIP);
   glVertex3f(1.25,1.25,1);
   glVertex3f(1.25,-1.0,1);
   glVertex3f(-1,1.25,0);
   glVertex3f(-1,-1.0,0);
  glEnd;

  glColor3f (1.0, 1.0, 0.0);
  glBegin(GL_QUAD_STRIP);
   glVertex3f(1.0,1.0,0);
   glVertex3f(1.0,-1.25,0);
   glVertex3f(-1.25,1.0,1);
   glVertex3f(-1.25,-1.25,1);
  glEnd;
 glEndList;

Функция glNewList создаёт новый список (объект). Он работает как Begin, а концом для него служит glEndList. Всё, что находиться между этими двумя функциями - это вершины, или стороны создаваемого нового объекта. В моём случае - это простые два квадрата, которые пересекают друг друга (см рисунок 1).

Теперь разберёмся с параметрами функции glNewList. В качестве первого параметра выступает цифра, которая идентифицирует новый объект. Она изменяется от 1 до 255 и по этой цифре мы будем в дальнейшем обращаться к этому объекту. Второй параметр - константа, которая указывает, как будет создаваться объект. Она может быть только GL_COMPILE - создать объект или GL_COMPILE_AND_EXECUTE - создать объект и вывести на экран. Я в своём примере только создаю новый объект.

Теперь корректируем событие OnPaint


procedure TForm1.FormPaint(Sender: TObject);
var
 ps:TPaintStruct;
begin
 BeginPaint(Handle,ps);
 glClearColor(1,0.5,0.5,1);
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glRotated(45,1,0,0);

  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);

  glCallList(1);
  glTranslatef(2,2,0);
  glCallList(1);
  glTranslatef(-4,-4,2);
  glCallList(1);

 glFlush();
 swapBuffers(dc);
 EndPaint(Handle,ps);
end;

Здесь я теперь вместо рисования пересекающихся квадратов, просто вызываю созданный объект с помощью glCallList . В качестве параметра выступает номер объекта (я создавал объект 1, значит и здесь должна быть 1). Я делаю это три раза в разных позициях, чтобы пример был более наглядным. Пример готов, можно запустить его и посмотреть на результат.

Теперь я хочу немного улучшить наш пример. В разделе private главной формы TForm я объявил несколько переменных:


  private
    X,Y,Z:real;
    RX,RY,RZ:real;

В событии OnCreate я присваиваю всем этим переменным 0. После этого создадим новое событие OnKeyDown и напишем в нём:


procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 if Key =VK_RIGHT then
  X:=X+0.1;
 if Key =VK_LEFT then
  X:=X-0.1;
 if Key =VK_UP then
  Y:=Y+0.1;
 if Key =VK_DOWN then
  Y:=Y-0.1;

 if Key =VK_INSERT then
  RY:=RY-2;
 if Key =VK_DELETE then
  RY:=RY+2;

 if Key =VK_HOME then
  RX:=RX-2;
 if Key =VK_END then
  RX:=RX+2;

 FormPaint(nil);
end;

И наконец событие OnPaint корректирую так:


procedure TForm1.FormPaint(Sender: TObject);
var
 ps:TPaintStruct;
begin
 BeginPaint(Handle,ps);
 glClearColor(1,0.5,0.5,1);
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

 glPushMatrix;
  glRotated(45,1,0,0);
  glTranslatef(X,Y,Z);

  glRotated(RX,1,0,0);
  glRotated(RY,0,1,0);
  glRotated(RZ,0,0,1);

  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);

  glCallList(1);
  glTranslatef(2,2,0);
  glCallList(1);
  glTranslatef(-4,-4,2);
  glCallList(1);
 glPopMatrix;

 glFlush();
 swapBuffers(dc);
 EndPaint(Handle,ps);
end;

Можно запустить программу и посмотреть на результат. Попробуй понажимать на клавиши стрелок, Insert, Home, Delete, End. Если результат удовлетворил, то давай перейдём к рассмотрению новых функций. С функцией glRotated мы уже знакомы, это поворот сцены. GlTranslatef - перемещает сцену по координатам указанным в скобках (X,Y,Z).

На функциях glPushMatrix и glPopMatrix я остановлюсь подольше. Они очень даже интересны и очень полезны. Их назначение - сохранить и восстановить текущую матрицу перемещений.

Найди пример из июльского номера и запусти. Теперь попробуй полностью перекрыть окно и снова показать его. Сцена изменилась. Это произошло из-за того, что снова произошла прорисовка экрана, а мы использовали функцию поворота glRotated. Когда программа запустилась, то вызвалась функция glRotated и сцена повернулась на 45 градусов. После того, как ты перекрыл окно и снова показал, сцена перерисовалась и повернулась ещё на 45 градусов (всего уже 90). Как избавится от этого эффекта? Легко. Заключить все повороты (glRotated), перемещения (glTranslatef) и масштабирование (clScale) и рисование соответствующих объектов между glPushMatrix и glPopMatrix. Первая их них сохраняет текущую матрицу поворотов, перемещений и масштабирование. После этого можно смело рисовать. После вызова glPopMatrix, матрица восстановиться в состояние, которое было до вызова glPushMatrix.

В нашем случае, я сохраняю нулевую матрицу (потому что я ещё не производил никаких действий до вызова glPushMatrix). Потом рисую объекты и в конце восстанавливаю нулевую матрицу. Если перед вызовом glPushMatrix поместить glRotate(45,1,0,0) (поворот на 45 градусов), то сохраниться матрица, в которой есть только этот поворот. После восстановления в матрице опять будет только этот поворот. Все действия между glPushMatrix и glPopMatrix будут отменены.

Вроде всё. Мы сегодня и так поработали слишком хорошо. Продолжим наши занятия в следующий раз, а пока играйся с новым примером. До встречи.

 Исходники примера забирай здесь Заголовочные файлы возьми на моей страничке в разделе "Полезности".


Copyright©: Horrific aka Флёнов Михаил
Design by FMk group©