Jump to content

MagnetarX10

Members
  • Posts

    10
  • Joined

  • Last visited

Posts posted by MagnetarX10

  1. @Josh Thanks for the help.  Here is a version that combines the OpenGL example. This seems to be working fine. This is exactly what I need.

     

    #include "UltraEngine.h"
    #include <GL/GL.h>
    #pragma comment (lib, "opengl32.lib")
    
    using namespace UltraEngine;
    
    const int SidePanelWidth = 200;
    const int Indent = 8;
    
    //Custom event ID
    const EventId EVENT_VIEWPORTRENDER = EventId(101);
    
    void GLRender(shared_ptr<Window> viewport)
    {
        // Get and set the current size of the viewport
        iVec2 sz = viewport->ClientSize();
        if (sz.x < 1 or sz.y < 1) return;
    
        glViewport(0, 0, sz.x, sz.y);
    
        // Set clear colour of viewport background
        glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
    
        // Clear colour and depth buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // Render our triangle
        glBegin(GL_TRIANGLES);
    
        // Vertex 1
        glColor3f(1, 0, 0);
        glVertex3f(0, 0.5, 0);
    
        // Vertex 2
        glColor3f(0, 1, 0);
        glVertex3f(0.5, -0.5, 0);
    
        // Vertex 3
        glColor3f(0, 0, 1);
        glVertex3f(-0.5, -0.5, 0);
    
        glEnd();
    
        HWND hwnd = viewport->GetHandle();
        auto hdc = GetDC(hwnd);
        SwapBuffers(hdc);
        ReleaseDC(hwnd, hdc);
    }
    
    // Callback function for resizing the viewport
    bool ResizeViewport(const Event& ev, shared_ptr<Object> extra)
    {
        // If the window resize event is captured
        auto window = ev.source->As<Window>();
    
        // Get the new size of the applications window
        iVec2 sz = window->ClientSize();
    
        auto viewport = extra->As<Window>();
    
        // Set the position and size of the viewport window
        viewport->SetShape(SidePanelWidth, Indent, sz.x - SidePanelWidth - Indent, sz.y - Indent * 2);
    
        return true;
    }
    
    int main(int argc, const char* argv[])
    {
        // Disable asynchronous rendering so window resizing will work with 3D graphics
        AsyncRender(false);
    
        // Get the available displays
        auto displays = GetDisplays();
    
        // Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR | WINDOW_RESIZABLE);
    
        // Create user interface
        auto ui = CreateInterface(window);
    
        // Get the size of the user interface
        iVec2 sz = ui->background->ClientSize();
    
        // Create a treeview widget
        auto treeview = CreateTreeView(Indent, Indent, SidePanelWidth - Indent * 2, sz.y - Indent * 2, ui->root);
    
        // Anchor left, top and bottom of treeview widget
        treeview->SetLayout(1, 0, 1, 1);
    
        // Add nodes to the treeview widget
        treeview->root->AddNode("Object 1");
        treeview->root->AddNode("Object 2");
        treeview->root->AddNode("Object 3");
    
        // Create a viewport window
        auto viewport = CreateWindow("", SidePanelWidth, Indent, sz.x - SidePanelWidth - Indent, sz.y - Indent * 2, window, WINDOW_CHILD);
    
        // Adjust the size of the viewport when the applications window is resized (this will callback to our ResizeViewport() function)
        ListenEvent(EVENT_WINDOWSIZE, window, ResizeViewport, viewport);
    
        // Initialize an OpenGL context (get a hdc)
        HWND hwnd = (HWND)(viewport->GetHandle());
        HDC hdc = GetDC(hwnd);
    
        // Specify the format of the default framebuffer
        PIXELFORMATDESCRIPTOR pfd =
        {
            sizeof(PIXELFORMATDESCRIPTOR),
            1,
    
            // Flags
            PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    
            // Framebuffer colour format (R, G, B, A)
            PFD_TYPE_RGBA,
    
            // Framebuffer colour depth (32 bit)
            32,
            0, 0, 0, 0, 0, 0,
            0,
            0,
            0,
            0, 0, 0, 0,
    
            // Number of bits for depth-buffer
            24,
    
            // Number of bits for stencil-buffer
            8,
    
            // Number of render-targets in default framebuffer
            0,
            PFD_MAIN_PLANE,
            0,
            0, 0, 0
        };
    
        // Select an appropriate pixel format that is supported by the hdc
        int format = ChoosePixelFormat(hdc, &pfd);
    
        if (SetPixelFormat(hdc, format, &pfd) == 0)
        {
            RuntimeError("SetPixelFormat() failed.");
        }
    
        // Create an OpenGL rendering context using our current hdc
        HGLRC glcontext = wglCreateContext(hdc);
    
        if (glcontext == NULL)
        {
            RuntimeError("wglCreateContext() failed.");
        }
    
        wglMakeCurrent(hdc, glcontext);
    
        // This varialble will be used for viewport refreshing
        bool dirty = false;
    
        // Main loop
        while (true)
        {
            // Wait for event
            const Event ev = WaitEvent();
    
            // Evaluate event
            switch (ev.id)
            {
            case EVENT_WINDOWMOVE:
                if (not dirty)
                {
                    dirty = true;
                    EmitEvent(EVENT_VIEWPORTRENDER, viewport);
                }
                break;
            case EVENT_WINDOWSIZE:
                if (not dirty)
                {
                    dirty = true;
                    EmitEvent(EVENT_VIEWPORTRENDER, viewport);
                }
                break;
                //Close window when escape key is pressed
            case EVENT_KEYDOWN:
                if (ev.source == window and ev.data == KEY_ESCAPE) return 0;
                break;
    
            case EVENT_WINDOWCLOSE:
                if (ev.source == window) return 0;
                break;
    
            case EVENT_WINDOWPAINT:
            {
                if (not dirty)
                {
                    // This prevents excessive paint events from building up, especially during window resizing
                    // This event is added to the end of the event queue, so if a lot of paint events build up, it will 
                    // only cause a single render to be performed.
                    dirty = true;
                    EmitEvent(EVENT_VIEWPORTRENDER, viewport);
                }
            }
            break;
    
            case EVENT_VIEWPORTRENDER:
                GLRender(viewport);
                dirty = false;
                break;
            }
        }
        return 0;
    }

     

    • Like 1
  2. I have the same issue with your EXE. 

    Video link: https://drive.google.com/file/d/1VxprAr7jaH9Ne5sWD-Ecmea1TBPF3Rp4/view?usp=share_link

    Something about my system, I guess. I could have some weird version issue with drivers or libs. I have two monitors. One is a wide screen monitor. I have seen other issues in the past that were particular to a wide monitor, but this happens on both of my screens.

    Not sure if any of this information is useful, but here it is:

    image.thumb.png.9167b93cb8eec4b89c737d47b6e4a849.png

    image.thumb.png.bdd19991a0e52191444f64e64271fa33.png

    image.thumb.png.48cce620785ef081315c071b1dad22ab.png

     

     

    image.thumb.png.90cfd5130fb2b84be6d1bde69b066bb6.png

  3. Here is a video. I think it is when I click outside of the Viewport region. I think I was doing this accidently initially and did not notice. My assumption is that the viewport is getting invalidated but it does not seem to be sent a render message. I added a little bit of code to track which render event was being sent so I could easily tell when a new render message we sent:

     case EVENT_VIEWPORTRENDER:
                world->Render(framebuffer);
                dirty = false;
                std::stringstream sstm;
                sstm << "Viewport render (count=" << ++renderCount << ")";
                Print(sstm.str());
                break;

     

  4. @reepblue I looked at your code again.  I am trying to figure out why it does not work the same as the ListenEvent() callback version I have. I assume that WaitEvent() returns an EVENT_WINDOWSIZE event on a different frequency than the ListenEvent() gets called. Your loop drops down to the Update() and Render() calls which seems like it should be functionally equivalent, but I see a dark window during the resize in your version. This means there is a difference.

    It has been a very long time since I did Windows programming but maybe the  WaitEvent() triggers in the messages that signal a begin and end to the sizing rather than getting message for WM_SIZING which (I think) happens continuously as the user is resizing the window.

  5. @reepblue Thanks! This is very, very helpful.

    I had worked on this a bit and got it largely working based on @Josh's info. 

    The nice thing about using the ListenEvent() callback is that the 3D Scene will remain visible while the Application Window is resized. I also called Update() to keep it rotating, but I am not sure if that is a bad idea.

    I added some buttons to change the rotation of the cube, but I do not understand is why it can take a few clicks to get the buttons to work. I assume there is a better way to get the button click or I need to select it based on mouse over?

    Also, it has been a while since I have programmed C++ ( over a decade), so I don't remember if there is a way to cast the "shared_ptr<Object> extra" parameter in the ListenEvent() callback to a struct or class of objects instead of the single pointer so I don't need to setup the panels and world objects as globals.

    #include "UltraEngine.h"
    #include "ComponentSystem.h"
    
    using namespace UltraEngine;
    
    const int WIN_WIDTH = 1000;
    const int WIN_HEIGHT = 1000;
    const int PANEL_WIDTH = 200;
    const int PADDING = 10;
    
    //global "cheats" to pass more data into the resize callback
    shared_ptr<Window> viewport;
    shared_ptr<World> world;
    shared_ptr<Framebuffer> framebuffer;
    shared_ptr<Widget> left_panel;
    shared_ptr<Widget> right_panel;
    
    //-------------------------------------------------------
    // Callback to handle dynamic resizing of the Viewport
    // and panels
    //-------------------------------------------------------
    
    bool ResizeViewport(const Event& ev, shared_ptr<Object> extra) 
    {
        // If the window resize event is captured
        auto window = ev.source->As<Window>();
    
        // Get the new size of the applications window
        iVec2 win_sz = window->ClientSize();
    
        auto viewport = extra->As<Window>();
    
        // Set the position and size of the viewport window AND the panels
        viewport->SetShape(PANEL_WIDTH + PADDING, PADDING, win_sz.x - (PANEL_WIDTH*2) - (PADDING * 2), win_sz.y - PADDING);
        if (left_panel != NULL)
            left_panel->SetShape(0, 0, PANEL_WIDTH, win_sz.y - PADDING);
    
        if (right_panel != NULL)
            right_panel->SetShape(win_sz.x - PANEL_WIDTH, 0, PANEL_WIDTH, win_sz.y - PADDING);
    
        //Render the Viewport to keep the 3D scene drawing during the resize
        world->Update();
        world->Render(framebuffer);
    
        return true;
    }
    
    
    int main(int argc, const char* argv[])
    {
        //Disable multithreaded rendering for RESIZABLE Windows
        AsyncRender(false); 
    
        auto displays = GetDisplays();
        auto window = CreateWindow("Ultra Engine Test", 0, 0, WIN_WIDTH, WIN_HEIGHT, displays[0], WINDOW_TITLEBAR | WINDOW_RESIZABLE);
        auto font = LoadFont("Fonts/Arial.ttf");
    
        //-------------------------------------------------------
        // Create 2D User Interface
        //-------------------------------------------------------
    
        auto ui = CreateInterface(window);
        iVec2 win_sz = ui->root->ClientSize();
        left_panel = CreatePanel(0, 0, PANEL_WIDTH, win_sz.y - PADDING, ui->root);
        left_panel->SetColor(0.20f, 0.20f, 0.20f, 1);
        left_panel->SetLayout(1, 1, 1, 1);
        right_panel = CreatePanel(win_sz.x - PANEL_WIDTH, 0, PANEL_WIDTH, win_sz.y - PADDING, ui->root);
        right_panel->SetColor(0.20f, 0.20f, 0.20f, 1);
        right_panel->SetLayout(1, 1, 1, 1);
        //Add Buttons
        iVec2 left_sz = left_panel->ClientSize();
        iVec2 right_sz = right_panel->ClientSize();
        auto rotate_left_btn = CreateButton("Rotate Left", left_sz.x / 2 - 75, left_sz.y / 2 - 15, 150, 30, left_panel);
        auto rotate_right_btn = CreateButton("Rotate Right", right_sz.x / 2 - 75, right_sz.y / 2 - 15, 150, 30, right_panel);
    
        //-------------------------------------------------------
        // Create 3D Viewport
        //-------------------------------------------------------
        viewport = CreateWindow("", PANEL_WIDTH + PADDING, PADDING, win_sz.x - (PANEL_WIDTH*2) - (PADDING*2), win_sz.y - PADDING, window, WINDOW_CHILD);
        framebuffer = CreateFramebuffer(viewport);
        world = CreateWorld();
    
        // Adjust the size of the viewport when the applications window is resized (this will callback to the ResizeViewport() function)
        ListenEvent(EVENT_WINDOWSIZE, window, ResizeViewport, viewport);
    
        //-------------------------------------------------------
        // Setup 3D Scene
        //-------------------------------------------------------
    
        //Setup Camera
        auto camera_3D = CreateCamera(world);
        camera_3D->SetClearColor(0.125);
        camera_3D->SetFov(50);
        camera_3D->SetPosition(0, 0, -3);
        //Create a light
        auto light = CreateBoxLight(world);
        light->SetRotation(35, 45, 0);
        light->SetRange(-10, 10);
        //Create a box
        auto box = CreateBox(world);
        box->SetColor(0, 0, 1);
        //Entity component system
        auto actor = CreateActor(box);
        auto component = actor->AddComponent<Mover>();
        //Rotate the Box
        component->rotation.y = 45;
    
        //-------------------------------------------------------
        // Main Loop
        //-------------------------------------------------------
    
        while (true)
        {
            while (PeekEvent())
            {
                const Event ev = WaitEvent();
                switch (ev.id)
                {
                case EVENT_WIDGETACTION:
                    //Set the rotation based on the button click
                    if (ev.source == rotate_right_btn)
                        component->rotation.y = -45;
                    else if (ev.source == rotate_left_btn)
                        component->rotation.y = +45;
                    break;
                case EVENT_WINDOWCLOSE:
                    if (ev.source == window)
                        return 0;
                    break;
                default:
                    ui->ProcessEvent(ev);
                    break;
                }
            }
    
            world->Update();
            world->Render(framebuffer);
       
        }
        return 0;
    }

     

  6. I am new to Ultra Engine and never used Leadworks and have only a little bit of 3D programming experience. I looked as some youtube examples and read what I think are the relevant portions of the programming reference, but I am not 100% sure what to do.

    I am trying to build something similar to the Editor interface I saw in the Gallery. I want a main window that has a left panel and a right panel with UI controls and a center panel that renders a 3D viewport. 

    • I have created the Window, FrameBuffer, World, and Interface Objects.
    • I have a Left and Right Panel on the Interface.
    • I setup 2 cameras, one for the 2D and one for the 3D Objects. 
    • I turned off the real-time rendering for the 2D camera.

    I am sure this is simple, I don't know how to setup the 3D world for only that middle space inside the main window.  Currently, the 3D world draws over the 2D UI and I get a lot of flashing.

     

     

×
×
  • Create New...