суббота, 17 августа 2013 г.

LWJGL. 2D графика.

Так, как lwjgl использует opengl api для вывода графики, вам нужно знать о матрицах.




В нашем случае графика в 2D, а значит матрица будет называться "matrix ortho".
Но как создать эту матрицу?
То есть, как задать текущую матрицу?
Для этого есть метод:

GL11.glMatrixMode();

С помощью него можно задавать матрицы, которые нам нужны.
В нашем случае будуть использоваться следующие матрицы:
GL_MODELVIEW - видовое пространство.
GL_PROJECTION
и единичная матрица, вызывается с помощью метода
GL11.glLoadIdentity();

После всех этих непонятных штук нам пригодится метод
GL11.glOrtho(left, right, bottom, top, zNear, zFar);
Обычно этот метод вызвается с функциями:

left = 0.0D;
right = Display.getWidth();
bottom = 0.0D;
top = Display.getHeight();
zNear = -1.0D;
zFar = 1.0D;

После создания матрицы уже можно рисовать.

Но, для до рисования нужно очистить буффер цвета для перерисовки содержимого в окне.
Это делается так:
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
И вызывается единичная матрица:
GL11.glLoadIdentity();

Ну вот и все! Теперь можно рисовать.

Для начала нам нужно выбрать метод рисования(треугольниками, квадратами, линиями или полигонами).

Чтобы рисовать квадратами, нужно вызвать метод:

GL11.glBegin(GL11.GL_QUADS);

Или же треугольниками:

GL11.GL_TRIANGLES);

Ну, вы решили метод рисования, но как рисовать!?

Для этого есть специальный метод
для 2D
GL11.glVertex2f(x, y);
для 3D
GL11.glVertex3f(x, y, z);
Эти методы задают координаты точек для соединения и преобразования их в квадраты, линии или треугольники.

Например, я рисую квадрат:

GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(0.0F, 0.0F); // точка в координатах 0, 0.
GL11.glVertex2f(50.0F, 0.0f); // точка в координатах 50 , 0.
GL11.glVertex2f(50.0F, 50.0F) // точка в координатах 50, 50.
GL11.glVertex2f(0.0F, 50.0F); // точка в координатах 0, 50.
GL11.glEnd(); // конец рисования

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

Но после рисования квадрата он по-умолчанию появляется в координатах 0, 0.
Как же его переместить в середину окна?
Для этого служит специальный метод
GL11.glTranslatef(x, y, z);
В 2D мире координата z = 0.0F;

Переместим квадрат

GL11.glTranslatef(200.0F, 300.0F, 0.0f);
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(0.0F, 0.0F); // точка в координатах 0, 0.
GL11.glVertex2f(50.0F, 0.0f); // точка в координатах 50 , 0.
GL11.glVertex2f(50.0F, 50.0F) // точка в координатах 50, 50.
GL11.glVertex2f(0.0F, 50.0F); // точка в координатах 0, 50.
GL11.glEnd(); // конец рисования

Но если мы нарисуем еще один квадрат, то они все будут в координатах 0, 0.
Почему так происходит?
Потому, что мы не сохраняем текущую матрицу!
Делается это так:
GL11.glPushMatrix();

Потом после рисования квадрата мы закрываем матрицу
GL11.glPopMatrix();

Чтобы изменить цвет квадрата есть метод
GL11.glColor3f(g, r, b);
Чтобы восстановить цвет по-умолчанию, нужно сделать так:
GL11.glColor3f(1.0F, 1.0F, 1.0F);

Весь код:
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

public final class SimpleProgram
{
    private SimpleProgram()
    {
    }

    private void initialize()
    {
        this.createDisplay(800, 600, "SimpleProgram");
        this.createMatrixOrtho();
        this.running();
    }

    private void createDisplay(int width, int height, String title)
    {
        try
        {
            Display.setDisplayMode(new DisplayMode(width, height));
            Display.setTitle(title);
            Display.create();
        }
        catch (LWJGLException ex)
        {
            Logger.getLogger(SimpleProgram.class.getName()).log(Level.SEVERE, null, ex);
            this.clearResources(true);
        }
    }

    private void createMatrixOrtho()
    {
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0.0D, (double) Display.getWidth(), 0.0D, (double) Display.getHeight(), -1.0D, 1.0D);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
    }

    private void running()
    {
        while (!Display.isCloseRequested())
        {
            this.displayUpdate();
        }
        this.clearResources(false);
    }

    private void displayUpdate()
    {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        GL11.glLoadIdentity();

        GL11.glColor3f(0.0F, 1.0F, 0.0F);
        GL11.glPushMatrix();
        GL11.glTranslatef(200.0F, 300.0F, 0.0F);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2f(0.0F, 0.0F);
        GL11.glVertex2f(50.0F, 0.0f);
        GL11.glVertex2f(50.0F, 50.0F);
        GL11.glVertex2f(0.0F, 50.0F);
        GL11.glEnd();
        GL11.glPopMatrix();
        GL11.glColor3f(1.0F, 1.0F, 1.0F);

        GL11.glPushMatrix();
        GL11.glTranslatef(100.0F, 200.0F, 0.0F);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glColor3f(1.0F, 0.0F, 0.0F);
        GL11.glVertex2f(0.0F, 0.0F);
        GL11.glColor3f(0.0F, 1.0F, 0.0F);
        GL11.glVertex2f(50.0F, 0.0f);
        GL11.glColor3f(0.0F, 0.0F, 1.0F);
        GL11.glVertex2f(50.0F, 50.0F);
        GL11.glColor3f(1.0F, 1.0F, 1.0F);
        GL11.glVertex2f(0.0F, 50.0F);
        GL11.glEnd();
        GL11.glPopMatrix();
        GL11.glColor3f(1.0F, 1.0F, 1.0F);

        Display.update();
        Display.sync(60);
    }

    private void clearResources(boolean hasCrash)
    {
        System.out.println(GLU.gluErrorString(GL11.glGetError()));
        Display.destroy();
        System.exit(hasCrash ? 1 : 0);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        new SimpleProgram().initialize();
    }
}

2 комментария:

  1. Чтобы изменить цвет фона, нужно вызвать один раз метод
    GL11.glClearColor(r, g, b, alpha);

    ОтветитьУдалить
    Ответы
    1. Аргументы: r, g, b - единичные. alpha равна 0 или 1.

      Удалить