Опубликован: 02.12.2011 | Доступ: свободный | Студентов: 980 / 117 | Оценка: 5.00 / 4.00 | Длительность: 09:26:00
Специальности: Программист
Теги: .net, open source, opengl
Лекция 11:

Интерактивные приложения OpenGL

< Лекция 10 || Лекция 11: 123 || Лекция 12 >
Аннотация: В лекции рассматриваются методы создания интерактивных приложений с использованием библиотеки OpenGL.

Цель лекции: Изучить методы определения выбранных объектов с помощью анализа их цвета и режима выбора объектов.

Примеры на C# (WinForms) и Object Pascal (Delphi)

Пример № 10.1 Пример демонстрирует определение объекта с помощью определения его цвета во вторичном буфере.

Пример № 10.2 Пример демонстрирует использование режима выбора объектов.

Для создания интерактивных приложений на базе OpenGL часто необходима возможность выбора объекта или нескольких объектов трехмерной сцены с помощью манипулятора (например, такого как "мышь"). По сравнению с двухмерными сценами при выборе объектов трехмерных сцен необходимо учитывать несколько факторов:

  1. Объекты могут заслонять друг друга. В этом случае обычно необходимо определить объект, который расположен ближе к наблюдателю.
  2. Сцена может отображаться с различных точек наблюдения. При изменении точки наблюдения объекты, которые располагались дальше от наблюдателя, могут оказаться ближе к нему и наоборот.
  3. Цвет объектов может зависеть от свойств источников света и материала, а так же от различных специальных эффектов, например, таких как туман. В этом случае может оказаться невозможным применение алгоритмов, основанных на определении цвета объекта в выделенной области.
  4. В зависимости от размера области отображения может изменяться видимость объектов. Например, небольшой объект при размере области отображения на экране монитора 800*600 пикселов может быть виден в виде одного или нескольких пикселов. При уменьшении области отображения той же самой сцены до 640*480 пикселов этот объект может быть уже не видим. При выборе объектов так же необходимо учитывать, что в одних случаях требуется учитывать в выбранной области наличие не отображаемых объектов, а в других случаях не принимать их во внимание.

При работе с библиотекой OpenGL для выбора объектов могут использоваться различные алгоритмы. Наиболее используемые из них рассмотрены ниже.

Анализ цвета объекта в области вывода

Этот алгоритм можно, наверное, отнести к наиболее простым. Основан он на том, что различные объекты имеют различные цвета, и цвет каждого из объектов не меняется. Такой алгоритм может быть применен для сцен без освещения, текстур, градиентного изменения цвета и специальных эффектов, например, тумана, прозрачности. Для определения цвета пикселов в выбранной области может использоваться команда ReadPixels библиотеки OpenGL. Ниже приведена реализация команды в библиотеке OpenTK на языке программирования C# и на языке Object Pascal. В библиотеке OpenTK для реализации команды используется статический метод класса GL.

C#:
  void ReadPixels(int x, int y, int width, int height, PixelFormat format, PixelType type, IntPtr pixels);
Object Pascal:
  procedure glReadPixels (x,y: GLint; width, height: GLsizei;  format, 
  _type: GLenum; pixels: Pointer);

Параметры имеют следующие значения:

  • x,y - координаты нижнего левого угла группы пикселов;
  • width, height – ширина и высота считываемой группы пикселов;
  • format – формат считываемых данных о пикселах;
  • type – тип возвращаемых данных;
  • pixels - указатель на массив для сохранения полученных данных.

Например, получение информации о цвете пиксела под указателем мыши, может быть выполнено с помощью фрагментов кода, приведенных в листингах 10.1 (C#) и 10.2 (Object Pascal).

private void glControl1_MouseDown(object sender, MouseEventArgs e)
{
  int pixel = new int();
  GL.ReadPixels(e.X, glControl1.Height - e.Y, 1, 1, PixelFormat.Bgra, PixelType.UnsignedByte, ref pixel);
  Color color = Color.FromArgb(pixel);
  if ((color.R == 255) && (color.G == 0) && (color.B == 0))
    MessageBox.Show("Выбран красный треугольник");
  if ((color.R == 0) && (color.G == 255) && (color.B == 0))
    MessageBox.Show("Выбран зелёный треугольник");
  if ((color.R == 0) && (color.G == 0) && (color.B == 255))
    MessageBox.Show("Выбран синий треугольник");
}
Листинг 10.1. Пример определения выбранного объекта с помощью определения его цвета с помощью команды ReadPixels на C#

Информация о цвете сохраняется в переменной color типа Color.

На Object Pascal определение цвета примитива может быть реализовано аналогично листингу 10.2 .

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  a: Array [0..2] of GLUbyte;
begin
  glReadPixels (X, ClientHeight -Y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, @a);
  if (a[0] = 255) and (a[1]=0) and (a[2]=0) then
    ShowMessage('Выбран красный треугольник')
  else if (a[0]=0) and (a[1]=255) and (a[2]=0) then
    ShowMessage('Выбран зелёный треугольник')
  else if (a[0]=0) and (a[1]=0) and (a[2]=255) then
    ShowMessage('Выбран синий треугольник');
end;
Листинг 10.2. Пример определения выбранного объекта с помощью анализа его цвета с помощью процедуры glReadPixels на Object Pascal

В листинге 10.2 информация о цвете пикселов сохраняется в байтовом массиве a (тип GLUbyte соответствует типу Byte). Каждый байт массива содержит информацию об интенсивности одной из цветовых составляющих пиксела: красной a[0], зеленой a[1] и синей a[2].

Анализ цвета объекта во вторичном (не отображаемом) буфере

Как уже было описано выше, использование анализа цвета в области вывода имеет целый ряд ограничений. Если же необходимо выполнить определение выбранного объекта при использовании градиентного изменения цвета, освещения, текстур или специальных эффектов, то можно использовать анализ цвета объекта во вторичном буфере.

Основная идея этого метода заключается в том, что во вторичном буфере формируется изображение аналогичное отображаемому по координатам вершин и координатным преобразованиям, но которое отличается тем, что в нем отключены освещение, текстуры и специальные эффекты. Это изображение не отображается, а используется только для определения выбранного объекта. Каждому объекту, который может быть выбран, задается индивидуальный цвет. Это позволяет по цвету пиксела во вторичном буфере определить выбранный пользователем объект. Для получения информации о цвете пикселов во вторичном буфере может использоваться уже известная команда ReadPixels.

Ограничением методов, основанных на анализе цвета, является возможность определения только видимых объектов. Если необходимо определить все объекты, которые находятся в определённой области, в том числе и полностью перекрываемые другими объектами, то необходимо использовать другие методы.

Использование режима выбора объектов

Библиотека OpenGL реализует специальный режим для выбора объектов. В отличие от определения выбранного объекта по цвету, этот метод позволяет определить все объекты, находящиеся в выбранной прямоугольной области. В том числе и те, которые перекрываются другими объектами и не отображаются из-за небольшого размера их проекции (размер проекции объекта меньше пиксела).

Основная идея этого метода заключается в том, что библиотека переключается в специальный режим (режим выбора), в котором не происходит формирование изображения (в том числе и во вторичном буфере). Область сцены задается равной области выбора. Сцена в остальном формируется обычным образом. Необходимо чтобы при формировании сцены в режиме выбора выполнялись те же самые преобразования как при отображении сцены. Библиотека фиксирует объекты, которые попали в эту область сцены (которая соответствует области выбора). Для определения выбранного объекта они именуются с использованием стека имен. При попадании объекта в область сцены информация об имени объекта сохраняется в стеке выбора, который после формирования сцены может быть проанализирован.

Описание реализации режима выбора приведено ниже.

Подготовка буфера для списка выбранных объектов

На этом этапе выполняется выделение памяти для буфера выбора, в который OpenGL будет помещать информацию об объектах, попавших в область выбора. При выделении памяти для этого буфера необходимо учитывать, что для описания каждого объекта библиотека OpenGL будет использовать как минимум 4 целочисленные значения. Желательно буфер задать такого размера, чтобы он был достаточен для сохранения информации обо всех объектах, которые могут быть одновременно выбраны. Если это условие не будет выполняться, то определение выбранного объекта может оказаться некорректным.

Буфер необходимого размера можно объявить в виде глобальной переменной:

C#:
  uint[] buf = new uint[128];
Object Pascal:
  var   buf: Array [0..128] of GLuint;

Инициализация буфера выбора

После того как для буфера зарезервирована память (в нашем примере это переменная buf) необходимо передать информацию об этом блоке памяти библиотеке OpenGL. Для этого используется команда SelectBuffer:

C#:  
  void SelectBuffer(int size, uint[] buffer);
Object Pascal:
  procedure glSelectBuffer (size: GLsizei; buffer: PGLuint);

Первый параметр процедуры size - размер буфера в байтах. В библиотеке OpenTK параметр buffer используется для передачи массива, в Object Pascal параметр buffer используется для передачи указателя на начало буфера.

Буфер buf может быть инициализирован следующим образом:

C#:
  GL.SelectBuffer(buf.Count(), buf);
Object Pascal:
  glSelectBuffer(SizeOf(selectBuf), @selectBuf);

Инициализация буфера выбора должна быть выполнена до перехода в режим выбора (об этом ниже). Достаточно эту операцию выполнить всего один раз, например, при запуске приложения.

< Лекция 10 || Лекция 11: 123 || Лекция 12 >
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!

Лариса Парфенова
Лариса Парфенова

1) Можно ли экстерном получить второе высшее образование "Программная инженерия" ?

2) Трудоустраиваете ли Вы выпускников?

3) Можно ли с Вашим дипломом поступить в аспирантуру?