From 59360094e5ac1ddeb5eda365ac4ccf765786635f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 27 Nov 2009 20:47:58 +0100 Subject: Initial commit --- main.cpp | 399 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 main.cpp (limited to 'main.cpp') diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..87f5060 --- /dev/null +++ b/main.cpp @@ -0,0 +1,399 @@ +#include "DisplayClass.h" +#include "gl.h" + +#ifdef _WIN32 +#else +#include +#include +#include +#include +#include +#endif + +#define MIN_FRAME_DELTA 16 +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 640 + +void initGL(bool multisample); +void resize(int width, int height); + +void initGL(bool multisample) { + glClearColor(0.0, 0.0, 0.0, 1.0); + glClearDepth(1.0); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + +#ifndef _WIN32 + if(multisample) + glEnable(GL_MULTISAMPLE_ARB); +#endif + + resize(DEFAULT_WIDTH, DEFAULT_HEIGHT); +} + +void resize(int width, int height) +{ + if(height==0) + { + height=1; + } + + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0f,(GLfloat)width/(GLfloat)height, 0.1, 1000); + + glMatrixMode(GL_MODELVIEW); +} + + +#ifdef _WIN32 + +bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC); +void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC); +LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) { + WNDCLASS wc; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)wndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = 0; + wc.lpszMenuName = 0; + wc.lpszClassName = "3D"; + + if (!RegisterClass(&wc)) + { + MessageBox(0, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; // Exit And Return FALSE + } + + DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + DWORD dwStyle = WS_OVERLAPPEDWINDOW; + + RECT windowRect; + windowRect.left = 0; + windowRect.right = DEFAULT_WIDTH; + windowRect.top = 0; + windowRect.bottom = DEFAULT_HEIGHT; + + AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); + + *hWnd = CreateWindowEx(dwExStyle, "3D" /* Class Name */, "3D" /* Title*/, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle, + 0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, 0, 0, hInstance, 0); + if(!*hWnd) + { + MessageBox(0, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; + } + + static PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + 16, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // No Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 16, // 16Bit Z-Buffer (Depth Buffer) + 0, // No Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + *hDC=GetDC(*hWnd); + if (!*hDC) + { + WGLUninit(*hWnd, 0, 0); + MessageBox(0, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; + } + + GLuint pixelFormat = ChoosePixelFormat(*hDC, &pfd); + if(!pixelFormat) + { + WGLUninit(*hWnd, *hDC, 0); + MessageBox(0, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(!SetPixelFormat(*hDC, pixelFormat, &pfd)) + { + WGLUninit(*hWnd, *hDC, 0); + MessageBox(0, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; + } + + *hRC=wglCreateContext(*hDC); + if(!*hRC) + { + WGLUninit(*hWnd, *hDC, 0); + MessageBox(0, "Can't Create A GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(!wglMakeCurrent(*hDC, *hRC)) + { + WGLUninit(*hWnd, *hDC, *hRC); + MessageBox(0, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); + return false; + } + + ShowWindow(*hWnd, SW_SHOW); + SetForegroundWindow(*hWnd); + SetFocus(*hWnd); + + return true; +} + +void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC) { + wglMakeCurrent(0, 0); + + if(hRC) + wglDeleteContext(hRC); + + if(hDC) + ReleaseDC(hWnd, hDC); + + if(hWnd) + DestroyWindow(hWnd); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + HWND hWnd = 0; + HDC hDC = 0; + HGLRC hRC = 0; + + if(!WGLInit(hInstance, &hWnd, &hDC, &hRC)) + { + return 0; + } + + initGL(false); + + bool running = true; + MSG msg; + + while(running) + { + unsigned long delta = 0; + unsigned long ticks = GetTickCount(); + + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if(msg.message == WM_QUIT) + { + running = false; + break; + } + else // If Not, Deal With Window Messages + { + TranslateMessage(&msg); // Translate The Message + DispatchMessage(&msg); // Dispatch The Message + } + } + + delta = GetTickCount()-ticks; + + if(delta < MIN_FRAME_DELTA) { + Sleep(MIN_FRAME_DELTA - delta); + delta = GetTickCount()-ticks; + } + + ticks += delta; + + static DisplayClass render; + render.renderScene(delta); + SwapBuffers(hDC); + } + + WGLUninit(hWnd, hDC, hRC); + return msg.wParam; +} + +LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + + case WM_SIZE: + resize(LOWORD(lParam), HIWORD(lParam)); + return 0; + + default: + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } +} + +#else + +bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *multisample) { + static const int msAttributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_X_RENDERABLE, True, + GLX_DOUBLEBUFFER, True, + GLX_DEPTH_SIZE, 1, + GLX_SAMPLE_BUFFERS, 1, + GLX_SAMPLES, 4, + None}; + + static const int attributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_X_RENDERABLE, True, + GLX_DOUBLEBUFFER, True, + GLX_DEPTH_SIZE, 1, + None}; + + bool ok = false; + *multisample = true; + + int nElements; + GLXFBConfig *fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), msAttributeList, &nElements); + if(!fbConfig || !nElements) { + if(fbConfig) { + XFree(fbConfig); + } + + *multisample = false; + fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), attributeList, &nElements); + } + + if(fbConfig && nElements) { + XVisualInfo *vi = glXGetVisualFromFBConfig(disp, *fbConfig); + + if(vi) { + Colormap cmap = XCreateColormap(disp, RootWindow(disp, vi->screen), vi->visual, AllocNone); + XSetWindowAttributes swa; + swa.colormap = cmap; + swa.border_pixel = 0; + swa.event_mask = /*PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask*/0; + + *wnd = XCreateWindow(disp, RootWindow(disp, vi->screen), 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0, vi->depth, InputOutput, + vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); + + XClassHint chint; + chint.res_name = const_cast("3D"); + chint.res_class = const_cast("3d"); + XSetClassHint(disp, *wnd, &chint); + + char *str = const_cast("3D"); + XTextProperty name; + if(XStringListToTextProperty(&str, 1, &name) != 0) + { + XSetWMName(disp, *wnd, &name); + XFree(name.value); + } + + XSetWMProtocols(disp, *wnd, &windele, 1); + + XMapWindow(disp, *wnd); + + *gc = glXCreateContext(disp, vi, NULL, True); + + glXMakeCurrent(disp, *wnd, *gc); + + ok = true; + + XFree(vi); + } + } + + if(fbConfig) + XFree(fbConfig); + + XSync(disp, 0); + + return ok; +} + +int main() { + Display *disp = XOpenDisplay(0); + Atom windele = XInternAtom(disp, "WM_DELETE_WINDOW", False); + Window wnd; + GLXContext gc; + + bool multisample; + if(!GLXinit(disp, windele, &wnd, &gc, &multisample)) + return 1; + initGL(multisample); + + GLint samples; + glGetIntegerv(GL_SAMPLES, &samples); + std::cerr << "Using " << samples << " samples" << std::endl; + + bool running = true; + + unsigned long delta = 0; + unsigned long frames = 0, tocks = 0; + + struct timeval tv; + gettimeofday(&tv, NULL); + unsigned long ticks = tv.tv_usec; + + while(running) { + while(XPending(disp)) { + XEvent event; + XNextEvent(disp, &event); + switch(event.type) { + case ClientMessage: + if(static_cast(event.xclient.data.l[0]) == windele) + running = false; + break; + } + } + + if(!running) break; + + static DisplayClass render; + render.renderScene(delta); + + glXSwapBuffers(disp, wnd); + XSync(disp, 0); + + gettimeofday(&tv, NULL); + delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000; + + if(delta < MIN_FRAME_DELTA) { + usleep((MIN_FRAME_DELTA-delta)*1000); + + gettimeofday(&tv, NULL); + delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000; + } + + ticks = (ticks + delta*1000) % 1000000; + + frames++; + tocks += delta*1000; + if(tocks > 1000000) { + std::cerr << frames << std::endl; + frames = 0; + tocks -= 1000000; + } + } + + XDestroyWindow(disp, wnd); + glXDestroyContext(disp, gc); + XCloseDisplay(disp); + + return 0; +} + +#endif -- cgit v1.2.3