Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SDL2 backend #32

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c586a79
Support for building under Linux (with SDL2).
CzechBlueBear Mar 25, 2019
e09f089
Fixed tabs/spaces.
CzechBlueBear Mar 25, 2019
d2ab3e2
Update .gitignore
Srinivasa314 Aug 4, 2020
9ec9533
ignore executable instead of whole directory
Srinivasa314 Aug 4, 2020
8065b61
Replace gl_FragColor with fragColor
Srinivasa314 Aug 4, 2020
2d01866
Fix number keypress detection
Srinivasa314 Aug 4, 2020
9837005
Exit if escape is pressed
Srinivasa314 Aug 4, 2020
471be26
Made fullscreen toggle work
Srinivasa314 Aug 4, 2020
2f77387
Did few fixes
Srinivasa314 Aug 5, 2020
5680843
Updated README
Srinivasa314 Aug 5, 2020
5dc16f1
Do keypress handling in SDL eventloop
Srinivasa314 Aug 5, 2020
3d6753d
Update README.md
Srinivasa314 Aug 5, 2020
74a796b
Compile in release mode
Srinivasa314 Aug 5, 2020
0a938b9
Merge branch 'master' of https://github.com/Srinivasa314/NonEuclidean…
Srinivasa314 Aug 5, 2020
66585b3
Update NonEuclidean.vcxproj
Srinivasa314 Aug 5, 2020
83d73e5
Change g++ to c++
Srinivasa314 Aug 5, 2020
bad1ab7
Merge branch 'master' of https://github.com/Srinivasa314/NonEuclidean…
Srinivasa314 Aug 5, 2020
22b44a0
Merge branch 'master' of https://github.com/HackerPoet/NonEuclidean i…
Srinivasa314 Aug 5, 2020
f6ca63c
Add build instructions
Srinivasa314 Aug 5, 2020
8ff86b7
Add newlines
Srinivasa314 Aug 5, 2020
00399db
Make window centered
Srinivasa314 Sep 13, 2020
2932025
Use SDL2 API for confining cursor
Srinivasa314 Sep 13, 2020
8bbf723
Fix fullscreen shortcut in Xorg
Srinivasa314 Sep 13, 2020
db50d85
fix linker error in OSX
Srinivasa314 Mar 14, 2021
9605024
set glewExperimental to true
Srinivasa314 Mar 17, 2021
4831ce9
put -std=c++11 in CXXFLAGS
Srinivasa314 Mar 17, 2021
4fca8e3
make it work on mac os and support hidpi
Srinivasa314 Sep 11, 2022
49d09a0
Fix fractional scaling and sluggish mouse movement
Srikanth-M-02 Sep 11, 2022
191fc4c
Merge pull request #1 from Srikanth-M-02/master
Srinivasa314 Sep 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ Release/
Floorplan/
Thumbs.db
glew-2.1.0
*.o
.vscode
NonEuclidean/NonEuclidean
313 changes: 32 additions & 281 deletions NonEuclidean/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
#include "Level4.h"
#include "Level5.h"
#include "Level6.h"
#include <GL/wglew.h>
#if defined(_WIN32)
#include <GL/wglew.h>
#else
#include <GL/glew.h>
#endif
#include <cmath>
#include <iostream>
#include <algorithm>
Expand All @@ -17,20 +21,13 @@ const Input* GH_INPUT = nullptr;
int GH_REC_LEVEL = 0;
int64_t GH_FRAME = 0;

LRESULT WINAPI StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
Engine* eng = (Engine*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (eng) {
return eng->WindowProc(hWnd, uMsg, wParam, lParam);
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Engine::Engine() : hWnd(NULL), hDC(NULL), hRC(NULL) {
Engine::Engine() {
GH_ENGINE = this;
GH_INPUT = &input;
isFullscreen = false;

SetProcessDPIAware();
isGood = InitOSWrapper();

CreateGLWindow();
InitGLObjects();
SetupInputs();
Expand All @@ -52,82 +49,36 @@ Engine::Engine() : hWnd(NULL), hDC(NULL), hRC(NULL) {
}

Engine::~Engine() {
ClipCursor(NULL);
wglMakeCurrent(NULL, NULL);
ReleaseDC(hWnd, hDC);
wglDeleteContext(hRC);
DestroyWindow(hWnd);
DestroyGLWindow();
}

int Engine::Run() {
if (!hWnd || !hDC || !hRC) {
return 1;
}
EnterMessageLoop();
DestroyGLObjects();
return 0;
}

//Recieve events from this window
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)this);

//Setup the timer
const int64_t ticks_per_step = timer.SecondsToTicks(GH_DT);
int64_t cur_ticks = timer.GetTicks();
GH_FRAME = 0;

//Game loop
MSG msg;
while (true) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
//Handle windows messages
if (msg.message == WM_QUIT) {
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} else {
//Confine the cursor
ConfineCursor();

if (input.key_press['1']) {
LoadScene(0);
} else if (input.key_press['2']) {
LoadScene(1);
} else if (input.key_press['3']) {
LoadScene(2);
} else if (input.key_press['4']) {
LoadScene(3);
} else if (input.key_press['5']) {
LoadScene(4);
} else if (input.key_press['6']) {
LoadScene(5);
} else if (input.key_press['7']) {
LoadScene(6);
}
void Engine::PeriodicRender(int64_t &cur_ticks) {

//Used fixed time steps for updates
const int64_t new_ticks = timer.GetTicks();
for (int i = 0; cur_ticks < new_ticks && i < GH_MAX_STEPS; ++i) {
Update();
cur_ticks += ticks_per_step;
GH_FRAME += 1;
input.EndFrame();
}
cur_ticks = (cur_ticks < new_ticks ? new_ticks: cur_ticks);

//Setup camera for rendering
const float n = GH_CLAMP(NearestPortalDist() * 0.5f, GH_NEAR_MIN, GH_NEAR_MAX);
main_cam.worldView = player->WorldToCam();
main_cam.SetSize(iWidth, iHeight, n, GH_FAR);
main_cam.UseViewport();

//Render scene
GH_REC_LEVEL = GH_MAX_RECURSION;
Render(main_cam, 0, nullptr);
SwapBuffers(hDC);
}
//Used fixed time steps for updates
const int64_t new_ticks = timer.GetTicks();
for (int i = 0; cur_ticks < new_ticks && i < GH_MAX_STEPS; ++i) {
Update();
cur_ticks += ticks_per_step;
GH_FRAME += 1;
input.EndFrame();
}
cur_ticks = (cur_ticks < new_ticks ? new_ticks: cur_ticks);

DestroyGLObjects();
return 0;
//Setup camera for rendering
const float n = GH_CLAMP(NearestPortalDist() * 0.5f, GH_NEAR_MIN, GH_NEAR_MAX);
main_cam.worldView = player->WorldToCam();
main_cam.SetSize(iWidth, iHeight, n, GH_FAR);
main_cam.UseViewport();

//Render scene
GH_REC_LEVEL = GH_MAX_RECURSION;
Render(main_cam, 0, nullptr);
}

void Engine::LoadScene(int ix) {
Expand Down Expand Up @@ -269,149 +220,6 @@ void Engine::Render(const Camera& cam, GLuint curFBO, const Portal* skipPortal)
#endif
}

LRESULT Engine::WindowProc(HWND hCurWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static PAINTSTRUCT ps;
static BYTE lpb[256];
static UINT dwSize = sizeof(lpb);

switch (uMsg) {
case WM_SYSCOMMAND:
if (wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER) {
return 0;
}
break;

case WM_PAINT:
BeginPaint(hCurWnd, &ps);
EndPaint(hCurWnd, &ps);
return 0;

case WM_SIZE:
iWidth = LOWORD(lParam);
iHeight = HIWORD(lParam);
PostMessage(hCurWnd, WM_PAINT, 0, 0);
return 0;

case WM_KEYDOWN:
//Ignore repeat keys
if (lParam & 0x40000000) { return 0; }
input.key[wParam & 0xFF] = true;
input.key_press[wParam & 0xFF] = true;
if (wParam == VK_ESCAPE) {
PostQuitMessage(0);
}
return 0;

case WM_SYSKEYDOWN:
if (wParam == VK_RETURN) {
ToggleFullscreen();
return 0;
}
break;

case WM_KEYUP:
input.key[wParam & 0xFF] = false;
return 0;

case WM_INPUT:
dwSize = sizeof(lpb);
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
input.UpdateRaw((const RAWINPUT*)lpb);
break;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hCurWnd, uMsg, wParam, lParam);
}

void Engine::CreateGLWindow() {
WNDCLASSEX wc;
hInstance = GetModuleHandle(NULL);
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)StaticWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = GH_CLASS;
wc.hIconSm = NULL;

if (!RegisterClassEx(&wc)) {
MessageBoxEx(NULL, "RegisterClass() failed: Cannot register window class.", "Error", MB_OK, 0);
return;
}

//Always start in windowed mode
iWidth = GH_SCREEN_WIDTH;
iHeight = GH_SCREEN_HEIGHT;

//Create the window
hWnd = CreateWindowEx(
WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
GH_CLASS,
GH_TITLE,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
GH_SCREEN_X,
GH_SCREEN_Y,
iWidth,
iHeight,
NULL,
NULL,
hInstance,
NULL);

if (hWnd == NULL) {
MessageBoxEx(NULL, "CreateWindow() failed: Cannot create a window.", "Error", MB_OK, 0);
return;
}

hDC = GetDC(hWnd);

PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.iLayerType = PFD_MAIN_PLANE;

const int pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0) {
MessageBoxEx(NULL, "ChoosePixelFormat() failed: Cannot find a suitable pixel format.", "Error", MB_OK, 0);
return;
}

if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
MessageBoxEx(NULL, "SetPixelFormat() failed: Cannot set format specified.", "Error", MB_OK, 0);
return;
}

DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);

if (GH_START_FULLSCREEN) {
ToggleFullscreen();
}
if (GH_HIDE_MOUSE) {
ShowCursor(FALSE);
}

ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
}

void Engine::InitGLObjects() {
//Initialize extensions
glewInit();
Expand All @@ -427,8 +235,7 @@ void Engine::InitGLObjects() {
//Check GL functionality
glGetQueryiv(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &occlusionCullingSupported);

//Attempt to enalbe vsync (if failure then oh well)
wglSwapIntervalEXT(1);
EnableVSync();
}

void Engine::DestroyGLObjects() {
Expand All @@ -437,66 +244,10 @@ void Engine::DestroyGLObjects() {
vPortals.clear();
}

void Engine::SetupInputs() {
static const int HID_USAGE_PAGE_GENERIC = 0x01;
static const int HID_USAGE_GENERIC_MOUSE = 0x02;
static const int HID_USAGE_GENERIC_JOYSTICK = 0x04;
static const int HID_USAGE_GENERIC_GAMEPAD = 0x05;

RAWINPUTDEVICE Rid[3];

//Mouse
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = hWnd;

//Joystick
Rid[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[1].usUsage = HID_USAGE_GENERIC_JOYSTICK;
Rid[1].dwFlags = 0;
Rid[1].hwndTarget = 0;

//Gamepad
Rid[2].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[2].usUsage = HID_USAGE_GENERIC_GAMEPAD;
Rid[2].dwFlags = 0;
Rid[2].hwndTarget = 0;

RegisterRawInputDevices(Rid, 3, sizeof(Rid[0]));
}

void Engine::ConfineCursor() {
if (GH_HIDE_MOUSE) {
RECT rect;
GetWindowRect(hWnd, &rect);
SetCursorPos((rect.right + rect.left) / 2, (rect.top + rect.bottom) / 2);
}
}

float Engine::NearestPortalDist() const {
float dist = FLT_MAX;
for (size_t i = 0; i < vPortals.size(); ++i) {
dist = GH_MIN(dist, vPortals[i]->DistTo(player->pos));
}
return dist;
}

void Engine::ToggleFullscreen() {
isFullscreen = !isFullscreen;
if (isFullscreen) {
iWidth = GetSystemMetrics(SM_CXSCREEN);
iHeight = GetSystemMetrics(SM_CYSCREEN);
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0,
iWidth, iHeight, SWP_SHOWWINDOW);
} else {
iWidth = GH_SCREEN_WIDTH;
iHeight = GH_SCREEN_HEIGHT;
SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
SetWindowPos(hWnd, HWND_TOP, GH_SCREEN_X, GH_SCREEN_Y,
iWidth, iHeight, SWP_SHOWWINDOW);
}
}
Loading