Clear and reuse a scene

Hi,
I have a very dynamic world in which something is always changing. That’s why I work with double scenes, where one scene is visible while I fill in the other. Then I switch the visibility of the two scenes and fill in the other scene.
It works well and is very fast. But after about 15 minutes or so the framerate suddenly drops very low and the game crashes within seconds.

I now assume that I do not release the individual components in the respective invisible scene cleanly.

I fill in everything by hand like in the demo “Writing code to modify scenes and transformations”. But I don’t know exactly how to get rid of it. I’ve tried different approaches.

So I would like to be able to delete everything in a scene, except for the loaded texture, so that it doesn’t take any more time. And then reuse this scene by being able to fill in new coordinates with texture points. What do I have to delete and how or in which order.

Many thanks for the help.
MBa

Basically, to delete the scene, just free it, FreeAndNil(MyScene). This releases all resources used by this scene, including OpenGL resources etc.

I’m not clear how do you want to reuse scene exactly, can you describe it in more details?

Maybe you’re looking for the Clone method of TCastleScene, which allows to copy the scene contents. It can be used to have a “template” scene that is then cloned multiple times:

TemplateScene := TCastleScene.Create(...);
TemplateScene.Url := 'castle-data:/monster.gltf';

Monster1 := TemplateScene.Clone(...);
Monster1.Translation := Vector3(1, 0, 0);
Viewport.Items.Add(Monster1);

Monster2 := TemplateScene.Clone(...);
Monster2.Translation := Vector3(2, 0, 0);
Viewport.Items.Add(Monster2);

....

You can also use TSerializedComponent if you want to instantiate many times the same design, like .castle-transform file:

TemplateSerializedComponent := TSerializedComponent.Create(
  'castle-data:/monster.castle-transform');

Monster1 := TemplateSerializedComponent.TransformLoad(...);
Monster1.Translation := Vector3(1, 0, 0);
Viewport.Items.Add(Monster1);

Monster2 := TemplateSerializedComponent.TransformLoad(...);
Monster2.Translation := Vector3(2, 0, 0);
Viewport2Items.Add(Monster1);

In both examples above, I use “…” where you should use some “owner” component (see about owner in TComponent: Modern Object Pascal Introduction for Programmers | Castle Game Engine ). You will typically use here FreeAtStop or Application.

See examples/advanced_editor/advanced_loading_designs/ for example of TSerializedComponent usage.

In both cases above, you can free monsters like just FreeAndNil(Monster1), FreeAndNil(Monster2) to reliably release their memory.

Michael, thank you for your reply.

The world looks a little like Minecraft. Many cubes drawn around the camera and redrawn when the camera moves. So I have to clear and rebuild them scenes.
And there is the terrain, which I also draw myself.

Depending on whether they are houses or people, they are refilled from time to time or frequently, houses don’t change that often.

So all I really need to do is delete the TCoordinateNode and the TTextureCoordinateNode I suppose because the textures and light settings stay the same. Then recalculate/draw them again because new houses, trees and people or terrain are visible.

But when I see that one depends on the other:
At the end in TCastleScene the RootNode is added which has a filled TTransformNode which has a TShapeNode, and so on…
And at the very beginning of the chain, TCoordinateNode was filled in: how can I clean out the TCoordinateNode and TTextureCoordinateNode without stepping on the feet of the others (in the chain where everything is connected, if I delete the wrong one and another one is dependent on that)?

Thanks again for the time and help.
MBa

Let me maybe go a bit from a different direction:

It may not be a good idea to rebuild a scene when something in-game changes, especially every frame. Scenes are complicated things and they require some resources reinitialization when rebuilt. This way you’ll need to call something like Scene.AllChanged which can in turn be far longer than a single frame. If you try to offload this time into a thread - unfortunately this indeed may result in the crash you’ve noted, as Castle Game Engine in most cases can be accessed only from a single thread, while indeed you can create some classes in threads, the most “costly” resources initialization will have to be done in the main thread.

So, the idea of optimization may be a bit different.

If you are aiming at voxels rendering you will be much “faster” having a bigger mesh (regardless of player’s camera position) and update it only when the Player or some internal logic actually modifies the world.

If for some reason you really need so show/hide significant elements of this mesh - you can have them as different scenes, and inside (if you want to go deeper) - a set of TSwitchNodes. Unlike rebuilding of the scene content and reinitialization of resources - it’s lighting fast.

It’s better to handle “moving” or “morphing” objects as separate scenes. This way, again, all their animations can fit inside of TSwitchNodes or analogues which in turn again will avoid rebuilding the scene every frame which can become a performance killer even if using it from a thread was a safe solution.

One more good optimization idea is to avoid rendering voxels as cubes, but generate a single TShape from the whole voxel volume. I believe this is the fastest way to, unless you want to go into writing a voxel renderer shader (this is possible and is significantly faster, but also by a few orders more complex).



Just a few quick pics.
The world looks like this.
But it’s only proof of concept! Nothing looks right yet. At the moment it has to work without a crash first.
You can see that over 700 people are visible at the same time. (in the background there are a few thousand).
It would be a shame if I had to change the concept again. It works for 15 minutes. Maybe it’s just a short game. :wink:
But I knew that threads might not work because you already described it that way in the documentation.

So I already have pairs of scenes for different types: separately for people, terrain or houses.
And i have no idea about voxels.

I will read your answer more closely and think about it.
Thanks again!

3 Likes

All these people are walking around. I only draw the ones that are close to the camera. When the camera moves, parts of the terrain are redrawn, others disappear. The same with the houses or trees. That’s why I always switch a couple of scenes back and forth, one is shown, the other is filled. It’s also surprisingly quick.
To be honest I have no idea how to do this with voxels or with the TSwitchNodes. Since it looks from a distance TSwitchNodes is closer to my existing design: do you have any examples? I don’t even know where to start.

It’s just a fancy world for a box in 3D world. Like “pixels” on 2D screen - same way “voxels” on a 3D grid. There are known approaches to render a hell lot of those efficiently (and by a hell lot I mean billions). Voxels not necessarily need to be boxes, they can be of different shape, but usually of a relatively simple one (in terms of math).
One of the ways to render voxels is to do it fully on GPU. However, this will require to write a whole voxel engine for GPU. Which while can result in very high performance, is very non trivial and as such can be very long, hard and unreliable (due to bugs). So it’s easier to make such things through the game engine.
You may check a working example of voxels rendering in Castle Game Engine here EugeneLoza / CastleCraft · GitLab (it’s slightly outdated, but very small and well documented). This does a very similar thing to what you do: recreates the TCastleScene every time the voxels in the world change.

Note, that if you have each person and chunks of terrain as separate TCastleScenes, you can simply toggle their Castle Game Engine: CastleTransform: Class TCastleTransform to false to make them disappear.

If the object are not moving too much and not animated (parts of the terrain, trees, buildings) then you don’t need to create separate scenes for those but can use scene internal structure to handle objects inside, namely TSwitchNode Castle Game Engine: X3DNodes: Class TSwitchNode. It can have several children and WhichChoice determines which of the children is shown at the current moment without rebuilding the whole scene. This way if you set WhichChoice = 0 it will show the “first child”, and if you set WhichChoice = -1 it will not show anything.

In practice having too many TSwitchNode is also not a good idea - so a combination of toggling TCastleScene.Exists (for larger elements, like map chunks) and TSwitchNode inside of those can offer the best performance.

Unfortunately I don’t have a good example of such code, you may try to look at one of my ancient projects Mazer.pas · master · EugeneLoza / Mazer · GitLab but first it’s desperately obsolete (7 years, eh?), and second it’s written in a bad style plus I have only been starting learning Castle Engine back then.

eugeneloza:
By the way, it was exactly your code from CastleCraft that got me further with one of my other questions. I just wanted to thank you for that.
That’s why I started with these boxes and stayed with them, also because of the speed.
Now that I look back into this source, I see: you clean the scene every time one is taken away or added. Now I’m wondering if your game also crashes after you change a few hundred boxes in each cycle. Or why would your version work but mine wouldn’t? It still looks very similar.

When I started the engine, I also tried to put every single object in a single scene. So every tree, etc. That was extremely slow. I wanted to give up and switch back to “my old engine”, which of course can never do that much.
After finding your code I was over the moon that I could draw so many things.
But I assume it was faster because there are so many triangles in a single scene that are drawn at the same time. And otherwise it would draw every single scene individually. If I understand correctly.

Since in CastleCraft, if I understand correctly, there is a huge cube with small cubes that can be switched on or off (array), it’s not that easy in my case. I don’t think I can occupy the whole world with points that are toggled.

Since I’ve been trying to find a way out of the problem for several weeks, I don’t know what else I could try at the moment.
Thanks again for the jump start.
MBa

1 Like

No, it doesn’t crash. But I don’t do that in a thread (I understood you are trying to do this in a thread?) If you do this and it still crashes - means you are doing something unexpected and it can be fixed. Note that I do not delete things manually, but simply use Scene.Load instead castlecraft.lpr · master · EugeneLoza / CastleCraft · GitLab - it makes sure everything is properly loaded automatically.

Also hypothetically it can crash if you provide something unexpected in the created TX3DRootNode (e.g. if some component refers to a “broken” texture, e.g. a texture that has been already freed).

No, in CastleCraft it’s very primitive. It just constructs a single TCastleScene with everything inside, nothing gets turned on/off. In Mazer on the contrary - it’s complicated, it constructs multiple TCastleScenes with multiple TSwitchNodes in each of those which get toggled on and off depending on the Player’s position and which of those are/can be visible from this position.

Thanks again.
I’ll take a closer look.
MBa

( Sorry for delay! ) Everything written above in this thread is valid, let me add a summary of possible approaches :slight_smile:

In general, there are 2 ways to have dynamic content in 3D viewport, they both make sense:

  1. Operate on TCastleScene “as a whole”, without changing the TCastleScene contents. E.g. you can add / remove TCastleScene instances, you can toggle the TCastleScene.Exists.

    Toggling the TCastleScene.Exists is always fast.

    Adding and loading a new scene may be “fast enough” if you use the approaches with TemplateScene.Clone or TemplateSerializedComponent.TransformLoad.

  2. Change the TCastleScene contents, by editing the nodes in TCastleScene.RootNode (adding / removing / changing properties of nodes).

    This can be ultra-fast… for some specialized changes.

    E.g. changing TSwitchNode.WhichChoice is ultra-fast.

    Updating vertexes of a given shape is ultra-fast too (we make sure to only update a relevant VBO on GPU). For example you could take a code from Writing code to modify scenes and transformations | Manual | Castle Game Engine (“11. Building a mesh using code”), and remake it to call the

     Coord.SetPoint([
         ....
     ]);
    

    very often (e.g. add the code into a code of your view, Designing user interface and handling events (press, update) within the view | Manual | Castle Game Engine , and call Coord.SetPoint... from every TViewXxx.Update). This will change the vertexes every frame. And it’s OK, we make sure it is fast. Changing the topology by calling

    IndexedFaceSet.SetCoordIndex([....]);
    

    every frame is also fast.

    It also will not cause any memory leaks.

    The things that are slow are in general adding / removing nodes. They generally require to reprocess the whole TCastleScene content internally.

In all cases, having a lot of scenes (TCastleScene) or lot of small shapes (lots of shapes in one TCastleScene, or lots of shapes across many TCastleScene) may cost performance, but then using batching (TCastleViewport.Batching) may help.

I hope that this is helpful. Some related docs are on Transformation hierarchy | Manual | Castle Game Engine , Optimization and profiling | Manual | Castle Game Engine . I know it’s not a straight answer “do this!” because there’s no straight answer – we try to optimize everything :slight_smile: