OpenGL использует правостороннюю координатную систему. Это значит, что ось x идет слева направо, ось y — снизу вверх, а ось z — из глубины экрана в сторону передней части экрана.
Перемещение (Translate)
Синтаксис:
public abstract void glTranslatef (float x, float y, float z)
Перемещения влияют на все вершины полигона в равной степени в рамках отдельной оси и отражают простые действия «суммирования» и «вычитания».
Пример: начальная точка имеет координаты {x:-2, y:1}. Мы хотим переместить ее в точку {x:1, y:3}, поэтому добавляем {x:3, y:2}.
В трехмерном пространстве находясь в точке {x:1, y:1, z:0}, мы добавляем {x:0, y:0, z:-3} и в результате будем находиться в точке {x:1, y:1, z:-3}.
Для того, чтобы увидеть площадь на экране, необходимо добавить {x:0, y:0, z:-4} к текущей позиции. Код:
// Translates 4 units into the screen.
gl.glTranslatef(0, 0, -4);
Вращение (Rotate)
Синтаксис:
public abstract void glRotatef(float angle, float x, float y, float z)
Вращение матрицы, где x, y и z — координаты вектора вращения, angle — угл вращения.
Несколько моментов:
1. Значение угла задается в градусах (не в радианах).
2. При нескольких вращениях порядок трансформаций играет роль. Для того, чтобы отменить вращение для glRotatef(angle, x, y, z), необходимо использовать glRotatef(angle, -x, -y, -z) или glRotatef(-angle, x, y, z).
Если же вы масштабируете объект до перемещения вы получите отличный от предыдущего результат — после масштабирования вы переместитесь всего лишь на 1 единицу.
Когда вы используете трансформации, вы не используете одинаковые условия, а применяете их к предыдущему состоянию объекта. Вам необходимо сбрасывать (reset) позиции.
glLoadIdentity:
public abstract void glLoadIdentity()
glLoadIdentity заменяет текущую матрицу на единичную:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
glPushMatrix:
public abstract void glPushMatrix()
glPushMatrix делает копию текущей матрицы и отправляет ее в стэк. Это означает, что все последующие изменения вы будете делать для копии.
glPopMatrix:
public abstract void glPopMatrix()
Для возвращения к предыдущей матрице используют команду glPushMatrix.
Хорошая практика — вызывать glLoadIdentity в начале каждого фрейма и после этого использовать glPushMatrix и glPopMatrix.
Используем все вместе
Итак, имеем три плоскости — A, B и C. Масштабируем их так, чтобы B была на 50% меньше чем A и C — меньше на 50%, чем B. Потом A будем вращать посредине экрана, B должна вращаться вокруг A и, наконец, C заставим вращаеться вокруг B и одновременно вокруг своего центра с бОльшей скоростью.
Код будет выглядеть следующим образом:
public void onDrawFrame(GL10 gl) {
// Clears the screen and depth buffer.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Replace the current matrix with the identity matrix
gl.glLoadIdentity();
// Translates 10 units into the screen.
gl.glTranslatef(0, 0, -10);
// SQUARE A
// Save the current matrix.
gl.glPushMatrix();
// Rotate square A counter-clockwise.
gl.glRotatef(angle, 0, 0, 1);
// Draw square A.
square.draw(gl);
// Restore the last matrix.
gl.glPopMatrix();
// SQUARE B
// Save the current matrix
gl.glPushMatrix();
// Rotate square B before moving it, making it rotate around A.
gl.glRotatef(-angle, 0, 0, 1);
// Move square B.
gl.glTranslatef(2, 0, 0);
// Scale it to 50% of square A
gl.glScalef(.5f, .5f, .5f);
// Draw square B.
square.draw(gl);
// SQUARE C
// Save the current matrix
gl.glPushMatrix();
// Make the rotation around B
gl.glRotatef(-angle, 0, 0, 1);
gl.glTranslatef(2, 0, 0);
// Scale it to 50% of square B
gl.glScalef(.5f, .5f, .5f);
// Rotate around it's own center.
gl.glRotatef(angle*10, 0, 0, 1);
// Draw square C.
square.draw(gl);
// Restore to the matrix as it was before C.
gl.glPopMatrix();
// Restore to the matrix as it was before B.
gl.glPopMatrix();
// Increse the angle.
angle++;
}
public class OpenGLRenderer implements Renderer {
private Square square;
private float angle; // Don't forget to add this.
...
Комментарии (0)
RSS свернуть / развернутьТолько зарегистрированные и авторизованные пользователи могут оставлять комментарии.