LXF167:Android
|
|
|
Android » Программирование Работа с сенсорным экраном при помощи библиотек OpenGL
Текстуры и OpenGL: На сенсорном экране
OpenGL в Android позволяет создавать улучшенную графику и использовать гибкий открытый подход к трехмерной графике. В предыдущей статье мы работали с фигурами, цветами, камерами и проекциями экрана и познакомились с перемещением фигуры; теперь мы продолжим работу с примером и будем перемещать фигуру по экрану в ответ на касания сенсорного экрана, а также познакомимся с умеренно сложной, но полезной технологией наложения текстур. Как и прежде, мы пользуемся OpenGL ES2.0, который поддерживается в Android 2.2 и выше. Помните, что код нельзя будет проверить в эмуляторе, так как он не работает с OpenGL 2, и для отладки вам потребуется реальное устройство.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
В развитие предыдущей статьи Джульетта Кемп переходит к текстурам и сенсорному экрану для перемещения фигур.
Перемещение и сенсорный экран
Прежде всего кратко ознакомимся с перемещением (объекта по экрану), не касаясь работы с сенсорным экраном. Это просто еще одна операция с матрицей, translateM(). Добавьте следующие две строки после поворота в CISGLRenderer.onSurfaceCreated():
Matrix.setIdentityM(iMatrix, 0);
Matrix.translateM(iMatrix, 0, 0.2f, 0.2f, 0f);
Также понадобится создать переменную класса iMatrix и добавить в onDrawFrame() строку
Matrix.multiplyMM(uMVPMatrix, 0, tMatrix, 0, uMVPMatrix, 0);
после других операций умножения матриц.
Эти вызовы переместят куб на 0.2 координаты влево и на 0.2 координаты вверх по экрану.
Помните, что порядок множителей при умножении матриц имеет значение! Подробности см. во врезке.
В качестве альтернативного варианта можно немного перемещать куб в каждом кадре, добавив следующую строку в onDrawFrame():
Matrix.translateM(iMatrix, 0, 0.001f, 0.001f, 0);
Скомпилируйте и запустите программу, и вы увидите, как куб медленно движется по экрану. События сенсорного экрана
Двигать кубиками – дело хорошее, но интереснее заставить куб перемещаться в контексте события сенсорного экрана.
Напишем код, который при движении пальцем по сенсорному экрану будет перемещать куб вослед. Чтобы происходящее было яснее, стоит закомментировать строку с поворотом на постоянный угол в CISGLRenderer.onDrawFrame() (так что происходит только перемещение) и строку насчет первоначального поворота в CISGLRenderer.onSurfaceCreated() (чтобы объект перемещался по обычным, а не повернутым осям X/Y/Z, о чем сказано ранее).
Для обработки событий сенсорного экрана нужно создать собственный класс SurfaceView, CISSurfaceView:
public class CISSurfaceView extends GLSurfaceView {
private CISGLRenderer renderer;
private float prevX = 0;
private float prevY = 0;
public CISSurfaceView(Context c) {
super(c);
setEGLContextClientVersion(2);
renderer = new CISGLRenderer(this.getContext());
setRenderer(renderer);
}
public boolean onTouchEvent(MotionEvent e) {
float x = e.getX();
float y = e.getY();
float height = getHeight();
float width = getWidth();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dx = (x - width/2) * -1;
float dy = (y - height/2) * -1;
renderer.diffX = (dx - prevX) / (width/2);
renderer.diffY = (dy - prevY) / (height/2);
prevX = dx;
prevY = dy;
}
return true;
}
}
Метод конструктора просто перемещает код из основного Занятия в Представление. Это производится в методе onTouchEvent(). Здесь мы получаем значения X и Y из обнаруженного события MotionEvent, затем высоту и ширину экрана.
Сейчас нам интересно только действие ACTION_MOVE, оно регистрируется при перемещении пальца по экрану. Это действие возникает повторно (и очень часто!) до тех пор, пока вы не снимете палец с экрана, так что этот метод будет вызываться много раз (в чем вы убедитесь, если добавите в него строку для записи сообщения в лог).
dx и dy используются для преобразования координат сенсорного экрана X и Y в координаты системы с точкой отсчета в центре экрана. Отсчет координат сенсорного экрана ведется из левого нижнего угла, ось x уходит вверх, а ось y – влево. В OpenGL используется система координат с началом отсчета в центре экрана (ось x по-прежнему уходит вправо, а ось y – вверх). dx и dy содержат расстояние до точки нажатия от центра экрана в пикселях.
Затем мы получаем разницу между предыдущими координатами (prevX и prevY) и текущими координатами (dx and dy) и преобразуем их из пикселей в координаты OpenGL. В OpenGL по умолчанию за 1 берется расстояние от центра до каждого края – очевидно, сенсорный экран имеет (0.5 * высота) пикселей от центра до верхнего края и (0.5 * ширина) пикселей от центра до каждой стороны, поэтому мы используем эти значения для генерирования координат OpenGL.
Наконец, мы передаем эти значения рендереру. Замените статичную строку translateM() в методе onDrawFrame() класса CISGLRenderer следующей:
Matrix.translateM(iMatrix, 0, diffX, diffY, 0);
(также понадобится объявить diffX и diffY как публичные переменные класса).
Скомпилируйте и запустите программу, и вы увидите, как куб перемещается вслед за пальцем.
Исправляем недочеты
Однако на самом деле он перемещается не вслед за пальцем, а по осям, сильно напоминающим ортогональные. Это связано с взаимодействием с проекционной матрицей и матрицей проекции камеры. Есть два способа это исправить. Один из них – изменить направление перемещения:
Matrix.translateM(iMatrix, 0, -diffX, diffY, 0);
Однако лучшим решением будет использовать другую матрицу для перемещения вслед за пальцем и домножать на нее заранее.
Для этой цели мы поместим в наш код следующий дополнительный фрагмент:
private float[] tMatrix = new float[16];
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
[ ... ]
Matrix.setIdentityM(tMatrix, 0);
}
public void onDrawFrame(GL10 gl) {
Matrix.translateM(tMatrix, 0, diffX, diffY, 0);
Matrix.setIdentityM(uMVPMatrix, 0);
Matrix.multiplyMM(uMVPMatrix, 0, mMatrix, 0, uMVPMatrix, 0);
Matrix.multiplyMM(uMVPMatrix, 0, tMatrix, 0, uMVPMatrix, 0);
Matrix.multiplyMM(uMVPMatrix, 0, vMatrix, 0, uMVPMatrix, 0);
Matrix.multiplyMM(uMVPMatrix, 0, projMatrix, 0, uMVPMatrix, 0);
Matrix.multiplyMM(uMVPMatrix, 0, iMatrix, 0, uMVPMatrix, 0);
[ ... ]
}
Перед выполнением с новой матрицей любых действий важно так установить значения ее элементов, чтобы она сделалась единичной (в противном случае она будет нулевой и останется такой, что бы вы ни делали).
Затем мы используем ее для передачи значений diffX и diffY и умножаем ее на унифицированную матрицу после поворота, но до умножения на проекционную матрицу/матрицу проекции камеры.
Снова скомпилируйте и запустите программу, и теперь куб должен перемещаться в нужном направлении. О дальнейшем улучшении кода см. во врезке «Начало и окончание движения» на предыдущей странице.