void VulkanExampleBase::renderLoop() { #if defined(_WIN32) MSG msg; while (TRUE) { auto tStart = std::chrono::high_resolution_clock::now(); if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } render(); frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count(); frameTimer = (float)tDiff / 1000.0f; // Convert to clamped timer value if (!paused) { timer += timerSpeed * frameTimer; if (timer > 1.0) { timer -= 1.0f; } } fpsTimer += (float)tDiff; if (fpsTimer > 1000.0f) { std::string windowTitle = getWindowTitle(); SetWindowText(window, windowTitle.c_str()); fpsTimer = 0.0f; frameCounter = 0.0f; } } #elif defined(__ANDROID__) while (1) { int ident; int events; struct android_poll_source* source; bool destroy = false; focused = true; while ((ident = ALooper_pollAll(focused ? 0 : -1, NULL, &events, (void**)&source)) >= 0) { if (source != NULL) { source->process(androidApp, source); } if (androidApp->destroyRequested != 0) { LOGD("Android app destroy requested"); destroy = true; break; } } // App destruction requested // Exit loop, example will be destroyed in application main if (destroy) { break; } // Render frame if (prepared) { auto tStart = std::chrono::high_resolution_clock::now(); render(); frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count(); frameTimer = tDiff / 1000.0f; // Convert to clamped timer value if (!paused) { timer += timerSpeed * frameTimer; if (timer > 1.0) { timer -= 1.0f; } } // Check gamepad state const float deadZone = 0.0015f; // todo : check if gamepad is present // todo : time based and relative axis positions bool updateView = false; // Rotate if (std::abs(gamePadState.axes.x - deadZone) > 0.0f) { rotation.y += gamePadState.axes.x * 0.5f * rotationSpeed; updateView = true; } if (std::abs(gamePadState.axes.y - deadZone) > 0.0f) { rotation.x -= gamePadState.axes.y * 0.5f * rotationSpeed; updateView = true; } // Zoom if (std::abs(gamePadState.axes.rz - deadZone) > 0.0f) { zoom -= gamePadState.axes.rz * 0.01f * zoomSpeed; updateView = true; } if (updateView) { viewChanged(); } } } #elif defined(__linux__) xcb_flush(connection); while (!quit) { auto tStart = std::chrono::high_resolution_clock::now(); xcb_generic_event_t *event; event = xcb_poll_for_event(connection); if (event) { handleEvent(event); free(event); } render(); frameCounter++; auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count(); frameTimer = tDiff / 1000.0f; // Convert to clamped timer value if (!paused) { timer += timerSpeed * frameTimer; if (timer > 1.0) { timer -= 1.0f; } } fpsTimer += (float)tDiff; if (fpsTimer > 1000.0f) { std::string windowTitle = getWindowTitle(); xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, windowTitle.size(), windowTitle.c_str()); fpsTimer = 0.0f; frameCounter = 0.0f; } } #endif }
HWND VulkanExampleBase::setupWindow(HINSTANCE hinstance, WNDPROC wndproc) { this->windowInstance = hinstance; bool fullscreen = false; // Check command line arguments for (int32_t i = 0; i < __argc; i++) { if (__argv[i] == std::string("-fullscreen")) { fullscreen = true; } } WNDCLASSEX wndClass; wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = wndproc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hinstance; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = name.c_str(); wndClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO); if (!RegisterClassEx(&wndClass)) { std::cout << "Could not register window class!\n"; fflush(stdout); exit(1); } int screenWidth = GetSystemMetrics(SM_CXSCREEN); int screenHeight = GetSystemMetrics(SM_CYSCREEN); if (fullscreen) { DEVMODE dmScreenSettings; memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); dmScreenSettings.dmSize = sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = screenWidth; dmScreenSettings.dmPelsHeight = screenHeight; dmScreenSettings.dmBitsPerPel = 32; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if ((width != screenWidth) && (height != screenHeight)) { if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { if (MessageBox(NULL, "Fullscreen Mode not supported!\n Switch to window mode?", "Error", MB_YESNO | MB_ICONEXCLAMATION) == IDYES) { fullscreen = FALSE; } else { return FALSE; } } } } DWORD dwExStyle; DWORD dwStyle; if (fullscreen) { dwExStyle = WS_EX_APPWINDOW; dwStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; } else { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; } RECT windowRect; if (fullscreen) { windowRect.left = (long)0; windowRect.right = (long)screenWidth; windowRect.top = (long)0; windowRect.bottom = (long)screenHeight; } else { windowRect.left = (long)screenWidth / 2 - width / 2; windowRect.right = (long)width; windowRect.top = (long)screenHeight / 2 - height / 2; windowRect.bottom = (long)height; } AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); std::string windowTitle = getWindowTitle(); window = CreateWindowEx(0, name.c_str(), windowTitle.c_str(), dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, windowRect.left, windowRect.top, windowRect.right, windowRect.bottom, NULL, NULL, hinstance, NULL); if (!window) { printf("Could not create window!\n"); fflush(stdout); return 0; exit(1); } ShowWindow(window, SW_SHOW); SetForegroundWindow(window); SetFocus(window); return window; }