de.keyle.dungeoncraft.editor.editors.world.render.Renderer.java Source code

Java tutorial

Introduction

Here is the source code for de.keyle.dungeoncraft.editor.editors.world.render.Renderer.java

Source

/*
 * This file is part of DungeonCraft-Editor
 *
 * Copyright (C) 2011-2014 Keyle
 * DungeonCraft-Editor is licensed under the GNU Lesser General Public License.
 *
 * DungeonCraft-Editor is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DungeonCraft-Editor 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package de.keyle.dungeoncraft.editor.editors.world.render;

import de.keyle.dungeoncraft.editor.util.Facing;
import org.lwjgl.opengl.GL11;

import static de.keyle.dungeoncraft.editor.editors.world.render.MinecraftConstants.TEX16;

public class Renderer {
    /**
     * Renders a nonstandard vertical rectangle (nonstandard referring primarily to
     * the texture size (ie: when we're not pulling a single element out of a 16x16
     * grid).  This differs from renderVertical also in that we specify two full
     * (x, y, z) coordinates for the bounds, instead of passing in y and a height.
     *
     * @param dimensions dimensions of the texture
     * @param x1         from x
     * @param y1         from y
     * @param z1         from z
     * @param x2         to x
     * @param y2         to y
     * @param z2         to z
     */
    public static void renderNonstandardVertical(TextureDimensions dimensions, float x1, float y1, float z1,
            float x2, float y2, float z2) {
        renderNonstandardVertical(dimensions.getTexLeft(), dimensions.getTexTop(), dimensions.getTexWidth(),
                dimensions.getTexHeight(), x1, y1, z1, x2, y2, z2);
    }

    /**
     * Renders a nonstandard vertical rectangle (nonstandard referring primarily to
     * the texture size (ie: when we're not pulling a single element out of a 16x16
     * grid).  This differs from renderVertical also in that we specify two full
     * (x, y, z) coordinates for the bounds, instead of passing in y and a height.
     * Texture coordinates are passed in as the usual float from 0 to 1.
     *
     * @param tx  X index within the texture
     * @param ty  Y index within the texture
     * @param tdx Width of texture
     * @param tdy Height of texture
     * @param x1
     * @param y1
     * @param z1
     * @param x2
     * @param y2
     * @param z2
     */
    public static void renderNonstandardVertical(float tx, float ty, float tdx, float tdy, float x1, float y1,
            float z1, float x2, float y2, float z2) {
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);

        GL11.glTexCoord2f(tx, ty + tdy);
        GL11.glVertex3f(x1, y1, z1);

        GL11.glTexCoord2f(tx + tdx, ty + tdy);
        GL11.glVertex3f(x2, y1, z2);

        GL11.glTexCoord2f(tx, ty);
        GL11.glVertex3f(x1, y2, z1);

        GL11.glTexCoord2f(tx + tdx, ty);
        GL11.glVertex3f(x2, y2, z2);

        // unflipped textures
        /*
        GL11.glTexCoord2f(tx, ty);
        GL11.glVertex3f(x1, y1, z1);
            
        GL11.glTexCoord2f(tx + tdx, ty);
        GL11.glVertex3f(x2, y1, z2);
            
        GL11.glTexCoord2f(tx, ty + tdy);
        GL11.glVertex3f(x1, y2, z1);
            
        GL11.glTexCoord2f(tx + tdx, ty + tdy);
        GL11.glVertex3f(x2, y2, z2);
         */
        GL11.glEnd();
    }

    public static void renderVertical(TextureDimensions dimensions, float x1, float z1, float x2, float z2, float y,
            float height) {
        renderVertical(dimensions.getTexLeft(), dimensions.getTexTop(), dimensions.getTexWidth(),
                dimensions.getTexHeight(), x1, z1, x2, z2, y, height);
    }

    /**
     * Renders a somewhat-arbitrary vertical rectangle.  Pass in (x, z) pairs for the endpoints,
     * and information about the height.  The texture variables given are in terms of 1/16ths of
     * the texture square, which means that for the default Minecraft 16x16 texture, they're in
     * pixels.
     *
     * @param x1
     * @param z1
     * @param x2
     * @param z2
     * @param y      The lower part of the rectangle
     * @param height Height of the rectangle.
     */
    public static void renderVertical(float tx, float ty, float tdx, float tdy, float x1, float z1, float x2,
            float z2, float y, float height) {
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        GL11.glTexCoord2f(tx, ty);
        GL11.glVertex3f(x1, y + height, z1);

        GL11.glTexCoord2f(tx + tdx, ty);
        GL11.glVertex3f(x2, y + height, z2);

        GL11.glTexCoord2f(tx, ty + tdy);
        GL11.glVertex3f(x1, y, z1);

        GL11.glTexCoord2f(tx + tdx, ty + tdy);
        GL11.glVertex3f(x2, y, z2);
        GL11.glEnd();
    }

    /**
     * Renders an arbitrary horizontal rectangle (will be orthogonal).  The texture parameters
     * are specified in terms of 1/16ths of the texture (which equates to one pixel, when using
     * the default 16x16 Minecraft texture.
     *
     * @param x1
     * @param z1
     * @param x2
     * @param z2
     * @param y
     */
    public static void renderHorizontal(TextureDimensions dimensions, float x1, float z1, float x2, float z2,
            float y, boolean flip_tex) {
        renderHorizontal(x1, z1, x2, z2, y, dimensions.getTexLeft(), dimensions.getTexTop(),
                dimensions.getTexWidth(), dimensions.getTexHeight(), flip_tex);
    }

    /**
     * Renders an arbitrary horizontal rectangle (will be orthogonal).  The texture parameters
     * are specified in terms of 1/16ths of the texture (which equates to one pixel, when using
     * the default 16x16 Minecraft texture.
     *
     * @param x1
     * @param z1
     * @param x2
     * @param z2
     * @param y
     */
    public static void renderHorizontal(float x1, float z1, float x2, float z2, float y, float tex_start_x,
            float tex_start_y, float tex_width, float tex_height, boolean flip_tex) {
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);

        if (flip_tex) {
            GL11.glTexCoord2f(tex_start_x, tex_start_y);
            GL11.glVertex3f(x1, y, z2);

            GL11.glTexCoord2f(tex_start_x + tex_width, tex_start_y);
            GL11.glVertex3f(x2, y, z2);

            GL11.glTexCoord2f(tex_start_x, tex_start_y + tex_height);
            GL11.glVertex3f(x1, y, z1);

            GL11.glTexCoord2f(tex_start_x + tex_width, tex_start_y + tex_height);
            GL11.glVertex3f(x2, y, z1);
        } else {
            GL11.glTexCoord2f(tex_start_x, tex_start_y);
            GL11.glVertex3f(x1, y, z1);

            GL11.glTexCoord2f(tex_start_x + tex_width, tex_start_y);
            GL11.glVertex3f(x1, y, z2);

            GL11.glTexCoord2f(tex_start_x, tex_start_y + tex_height);
            GL11.glVertex3f(x2, y, z1);

            GL11.glTexCoord2f(tex_start_x + tex_width, tex_start_y + tex_height);
            GL11.glVertex3f(x2, y, z2);
        }
        GL11.glEnd();
    }

    /**
     * Renders a nonstandard horizontal rectangle (nonstandard referring primarily to
     * the texture size (ie: when we're not pulling a single element out of a 16x16
     * grid).
     *
     * @param dimensions dimensions of the texture
     * @param x1
     * @param z1
     * @param x2
     * @param z2
     * @param y
     */
    public static void renderNonstandardHorizontal(TextureDimensions dimensions, float x1, float z1, float x2,
            float z2, float y) {
        renderNonstandardHorizontal(dimensions.getTexLeft(), dimensions.getTexTop(), dimensions.getTexWidth(),
                dimensions.getTexHeight(), x1, z1, x2, z2, y);
    }

    /**
     * Renders a nonstandard horizontal rectangle (nonstandard referring primarily to
     * the texture size (ie: when we're not pulling a single element out of a 16x16
     * grid).
     *
     * @param tx  X index within the texture
     * @param ty  Y index within the texture
     * @param tdx Width of texture
     * @param tdy Height of texture
     * @param x1
     * @param z1
     * @param x2
     * @param z2
     * @param y
     */
    public static void renderNonstandardHorizontal(float tx, float ty, float tdx, float tdy, float x1, float z1,
            float x2, float z2, float y) {
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        GL11.glTexCoord2f(tx, ty);
        GL11.glVertex3f(x1, y, z1);

        GL11.glTexCoord2f(tx + tdx, ty);
        GL11.glVertex3f(x1, y, z2);

        GL11.glTexCoord2f(tx, ty + tdy);
        GL11.glVertex3f(x2, y, z1);

        GL11.glTexCoord2f(tx + tdx, ty + tdy);
        GL11.glVertex3f(x2, y, z2);
        GL11.glEnd();
    }

    public static void renderHorizontalAskew(TextureDimensions dimensions, float x1, float z1, float x2, float z2,
            float x3, float z3, float x4, float z4, float y) {
        renderHorizontalAskew(dimensions.getTexLeft(), dimensions.getTexTop(), dimensions.getTexWidth(),
                dimensions.getTexHeight(), x1, z1, x2, z2, x3, z3, x4, z4, y);
    }

    /**
     * Render a surface on a horizontal plane; pass in all four verticies.  This can result,
     * obviously, in non-rectangular and non-orthogonal shapes.
     *
     * @param tx
     * @param ty
     * @param tdx
     * @param tdy
     * @param x1
     * @param z1
     * @param x2
     * @param z2
     * @param x3
     * @param z3
     * @param x4
     * @param z4
     * @param y
     */
    public static void renderHorizontalAskew(float tx, float ty, float tdx, float tdy, float x1, float z1, float x2,
            float z2, float x3, float z3, float x4, float z4, float y) {
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        GL11.glTexCoord2f(tx, ty);
        GL11.glVertex3f(x1, y, z1);

        GL11.glTexCoord2f(tx + tdx, ty);
        GL11.glVertex3f(x2, y, z2);

        GL11.glTexCoord2f(tx, ty + tdy);
        GL11.glVertex3f(x3, y, z3);

        GL11.glTexCoord2f(tx + tdx, ty + tdy);
        GL11.glVertex3f(x4, y, z4);
        GL11.glEnd();
    }

    /**
     * Renders a decoration which is supposed to be a "cross" in a single block.
     */
    public static void renderCrossDecoration(TextureDimensions dimensions, int x, int y, int z) {
        float width = dimensions.getTexWidth() / TEX16;
        float width_h = width / 2f;
        float height = dimensions.getTexHeight() / TEX16;

        renderNonstandardVertical(dimensions, x - width_h, y + height, z - width_h, x + width_h, y, z + width_h);
        renderNonstandardVertical(dimensions, x + width_h, y + height, z - width_h, x - width_h, y, z + width_h);
    }

    /**
     * Renders a rectangular decoration.
     *
     * @param dimensions     Dimension of the Texture
     * @param x              Block X
     * @param y              Block Y
     * @param z              Block Z
     * @param rotate_degrees Degrees to rotate, use zero for no rotation
     * @param rotate_x       Use 1.0f to rotate in the X direction (passed to glRotatef)
     * @param rotate_z       Use 1.0f to rotate in the Z direction (passed to glRotatef)
     * @param x_off          X offset, so it's not just in the center
     * @param z_off          Z offset, so it's not just in the center
     */
    public static void renderRectDecoration(TextureDimensions dimensions, float x, float y, float z,
            int rotate_degrees, float rotate_x, float rotate_z, float x_off, float z_off) {

        boolean do_rotate = false;
        float tx = 0, ty = 0, tz = 0;
        if (rotate_degrees != 0) {
            tx = x;
            ty = y;
            tz = z;
            x = x_off;
            y = 0;
            z = z_off;
            do_rotate = true;
        }

        float width = dimensions.getTexWidth() / TEX16;
        float width_h = width / 2f;
        float height = dimensions.getTexHeight() / TEX16;
        float top_tex_height;
        if (height > width) {
            top_tex_height = dimensions.getTexWidth() / 2f;
        } else {
            top_tex_height = dimensions.getTexHeight();
        }

        // Math is for suckers; let's let the video hardware take care of rotation
        // Relatedly, is this how I should be drawing *everything?*  Draw relative
        // to the origin for the actual verticies, and then translate?
        if (do_rotate) {
            GL11.glPushMatrix();
            GL11.glTranslatef(tx, ty, tz);
            GL11.glRotatef((float) rotate_degrees, rotate_x, 0f, rotate_z);
        }

        // First draw the borders
        renderNonstandardVertical(dimensions, x - width_h, y + height, z - width_h, x + width_h, y, z - width_h);
        renderNonstandardVertical(dimensions, x - width_h, y + height, z + width_h, x + width_h, y, z + width_h);
        renderNonstandardVertical(dimensions, x + width_h, y + height, z - width_h, x + width_h, y, z + width_h);
        renderNonstandardVertical(dimensions, x - width_h, y + height, z + width_h, x - width_h, y, z - width_h);

        // Now the top
        renderNonstandardHorizontal(dimensions.getTexLeft(), dimensions.getTexTop(), dimensions.getTexWidth(),
                top_tex_height, x - width_h, z - width_h, x + width_h, z + width_h, y + height);

        if (do_rotate) {
            GL11.glPopMatrix();
        }
    }

    /**
     * Renders a "grid" decoration (in the manner of crops and netherwart)
     *
     * @param dimensions Texture dimensions
     * @param x
     * @param y
     * @param z
     */
    public void renderGridDecoration(TextureDimensions dimensions, int x, int y, int z) {
        float width_h = dimensions.getTexWidth() / 16 / 2;
        float side_offset = .25f;
        float bottom = y - .5f;
        float top = bottom + dimensions.getTexHeight() / 16;

        renderNonstandardVertical(dimensions, x - width_h, top, z + side_offset, x + width_h, bottom,
                z + side_offset);

        renderNonstandardVertical(dimensions, x - width_h, top, z - side_offset, x + width_h, bottom,
                z - side_offset);

        renderNonstandardVertical(dimensions, x + side_offset, top, z - width_h, x + side_offset, bottom,
                z + width_h);

        renderNonstandardVertical(dimensions, x - side_offset, top, z - width_h, x - side_offset, bottom,
                z + width_h);
    }

    /**
     * Renders a block sized face with the given facing.
     *
     * @param dimensions Texture dimensions
     * @param x
     * @param y
     * @param z
     * @param facing     The face that should be drawn
     */
    public static void renderBlockFace(TextureDimensions dimensions, float x, float y, float z, Facing facing) {
        float curFace[][];
        switch (facing) {
        case UP:
            curFace = new float[][] { { 0f, 1f, 1f }, { 0f, 1f, 0f }, { 1f, 1f, 1f }, { 1f, 1f, 0f } };
            break;
        case DOWN:
            curFace = new float[][] { { 0f, 0f, 1f }, { 0f, 0f, 0f }, { 1f, 0f, 1f }, { 1f, 0f, 0f } };
            break;
        case NORTH:
            curFace = new float[][] { { 0f, 1f, 0f }, { 1f, 1f, 0f }, { 0f, 0f, 0f }, { 1f, 0f, 0f } };
            break;
        case SOUTH:
            curFace = new float[][] { { 0f, 1f, 1f }, { 1f, 1f, 1f }, { 0f, 0f, 1f }, { 1f, 0f, 1f } };
            break;
        case WEST:
            curFace = new float[][] { { 0f, 1f, 1f }, { 0f, 1f, 0f }, { 0f, 0f, 1f }, { 0f, 0f, 0f } };
            break;
        case EAST:
            curFace = new float[][] { { 1f, 1f, 1f }, { 1f, 1f, 0f }, { 1f, 0f, 1f }, { 1f, 0f, 0f } };
            break;
        default:
            return;
        }

        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        GL11.glTexCoord2f(dimensions.getTexLeft(), dimensions.getTexTop());
        GL11.glVertex3f(x + curFace[0][0], y + curFace[0][1], z + curFace[0][2]);

        GL11.glTexCoord2f(dimensions.getTexLeft() + dimensions.getTexWidth(), dimensions.getTexTop());
        GL11.glVertex3f(x + curFace[1][0], y + curFace[1][1], z + curFace[1][2]);

        GL11.glTexCoord2f(dimensions.getTexLeft(), dimensions.getTexTop() + dimensions.getTexHeight());
        GL11.glVertex3f(x + curFace[2][0], y + curFace[2][1], z + curFace[2][2]);

        GL11.glTexCoord2f(dimensions.getTexLeft() + dimensions.getTexWidth(),
                dimensions.getTexTop() + dimensions.getTexHeight());
        GL11.glVertex3f(x + curFace[3][0], y + curFace[3][1], z + curFace[3][2]);
        GL11.glEnd();
    }
}