import win32.windows; import std.string; //import gl.gl; // commented out due to improper name mangline //import gl.glu; import std.loader; import std.stdio; pragma(lib, "opengl32.lib"); pragma(lib, "gdi32.lib"); alias DefWindowProcA DefWindowProc; extern (C) void gc_init(); extern (C) void gc_term(); extern (C) void _minit(); extern (C) void _moduleCtor(); extern (C) void _moduleDtor(); extern (C) void _moduleUnitTests(); /////////////////////////////////////////////////////////////////////////////////////// alias uint GLenum; alias ubyte GLboolean; alias uint GLbitfield; alias void GLvoid; alias byte GLbyte; alias short GLshort; alias int GLint; alias ubyte GLubyte; alias ushort GLushort; alias uint GLuint; alias int GLsizei; alias float GLfloat; alias float GLclampf; alias double GLdouble; alias double GLclampd; alias char GLchar; alias ptrdiff_t GLintptr; alias ptrdiff_t GLsizeiptr; const GLuint GL_COLOR_BUFFER_BIT = 0x00004000; const GLuint GL_DEPTH_BUFFER_BIT = 0x00000100; const GLuint GL_SMOOTH = 0x1D01; const GLuint GL_DEPTH_TEST = 0x0B71; const GLuint GL_LEQUAL = 0x0203; const GLuint GL_MODELVIEW = 0x1700; const GLuint GL_PROJECTION = 0x1701; const GLuint GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50; const GLuint GL_NICEST = 0x1102; extern (Windows) { typedef void function(GLbitfield) pfglClear; typedef GLvoid function(GLenum) pfglShadeModel; typedef GLvoid function(GLclampf, GLclampf, GLclampf, GLclampf) pfglClearColor; typedef GLvoid function(GLclampd) pfglClearDepth; typedef GLvoid function() pfglLoadIdentity; typedef GLvoid function(GLenum) pfglMatrixMode; typedef GLvoid function(GLint, GLint, GLsizei, GLsizei) pfglViewport; typedef GLvoid function(GLenum) pfglEnable; typedef GLvoid function(GLenum) pfglDepthFunc; typedef GLvoid function(GLenum, GLenum) pfglHint; pfglHint glHint; pfglDepthFunc glDepthFunc; pfglEnable glEnable; pfglViewport glViewport; pfglMatrixMode glMatrixMode; pfglLoadIdentity glLoadIdentity; pfglClearDepth glClearDepth; pfglClearColor glClearColor; pfglClear glClear; pfglShadeModel glShadeModel; typedef GLvoid function(GLdouble, GLdouble, GLdouble, GLdouble) pfgluPerspective; pfgluPerspective gluPerspective; } private HXModule gldrv; private HXModule gludrv; private void* getProc (HXModule mod, string procname) { void* symbol = ExeModule_GetSymbol(mod, procname); if (symbol is null) printf (("Failed to load proc address " ~ procname ~ ".\n\0").ptr); return symbol; } static this () { version (Windows) { gldrv = ExeModule_Load("OpenGL32.dll"); } else version (linux) { gldrv = ExeModule_Load("libGL.so"); } else version (darwin) { gldrv = ExeModule_Load("/System/Library/Frameworks/OpenGL.framework"); } version(Windows) { gludrv = ExeModule_Load("glu32.dll"); } else version (linux) { gludrv = ExeModule_Load("libGLU.so"); } else version (darwin) { gludrv = ExeModule_Load("/System/Library/Frameworks/OpenGL.framework"); } glHint = cast(pfglHint)getProc(gldrv, "glHint"); glDepthFunc = cast(pfglDepthFunc)getProc(gldrv, "glDepthFunc"); glEnable = cast(pfglEnable)getProc(gldrv, "glEnable"); glViewport = cast(pfglViewport)getProc(gldrv, "glViewport"); glMatrixMode = cast(pfglMatrixMode)getProc(gldrv, "glMatrixMode"); glLoadIdentity = cast(pfglLoadIdentity)getProc(gldrv, "glLoadIdentity"); glClearDepth = cast(pfglClearDepth)getProc(gldrv, "glClearDepth"); glClearColor = cast(pfglClearColor)getProc(gldrv, "glClearColor"); glClear = cast(pfglClear)getProc(gldrv, "glClear"); glShadeModel = cast(pfglShadeModel)getProc(gldrv, "glShadeModel"); gluPerspective = cast(pfgluPerspective)getProc(gludrv, "gluPerspective"); } static ~this() { ExeModule_Release(gldrv); } /////////////////////////////////////////////////////////////////////////////////////// class Game { Window wnd; bool terminated; bool active; this() { wnd = new Window(); wnd.show(); wnd.resizeScene(640, 480); wnd.init(); active = true; terminated = false; } void drawScene(float t) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); } void step(float t) { } } class Window { HGLRC hRC; HDC hDC; HWND hWnd; HINSTANCE hInst; RECT rect; WNDCLASSEX wc; uint dwExStyle; uint dwStyle; bool visible; GLuint PixelFormat; string title; this(int width = 640, int height = 480, bool _visible = false) { rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = height; hInst = GetModuleHandle(null); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = &WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = LoadIcon(null, IDI_WINLOGO); wc.hCursor = LoadCursor(null, IDC_ARROW); wc.hbrBackground = null; wc.lpszMenuName = null; wc.lpszClassName = cast(char*)toStringz("OpenGL"); if (!RegisterClassEx(&wc)) { throw new Exception("Aaaaaaaagh!"); } dwExStyle |= WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle |= WS_OVERLAPPEDWINDOW; AdjustWindowRectEx(&rect, dwStyle, false, dwExStyle); if ((hWnd = CreateWindowEx( dwExStyle, wc.lpszClassName, cast(char*)toStringz(title), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle, 0, 0, rect.right-rect.left, rect.bottom-rect.top, null, null, hInst, null)) == null) { throw new Exception("Aaaaaaaagh!"); } PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR( PIXELFORMATDESCRIPTOR.sizeof, 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 ); if ((hDC = GetDC(hWnd)) == null) { throw new Exception("Aaaaaaaagh!"); } if ((PixelFormat = ChoosePixelFormat(hDC, &pfd)) == 0) { throw new Exception("Aaaaaaaagh!"); } if(!SetPixelFormat(hDC, PixelFormat, &pfd)) { throw new Exception("Aaaaaaaagh!"); } if ((hRC = wglCreateContext(hDC)) == null) { throw new Exception("Aaaaaaaagh!"); } if(!wglMakeCurrent(hDC,hRC)) { throw new Exception("Aaaaaaaagh!"); } } ~this() { if (hRC) { wglMakeCurrent(null, null); wglDeleteContext(hRC); hRC = null; } if (hDC) { ReleaseDC(hWnd, hDC); hDC = null; } if (hWnd) { DestroyWindow(hWnd); hWnd = null; } UnregisterClass(wc.lpszClassName, hInst); hInst = null; } void resizeScene(uint width, uint height) { if (height == 0) { height = 1; // Prevent division by zero. } glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, cast(GLfloat)width / cast(GLfloat)height, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void init() { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } void show() { ShowWindow(hWnd, SW_SHOWNA); SetForegroundWindow(hWnd); SetFocus(hWnd); } void hide() { ShowWindow(hWnd, SW_HIDE); } } extern(Windows) LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_QUIT: case WM_CLOSE: game.terminated = true; game.active = false; return 0; break; case WM_ACTIVATE: game.active = (wParam != WA_INACTIVE); break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return DefWindowProc(hWnd, msg, wParam, lParam); } extern(Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { gc_init(); _minit(); int result; try { _moduleCtor(); version(Debug) { _moduleUnitTests(); } // Initialize stuff here result = GameMain(lpCmdLine); _moduleDtor(); } catch(Object o) { writefln(o.toString); result = 0; } gc_term(); return result; } Game game; int GameMain(LPSTR args) { game = new Game(); MSG msg; while (!game.terminated) { while (game.active) { if (PeekMessage(&msg, game.wnd.hWnd, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { if (game.active) { game.drawScene(1); game.step(1); } } } if (game.terminated) { break; } while (!game.active) { int ret = GetMessage(&msg, game.wnd.hWnd, 0, 0); if (ret == -1) { return -1; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } } return 0; }