Jump to content

Ultra Engine testing


Josh
 Share

Recommended Posts

7 hours ago, Josh said:

Yeah, just nudge it forward away from the camera:

line->SetPosition(line->position + Vec3(0,0,0.1));

Is each widget created at its own z depth?  I'm wondering if it would be better to do something like this:

line->SetPosition(line->position.x, line_position.y, panel_position.z + 0.1f);

I can get the depth of a sprite (position.z) but I don't think I can get the depth of a widget...

Link to comment
Share on other sites

For each widget in the interface, there is a value that starts with one and increments. The Z position of each widgetblock's sprite is calculated as follows:

pos.z = 0.999f - float(gui->orderiterator) / 10000.0f;

So if you set the Z position of your sprite to 0.999f it will appear behind all widgets, but still within the default orthographic camera depth range.

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I'd like to set it between two panels like so:

Depth.png.5253dbf3cfb7eb2bb2aacc7ba3d5a742.png

In this case I tried random values until it worked, just to see if it would.

float GetDepth() {
	return 0.999f - float(102) / 10000.0f;
}

 

5 minutes ago, Josh said:

It's probably an uninitialized value that hasn't been set yet. That should really be made a private member.

If you could make some way of getting it's depth or order that would be great.  Maybe a widget could have the above function implemented? Taking a block index maybe?

  • Sad 1
Link to comment
Share on other sites

Panel pixmaps are working but they do not seem to be responding to alpha.  Also this example now shows that if the panel is smaller than the pixmap the border doesn't match up.

#include "UltraEngine.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

int main(int argc, const char* argv[])
{
    auto displays = GetDisplays();
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    auto world = CreateWorld();
    auto framebuffer = CreateFramebuffer(window);

    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 0, -3);

    auto font = LoadFont("Fonts\\arial.ttf");
    auto ui = CreateInterface(world, font, framebuffer->size);
    ui->SetRenderLayers(2);
    ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f);

    auto ui_camera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC);
    ui_camera->SetPosition((float)framebuffer->size.x * 0.5f, (float)framebuffer->size.y * 0.5f, 0);
    ui_camera->SetRenderLayers(2);
    ui_camera->SetClearMode(CLEAR_DEPTH);

    auto light = CreateBoxLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    auto box = CreateBox(world);
    box->SetColor(0, 0, 1);

    auto actor = CreateActor(box);
    auto component = actor->AddComponent<Mover>();
    component->rotation.y = 45;

    auto widget = CreatePanel(600, 350, 64, 64, ui->root, PANEL_BORDER);
    widget->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
    widget->SetPixmap(LoadPixmap("Background.dds"));

    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

Background.zip

Link to comment
Share on other sites

Loading classic assets isn't working the way it should. In my project, I'm unable to load anything when I point to my Cyclone packages but in this example, it just fails to load materials.

#include "UltraEngine.h"
using namespace UltraEngine;

int main(int argc, const char* argv[])
{
    //Load Package
    auto pkg = LoadPackage("classic_assets.zip");
    if (!pkg)
    {
        Print("Failed to read package!");
        return 1;
    }

    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create a world
    auto world = CreateWorld();

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 0.64f, -1.28);

    auto scene = LoadScene(world, "Maps/start.map");
    if (!scene)
    {
        Print("Failed to load scene!");
        return 1;
    }

    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

classic_assets.zip

  • Thanks 1

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

I made a prototype map loader tonight. One thing I wanted to do is see if I could break the ice with multithreading and load the scene in a different thread. This way I can at least do a loading bar or a spinner on the loading screen. One thing you can also do is level streaming, but I was getting crashes and other issues when rendering the world in the while loop. On small maps it loaded fine, and it was cool to see the assets slowly load in. But on the bigger maps, it wasn't successful. 

Also, if you reload a Cyclone map, models with bones/animations (ball catcher, pedestal button) does not load with the rest of the map, You're free to load the Cyclone assets with this demo code. Maybe you can also give a multithread noob some tips on how to make it more stable/actually work right.

#include "UltraEngine.h"
#include "ComponentSystem.h"
using namespace UltraEngine;

static std::shared_ptr<Camera> camera = NULL;

class SceneLoader : public UltraEngine::Object
{
    std::shared_ptr<UltraEngine::Thread> m_spThread;
    //std::shared_ptr<UltraEngine::Mutex> m_spMutex;
public:
    std::shared_ptr<UltraEngine::Scene> m_spScene;
    UltraEngine::WString m_pszScene;
    std::weak_ptr<UltraEngine::World> m_wpWorld;
    std::vector<std::shared_ptr<Actor>> m_spActors;

    SceneLoader()
    {
        m_spScene = NULL;
        m_spActors.clear();

        m_spThread = NULL;
        m_pszScene.clear();
    }

    ~SceneLoader()
    {
        m_spScene = NULL;
        m_spActors.clear();

        m_spThread = NULL;
        m_pszScene.clear();
    }

    static shared_ptr<Object> LoadingThread(shared_ptr<Object> extra)
    {
        auto ml = extra->As<SceneLoader>();
        return UltraEngine::LoadScene(ml->GetWorld(), ml->m_pszScene);
    }

    static shared_ptr<Object> ClearThread(shared_ptr<Object> extra)
    {
        auto ml = extra->As<SceneLoader>();
        ml->m_spScene = NULL;
        return NULL;
    }

    void Load(std::shared_ptr<UltraEngine::World> pWorld, const UltraEngine::WString& psScenePath, const bool bMultiThreaded = false)
    {
        m_pszScene = psScenePath;
        m_wpWorld = pWorld;

        // Pause the world
        GetWorld()->Pause();

        // Clear the current scene.
        m_spScene = NULL;
        //for (auto& e : m_spActors)
        //{
        //    e = NULL;
        //}

        if (bMultiThreaded)
        {
            //auto mutex = UltraEngine::CreateMutex();
            m_spThread = UltraEngine::CreateThread(LoadingThread, Self(), true);

            while (m_spThread->GetState() != UltraEngine::THREAD_FINISHED)
            {
                //mutex->Lock();

                // Print spam
                Print("L O A D I N G . . . ");

                //mutex->Unlock();
            }

            auto o = m_spThread->GetResult();
            m_spScene = o->As<UltraEngine::Scene>();

            m_spThread = NULL;
            //mutex = NULL;
        }
        else
        {
            m_spScene = UltraEngine::LoadScene(m_wpWorld.lock(), m_pszScene);
        }

        if (m_spScene)
        {
            // If there's no actors, make this the spec cam.
            if (m_spActors.empty())
            {
                if (camera)
                {
                    auto actor = CreateActor(camera);
                    actor->AddComponent<CameraControls>();
                    m_spActors.push_back(actor);
                }
            }
        }

        // Resume the world
        GetWorld()->Resume();
    }

    void Clear()
    {
        if (m_spScene)
        {
            Print("Clearing scene...");
            GetWorld()->Pause();
            GetWorld()->SetEnvironmentMap(NULL);
            GetWorld()->SetEnvironmentMap(NULL, UltraEngine::ENVIRONMENTMAP_DIFFUSE);
            GetWorld()->SetEnvironmentMap(NULL, UltraEngine::ENVIRONMENTMAP_SPECULAR);

            m_spScene = NULL;
            for (auto& e : m_spActors)
            {
                e = NULL;
            }
            m_spActors.clear();

            GetWorld()->Resume();
        }
    }

    std::shared_ptr<UltraEngine::Scene> GetScene()
    {
        return m_spScene;
    }

    std::shared_ptr<UltraEngine::World> GetWorld()
    {
        return m_wpWorld.lock();
    }
};
static std::shared_ptr<SceneLoader> sceneloader;

const WString GetStringArg(nlohmann::json& j3, const WString& defaultval = "")
{
    if (!j3.is_null())
    {
        return JSONGetString(j3);
    }

    return defaultval;
}
const bool IsFlagSet(nlohmann::json& j3, const bool defaultval = false)
{
    if (!j3.is_null() && j3.is_boolean())
    {
        return j3.get<bool>();
    }

    return defaultval;
}

int main(int argc, const char* argv[])
{
    auto args = ParseCommandLine(argc, argv);

    //Get the displays
    auto displays = GetDisplays();

    //Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    //Create framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create world
    auto world = CreateWorld();

    camera = CreateCamera(world);
    camera->SetFov(70);
    camera->SetPosition(0, 0, 0);
    camera->SetRotation(0, 0, 0);

    sceneloader = std::make_shared<SceneLoader>();

    auto mapfile = GetStringArg(args["map"], "Maps/start.map");
    auto multithread_load = IsFlagSet(args["multithread"], false);
    sceneloader->Load(world, mapfile, IsFlagSet(args["multithread"], multithread_load));

    //Main loop
    while (window->Closed() == false and window->KeyHit(KEY_ESCAPE) == false)
    {
        if (window->KeyHit(KEY_ENTER))
        {
            Print("Reloading map.");
            sceneloader->Load(world, mapfile, multithread_load);
            camera->SetPosition(0, 0, 0);
            camera->SetRotation(0, 0, 0);
        }
           
        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

Also, @SpiderPig said something about the fog being broken and here's a picture of it. Load any lvl# map of Cyclone to notice no fog in the void. I got this artifact randomly and took a screen of it.

image.thumb.png.5c731be95ada313cb2a88a0ba7e7acec.png

  • Upvote 1

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

GetBonePosition(true) is not returning the global position of the bone.  It's not taking into account the model scale and I don't think the rotation either...

bone_pos = TransformPoint(bone_pos, Mat4(), model->GetMatrix().Inverse());

EDIT : Yeah, it's just not being transformed.

Link to comment
Share on other sites

I think I've narrowed down a problem I've been having with the GUI call-backs.  The child seems to be blocking a lot of the events to its parent.  If the child is smaller than the parent it receives more events but I don't think it gets all of them, hard to tell.

#include "UltraEngine.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

bool EventCallback(const Event& event, shared_ptr<Object> extra) {
    switch (event.id) {
    case EVENT_MOUSEENTER:
        Print("MOUSE_ENTER");
        break;
    case EVENT_MOUSELEAVE:
        Print("MOUSE_LEAVE");
        break;
    case EVENT_MOUSEDOWN:
        Print("MOUSE_DOWN");
        break;
    case EVENT_MOUSEMOVE:
        Print("MOUSE_MOVE");
        break;
    case EVENT_MOUSEUP:
        Print("MOUSE_UP");
        break;
    case EVENT_MOUSEWHEEL:
        Print("MOUSE_WHEEL");
        break;
    }

    return true;
}

int main(int argc, const char* argv[])
{
    auto displays = GetDisplays();
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    auto world = CreateWorld();
    auto framebuffer = CreateFramebuffer(window);

    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFov(70);
    camera->SetPosition(0, 0, -3);

    auto font = LoadFont("Fonts\\arial.ttf");
    auto ui = CreateInterface(world, font, framebuffer->size);
    ui->SetRenderLayers(2);
    ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f);

    auto ui_camera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC);
    ui_camera->SetPosition((float)framebuffer->size.x * 0.5f, (float)framebuffer->size.y * 0.5f, 0);
    ui_camera->SetRenderLayers(2);
    ui_camera->SetClearMode(CLEAR_DEPTH);

    auto light = CreateBoxLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    auto box = CreateBox(world);
    box->SetColor(0, 0, 1);

    auto actor = CreateActor(box);
    auto component = actor->AddComponent<Mover>();
    component->rotation.y = 45;

    auto w0 = CreatePanel(10, 10, 128, 128, ui->root);
    auto w1 = CreatePanel(10, 10, 128, 128, w0);
    w1->SetColor(1, 0, 0);


    ListenEvent(EVENT_NONE, w0, EventCallback);

    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        while (PeekEvent()) {
            auto event = WaitEvent();
            ui->ProcessEvent(event);
        }

        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

Link to comment
Share on other sites

2 hours ago, SpiderPig said:

The child seems to be blocking a lot of the events to its parent. 

If i understand correctly your case and how mouse/keys events works a callbacks triggers only for upper UI element under mouse cursor. In UAK i solved it for my custom widgets by calling parent event methods

void InnerContainer::MouseEnter(const int x, const int y) {
    GetParent()->MouseEnter(x, y);
}

 

Link to comment
Share on other sites

13 hours ago, SpiderPig said:

I'd like to set it between two panels like so:

Depth.png.5253dbf3cfb7eb2bb2aacc7ba3d5a742.png

In this case I tried random values until it worked, just to see if it would.

float GetDepth() {
	return 0.999f - float(102) / 10000.0f;
}

If you could make some way of getting it's depth or order that would be great.  Maybe a widget could have the above function implemented? Taking a block index maybe?

Widgets don't have a persistent order. Widget blocks are assigned an order any time anything changes. The number of widget blocks, and whether they are hidden or shown, can change from one action to the next.

What's really needed here is a widget block that can display a line. I don't want to add this until there is time to test on Quartz, GDI, and XRender, because I don't want to start adding features to the 3D GUI that are not supported by a GUI created on a window.

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

16 hours ago, SpiderPig said:

Panel pixmaps are working but they do not seem to be responding to alpha.  Also this example now shows that if the panel is smaller than the pixmap the border doesn't match up.

The issue is that widget pixmaps do not get tinted by the widgetblock color. The reason for this is I am not sure if it is possible to draw a colored picture with XRender. It would be easy to enable this for Vulkan, but I want the GUI to have consistent capabilities everywhere it is being used.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

5 hours ago, SpiderPig said:

Thanks for the your input!  I didn't know those functions existed.  I have actually tried something similar but to no avail, but I will try your way as well.  Thanks.

These functions are for creating custom widgets, but I don't see any problem in how they are being used in the suggested solution above.

Well, that's not exactly true. According to the documentation, these are supposed to be protected methods, meaning another class cannot access them, although they are not actually declared that way in the current build.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

10 hours ago, SpiderPig said:

GetBonePosition(true) is not returning the global position of the bone.  It's not taking into account the model scale and I don't think the rotation either...

bone_pos = TransformPoint(bone_pos, Mat4(), model->GetMatrix().Inverse());

EDIT : Yeah, it's just not being transformed.

A model can have a skeleton, but a skeleton does not have a model. A skeleton can be used across multiple models:

https://www.ultraengine.com/learn/Model_SetSkeleton?lang=cpp

So the position and rotation will be relative to the skeleton, not to any model.

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

8 hours ago, SpiderPig said:

I think I've narrowed down a problem I've been having with the GUI call-backs.  The child seems to be blocking a lot of the events to its parent.  If the child is smaller than the parent it receives more events but I don't think it gets all of them, hard to tell.

It's working perfectly. Notice the MOUSELEAVE event is even being emitted when you hover over the child. This is exactly what it is supposed to do. :)

Don't think in terms of hierarchies, think in terms of "which widget is directly under the mouse cursor?".

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

12 hours ago, reepblue said:

One thing I wanted to do is see if I could break the ice with multithreading and load the scene in a different thread.

Please do not do this! You will definitely break things badly! 😂

This will cause newly created entities to modify the world octree and add commands to the rendering and physics command buffers, none of which is a thread-safe operation.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • Josh locked this topic
Guest
This topic is now closed to further replies.
 Share

×
×
  • Create New...