EZGL

// -------------------------------------------------------------
// Ezgl.h
// - Simple little utility framework for tinkering
// - Requires GLUT (or one of its offspring) and one of the
//   extension loading utilities such as GLEE or GLEW
// -------------------------------------------------------------
#pragma once

#include "glut.h"
#include <stdio.h>
#include <assert.h>

namespace Ezgl
{
    inline double ElapsedTime()
    {
        static double spc = 0;

        if (spc == 0)
        {
            LARGE_INTEGER freq;
            if (QueryPerformanceFrequency(&freq))
            {
                spc = 1.0 / (double)freq.QuadPart;
            }
            else
            {
                printf("QueryPerformanceFrequency failed\n");
            }
        }

        if (spc != 0)
        {
            LARGE_INTEGER counter;
            if (QueryPerformanceCounter(&counter))
            {
                return (double)counter.QuadPart * spc;
            }
            else
            {
                printf("QueryPerformanceCounter failed\n");
            }
        }
        else
        {
            return 0;
        }
    }

    struct Camera
    {
        float x, y, z;
        float boom;
        float angleX, angleY, angleZ;
        float hither, yon;
        float fov;
        float width, height;

        Camera()
            : x(0), y(0), z(0)
            , boom(128)
            , angleX(-45), angleY(45), angleZ(0)
            , hither(1), yon(8192)
            , fov(80)
        { }

        void ApplyPerspective()
        {
            // TODO: Get rid of the deprecated GL matrix stuff...

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            gluPerspective(fov, width / height, hither, yon);

            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glTranslatef(0, 0, -boom);
            glRotatef(-angleX, 1, 0, 0);
            glRotatef(-angleY, 0, 1, 0);
            glRotatef(-angleZ, 0, 0, 1);
            glTranslatef(-x, -y, -z);
        }

        void ApplyOrtho()
        {
            // TODO: Get rid of the deprecated GL matrix stuff...

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0, width, height, 0, -1, 1);

            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
        }
    };

    struct Input
    {
        int keyStates[256];

        float mouseX, mouseY;
        float mouseLookScale;

        Input()
            : mouseX(-1), mouseY(-1)
            , mouseLookScale(0.1f)
        { }
    };

    struct EzglApp
    {
        Camera camera;
        Input input;
        double timeElapsed;
        double timeDelta;

        EzglApp()
        {
            assert(singleton == NULL);

            singleton = this;
        }

        ~EzglApp()
        {
            singleton = NULL;
        }

        void Run(int argc, char** argv)
        {
            glutInit(&argc, argv);
            glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL);
            glutInitWindowPosition(200, 200);
            glutInitWindowSize(1024, 768);
            glutCreateWindow(argv[0]);

            glutReshapeFunc(Reshape);
            glutDisplayFunc(Display);
            glutKeyboardFunc(Keyboard);
            glutEntryFunc(Entry);
            glutMouseFunc(Mouse);
            glutMotionFunc(Motion);
            glutPassiveMotionFunc(PassiveMotion);
            glutIdleFunc(Idle);

            atexit(Shutdown);

            Startup();

            glutMainLoop();
        }

    protected:
        virtual void OnStartup() { }
        virtual void OnShutdown() { }
        virtual void OnReshape(int width, int height) { }
        virtual void OnKeyboard(unsigned char key, int x, int y) { }
        virtual void OnEntry(int state) { }
        virtual void OnMouse(int button, int state, int x, int y) { }
        virtual void OnMotion(int x, int y) { }
        virtual void OnPassiveMotion(int x, int y) { }
        virtual void OnIdle() { }
        virtual void OnDisplay() { }

        virtual void DrawGrid(int radius, int gridSize)
        {
            // TODO: Replace fixed function drawing with vertex/index buffers

            glColor4f(0.3f, 0.3f, 0.3f, 0.5f);
            glBegin(GL_LINES);
            for (int i = -radius; i <= radius; i += gridSize)
            {
                glVertex3f(i, 0, -radius);
                glVertex3f(i, 0, radius);
                glVertex3f(-radius, 0, i);
                glVertex3f(radius, 0, i);
            }
            glEnd();
        }

        virtual void DrawAxes(float radius)
        {
            // TODO: Replace fixed function drawing with vertex/index buffers

            glBegin(GL_LINES);
            glColor4f(1,0,0,0.5f); glVertex3f(0,0,0); glVertex3f(radius, 0, 0);
            glColor4f(0,1,0,0.5f); glVertex3f(0,0,0); glVertex3f(0, radius, 0);
            glColor4f(0,0,1,0.5f); glVertex3f(0,0,0); glVertex3f(0, 0, radius);
            glEnd();
        }

        virtual void DrawString(const char* str, int x, int y)
        {
            // TODO: Replace fixed function drawing with vertex/index buffers

            int length = strlen(str);

            glColor4f(255,255,255,255);

            glWindowPos2i(x, singleton->camera.height - y);

            // TODO: Replace with texture-based font...
            for (int i = 0; i < length; i++)
            {
                //GLUT_BITMAP_TIMES_ROMAN_10
                //GLUT_BITMAP_HELVETICA_18
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[i]);
            }
        }

        virtual void DumpCaps()
        {
            printf("Vendor = '%s'\n", glGetString(GL_VENDOR));
            printf("Renderer = '%s'\n", glGetString(GL_RENDERER));
            printf("Version = '%s'\n", glGetString(GL_VERSION));
            printf("GLSL Version = '%s'\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

            printf("Extensions = \n");
            DumpExtensions((const char*)glGetString(GL_EXTENSIONS));

            printf("WGL Extensions = \n");
            DumpExtensions(wglGetExtensionsStringARB(wglGetCurrentDC()));

            // TODO: Dump device limits too...
        }   

        virtual void DumpExtensions(const char* e)
        {
            if (e != 0)
            {
                for (;;)
                {
                    while (*e == ' ') ++e;
                    if (*e == 0) break;

                    do { putc(*e, stdout); ++e; }
                    while (*e != 0 && e != ' ');
                    putc('\n', stdout);
                }
            }
        }

    private:
        static EzglApp* singleton;

        static void Startup()
        {
            glFrontFace(GL_CCW);
            glCullFace(GL_BACK);
            glEnable(GL_CULL_FACE);

            glDepthFunc(GL_LESS);
            glEnable(GL_DEPTH_TEST);

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

            // Disable vsync by default
            wglSwapIntervalEXT(0);

            singleton->timeElapsed = ElapsedTime();

            singleton->DumpCaps();

            singleton->OnStartup();
        }

        static void Shutdown()
        {
            printf("Shutdown\n");

            singleton->OnShutdown();
        }

        static void Idle()
        {
            singleton->OnIdle();

            glutPostRedisplay();
        }

        static void Reshape(int width, int height)
        {
            glViewport(0, 0, width, height);

            singleton->camera.width = width;
            singleton->camera.height = height;

            singleton->OnReshape(width, height);
        }

        static void Entry(int state)
        {
            // State = LEFT/ENTERED
            singleton->OnEntry(state);
        }

        static void Mouse(int button, int state, int x, int y)
        {
            singleton->input.mouseX = x;
            singleton->input.mouseY = y;

            // Button = LEFT_BUTTON/RIGHT_BUTTON/MIDDLE_BUTTON
            // State = UP/DOWN
            singleton->OnMouse(button, state, x, y);
        }

        static void Motion(int x, int y)
        {
            singleton->camera.angleY += (singleton->input.mouseX - x) * singleton->input.mouseLookScale;
            singleton->camera.angleX += (singleton->input.mouseY - y) * singleton->input.mouseLookScale;

            singleton->input.mouseX = x;
            singleton->input.mouseY = y;

            singleton->OnMotion(x, y);
        }

        static void PassiveMotion(int x, int y)
        {
            singleton->OnPassiveMotion(x, y);
        }

        static void Keyboard(unsigned char key, int x, int y)
        {
            singleton->input.keyStates[key] ^= 1;

            singleton->OnKeyboard(key, x, y);
        }

        static void Display()
        {
            double time = ElapsedTime();
            singleton->timeDelta = time - singleton->timeElapsed;
            singleton->timeElapsed = time;

            singleton->OnDisplay();

            char fps[80];
            sprintf(fps, "%i fps", (int)(1 / singleton->timeDelta));
            singleton->DrawString(fps, 10, 20);

            glutSwapBuffers();
        }
    };

    App* EzglApp::singleton;
}

// ----------------------------------------------------------------
// Test.cpp
// - Simple demonstration of Ezgl
// - Requires GLEE (or GLEW, etc) to load OpenGL extensions
// - Requires OpenGL 2.0 or better for shader stuff
// ----------------------------------------------------------------

#include "Glee.h"
#include "Ezgl.h"
using namespace Ezgl;

struct TestApp : public EzglApp
{
	GLuint program;

	void OnStartup()
	{
		GLint status;

		// VS
		const char* source =
			"void main()"
			"{"
				"gl_FrontColor = gl_Color;"
				"gl_Position = ftransform();"
			"}";

		GLuint vs = glCreateShader(GL_VERTEX_SHADER);
		glShaderSource(vs, 1, &source, NULL);
		glCompileShader(vs);
		glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
		if (status == 0)
		{
			printf("glCompileShader vs failed\n");
		}

		// FS
		source =
			"void main()"
			"{"
				"gl_FragColor = gl_Color;"
			"}";

		GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(fs, 1, &source, NULL);
		glCompileShader(fs);
		glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
		if (status == 0)
		{
			printf("glCompileShader fs failed\n");
		}

		// Program
		program = glCreateProgram();
		glAttachShader(program, vs);
		glAttachShader(program, fs);
		glLinkProgram(program);
		glGetProgramiv(program, GL_LINK_STATUS, &status);
		if (status == 0)
		{
			printf("Link failed\n");
		}
	}

	void OnDisplay()
	{
		glClearColor(0, 0, 0, 0);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

		camera.ApplyPerspective();

		glUseProgram(program);
		DrawGrid(1024, 32);
		DrawAxes(64);
		glUseProgram(0);
	}
};

void main(int argc, char** argv)
{
	TestApp app;

	app.Run(argc, argv);
}

Post a Comment

Required fields are marked *

*
*

%d bloggers like this: