Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки? Спасибо! |
Интерактивные приложения OpenGL
Определение области выбора объектов
Обычно область, в которой необходимо определить наличие объектов (область выбора объектов), определяется как фрагмент проекции сцены. Например, пользователь на изображении проекции выделяет с помощью манипулятора (например, указателя типа "мышь") прямоугольную область или просто щелкает кнопкой "мыши", определяя, таким образом, область выбора.
Так как в этих случаях область выбора определяется на проекции трехмерной сцены, то необходимо определить соответствующую ей область трехмерной сцены (сцена выбора). Сцена выбора будет зависеть от нескольких факторов: используемой проекции, размеров сцены и области вывода.
Для определения трехмерной области выбора на основании прямоугольного фрагмента проекции сцены необходима информация о матрице проекции. Для этого можно использовать некоторые функции из библиотеки GLUT, которая является надстройкой над библиотекой OpenGL и предоставляет ряд дополнительных возможностей.
В библиотеке OpenTK функции библиотеки GLUT находятся в классе Glu в пространстве имен Tao.OpenGL (C#). В Object Pascal все функции и процедуры библиотеки GLUT имеют префикс "glu", что позволяет их отличать от процедур и функций OpenGL.
Для формирования матрицы проекции на основе выбранного фрагмента проекции сцены можно использовать команду PickMatrix библиотеки GLUT:
C#: void gluPickMatrix(double x, double y, double width, double height, int[] viewport); Object Pascal: procedure gluPickMatrix(x,y,width,height: GLdouble; viewport: PGLint);
Команда PickMatrix библиотеки GLUT изменяет текущую матрицу таким образом, чтобы размер области сцены соответствовал области выбора, определённой в координатах проекции этой сцены. Команды имеет следующие параметры:
- x, y – горизонтальная и вертикальная координаты области выбора в координатах окна, в котором отображается проекция трехмерной сцены.
- width, height – ширина и высота выбранной прямоугольной области проекции трехмерной сцены в координатах окна.
- viewport – массив четырех целочисленных элементов. В C# передается непосредственно массив в качестве параметра, в Object Pascal в качестве параметра передаётся указатель на массив. Массив определяет область вывода проекции трехмерной сцены. Значения массива должны соответствовать координатам области вывода, определённым с помощью команды ViewPort. Элементы этого массива должны иметь следующие значения: 1й и 2й элементы – координаты x и у левого верхнего угла выделенной области в координатах экрана, 3 и 4 элементы – ширина и высота этой области.
Команда должна быть выполнена перед выполнением команд Ortho или Frushtum, с помощью которых формируется матрица проекции.
Перевод библиотеки OpenGL в режим выбора
Для перевода библиотеки в режим выбора используется команда RenderMode:
C#: int RenderMode(RenderingMode mode); Object Pascal: function glRenderMode(mode: GLenum): GLint;
Параметр mode определяет режим работы библиотеки OpenGL и может принимать одно из трех значений:
Описание | Значение | |
---|---|---|
Библиотека OpenTK, C# | Object Pascal | |
Режим выбора, данное значение используется для перевода библиотеки в режим выбора. | RenderingMode.Select | GL_SELECT |
Режим формирования изображения сцены. Этот режим используется по умолчанию после инициализации библиотеки OpenGL. Именно в этом режиме выполняется формирование изображения библиотекой OpenGL. | RenderingMode.Render | GL_RENDER |
Режим обратной связи. | RenderingMode.Feedback | GL_FEEDBACK |
После переключения в режим выбора библиотека OpenGL не формирует изображение до тех пор, пока режим не будет изменен на режим формирования изображения сцены с помощью команды RenderMode со значением параметра RenderingMode.Render на C# и GL_RENDER на Object Pascal.
Именование и формирование объектов сцены
Как уже обсуждалось выше, в режиме выбора изображение не формируется. Команды формирования изображения в этом режиме используются для определения объектов, попадающих в область выбора.
Так как объекты, с которыми работает пользователь, обычно формируются из множества различных примитивов, то для определения выбранного объекта используется стек имен. Имена представляют собой целочисленные значения. Перед началом вывода очередного объекта в стек имен помещается имя (номер) этого объекта. Если при формировании объекта библиотека обнаруживает, что примитивы этого объекта попадают в область выбора, то содержание стека имен копируется в буфер выбора (вместе с некоторой дополнительной информацией), инициализированного с помощью команды SelectBuffer. При попадании в область сцены примитивов другого именованного объекта, содержание стека имен так же будет скопировано в буфер выбора. Таким образом, могут быть получены имена (номера) объектов, которые полностью или частично попали в область выбора. Необходимо учитывать, что для корректного определения выбранных объектов необходимо, чтобы координатные преобразования объектов, совпадали с теми, которые выполнялись при формировании изображения сцены.
Для работы со стеком имен используются несколько команд. Очистка стека имён выполняется с помощью команды InitNames:
C#: void InitNames(); Object Pascal: procedure glInitNames;
Помещение имени в стек выполняется с помощью команды PushName:
C#: void PushName(uint name); Object Pascal: procedure glPushName(name: GLuint);
Имя передается в качестве параметра команды.
Удаление последнего имени из стека выполняется с помощью команды PopName:
C#: void PopName(); Object Pascal: procedure glPopName
Для замены последнего имени в стеке используется команда LoadName:
C#: void LoadName(uint name); Object Pascal: procedure glLoadName(name: GLuint);
Новое имя передаётся команде в качестве параметра.
В режиме выбора при попадании примитива в сцену весь стек имен копируется в буфер выбора. Если сцена не очень сложная, то обычно в стеке имен располагают одно имя, соответствующее объекту. Если же сцена сложная, или необходимо отслеживать иерархические связи между объектами, то для обозначения объектов может использоваться несколько имен. Например, для автомобиля: колесо-болт-гайка. Ниже будет рассмотрен простой вариант, в котором для определения выбранного объекта используется только один элемент в стеке имен.
Перед использованием стека имен он должен быть инициализирован с помощью команды InitNames. Затем в стек необходимо поместить один элемент с помощью команды PushName. Перед формированием каждого из объектов единственный элемент стека имен будет заменяться на имя формируемого объекта с помощью команды LoadName. Процедура заменяет последний элемент в стеке имен на заданный в качестве параметра. Таким образом, инициализация и использование стека имен схематически можно представить следующим образом:
InitNames; PushName(0); … LoadName(1); //формирование объекта № 1 LoadName(2); //формирование объекта № 2 LoadName(3); //формирование объекта № 3 //и т.д.Листинг 10.7. Схема использования стека имен для выбора объектов