Java tutorial
/* * Copyright 2016 Clment "w67clement" Wagner * * This file is part of OpenW67Render. * * OpenW67Render is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenW67Render is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with OpenW67Render. If not, see <http://www.gnu.org/licenses/>. */ package com.w67clement.openw67render.gui.graphics; import com.w67clement.openw67render.gui.components.OpenComponent; import com.w67clement.openw67render.gui.graphics.fonts.EasyFont; import com.w67clement.openw67render.gui.graphics.fonts.Font; import com.w67clement.openw67render.utils.Texture; import com.w67clement.openw67render.utils.TextureRegion; import com.w67clement.openw67render.window.OpenWindow; import java.awt.Color; import org.lwjgl.opengl.GL11; import static org.lwjgl.opengl.GL11.*; /** * Created by w67clement on 27/04/2016. * <p> * Class of project: openw67render */ public class OpenGraphics { private float complementX = 0; private float complementY = 0; private Color currentColor = Color.BLACK; private OpenWindow window; private boolean drawing = false; public OpenGraphics(OpenWindow window) { this.window = window; complementX = 0; complementY = 0; } public OpenGraphics(OpenWindow window, float complementX, float complementY) { this.window = window; this.complementX = complementX; this.complementY = complementY; } public OpenGraphics(OpenWindow window, OpenComponent component) { this.window = window; float tempComplementX; float tempComplementY; if (component.hasParent()) { tempComplementX = component.getX(); tempComplementY = component.getY(); OpenComponent last = component; while (last.hasParent()) { last = last.getParent(); tempComplementX = tempComplementX + last.getX(); tempComplementY = tempComplementY + last.getY(); } } else { tempComplementX = component.getX(); tempComplementY = component.getY(); } complementX = tempComplementX; complementY = tempComplementY; } /** * Preserve the OpenGL settings that will be affected when we draw in ortho * mode over the scene. For example if we're drawing an interface layer, * buttons, popup menus, cursor, text, etc. we need to turn off lighting, * turn on blending, set color to white and turn off depth test. * <p> * call pushAttribOverlay(), enable settings that you need, when done call * popAttrib() */ public static void pushAttribOrtho() { glPushAttrib( GL11.GL_COLOR_BUFFER_BIT | GL11.GL_TEXTURE_BIT | GL11.GL_LIGHTING_BIT | GL11.GL_DEPTH_BUFFER_BIT); } /** * <p><a href="http://www.opengl.org/sdk/docs/man/html/glViewport.xhtml">OpenGL SDK Reference</a></p> * <p> * Specifies the viewport transformation parameters for all viewports. * * @param x The left viewport coordinate. * @param y The bottom viewport coordinate. * @param width The viewport width. * @param height The viewport height. */ public static void setViewport(int x, int y, int width, int height) { glViewport(x, y, width, height); } public OpenWindow getWindow() { return window; } /** * Sets the current color. * * @param color Color. */ public void setColor(Color color) { currentColor = color; glColor4f((float) color.getRed() / 255f, (float) color.getGreen() / 255f, (float) color.getBlue() / 255f, (float) color.getAlpha() / 255f); } /** * Gets the current color. * * @return AWT color object. */ public Color getCurrentColor() { return currentColor; } /** * Enables the transparency. */ public void enableTransparency() { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } /** * Disable the transparency. */ public void disableTransparency() { glDisable(GL_BLEND); } public void view2D() { } /** * Set OpenGL to render in flat 2D (no perspective) on top of current scene. * Preserve current projection and model views, and disable depth testing. * Ortho world size will be same as viewport size, so any ortho drawing * (drawQuad(), drawImageFullscreen(), etc.) will be scaled to fit viewport. * <p> * NOTE: if the viewport is the same size as the window (by default it is), * then setOrtho() will make the world coordinates exactly match the screen * pixel positions. This is convenient for mouse interaction, but be warned: * if you setViewport() to something other than fullscreen, then you need to * use getWorldCoordsAtScreen() to convert screen xy to world xy. * <p> * Once Ortho is on, glTranslate() will take pixel coords as arguments, with * the lower left corner 0,0 and the upper right corner 1024,768 (or * whatever your screen size is). !!! */ public void setOrthoOn() { int[] size = window.getSize(); int width = size[0]; int height = size[1]; // prepare projection matrix to render in 2D glMatrixMode(GL11.GL_PROJECTION); glPushMatrix(); // preserve perspective view glLoadIdentity(); // clear the perspective matrix glOrtho( // turn on 2D mode //// viewportX,viewportX+viewportW, // left, right //// viewportY,viewportY+viewportH, // bottom, top !!! 0, width, // left, right height, 0, // bottom, top -500, 500); // Zfar, Znear // clear the modelview matrix glMatrixMode(GL11.GL_MODELVIEW); glPushMatrix(); // Preserve the Modelview Matrix glLoadIdentity(); // clear the Modelview Matrix // disable depth test so further drawing will go over the current scene glDisable(GL11.GL_DEPTH_TEST); } /** * Turn 2D mode off. Return the projection and model views to their * preserved state that was saved when setOrthoOn() was called, and * re-enable depth testing. */ public void setOrthoOff() { // restore the original positions and views glMatrixMode(GL11.GL_PROJECTION); glPopMatrix(); glMatrixMode(GL11.GL_MODELVIEW); glPopMatrix(); // turn Depth Testing back on glEnable(GL11.GL_DEPTH_TEST); } /** * Return to the OpenGL settings that were preserved by the previous * pushAttrib() call. */ public void popAttrib() { glPopAttrib(); } /** * Flush with glFlush() function. */ public void flush() { glFlush(); } /** * Applies the given 2D or 3D translation to the current matrix. * * @param x The amount of pixels to translate on X axis. * @param y The amount of pixels to translate on Y axis. * @param z The amount of pixels to translate on Z axis. */ public void translate(float x, float y, float z) { glTranslatef(x, y, z); } /** * Applies the given 2D or 3D scale to the current matrix. * * @param x The amount of pixels to scale on X axis. * @param y The amount of pixels to scale on Y axis. * @param z The amount of pixels to scale on Z axis. */ public void scale(float x, float y, float z) { glScalef(x, y, z); } /** * Pushes the current matrix stack down by one, duplicating the current matrix in both the top of the stack and the entry below it. */ public void glPushMatrix() { GL11.glPushMatrix(); } /** * Pops the top entry off the current matrix stack, replacing the current matrix with the matrix that was the second entry in the stack. */ public void glPopMatrix() { GL11.glPopMatrix(); } /** * Defines a GL scissor box. All outside pixels cannot modified. * * @param x X of start of the box. * @param y Y of start of the box. * @param width Width of the box. * @param height Height of the box. * * @see #resetScissor() */ public void useScissor(float x, float y, float width, float height) { int[] size = window.getSize(); float yScissor; if (complementY == 0) yScissor = size[1]; else yScissor = size[1] - (complementY + y + height); glScissor((int) (complementX + x), (int) yScissor, (int) width, (int) height); glEnable(GL_SCISSOR_TEST); } /** * Defines the default GL scissor box. All outside pixels cannot modified. * * @see #useScissor(float, float, float, float) * @see #resetScissor() */ public void useDefaultScissor() { int[] size = window.getSize(); glScissor(0, 0, size[0], size[1]); glEnable(GL_SCISSOR_TEST); } /** * Resets the GL scissor box defined by {@link #useScissor(float, float, float, float)}. * * @see #useScissor(float, float, float, float) * @see #resetScissor(boolean) */ public void resetScissor() { resetScissor(false); } /** * Resets the GL scissor box defined by {@link #useScissor(float, float, float, float)}. * * @param disable Disable the GL scissor box. * * @see #useScissor(float, float, float, float) */ public void resetScissor(boolean disable) { if (disable) glDisable(GL_SCISSOR_TEST); int[] size = window.getSize(); glScissor(0, 0, size[0], size[1]); } /** * Gets complement X. * <p> * It's for coordinates of drawing things. * </p> * * @return Complement X. */ public float getComplementX() { return complementX; } /** * Gets complement Y. * <p> * It's for coordinates of drawing things. * </p> * * @return Complement Y. */ public float getComplementY() { return complementY; } /* DRAW */ /** * Begins to draw. * * @param type The thing to draw. */ public void beginDraw(DrawType type) { if (drawing) throw new RuntimeException(); glBegin(type.getId()); drawing = true; } /** * Ends to draw. */ public void endDraw() { if (!drawing) throw new RuntimeException("Not drawing, cannot endDraw."); glEnd(); drawing = false; } /** * <p><a href="http://www.opengl.org/sdk/docs/man2/html/glVertex2f.xhtml">OpenGL SDK Reference</a> - <em>This function is deprecated and unavailable in the Core profile</em></p> * <p> * Specifies a single vertex between {@link #beginDraw(DrawType)} Begin} and {@link #endDraw()} End} by giving its coordinates in two dimensions. * The Z coordinate is implicitly set to zero and the W coordinate to one. * * @param x The vertex X coordinate. * @param y The vertex Y coordinate. */ public void setVertex2f(float x, float y) { glVertex2f(x, y); } /** * Draw a line. * * @param x X position of the first point. * @param y Y position of the first point. * @param x2 X position of the second point. * @param y2 Y position of the second point. */ public void drawLine(float x, float y, float x2, float y2) { x = x + complementX; y = y + complementY; x2 = x2 + complementX; y2 = y2 + complementY; beginDraw(DrawType.LINES); setVertex2f(x, y); setVertex2f(x2, y2); endDraw(); } /** * Draws a simple rectangle. * * @param x X position of the rectangle. * @param y Y position of the rectangle. * @param width The width of the rectangle. * @param height The height of the rectangle. */ public void drawRectangle(float x, float y, float width, float height) { drawRectangle(x, y, width, height, null); } /** * Draws a simple colored rectangle. * * @param x X position of the rectangle. * @param y Y position of the rectangle. * @param width The width of the rectangle. * @param height The height of the rectangle. * @param color Color of the rectangle. */ public void drawRectangle(float x, float y, float width, float height, Color color) { x = x + complementX; y = y + complementY; if (color != null) setColor(color); beginDraw(DrawType.QUADS); setVertex2f(x, y); setVertex2f(x, y + height); setVertex2f(x + width, y + height); setVertex2f(x + width, y); endDraw(); } /** * Draws a simple colored rectangle. * * @param x X position of the rectangle. * @param y Y position of the rectangle. * @param width The width of the rectangle. * @param height The height of the rectangle. * @param leftTopColor The color of the left top corner of the rectangle. * @param leftBottomColor The color of the left bottom corner of the rectangle. * @param rightBottomColor The color of the right bottom corner of the rectangle. * @param rightTopColor The color of the right top corner of the rectangle. */ public void drawRectangle(float x, float y, float width, float height, Color leftTopColor, Color leftBottomColor, Color rightBottomColor, Color rightTopColor) { x = x + complementX; y = y + complementY; beginDraw(DrawType.QUADS); setColor(leftTopColor); setVertex2f(x, y); setColor(leftBottomColor); setVertex2f(x, y + height); setColor(rightBottomColor); setVertex2f(x + width, y + height); setColor(rightTopColor); setVertex2f(x + width, y); endDraw(); } /** * Enable the texture 2D. */ public void enableTexture2D() { glEnable(GL_TEXTURE_2D); } /** * Draws an 2D image with a defined texture. * * @param texture The defined texture to draw. * @param x X position of the image. * @param y Y position of the image. * @param width Width of the image. * @param height Height of the image. * * @see #drawImage(Texture, float, float, float, float, TextureRegion) */ public void drawImage(Texture texture, float x, float y, float width, float height) { drawImage(texture, x, y, width, height, TextureRegion.BASE); } /** * Draws an 2D image with a defined part texture. * * @param texture The defined texture to draw. * @param x X position of the image. * @param y Y position of the image. * @param width Width of the image. * @param height Height of the image. * @param region Part of the texture to draw. */ public void drawImage(Texture texture, float x, float y, float width, float height, TextureRegion region) { x = x + complementX; y = y + complementY; texture.bind(); beginDraw(DrawType.QUADS); glTexCoord2f(region.getMinX(), region.getMinY()); setVertex2f(x, y + height); glTexCoord2f(region.getMinX(), region.getMaxY()); setVertex2f(x, y); glTexCoord2f(region.getMaxX(), region.getMaxY()); setVertex2f(x + width, y); glTexCoord2f(region.getMaxX(), region.getMinY()); setVertex2f(x + width, y + height); endDraw(); texture.unbind(); } /** * <p>Draws simple ASCII text with STB.</p> * * @param text Text to draw. * @param x X start of the text. * @param y Y start of the text. */ public void drawSTBEasyText(String text, float x, float y) { x = x + complementX; y = y + complementY; drawText(EasyFont.INSTANCE, text, x, y); } /** * Draws a text. * * @param font Font used for the text. * @param text Text to draw. * @param x X start of the text. * @param y Y start of the text. */ public void drawText(Font font, String text, float x, float y) { x = x + complementX; y = y + complementY; font.draw(this, text, x, y); } }