Jump to content

Ma-Shell

Members
  • Posts

    371
  • Joined

  • Last visited

Blog Comments posted by Ma-Shell

  1. This is pretty cool. I have a small suggestion though:

    The first scenario you showcased, could leave you with objects, which are not part of the scene-tree, resulting in inconsistent behaviour, if you do not call CreateSceneObject. I would suggest to have a callback-system like a ObjectCreated-hook built into the engine, which the editor then could use to automatically call CreateSceneObject with the new object. It makes for one less gotcha you need to watch for when writing scripts and imho better reflects the intention of the scene-browser as a way to see ALL objects in the scene. Also I can imagine this hook to be beneficial for other use cases.

    Of course, there would need to be a way to retrieve the scene-object for a given object, as well, since the user is not generating the element themselves anymore and thus does not have a reference if they need it (e.g. for selecting the object as in the example).

  2. Please don't use Window::MoveMouse! You will have users constantly asking themselves, whether that's absolute (i.e. move mouse to x, y) or relative (i.e. move mouse by dx, dy). Even if you can easily look it up I think, it is more helpful when scrolling through the autocompletion-options to just see on the first look what the function does without ambiguities.

    • Like 2
    • Thanks 1
  3. This is looking great. I've always been bothered by the available options for a lightweight GUI. I also think that cross platform support for a GUI framework is quite a big deal and can only second the opinion that this is the most important bonus goal.

    From the material you have posted, there is one thing I am quite curious about: In your code example you are placing the button and panel using fixed coordinates and sizes. Moreover, the widget is only created once and does not run through a loop, where the user would constantly recalculate the coordinates. When looking at the video, however, the widgets resize, when you resize the window. Did you implement a resizing-handler for the GUI shown in the video or are you planning to have a sort of automatic layouting system (i.e. defining anchors and having horizontal/vertical/grid layouts, which automatically manage the sizes of their contents) (clearly such a layouting system internally needs to use such a resize-event-handler but the question is, whether the logic behind that is tucked away some place within the API or whether a user needs to implement the handler themself). Maybe you could extend the example code by the GUI which is shown in the video and if there is such a system leave some words about how you plan it to work.

  4. This is certainly a pretty cool feature! Whenever physics is involved, however, the programmer needs to keep in mind that there might be slower systems out there and things might break when executed on slower systems. The programmer might e.g. be tempted to give an option to reduce the particle effects on lower end hardware but then the entire physics might break.

  5. I see two possible issues with filters:
    1. I understand a filter as having some sort of "layer-id" on the objects and a camera only rendering objects with a given layer-id. Suppose, you have two objects A and B. If you want to first render A and B and then from a different camera only B (e.g. you have a vampire in front of a mirror. You would want the entire scenery to include the vampire but when rendering the mirror, you would want to render the scenery from that perspective without the vampire). This would not be easily possible with a layer-id.

    2. Performance: You have to run through all objects and see, whether they match the filter in order to decide, whether to cull them or not. If you instead just walk the world's list of entities, this does not happen.

     

    Why not using something like this:

    camWorldA->SetClearMode(ColorBit | DepthBufferBit);
    camWorldB->SetClearMode(DepthBufferBit);
    camWorldC->SetClearMode(DepthBufferBit);
    
    context->ClearWorlds(); // nothing is being rendered
    context->AddWorld(worldA); // All cameras of world A are rendered
    context->AddWorld(worldB); // First all cameras of world A are rendered, then all of world B
    context->AddWorld(worldC); // First all cameras of world A are rendered, then all of world B, then all of world C

    This would give the user maximum flexibility and only require the context to hold a list of worlds, which are rendered one after another instead of having a single active world.

    For compatibility and comfortability reasons, you could additionally define

    void World::Render(Context* ctx)
    {
    	ctx->ClearWorlds();
    	ctx->AddWorld(this);
    }

    This way, you could still use the system as before without ever knowing of being able to render multiple worlds.

     

    EDIT: I see, my vampire wouldn't work with this system, as well (unless you allow a mesh to be in multiple worlds) but I still think, this is quite a flexible and easy to use system without much of an overhead

    • Like 1
  6. Ah, I see... So the rendering always uses the last world, which called World::Render() and uses all cameras from that world in the specified order?

    Would it be possible to implement the same ordering as with cameras for worlds then? Like the following

    realWorld->setOrder(1);
    HUDWorld->setOrder(2);

    where it would first render all cameras from realWorld and after that all cameras from HUDWorld.

    This would probably mean, it is more intuitive to have the render-call on the context instead of the world, since all worlds would be rendered.

     

    By the way, is there any way to disable certain cameras, so they get skipped? Like setting a negative order or something like this. What happens if you set two cameras to the same order?

  7. You mean, because unlike the previous version the user does not directly call Render() anymore, since it is run on a different thread and thus the user can not correctly orchestrate the rendering? This should not be a problem, since in CreateCamera you can specify the world.

    auto realCamera = CreateCamera(realWorld);
    auto HUDCamera = CreateCamera(HUDWorld);
    realCamera->setOrder(1);
    HUDCamera->setOrder(2);
    realCamera->SetClearMode(CLEAR_DEPTH | CLEAR_COLOR);
    HUDCamera->SetClearMode(CLEAR_DEPTH);

     

  8. On 4/24/2019 at 10:58 PM, Josh said:

    Our new engine makes speed gains in a different way and I don't think Vulkan will make anything faster at all, honestly, over what the engine could do with OpenGL 4.3. We already have zero driver overhead, but Vulkan is more widely supported and the brand is synonymous with speed in the customer's mind. I know this because when I talk to people in person the first thing they say is "does it use Vulkan?"

    It will be a lot faster than Leadwerks 4 but so was the OpenGL implementation.

    Using Vulkan does not automatically make anything faster. No one will listen to me if I try to argue with that, which is fine, because I am just going to let everyone else mess up and I will make the fastest engine.

    (https://www.leadwerks.com/community/blogs/entry/2387-getting-started-with-vulkan/?tab=comments#comment-10207)

    So, do you wish to take back that statement or did you now find other ways to optimize that were not possible in the OpenGL implementation?

    Anyway, I'm happy, you decided to go with Vulkan

     

  9. Nice, I like the concept you are proposing here. Just adding my 2 ct:

     

    When you said, there was no remove-function for a script, that makes perfect sense for scripts that are only setting variables, as you mentioned. However, you might want to have the option to remove these functions. Let's consider your tank-example: If you somehow lose your main cannon, you might want to remove the script associated with it, such that future calls to GetTarget() do not call the function of the main cannon anymore.

     

    There is another issue with your tank-example: If you have two functions called GetTarget(), you would likely also name the corresponding setter-function SetTarget(), each. However, this would mean that you can only set the target of both at the same time, if you did not name them AISetTarget() and CanonSetTarget(). For this reason, I think, you should draw a line here so you have to make explicit whether you want to call functions from a different script or only those of the same script. I would suggest, you do the following:

    • SetTarget() will only execute the function from the current script. If there is no function named SetTarget in the current script, an error should be thrown
    • All::SetTarget() (or something similar) will execute functions from all attached scripts (as well, as the current script) with the current name (i.e. the way you proposed)
    • FILENAME::SetTarget() will only execute the function from the script called FILENAME. If this script does not exist or it does not have this function, an error should be thrown

    So for each function you define in your script, you would need to internally create three different mappings. Doing this would give everyone maximal flexibility while at the same time preventing some unforeseen errors. So, everyone could still use their isolated scripts the way they used them before without even needing to change anything. If you want to call functions from other scripts, you have the choice to select either only one specific other script or all others

     

  10. @reepblue:

    Quote

    This could solve a lot of problems and give us a much smoother transition from here to where we want to go in the future:

    1. Leadwerks Game Engine 4 (deferred rendering, existing editor) [Now]
    2. Leadwerks Game Engine 5 (clustered forward rendering, real-time GI, PBR materials, existing architecture, existing editor) [Christmas 2018]
    3. Turbo Game Engine (clustered forward rendering, new architecture,  new editor) [April 2020]

    I just thought of this a couple hours ago, so I can't say right now for sure if we will go this route, but we will see. No matter what, I want to get a version 4.6 out first with a few features and fixes.

    Source: 

    So it's planned for LW 5

  11. 1 hour ago, AggrorJorn said:

    Looks like VS code is build on top of Atom. Looking at their repo https://atom.io/ it looks pretty customisable too.

    As far as I know, VS code is not directly built on top of Atom. Both, however, depend on the Electron framework (https://electronjs.org/) for rendering and thus are mainly written in JS. From my experience, both are quite good editors but both are quite heavyweight. Compared to Sublime Text (which is clearly what the devs took as their inspiration, but which unfortunately is not free), they lack somewhat in responsiveness. This comes from both being JS-applications, while Sublime Text is a native application. This also reflects in the sizes with 300 MB and 200 MB vs 30 MB.

     

    With that being said, I would go for VS code, since it seems more responsive than Atom and does weight less. In terms of features, both should be pretty equal and both are cross platform and open source.

    • Like 1
  12. The problem you're describing in the end can be solved with by deriving from "std::enable_shared_from_this" (http://en.cppreference.com/w/cpp/memory/enable_shared_from_this). This basically does what you planned with the weak_ptr-stuff but without additional overhead on your side.

    Translating your code-example, this would be:

    #include <memory>
    #include <iostream>
    using namespace std;
    class Thing : public enable_shared_from_this<Thing>
    {
    public:
    	shared_ptr<Thing> GetSelf();
    };
    
    shared_ptr<Thing> Thing::GetSelf()
    {
    	return shared_from_this();
    }
    
    int main(int argc, const char *argv[])
    {
    	shared_ptr<Thing> p1 = make_shared<Thing>();
    	shared_ptr<Thing> p2 = p1->GetSelf();
    }

    EDIT: It is important to derive publicly! In the example of the cppreference-link, they are using a struct, which derives publicly by default. For classes, you have to explicitly write ": public". I edited the code above

    • Upvote 2
  13. Quote

    All client machines, anywhere in the world, can retrieve a list of public games and choose one to join:

    
    for n=0,client:CountServers()-1 do
    	local remotegame = client:GetServer(n)
      	print(remotegame.address)
      	print(remotegame.description)
    end

    Shouldn't there be the name of the game somewhere in there, as well? Or do you just get a list of all servers and then have to read through the descriptions to see, if it is a server for your game?

  14. I also added a small optimization that checks if a moved light has the same 4x4 matrix it did at the time of the last shadow render. This makes it so if you are standing still and nothing is moving, the flashlight shadow won't update unnecessarily, even though your code is repositioning it each frame.

    When objects other than the light move, the matrix of the light stays the same. So does this mean that shadows for dynamic objects are only updated, when the lights move?

  15. That's quite an interesting bug you have right there. What flags are you using in release mode with gcc? Also, have you tried printing out all the values after each intermediate step to find out, where exactly the values turn to -NaN? From the function you posted, the only two ways for getting NaN, would be a division of 0/0, or calculating acos of a value outside the range ]-1,1[. Both functions would be only possible inside the if(d<1.0f) - branch. However, in your case, in order to get to this branch, the value of d must be in the range [0.0, 1.0[, thus the acos-function can't produce NaN. Furthermore, the value of si = sin(acos(d)) is only zero for d==-1 or d==1, which again can not happen. All the other math-functions can only return NaN, if (at least) one of their inputs is already NaN, so I would be very interested in seeing, where the values actually start turning crazy. Can you provide input values for "q" and "result", and "this", that reliably produce this misbehaviour?

×
×
  • Create New...