Castle of Magic - красивая сказка от Gameloft Real Tennis 2009
Июн 17

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

Краткий обзор прошлого урока и введение в следующий

На прошлом уроке, оттолкнувшись от «чистого холста» в виде проекта Xcode мы получили белый треугольник с заливкой. Для этого мы создали массив вершин, с помощью “glVertexPointer()” сообщили OpenGL о данных и их формате, активировали готовность к визуализации массива вершин и выполнили собственно рендеринг с помощью “glDrawArrays()“.

На сей раз, взяв этот код за основу, мы сделаем из треугольника квадрат. Для этого достаточно будет отредактировать пару строк кода. Во-первых, как все, наверное, уже догадались, количество точек с 3 нужно изменить на 4. Изменится и способ рисования, о чем и сообщим OpenGL через “glDrawArrays()“.

Приступим.

Назначение вершин квадрата

Откройте проект Xcode из предыдущего урока и перейдите к методу “drawView“. Откомментируйте константу “triangleVertices[]” — избавляться от нее не стоит, поскольку она пригодится при трансформациях — и добавьте приведенный ниже код:

1
2
3
4
5
6
const GLfloat squareVertices[] = {
-1.0, 1.0, -6.0, // Верхний левый угол
-1.0, -1.0, -6.0, // Нижний левый
1.0, -1.0, -6.0, // Верхний правый
1.0, 1.0, -6.0 // Нижний правый
};

Мы описали квадрат. Обратили внимание на перечисление вершин в направлении против часовой стрелки?

Теперь откомментируйте код рисования для треугольника (оставим его тоже — позже пригодится), а именно три запроса к функциям “glVertexArray()“, “glEnableClientState()” и “glDrawArrays()” и добавьте представленный ниже фрагмент:

1
2
3
glVertexPointer(3, GL_FLOAT, 0, squareVertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

Три функции остались теми же, но в слегка отредактированном виде.

1
glVertexPointer(3, GL_FLOAT, 0, squareVertices);

Единственное изменение в том, что мы задаем для OpenGL другой комплект вершин — не для треугольника, а для квадрата.

Метод “glEnableClientState()” остается тем же самым, поскольку при рисовании OpenGL будет работать с массивом вершин (а не с массивом цветов или чего-то еще).

1
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

А вот здесь изменения существеннее. В предыдущем уроке в качестве первого параметра мы использовали “GL_TRIANGLES“, а третьим сделали 3. Если помните, второй параметр представляет собой смещение от начала массива. Он опять установлен на 0, поскольку наш массив вершин содержит исключительно вершины квадрата.

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

GL_POINTS
GL_LINES
GL_LINE_LOOP
GL_LINE_STRIP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN

Точки и линии мы пока не обсуждали, поэтому рассмотрим три последних способа, относящихся к треугольникам. Сразу хочу напомнить, что массив вершин может включать не только треугольник: вариант с одним объектом в массиве — не предел.

GL_TRIANGLES: передача данного параметра означает, что OpenGL обрабатывает массив комплектами по 3 вершины. То есть, из первых трех создается треугольник, привязанный к вершине 1, вершине 2 и вершине 3. После этого программа переходит к обработке трех следующих вершин и так далее до конца массива.

GL_TRIANGLE_STRIP: OpenGL начинает с двух первых вершин, потом выстраивает треугольник, основываясь на каждой последующей и двух первых. Т.е. для “squareVertices[6~8]” треугольник формируется из “squareVerticies[0~2]” и “squareVerticies[3~5]“. Для “squareVertices[9~11]” треугольник формируется из “squareVertices[3~5]” и “squareVertices[6~8]” и т. д. до конца массива.

Примечание: ссылка на “squareVertices[0~2]” относится к:
        squareVertices[0]  — координата X
        squareVertices[1] — координата Y
        squareVertices[2] — координата Z

Если пока непонятно, не волнуйтесь — к этому моменту мы еще вернемся позже.

GL_TRIANGLE_FAN: после двух первых вершин для каждой последующей OpenGL формирует треугольник из предыдущей и первой вершины. То есть, для “squareVertices[6~8]” треугольник выстраивается из “squareVertices[3~5]” (предыдущая вершина) и “squareVertices[0~2]” (первая вершина).

Поскольку мы использовали “GL_TRIANGLES_FAN“, то на экране получим квадрат. Кнопка “Build & Go” выдаст долгожданный белый результат:

square
Вернитесь и взгляните на массив вершин. Постарайтесь представить, как треугольниками рисуется квадрат. OpenGL визуализирует это следующим образом:

Triangle Point 1: squareVertices[0~2]         — Верхний левый угол квадрата
Triangle Point 2: squareVertices[3~5]         — Нижний левый угол квадрата
Triangle Point 3: squareVertices[6~8]         — Нижний правый угол квадрата

Итак, OpenGL рисует треугольник, который составит нижнюю левую половину квадрата. Представьте квадрат, поделенный надвое по диагонали линией из верхнего левого угла к правому нижнему. Увидели два треугольника? Нижний левый как раз и нарисовал OpenGL.

Примечание: ссылка на “squareVertices[0~2]” относится к:
        squareVertices[0] — координата X
        squareVertices[1] — координата Y
        squareVertices[2] — координата Z

Точка треугольника 1: squareVertices[9~11]         — Верхняя правая вершина квадрата
Точка треугольника 2: squareVertices[6~8]         — Предыдущая вершина, нижняя правая
Точка треугольника 3: squareVertices[0~2]        — Первая вершина, верхняя левая

Воспользовавшись всего одной новой точкой, программа визуализирует треугольник, завершая квадрат.

GL_TRIANGLE_STRIP

Вернитесь к коду и измените первый параметр в “glDrawArrays()” с “GL_TRIANGLE_FAN” на “GL_TRIANGLE_STRIP“:

1
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Нажав кнопку “Build & Go“, получим следующее изображение:

trianglesstrip 

Давайте разберемся, почему замена метода рисования не позволила получить квадрат. OpenGL обрабатывает массив вершин следующим образом:

Точка треугольника 1: squareVertices[0~2]         — нижняя левая
Точка треугольника 2: squareVertices[3~5]         — верхняя левая
Точка треугольника 3: squareVertices[6~8]         — нижняя правая

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

Точка треугольника 1: squareVertices[9~11]         — верхняя правая
Точка треугольника 2: squareVertices[6~8]       — Предыдущая вершина, нижняя правая
Точка треугольника 3: squareVertices[3~5]        — 2-я предыдущая, нижняя левая

В итоге OpenGL визуализирует треугольник по трем этим точкам. В данном примере он получился повернутым на 90º от нужного нам положения.

Если упорядочить массив по-другому, то и метод “GL_TRIANGLE_STRIP” даст такой же квадрат, как “GL_TRIANGLE_FAN“. Помните, что массив вершин и метод рисования необходимо согласовывать, иначе результаты будут такими же непредсказуемыми, как при смене “FAN” на “STRIP“. Надеюсь, все запомнили, что нарисовать квадрат можно и с помощью “GL_TRIANGLE_STRIP” — достаточно лишь перекомпоновать массив:

1
2
3
4
5
6
const GLfloat stripSquare[] = {
-1.0, -1.0, -6.0, // нижняя левая
1.0, -1.0, -6.0, // нижняя правая
-1.0, 1.0, -6.0, // верхняя левая
1.0, 1.0, -6.0 // верхняя правая
};

В данном случае первый треугольник формируется из трех первых вершин, давая следующий результат:

gltrianglestrip1

подпись на фото: вершина формируется соединением третьей вершины со второй предыдущей вершиной

Теперь, указав точку для верхней правой вершины (P4), формируем новый треугольник с верхней левой (Р3) и второй предыдущей вершиной (Р2) в качестве нижней правой. На рис. ниже новые вершины показаны оранжевым, зеленым и красным цветами.

gltrianglestrip2

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

И последнее…

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

Научившись раскрашивать объекты, будем переходить к трехмерным текстурам. Doom 3 не обещаю, но самостоятельно создавать трехмерные объекты научу.

Исходный код скачать можно [здесь]

Текст оригинальной статьи на английском языке [здесь]

Уважаемые читатели, данный материал был переведен и подготовлен к публикации проектом LookApp.ru, при публикации на другом сайте ссылка на LookApp.ru обязательна.

1 звезда2 звезд3 звезд4 звезд5 звезд (6 голосов, средний: 4.83 из 5)
Загрузка ... Загрузка ...


Оставьте комментарий