Главная » Программирование игр под Android » ИНДЕКСИРОВАННЫЕ ВЕРШИНЫ: ИСПОЛЬЗУЕМ ПОВТОРНО – РАЗРАБОТКА ИГР ДЛЯ ОС ANDROID

0

 

До сих пор мы всегда описывали список треугольников, где каждый треугольник имеет собственный набор вершин. В действительности мы успели нарисовать только один треугольник, но добавить еще несколько не составит особого труда.

Тем не менее существуют случаи, когда два или больше треугольников могут делить некоторые вершины. Рассмотрим, как мы можем визуализировать прямоугольник с помощью уже изученных приемов. Мы просто определим два треугольника, которые будут иметь две вершины с одинаковыми координатами места, цветами и текстурами.

Однако мы можем сделать еще лучше. На рис. 7.14 показаны старый и новый способы визуализации прямоугольника.

Рис. 7.14. Визуализация прямоугольника как двух треугольников с шестью вершинами (слева) и его визуализация с четырьмя вершинами (справа)

Вместо дублирования вершин vl и v2 с вершинами v4 и v6 мы просто описываем эти вершины один раз. Мы по-прежнему визуализируем два треугольника в данном случае, однако явно сообщаем OpenGL ES, какие вершины использовать для каждого треугольника (например, vl, v2 и v3 для первого треугольника и v3, v4 и vl для второго). То, какие вершины применять для каждого треугольника, определяется по индексам в массиве вершин. Первая вершина в нашем массиве имеет индекс О, вторая вершина имеет индекс 1 и т. д. Для предыдущего прямоугольника у нас будет следующий список индексов:

Кстати, OpenGL ES предпочитает определять индексы в формате чисел short (правда, здесь мы также можем использовать байты). Тем не менее, как и с данными вершин, мы не можем просто передать OpenGL ES массив short. Ему нужен прямой ShortBuf fer. Вы уже знаете, как это делать:

Short нужно 2 байта памяти, так что выделяем i ndi ces. 1 ength х 2 байтов для нашего ShortBuffer. Снова устанавливаем изначальный порядок и получаем вид ShortBuffer, чтобы нам было проще обработать базовый ByteBuffer. Все, что осталось, – собрать все индексы в ShortBuffer и вызвать f1iр, чтобы все позиции были установлены правильно.

Если бы нам было нужно нарисовать Боба как прямоугольник с двумя индексированными, мы могли бы описать вершины следующим образом:

Порядок вершин полностью совпадает с правой частью рис. 7.14. Мы сообщаем OpenGL ES, что у нас есть координаты положения, а также текстуры для наших вершин. Еще сообщаем, где можно найти эти свойства вершин с помощью обычного вызова gl Enabl eCli entState О и gl VertexPoi nter/glTexCoordPoi nter . Единственная разница состоит в методе, который мы вызываем для рисования двух треугольников:

Все это очень похоже на gl DrawArrays. Первый параметр определяет тип элемента, который мы хотим визуализировать, – в нашем случае это список треугольников. Следующий параметр задает, сколько вершин мы хотим использовать (в нашем случае – шесть). Третий параметр указывает, какой тип индексов мы задействуем (у нас это числа short без знака). Обратите внимание, что в Java нет типов беззнаковых типов. Тем не менее, учитывая кодирование чисел со знаками с поразрядным дополнением до единицы, вполне уместно использовать ShortBuffег, который работает с числами short со знаками. Последний параметр – наш ShortBuf fer, содержащий шесть индексов.

Что же делает OpenGL ES? Системе известно, что мы хотим визуализировать два треугольники, поскольку мы указали, что собираемся визуализировать шесть вершин. Но вместо того, чтобы перенести шесть вершин по очереди из массива вершин, он последовательно проходит через буфер индексов и использует индексированные вершины.

Все вместе

Когда мы все объединим, получим код, как в листинге 7.9.

Листинг 7.9. Отрывок из IndexedTest.java; рисуем два индексированных треугольника

Обратите внимание, как удобно использовать класс Texture, который значительно сокращает количество кода. На рис. 7.15 показан результат.

Теперь все очень похоже на то, как мы работали с Canvas. У нас также гораздо больше гибкости сейчас, поскольку мы больше не ограничены осями.

Этот пример описывает все, что нам на данный момент надо знать о вершинах. Мы увидели, что каждая вершина должна иметь как минимум положение, но она также может обладать дополнительными свойствами, такими как цвет, данный в четырех значениях с плавающей точкой (формат RGBA), и текстурные координаты. Мы также увидели, что можем повторно использовать вершины с помощью индексации в случае, если хотим избежать дублирования. Это позволяет нам немного ускорить работу, поскольку OpenGL ES придется умножать вершины на проекцию и матрицы вида модели не более, чем требуется (давайте остановимся на такой интерпретации, хотя она и не совсем верна).

Рис. 7.15. Индексированный Боб

Класс Vertices

Давайте упростим код, создав класс Vertices, который может содержать максимальное количество вершин и при необходимости индексов, используемых при визуализации. Он должен также обеспечивать все состояния, нужные для визуализации, а также очищать состояния после визуализации, чтобы другой код мог основываться на чистом наборе состояний OpenGL ES. В листинге 7.10 показан класс Vertices.

Листинг 7.10. Vertices.java; инкапсулированные (индексированные) вершины package com.badlogiс.androidgames.framework.gl;

Класс Vertices содержит ссылку на экземпляр класса GLGraphics, поэтому мы можем получить экземпляр класса GL10, как только он понадобится. Мы также сохраняем информацию о том, имеют ли вершины цвет и текстурные координаты. Так достигается значительная гибкость, поскольку мы можем выбрать минимальный набор свойств, которые нам нужны для визуализации. Мы также сохраняем  FloatBuffer, который содержит наши вершины, и ShortBuffer, включающий в себя дополнительные индексы.

В конструкторе определяем, какое максимальное количество вершин и индексов может содержать экземпляр класса Verti ces, а также имеют ли вершины цвет и текстурные координаты. Внутри конструктора устанавливаем соответствующие элементы и указываем значения буферам. Обратите внимание: если maxlndices равен нулю, ShortBuffer получит значение null. В таком случае визуализация будет выполняться без индексирования.

Переходим к методам setVertices и setlndices. Последний будет выдавать исключение NullPointerException, если экземпляр класса Vertices не сохраняет индексы. Все, что нам надо делать, – очищать буферы и копировать содержимое массивов.

Последний метод класса Vertices – draw. Он использует тип элемента (например, GL10 .GLTRI ANGLES), смещение в буфере вершин (или буфере индексов, если мы пользуемся индексами) и количество вершин, применяемых для визуализации. В зависимости от того, имеют ли вершины цвет и текстурные координаты, включаем соответствующие состояния OpenGL ES и сообщаем OpenGL ES, где найти данные. Естественно, мы делаем то же самое для положения вершин, поскольку эта информация будет нам требоваться постоянно. В зависимости от того, используются ли индексы, вызываем glDrawElements или glDrawArrays с соответствующими параметрами. Обратите внимание, что параметр смещения может также применяться при индексированной визуализации: мы просто устанавливаем положение буфера индексов таким образом, что OpenGL ES начинает читать индексы с точки, где произошло смещение, а не с первого индекса буфера. В методе draw О осталось только очистить состояния OpenGL ES. Вызываем gl Disabled ientStateC) с GL10. GL C0L0R ARRAY или GL10 ,GL TEXTURE COORD ARRAY, если у вершин есть эти атрибуты. Нам нужно это сделать, поскольку другой экземпляр класса Vertices может не использовать эти атрибуты. Если бы мы визуализировали другой экземпляр класса Vertices, OpenGL ES по-прежнему искал бы координаты цвета и текстур.

Мы можем заменить весь сложный код конструктора из предыдущего примера следующим фрагментом:

Мы также можем заменить все вызовы, занятые установкой наших массивов с атрибутами, а также занятые отображением, следующим вызовом:

Вместе с классом Texture у нас может получиться достаточно хорошая основа для двухмерной визуализации в OpenGL ES. Одна из деталей, которых нам до сих пор не хватает для полного воссоздания возможностей нашего Canvas, – это смешивание. Давайте им займемся.

Источник: Mario Zechner / Марио Цехнер, «Программирование игр под Android», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии