3.1 Вывод треугольника с помощью OpenGl es
Базовой фигурой 3D графики является треугольник, т.к. любой трёхмерный объект можно представить в виде набора треугольников. Поэтому рассмотрим простейший пример о том, как вывести треугольник при помощи OpenGL ES на Android.
Создаём в Eclipse новый Android проект. Назовём его TriangleDemo. В поля Package name, Activity name и Application name впишите com.goodroid.triangledemo, TriangleDemo, и TriangleDemo соответственно. Для примера нам понадобится файл GLSufaceView.java из Android SDK (лежит он в папке samples\ApiDemos\src\com\example\android\apis\graphics).
Создадим в нашем проекте пакет с именем com.example.android.apis.graphics и скопируем в него GLSufaceView.java. Структура проекта показана на рисунке 5.
Рис. 5 Структура проекта TriangleDemo
Класс GLSufaceView позволяет нам не задумываться о том, как инициализировать OpenGL, он делает это сам. Нам остаётся только написать класс, имплементирующий интерфейс GLSurfaceView.Renderer, который будет заниматься отрисовкой или рендерингом (кому как больше нравится). Назовём его Renderer.
Для этого, в Eclipse, надо нажать правой кнопкой мыши в окне Package Explorer на пакете com.goodroid.triangledemo и в открывшемся меню выбрать New - Class. Откроется помощник создания нового класса. В поле Name напишем Renderer, а в поле Interfaces добавим интерфейс com.example.android.apis.graphics.GLSurfaceView.Renderer и нажмем кнопку Finish. После этих манипуляций Eclipse создаст наш Renderer с пустыми методами.
Код класса Renderer:
package com.goodroid.triangledemo;
import javax.microedition.khronos.opengles.GL10;
public class Renderer implements
com.example.android.apis.graphics.GLSurfaceView.Renderer {
@Override
public void drawFrame(GL10 gl) {
// TODO Auto-generated method stub
}
@Override
public int[] getConfigSpec() {
// TODO Auto-generated method stub
return null;
}
@Override
public void sizeChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(GL10 gl) {
// TODO Auto-generated method stub
}
}
О назначении пустых методов будет указано чуть позже. Теперь откройте файл TriangleDemo.java.
import com.example.android.apis.graphics.GLSurfaceView;
Добавим новую переменную
private GLSurfaceView glView;
А в методе onCreate заменим строчку
setContentView(R.layout.main);
следующим кодом:
glView = new GLSurfaceView(this);
glView.setRenderer(new Renderer());
setContentView(glView);
Откроем файл Renderer.java. И сделаем некоторые изменения.
Первым делом при инициализации OpenGL ES контекста вызывается метод getConfigSpec().Он задаёт конфигурацию OpenGL ES, которая представляет из себя список (массив типа int) пар атрибут - значение и завершается атрибутом EGL_NONE. Если какой-то атрибут не указан в списке, то его значение принимается равным по умолчанию.
Для нашего примера будет достаточно конфигурации по умолчанию, но вернуть атрибут EGL_NONE мы всё равно должны. Поэтому, заменим пустышку getConfigSpec() следующим кодом:
public int[] getConfigSpec() {
int[] configSpec = {
EGL10.EGL_NONE
};
return configSpec;
}
Следующим по очереди вызывается метод surfaceCreated(GL10 gl).
Вызывается он при создании поверхности. Здесь можно сделать инициализацию каких-нибудь данных. Например, загрузить текстуры. Нам пока этого не требуется, поэтому оставим его пустым.
Потом вызывается метод sizeChanged(GL10 gl, int width, int height). Как видно из названия метода, вызывается он и при изменении размера экрана, например, при повороте.
Добавим в него код настройки области просмотра (т.е. viewport) и типа проекции:
public void sizeChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}
Пусть координаты вершин треугольника мы записали в массив rectangle.
Java реализация OpenGL ES работает с буферами из пакета java.nio. Поэтому массив rectangle надо предварительно поместить в буфер соответствующего типа (в нашем случае это FloatBuffer).
Для этого добавим в раздел импорта строчку:
import java.nio.*;
а в код класса Renderer переменную
FloatBuffer triangleBuffer;
и конструктор следующего содержания:
public Renderer() {
ByteBuffer bb = ByteBuffer.allocateDirect(36);
bb.order(ByteOrder.nativeOrder());
triangleBuffer = bb.asFloatBuffer();
triangleBuffer.put(triangle);
triangleBuffer.position(0);
}
Строка
ByteBuffer bb = ByteBuffer.allocateDirect(36);
Создаёт direct-буфер или прямой буфер размером 36 байт (3 вершины по 3 координаты по 4 байта каждая). Он создаётся в системной куче. Делается это для того чтобы сборщик мусора не мог его никуда переместить.
bb.order(ByteOrder.nativeOrder());
Для многобайтовых типов данных таких как: short, int, float, задаёт порядок байт в буфере как в системе.
triangleBuffer = bb.asFloatBuffer();
Метод asFloatBuffer создаёт экземпляр класса FloatBuffer, ссылающийся на данные из байтового буфера. Т.е. дальше мы будем работать с байтовым буфером как с вещественным буфером.
triangleBuffer.put(triangle);
Запишем наш треугольник в буфер.
triangleBuffer.position(0);
Установим указатель на начало буфера.
Подготовка окончена, пора приступать к рисованию.
За рисование отвечает метод drawFrame(GL10 gl).
public void drawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -3.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
}
Строка
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
отвечает за очистку экрана. Параметр GL10.GL_COLOR_BUFFER_BIT означает, что нужно очистить буфер цвета.
gl.glMatrixMode(GL10.GL_MODELVIEW);
говорит о том, что мы будем работать с матрицей модели.
gl.glTranslatef(0, 0, -3.0f);
перемещает наш треугольник по оси Z в глубь экрана в точку (0, 0, -3). Если этого не сделать, то мы бы не увидели треугольник.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
включает режим рисования массива вершин.
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleBuffer);
указывет OpenGL, что при отрисовке будет использоваться массив вершин triangleBuffer.
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
эта строка наиболее интересна, т.к. она выводит наш треугольник на экран. Параметр GL10.GL_TRIANGLES задаёт способ вывода вершин из массива. Вывод начнётся с вершины 0. Будет выведено 3 вершины.
Вот собственно и всё. Можно запускать программу. Результат работы программы представлен на рисунке 6.
Рис. 6. Результат работы программы
- Оглавление
- 1 Базовые сведения о платформе Android
- 1) Уровень ядра
- 1.1 Уровень ядра
- 1.2 Уровень библиотек
- 1.2.1 Среда выполнения
- 1.3 Уровень каркаса приложений.
- 1.4 Уровень приложений
- 2 Среда разработки
- 2.1 Установка jdk
- 2.2 Установка Eclipse
- 2.3 Установка Android sdk
- 2.4 Установка Android Development Tools
- 2.5 Обзор Android sdk
- 3 Простейшее графическое приложение для Android
- 3.1 Вывод треугольника с помощью OpenGl es