eu.over9000.veya.Veya.java Source code

Java tutorial

Introduction

Here is the source code for eu.over9000.veya.Veya.java

Source

/*
 * Veya
 * Copyright (C) 2015 s1mpl3x
 *
 * This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package eu.over9000.veya;

import java.awt.*;
import java.io.IOException;
import java.util.EnumSet;

import javax.imageio.ImageIO;

import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.*;

import eu.over9000.veya.console.Console;
import eu.over9000.veya.rendering.Camera;
import eu.over9000.veya.rendering.Program;
import eu.over9000.veya.rendering.Scene;
import eu.over9000.veya.util.MathUtil;
import eu.over9000.veya.world.BlockType;

public class Veya {
    public static final int RESTART = 0xFFFFFFFF;

    public static boolean ENABLE_DAY_NIGHT = false;
    public static final float MOVEMENT_MULTIPLIER_WALK = 4.5f;

    public static final float MOVEMENT_MULTIPLIER_FLY = 25f;
    private static final float MOUSE_SENSITIVITY = 0.01f;

    public static final float FIELD_OF_VIEW = 75.0f;
    public static final float NEAR_CLIPPING_PLANE = 0.1f;
    public static final float FAR_CLIPPING_PLANE = 1000.0f;

    public static Camera camera;

    public static Program program_normal;
    public static Program program_shadow;
    public static Program program_debug;

    public static Scene scene;
    public static boolean colorSwitch = false;

    public static boolean aoSwitch = true;
    public static boolean gravitySwitch = true;
    public static boolean collisionSwitch = true;
    public static boolean wireframeSwitch = false;

    private static float ambient = 0.60f;
    private static float diffuse = 0.40f;

    private static float specular = 0.30f;
    private static final float df = 0.05f;

    private static Frame frame;
    private static boolean shutdown = false;

    public static boolean debugShadow = true;

    private static long lastSpacePress = 0;
    public static final EnumSet<BlockType> ignoreBlocks = EnumSet.noneOf(BlockType.class);

    //public static final EnumSet<BlockType> ignoreBlocks = EnumSet.of(BlockType.STONE);

    public static void main(final String[] args) throws LWJGLException {

        System.setProperty("org.lwjgl.util.Debug", "true");

        Veya.init();
        Veya.run();
        Veya.end();
    }

    private static void init() throws LWJGLException {
        final Canvas canvas = new Canvas();
        frame = new Frame();
        frame.add(canvas);
        frame.setSize(1280, 720);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        frame.setExtendedState(Frame.MAXIMIZED_BOTH);
        frame.setIconImage(loadIcon());

        Display.setParent(canvas);
        Display.create(new PixelFormat().withSamples(4).withDepthBits(24), new ContextAttribs(3, 3));

        System.out.println("OpenGL version: " + GL11.glGetString(GL11.GL_VERSION));
        System.out.println("Java version: " + System.getProperty("java.version"));
        System.out.println("graphics adapter: " + Display.getAdapter());

        Veya.program_normal = new Program("normal",
                new String[] { "modelMatrix", "viewMatrix", "projectionMatrix", "lightPosition", "lightColor",
                        "lightFactors", "colorSwitch", "aoSwitch", "cameraPosition", "lightSpaceMatrix",
                        "textureData", "shadowMap" });
        Veya.program_shadow = new Program("shadow", new String[] { "modelMatrix", "lightSpaceMatrix" });
        Veya.program_debug = new Program("debug", new String[] { "near_plane", "far_plane" });

        Util.checkGLError();

        Veya.camera = new Camera(-40, 120, -40);
        Veya.scene = new Scene(1337);

        Util.checkGLError();

        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glEnable(GL11.GL_CULL_FACE);
        GL11.glLineWidth(2.5f);

        Util.checkGLError();

        GL11.glEnable(GL31.GL_PRIMITIVE_RESTART);
        GL31.glPrimitiveRestartIndex(Veya.RESTART);
        GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
        GL11.glClearColor(124f / 255f, 169f / 255f, 255f / 255f, 1.0f);

        Mouse.setGrabbed(true);

        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        Console.start();
    }

    private static void run() {
        Util.checkGLError();

        Veya.program_normal.use(true);
        Veya.camera.updateProjectionMatrix(Display.getWidth(), Display.getHeight());
        Veya.camera.updateViewMatrix();
        Veya.scene.init();

        Veya.program_normal.use(false);

        program_normal.use(true);
        GL20.glUniform1i(Veya.program_normal.getUniformLocation("colorSwitch"), Veya.colorSwitch ? 1 : 0);
        program_normal.use(false);

        program_normal.use(true);
        GL20.glUniform1i(Veya.program_normal.getUniformLocation("aoSwitch"), Veya.aoSwitch ? 1 : 0);
        program_normal.use(false);

        Util.checkGLError();

        long start = Sys.getTime();
        long lastTime = start;
        long count = 0;

        while (!Display.isCloseRequested() && !shutdown) {
            final long time = Sys.getTime();
            final float dt = (time - lastTime) / 1000.0f;
            lastTime = time;

            checkResize();

            handleMovementKeys(dt);
            handleOtherKeys();
            handleMouseInput();

            if (gravitySwitch) {
                Veya.camera.applyGravity(dt);
            }

            Veya.camera.performMove();

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

            Veya.program_normal.use(true);

            if (ENABLE_DAY_NIGHT) {
                final float posX = (float) Math.sin(System.currentTimeMillis() / 10000.0) * 512;
                final float posY = (float) Math.cos(System.currentTimeMillis() / 10000.0) * 512;
                // final float posZ = (float) Math.cos(System.currentTimeMillis() / 1500.0) * 20f;
                ambient = 0.25f + MathUtil.scale(posY, -1024, 1024, 0, 0.55f);
                diffuse = MathUtil.scale(posY, -1024, 1024, 0, 0.5f);
                specular = MathUtil.scale(posY, -1024, 1024, 0, 0.5f);
                final float kek = (posY / 1024f + 1) / 2;

                GL11.glClearColor(kek * 124f / 255f, kek * 169f / 255f, kek * 255f / 255f, 1.0f);
                Veya.scene.getLight().updateLightPosition(posX + Veya.camera.getPosition().getX(), posY,
                        1 + Veya.camera.getPosition().getZ());
            }

            //Veya.scene.getLight().updateLightPosition(Veya.camera.getPosition().getX() + 1, 500, Veya.camera.getPosition().getZ() + 250);

            Veya.camera.updateViewMatrix();
            Veya.camera.updateCameraPosition();
            Veya.scene.getLight().updateLightFactors(Veya.ambient, Veya.diffuse, Veya.specular);
            Veya.scene.render();

            Util.checkGLError();

            Veya.program_normal.use(false);

            Display.update();
            // Display.sync(60);
            Util.checkGLError();

            final long end = Sys.getTime();
            if (end - start > 1000) {
                start = end;
                frame.setTitle("VEYA | fps: " + count + " | pos: x=" + Veya.camera.getPosition().x + ", y="
                        + Veya.camera.getPosition().y + ", z=" + Veya.camera.getPosition().z
                        + " | #chunks displayed: " + Veya.scene.getChunkCount() + " | lightFactors: A="
                        + Veya.ambient + ", D=" + Veya.diffuse + ", S=" + Veya.specular + " | chunk updates: "
                        + scene.chunkUpdateCounterInRender.get() + "/" + scene.chunkUpdateCounterOffRender.get()
                        + " | selected block: " + scene.placeBlockType);
                count = 0;
                scene.chunkUpdateCounterInRender.set(0);
                scene.chunkUpdateCounterOffRender.set(0);

            } else {
                count++;
            }
        }
    }

    private static void handleOtherKeys() {
        while (Keyboard.next()) {
            if (Keyboard.getEventKey() == Keyboard.KEY_C && Keyboard.getEventKeyState()) {
                Veya.colorSwitch = !Veya.colorSwitch;
                program_normal.use(true);
                GL20.glUniform1i(Veya.program_normal.getUniformLocation("colorSwitch"), Veya.colorSwitch ? 1 : 0);
                program_normal.use(false);
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_Y && Keyboard.getEventKeyState()) {
                Veya.aoSwitch = !Veya.aoSwitch;
                program_normal.use(true);
                GL20.glUniform1i(Veya.program_normal.getUniformLocation("aoSwitch"), Veya.aoSwitch ? 1 : 0);
                program_normal.use(false);
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_V && Keyboard.getEventKeyState()) {
                Veya.wireframeSwitch = !Veya.wireframeSwitch;
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_Q && Keyboard.getEventKeyState()) {
                Veya.debugShadow = !Veya.debugShadow;
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_SPACE && Keyboard.getEventKeyState()) {
                final long diff = Keyboard.getEventNanoseconds() - lastSpacePress;
                if (diff < 250 * 1000000) {
                    Veya.gravitySwitch = !Veya.gravitySwitch;
                    camera.resetVelocity();
                }
                lastSpacePress = Keyboard.getEventNanoseconds();
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_X) {
                Mouse.setGrabbed(!Keyboard.getEventKeyState());
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_PRIOR && Keyboard.getEventKeyState()) {
                if (Veya.specular + Veya.df <= 1.0f) {
                    Veya.specular += Veya.df;
                } else {
                    Veya.specular = 1.0f;
                }
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_NEXT && Keyboard.getEventKeyState()) {
                if (Veya.specular - Veya.df >= 0.0f) {
                    Veya.specular -= Veya.df;
                } else {
                    Veya.specular = 0.0f;
                }
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_HOME && Keyboard.getEventKeyState()) {
                if (Veya.diffuse + Veya.df <= 1.0f) {
                    Veya.diffuse += Veya.df;
                } else {
                    Veya.diffuse = 1.0f;
                }
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_END && Keyboard.getEventKeyState()) {
                if (Veya.diffuse - Veya.df >= 0.0f) {
                    Veya.diffuse -= Veya.df;
                } else {
                    Veya.diffuse = 0.0f;
                }
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_INSERT && Keyboard.getEventKeyState()) {
                if (Veya.ambient + Veya.df <= 1.0f) {
                    Veya.ambient += Veya.df;
                } else {
                    Veya.ambient = 1.0f;
                }
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_DELETE && Keyboard.getEventKeyState()) {
                if (Veya.ambient - Veya.df >= 0.0f) {
                    Veya.ambient -= Veya.df;
                } else {
                    Veya.ambient = 0.0f;
                }
            }
            if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState()) {
                shutdown = true;
            }
        }
    }

    private static void handleMovementKeys(final float dt) {
        if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
            Veya.camera.tryWalkForward(Veya.getMovementMultiplier() * dt);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
            Veya.camera.tryWalkBackwards(Veya.getMovementMultiplier() * dt);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            Veya.camera.tryStrafeLeft(Veya.getMovementMultiplier() * dt);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
            Veya.camera.tryStrafeRight(Veya.getMovementMultiplier() * dt);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
            Veya.camera.tryMoveUp(Veya.getMovementMultiplier() * dt);
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
            Veya.camera.tryMoveDown(Veya.getMovementMultiplier() * dt);
        }
    }

    private static void checkResize() {
        if (Display.wasResized()) {
            Veya.program_normal.use(true);
            Veya.camera.updateProjectionMatrix(Display.getWidth(), Display.getHeight());
            Veya.program_normal.use(false);
            GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
            System.out.println("resized");
        }
    }

    private static void handleMouseInput() {
        if (!Keyboard.isKeyDown(Keyboard.KEY_X)) {
            final float dx = Mouse.getDX();
            final float dy = Mouse.getDY();

            Veya.camera.yaw(dx * Veya.MOUSE_SENSITIVITY);
            Veya.camera.pitch(dy * Veya.MOUSE_SENSITIVITY);
        }
        while (Mouse.next()) {
            if (Mouse.getEventButton() == 0 && Mouse.getEventButtonState()) {
                scene.performLeftClick();
            }
            if (Mouse.getEventButton() == 1 && Mouse.getEventButtonState()) {
                scene.performRightClick();
            }
            if (Mouse.getEventButton() == 2 && Mouse.getEventButtonState()) {
                scene.performMiddleClick();
            }
        }
    }

    private static void end() {
        Veya.scene.dispose();
        Veya.program_normal.unload();
        Display.destroy();
        frame.setVisible(false);

        Console.stop();

        System.exit(0);
    }

    private static Image loadIcon() {
        try {
            return ImageIO.read(Veya.class.getResourceAsStream("/icon/veya.png"));
        } catch (final IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static float getMovementMultiplier() {
        return gravitySwitch ? MOVEMENT_MULTIPLIER_WALK : MOVEMENT_MULTIPLIER_FLY;
    }
}