This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
neofx-zoom-plusplus/zoom.cpp

387 lines
9.9 KiB
C++
Raw Normal View History

2009-12-13 18:49:36 +01:00
#include "Game.h"
#include "config.h"
#include "gl.h"
#ifdef _WIN32
#else
#include <iostream>
#include <X11/X.h>
#include <GL/glx.h>
#include <sys/time.h>
#include <unistd.h>
#endif
void resize(int width, int height)
{
if(height==0)
{
height=1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50.0f, (GLfloat)width/(GLfloat)height, 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, width, height);
}
#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;
}
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
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 = StructureNotifyMask/* | PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask*/;
*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<char*>("3D");
chint.res_class = const_cast<char*>("3d");
XSetClassHint(disp, *wnd, &chint);
char *str = const_cast<char*>("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;
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
Zoom::Game game(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 ConfigureNotify:
resize(event.xconfigure.width, event.xconfigure.height);
break;
case ClientMessage:
if(static_cast<Atom>(event.xclient.data.l[0]) == windele)
running = false;
}
}
if(!running) break;
game.run(delta);
game.render();
glXSwapBuffers(disp, wnd);
XSync(disp, 0);
long slept = 0;
gettimeofday(&tv, NULL);
delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000;
if(delta < MIN_FRAME_DELTA) {
usleep((MIN_FRAME_DELTA-delta)*1000);
slept += (MIN_FRAME_DELTA-delta);
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 << " fps; slept a total of " << slept << " ms" << std::endl;
frames = 0;
tocks -= 1000000;
slept = 0;
}
}
XDestroyWindow(disp, wnd);
glXDestroyContext(disp, gc);
XCloseDisplay(disp);
return 0;
}
#endif