org.lwjgl.demo.glfw.Gears.java Source code

Java tutorial

Introduction

Here is the source code for org.lwjgl.demo.glfw.Gears.java

Source

/*
 * Copyright LWJGL. All rights reserved.
 * License terms: https://www.lwjgl.org/license
 */
package org.lwjgl.demo.glfw;

import org.lwjgl.demo.opengl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;
import java.util.*;

import static org.lwjgl.demo.glfw.GLFWUtil.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

/** The Gears demo implemented using GLFW. */
public class Gears extends AbstractGears {

    private Callback debugProc;

    private long window;

    private int xpos;
    private int ypos;
    private int width;
    private int height;

    public static void main(String[] args) {
        new Gears().run();
    }

    private void run() {
        try {
            init();
            initGLState();

            loop();
        } finally {
            try {
                destroy();
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }

    private static void framebufferSizeChanged(long window, int width, int height) {
        if (width == 0 || height == 0) {
            return;
        }

        float f = height / (float) width;

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-1.0f, 1.0f, -f, f, 5.0f, 100.0f);
        glMatrixMode(GL_MODELVIEW);

        glViewport(0, 0, width, height);
    }

    private void init() {
        GLFWErrorCallback.createPrint().set();
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize glfw");
        }

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
        glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
        if (Platform.get() == Platform.MACOSX) {
            glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
        }

        int WIDTH = 300;
        int HEIGHT = 300;

        long window = glfwCreateWindow(WIDTH, HEIGHT, "GLFW Gears Demo", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        /*
          // This code did the equivalent of glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE) before GLFW 3.3
        if ( Platform.get() == Platform.MACOSX ) {
           long cocoaWindow = glfwGetCocoaWindow(window);
            
           long objc_msgSend = ObjCRuntime.getLibrary().getFunctionAddress("objc_msgSend");
           long contentView = invokePPP(objc_msgSend, cocoaWindow, sel_getUid("contentView"));
            
           invokePPV(objc_msgSend, contentView, sel_getUid("setWantsBestResolutionOpenGLSurface:"), false);
            
           boolean bool = invokePPZ(objc_msgSend, contentView, sel_getUid("wantsBestResolutionOpenGLSurface"));
           System.out.println("wantsBestResolutionOpenGLSurface = " + bool);
        }
        */

        glfwSetWindowSizeLimits(window, WIDTH, HEIGHT, GLFW_DONT_CARE, GLFW_DONT_CARE);
        //glfwSetWindowAspectRatio(window, 1, 1);

        long monitor = glfwGetPrimaryMonitor();

        GLFWVidMode vidmode = Objects.requireNonNull(glfwGetVideoMode(monitor));
        // Center window
        glfwSetWindowPos(window, (vidmode.width() - WIDTH) / 2, (vidmode.height() - HEIGHT) / 2);

        glfwSetKeyCallback(window, (windowHnd, key, scancode, action, mods) -> {
            if (action != GLFW_RELEASE) {
                return;
            }

            switch (key) {
            case GLFW_KEY_ESCAPE:
                glfwSetWindowShouldClose(windowHnd, true);
                break;
            case GLFW_KEY_A:
                glfwRequestWindowAttention(windowHnd);
                break;
            case GLFW_KEY_F:
                if (glfwGetWindowMonitor(windowHnd) == NULL) {
                    try (MemoryStack s = stackPush()) {
                        IntBuffer a = s.ints(0);
                        IntBuffer b = s.ints(0);

                        glfwGetWindowPos(windowHnd, a, b);
                        xpos = a.get(0);
                        ypos = b.get(0);

                        glfwGetWindowSize(windowHnd, a, b);
                        width = a.get(0);
                        height = b.get(0);
                    }
                    glfwSetWindowMonitor(windowHnd, monitor, 0, 0, vidmode.width(), vidmode.height(),
                            vidmode.refreshRate());
                    glfwSwapInterval(1);
                }
                break;
            case GLFW_KEY_G:
                glfwSetInputMode(windowHnd, GLFW_CURSOR,
                        glfwGetInputMode(windowHnd, GLFW_CURSOR) == GLFW_CURSOR_NORMAL ? GLFW_CURSOR_DISABLED
                                : GLFW_CURSOR_NORMAL);
                break;
            case GLFW_KEY_O:
                glfwSetWindowOpacity(window, glfwGetWindowOpacity(window) == 1.0f ? 0.5f : 1.0f);
                break;
            case GLFW_KEY_R:
                glfwSetWindowAttrib(windowHnd, GLFW_RESIZABLE, 1 - glfwGetWindowAttrib(windowHnd, GLFW_RESIZABLE));
                break;
            case GLFW_KEY_U:
                glfwSetWindowAttrib(windowHnd, GLFW_DECORATED, 1 - glfwGetWindowAttrib(windowHnd, GLFW_DECORATED));
                break;
            case GLFW_KEY_W:
                if (glfwGetWindowMonitor(windowHnd) != NULL) {
                    glfwSetWindowMonitor(windowHnd, NULL, xpos, ypos, width, height, 0);
                }
                break;
            }
        });

        glfwSetFramebufferSizeCallback(window, Gears::framebufferSizeChanged);

        glfwSetWindowRefreshCallback(window, windowHnd -> {
            renderLoop();
            glfwSwapBuffers(windowHnd);
        });

        glfwMakeContextCurrent(window);
        GL.createCapabilities();
        debugProc = GLUtil.setupDebugMessageCallback();

        glfwSwapInterval(1);
        glfwShowWindow(window);

        glfwInvoke(window, null, Gears::framebufferSizeChanged);

        this.window = window;
    }

    private void loop() {
        long lastUpdate = System.currentTimeMillis();

        int frames = 0;
        while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();

            renderLoop();

            glfwSwapBuffers(window);

            frames++;

            long time = System.currentTimeMillis();

            int UPDATE_EVERY = 5; // seconds
            if (UPDATE_EVERY * 1000L <= time - lastUpdate) {
                lastUpdate = time;

                System.out.printf("%d frames in %d seconds = %.2f fps\n", frames, UPDATE_EVERY,
                        (frames / (float) UPDATE_EVERY));
                frames = 0;
            }
        }
    }

    private void destroy() {
        if (debugProc != null) {
            debugProc.free();
        }

        if (window != NULL) {
            glfwFreeCallbacks(window);
            glfwDestroyWindow(window);
        }

        glfwTerminate();
        Objects.requireNonNull(glfwSetErrorCallback(null)).free();
    }

}