csisy

Members
  • Content count

    124
  • Joined

  • Last visited

Community Reputation

400 Neutral

About csisy

  • Rank
    Member
  1. I've made a small test program in a single cpp file. I've sent the binary to one of my friend and it works as expected. So it seems the problem is with my computer. :) Can it be a driver bug? If so where should I ask/report the bug? Btw, I have a Radeon HD 6670.  
  2.   No, it isn't, just turned on to check if I have an FPS counter at all.   The strange thing is if I set the SWP_NOSIZE flag, everything works fine... except that the client area won't be 1280x720 but 1296x758, because the width and height parameters are ignored. So if the client area is changed, the problem disappers.   Probably I'll end up using 2 window mode, Windowed and Borderless, where Borderless will be the Fullscreen. :) It will have the same size as the monitor's resolution. The current Fullscreen mode won't be used because it's used with ChangeDisplayMode and that can rearrange icons on the desktop and resize other windows if alt-tabbed and the user won't be happy. :)
  3. Exactly! And my FRAPS displays fps at the bottom-right corner and after the style change, the fps counter is invisible, because it's "outside" of the window. It's like the contexts are not updated properly here.   Unfortunately nothing helps :(
  4. Thanks for the tests!   Hm, it's strange that it works for you. I get a little "un-updated" area at the top of the window, when changing to borderless mode.   @Shaarigan: I have a more flexible setup for styles, so I'm not using nor overlapped nor thickframe directly. And also I don't let the user to resize the window by hand. So those styles are not set.   @Erik: Hm, I'll probably change my code to the save/restore version, but I'm not sure if the current solution is wrong. First, I remove the fullscreen bits THEN add the windowed bits, so if the bits overlap, it's not a problem, because the correct bits will be set at the end. Also, the windowed style is not changed at run-time, it's defined only once, when the window is created.   Well... some players like to have a non-fullscreen window without borders and stuffs. I don't know why. If I can't get it working I won't let the user have a borderless window with smaller size than the monitor's resolution. :/
  5. Thanks for your replies!   Using xor does not solve my problem unfortunately. :( BTW, don't you have to set the SWP_FRAMECHANGED flag to the SetWindowPos function?   I don't understand this whole process. I mean, if I change the size/resolution as well, everything works. And also, if I start the application with a Windowed (WS_CAPTION, WS_BORDER, etc.) window, then switch to Borderless (WS_POPUP) mode, a WM_SIZE message is not sent. However, if I switch back to Windowed then to Borderless again, two WM_SIZE is sent, first with 1296x758 then with 1280x720.   "Stranger things have happened"   Edit: Attached a simple test program (does nothing just clears the window with a red color). You can switch between windowed and borderless mode with F1 and F2 keys. Don't worry it's not a virus. :) [attachment=32085:WindowStyleChange.zip] If you check the red area of the windowed mode and the full area of the borderless (not-looking-properly) window, it's the same (1280x720) and this is what I want.
  6.   That flag is added to the SetWindowPos function both in my original and your posted code.   @Shaarigan: Thanks! Is it necessary to use xor instead of and/or? Besides that your code is similar to mine. Of course the WM_SIZE message is handled.   The main problem is that the client area is not changed. So if the window was in 1296x758 Windowed, it had 1280x720 client area (which is what I want!). So if I change the style only (from windowed to borderless) the client are is the same. If I change both the style AND the size of the window, everything works fine.   So this works: if (key->GetName() == InputKeys::F1) mainWindow->Reshape(1024, 768, WindowMode::Windowed); else if (key->GetName() == InputKeys::F2) mainWindow->Reshape(1280, 720, WindowMode::Borderless); This isn't: if (key->GetName() == InputKeys::F1) mainWindow->Reshape(viewportSize.width, viewportSize.height, WindowMode::Windowed); else if (key->GetName() == InputKeys::F2) mainWindow->Reshape(viewportSize.width, viewportSize.height, WindowMode::Borderless); I post a larger chunk of code: // register class WNDCLASSEXA wnd = { 0 }; wnd.cbSize = sizeof(wnd); wnd.lpszClassName = WindowsWindow::WindowName; wnd.hInstance = GetModuleHandle(nullptr); wnd.lpfnWndProc = &WindowsApplication::WndProc; wnd.style = CS_OWNDC; // | CS_HREDRAW | CS_VREDRAW wnd.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW); wnd.hCursor = LoadCursor(NULL, IDC_ARROW); if (RegisterClassExA(&wnd) == 0) { LOG_ERROR("Failed to register class"); return nullptr; } // ... // create window bool WindowsWindow::Create(const GenericWindowPtr& parent, const GenericWindowDefinition& def) { this->title = def.title; this->windowMode = def.windowMode; // first, setup styles GetStyleFromDef(def, windowedStyle, fullscreenStyle, extendedStyle); // then adjust window region and assign the correct style int32 x = def.x; int32 y = def.y; uint32 width = def.width; uint32 height = def.height; Adjust(x, y, width, height); const uint32 style = (def.windowMode == WindowMode::Windowed) ? windowedStyle : fullscreenStyle; HWND parentHWND = nullptr; if (parent) { // it's safe to cast here parentHWND = (static_cast<WindowsWindow*>(parent.get()))->GetHWND(); } hwnd = CreateWindowExA(extendedStyle, WindowName, def.title.c_str(), style, x, y, width, height, parentHWND, nullptr, GetModuleHandle(nullptr), nullptr); if (!hwnd) { LOG_ERROR("Failed to create window"); return false; } return true; } void WindowsWindow::GetStyleFromDef(const GenericWindowDefinition& def, LONG& style, LONG& fullscreenStyle, LONG& exStyle) { if (def.hasBorder) { exStyle = WS_EX_APPWINDOW; //style = WS_OVERLAPPED | WS_BORDER | WS_CAPTION; style = WS_BORDER | WS_CAPTION; if (def.supportSysMenu) { style |= WS_SYSMENU; if (def.supportMinimize) style |= WS_MINIMIZEBOX; if (def.supportMaximize) style |= WS_MAXIMIZEBOX; } } else { exStyle = WS_EX_WINDOWEDGE; style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; exStyle |= (def.showInTaskbar ? WS_EX_APPWINDOW : WS_EX_TOOLWINDOW); } if (def.isTopmost) exStyle |= WS_EX_TOPMOST; fullscreenStyle = WS_POPUP; } // the current Reshape function which works when the size is changed as well // note that the problem appears when the client area is not changed void WindowsWindow::Reshape(uint32 width, uint32 height, WindowMode mode) { // TODO: fix this // change style based on window mode change if (windowMode != mode) { LONG currStyle = GetWindowLongPtr(hwnd, GWL_STYLE); if (mode == WindowMode::Windowed) // going windowed { currStyle &= ~fullscreenStyle; currStyle |= windowedStyle; } else // going full-screen { currStyle &= ~windowedStyle; currStyle |= fullscreenStyle; } SetWindowLongPtr(hwnd, GWL_STYLE, currStyle); windowMode = mode; } uint32 flags = SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED; int32 x = 0; int32 y = 0; // adjust window size and position //if (windowMode == WindowMode::Windowed) flags |= SWP_NOMOVE; Adjust(x, y, width, height); SetWindowPos(hwnd, 0, x, y, width, height, flags); } // of course after the window is created: ShowWindow(hwnd, SW_SHOW); // OpenGL side: // currently I'm just setting the viewport and calling glClear for testing purposes // call list from GLIntercept: glViewport(0,0,1280,720) glClearColor(1.000000,0.000000,0.000000,1.000000) glClear(GL_COLOR_BUFFER_BIT) wglSwapBuffers(FF0117F9)=true
  7. The loop is pretty standard, this is called every frame: void WindowsApplication::PumpMessages(const float32 dt) { MSG msg = { 0 }; while (PeekMessageA(&msg, nullptr, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessageA(&msg); } } LRESULT WindowsApplication::ProcessMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { static ModifierKeys modifiers; Windows::iterator it = windows.find(hwnd); GenericWindowPtr window = (it != windows.end()) ? it->second : nullptr; switch (msg) { // alt+f4 or X button case WM_CLOSE: REQUIRE(window != nullptr); messageHandler.OnWindowClose(window); return 0; case WM_DESTROY: REQUIRE(window != nullptr); windows.erase(hwnd); return 0; case WM_SIZE: { const int32 w = LOWORD(lparam); const int32 h = HIWORD(lparam); switch (wparam) { case SIZE_MINIMIZED: // minimized break; case SIZE_MAXIMIZED: // fall through case SIZE_RESTORED: if (window != nullptr) messageHandler.OnWindowResized(window, w, h); break; default: break; } } break; case WM_ACTIVATE: { REQUIRE(window != nullptr); const bool activated = (LOWORD(wparam) != WA_INACTIVE); messageHandler.OnWindowActivationChanged(window, activated); } return 0; // tons of input handler default: break; } return DefWindowProc(hwnd, msg, wparam, lparam); }
  8. I've shortened (and copy-pasted) the code and tested it: void WindowsWindow::Reshape(uint32 width, uint32 height, WindowMode mode) { if (mode != WindowMode::Windowed) { windowMode = mode; int32 x = 0; int32 y = 0; Adjust(x, y, width, height); SetWindowLongPtr(hwnd, GWL_STYLE, WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPED | WS_VISIBLE); SetWindowLongPtr(hwnd, GWL_EXSTYLE, 0); SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, SWP_FRAMECHANGED | SWP_DRAWFRAME); return; } // ... } This is called when I try to switch to borderless mode. The adjust function is nothing special: void WindowsWindow::Adjust(int32& x, int32& y, uint32& width, uint32& height) { if (windowMode == WindowMode::Windowed) { if ((windowedStyle & WS_BORDER) != 0) // hasBorder { RECT r = { x, y, x + width, y + height }; // left, top, right, bottom AdjustWindowRectEx(&r, windowedStyle, 0, extendedStyle); x = r.left; y = r.top; width = r.right - r.left; height = r.bottom - r.top; } } else { HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); MONITORINFO monitorInfo; monitorInfo.cbSize = sizeof(MONITORINFO); ::GetMonitorInfoA(monitor, &monitorInfo); const int32 monitorWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; const int32 monitorHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; // use the width/height <= monitor's width/height width = Math::Min<int32>(monitorWidth, width); height = Math::Min<int32>(monitorHeight, height); // use the monitor's left/top x = monitorInfo.rcMonitor.left; y = monitorInfo.rcMonitor.top; } } And the problem is the same, strange un-updated window are appears. Maybe it's not a WinAPI problem? Or do I miss a message which should be handled? It seems like the OpenGL does not know that the window is changed. After I actually resize the window back and forth (1280x720 -> 1024x768 -> 1280x720), everything is fine.
  9. Thanks Erik, I'll check your solution soon and if it works, I'll try to find the difference which makes it work. :)   Edit: An interesting difference: when creating a window I define a style based on the parameters. The return value of SetWindowLongPtr is the previous window style which should be the same as the manually defined style, but it's not. Is that normal?
  10. I though something similar, thanks for the feedback!   It solves the resizing issue (which is irrelevant from the graphics API) but unfortunately the strange behavior remains :(
  11. Hey,   Unfortunately I cannot find my answer in the already existing topics, so here I come. I have some problems with the windowing system, especially with chaning the window style at runtime.   First of all, the window has 3 different mode: Windowed, Borderless and Fullscreen. Borderless and Fullscreen mode means the window's style is simply a WS_POPUP, while the Windowed mode means the window can have borders, system menu, maximize button, and so on. The window has border, caption, minimize-maximize-close buttons by default when selecting Windowed mode.   I'm using the WM_SIZE message to resize the frame buffers (aka render targets). The window does not have a resizing border, so only the engine (and the maximize/restore buttons) can change the size and cause the message to arrive.   I have a function in my Window class which supposed to be used to change the style and/or the resolution of the window. And this is not working. :) Initially, I'm creating a window with the startup settings. Now it's 1280x720 windowed = border + caption. The size is adjusted, so the client area is the 1280x720, the window itself is bigger.   For testing purposes, I'm using the F1-F3 keys to select the new window mode. The resolution is the same for now. I'm also running FRAPS to check if everything is okay. Here are the steps:   0) the window is shown, everything is okay (I have a really simple test scene)   1) switch to borderless mode: it looks like the style is changed (the borders are gone), however the FPS counter is gone and I have a strange "border" at the left and top side of the window. So it seems the style change was not really successful.   2) switch back to windowed mode: everything works again, the FPS counter is back, the window border is back, and the viewport fits.   3) switch to borderless mode again: this is the worst case - a double resize event is raised, first with size 1296x758 (which is the full size of the window with borders) then back to 1280x720. This means a double-resize of textures but the size actually isn't changed. And of course the same problems as in the 1st step.   And here is the code of the window changing function: void WindowsWindow::Reshape(uint32 width, uint32 height, WindowMode mode) { // change style based on window mode change if (windowMode != mode) { windowMode = mode; //const uint32 styleChangeFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED; if (mode == WindowMode::Fullscreen || mode == WindowMode::Borderless) // going full-screen { SetWindowLongPtr(hwnd, GWL_STYLE, fullscreenStyle); //SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, styleChangeFlags); } else // going windowed { SetWindowLongPtr(hwnd, GWL_STYLE, windowedStyle); //SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, styleChangeFlags); } } uint32 flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW; int32 x = 0; int32 y = 0; // adjust window size and position if (windowMode == WindowMode::Windowed) flags |= SWP_NOMOVE; Adjust(x, y, width, height); SetWindowPos(hwnd, nullptr, x, y, width, height, flags); } I hope someone can help me solve this issue.   Edit: The code was just changed that's why I have comments and "strange if" there. :)   Edit 2: If I change the window mode to borderless, I get a window which looks like as in the 2nd image above. However if after this I change the resolution to ... say 1024x768 then back to 1280x720, everything works fine. (Haven't tested fullscreen mode yet, that will be another problem)
  12.   This tree can be used for selecting the visible objects by the camera or by a point light as well. But of course I'll use the same implementation for collision-detection (when I'll implement one :P)     So yea, in short, it would be better to make a separate quad tree for each component. And should it be a template class or a class with a generic "QuadTreeElement" container and statically cast when I query the components?
  13. Thanks for your reply!   In the past I implemented the QuadTree to store the objects and not components but things changed. :)   An object itself does not have bounds. And if I attach a DirLight component to an object, what would be the AABB of the object? Or if I attach multiple components to the same object, eg. a RenderableMesh and a Collider. The Collider can be "bigger" than the actual mesh which means the two component's bounds are different. This was the reason why I decided to store the components and not the objects.   What's about the 1:1 relation of components and quadtrees? I mean to create a separate quad tree for each sortable component? This solution has the highest memory cost but probably the fastest search. But the extra memory consuption is not a big deal IMHO, it's just a couple extra MB at most.
  14. Actually the Nvidia paper describes it pretty well on the 7th page. if you have a directional light, you can calculate a view matrix from zero to the light direction (light position is actually irrelevant). When you have this generic view matrix, you calculate the camera's frustum corners for each split. These corners are then transformed into the light's space (with the previous view matrix and a generic ortho projection matrix). A light-space bounding box is calculated from the transformed corners. Then the C crop matrix is calculated (as shown in the Nvidia paper) and the projection matrix becomes P = Pz * C, where Pz is an orto proj matrix with the calculated min and max z values.   So in short: - calculate view once - calculate proj and view*proj for each split - render shadow map for each split with the calculated viewProj matrix - use the shadow map textures to render the shadowed scene   But this is described better in the Nvidia paper, check it out again! You can find your answers there!
  15. Hey,   I've implemented a QuadTree but I'm not sure if I'm doing it in the best way. Here is my concept:   First, the basic design of my scene system:   I'm using an object+component system, where the object can be placed in the world but actually does nothing. The objects contain components, eg. RenderableMesh, PointLight, Camera, etc. which are stored by the corresponding system (DisplaySystem, PhysicsSystem and so on).   Some components should be structured by a QuadTree (or any other spatial partitioning tree). These are inherited from a class, let's call it TreeElement. The TreeElement is nothing more just stores a pointer to the container node (which can be modified by the spatial implementation only - friend class) and the world-space bounding volume (AABB) which tells us where to put the object in the tree.   I'm also using a layer-system. The user can define a custom layer and place objects into it. An object belongs to a single layer. Some components have to be stored per layer (it's only the RenderableMesh for now). This way, the user can say that a camera should render only the specific layers. This is similar to the Unity's solution.   And finally, I'm using a simple reflection-system, so I can query the type of a component, like this: const TypeInfo& t = TypeOf<RenderableMesh>(); // or if I have a pointer to a component const TypeInfo& t2 = component->GetTypeInfo(); The QuadTree design   Because I wanted to re-use the same implementation over and over again I had to make it generic - at least from the component side of view. When I'm rendering the scene, I have to query the visible RenderableMesh components, so it's more efficient to store the different type of components in different containers in the quad tree.   And here comes the reflection system. When I'm creating the quad tree, a set of type infos can be passed to the constructor, which stores a <typeInfo, id> map. The size of this map determines how many containers will be created for each quad tree node (referred as node in the future). When querying a specific component (like RenderableMesh), the proper container is selected by this map. Like this (sample code) template <class T> void CollectElements(std::vector<T*>& result) {     auto it = typeIdMap.find(TypeOf<T>());     // error handling for invald iterator     const uint32 typeId = it->second;          // ...          for (Node* node : visibleNodes)     {         const Node::Elements& elements = node->elements[typeId]; // <--- here                  // ...     } }   Placing an element into the tree is similar, I have to find the typeId of the component. This whole process made it generic for every component but it's another map search (which is pretty small btw, contains only 1-2 elements).   Another problem is the layer system I'm using. Because some components have to be stored per layer, I ended up using a different quad tree for each layer. So if I have n layer, I have at least n+1 quad tree (+1 for the "global", non-layer-related components).   The QuadTree structure   The whole QuadTree is (re)built when the scene loading is completed or when a transformed object's bound component would be outside of the current quad tree bounds. The rebuilding means to drop all the previos data, create a completely new tree and reinsert all elements.   I'm actually using a hiearchial-grid design like in this article (I've found it after I've done with the implementation :)). It costs more memory, but no run-time merging and splitting is required. And with some maths, the tree's node can be indexed easily without recursion when searching for an element's location. However this is not implemented yet, and I'm using a simple recursive search (which works O(log n) I guess).   Questions   This seems to work but I'm not sure this is the best design.   * Should I use a template quad tree class and store only one type of component in each tree? * Or should I hardcode every type of component in the quad tree? * Or just use a single container and store the type of the element (component) as well. And when querying, I get ALL visible elements, iterate over the result and filter the components by its type. - this is pretty bad IMHO   If I'll use the current design, the same QuadTree class can be re-used many times with a cost of another small map search.