TCastleScene cache vs clone?

Does setting cache to true mean that loading and placing multiple copies of the same url (ie house) will automatically clone? Or should I clone in addition to setting cache to true when making copies? I am disappointed by the number of houses I can place on my map (about 85) before running out of memory with cache set to true. Maybe I need to clone to get the memory benefit?

Or maybe I need to insert the same house instance into the scene again and again without reloading or cloning?

TCastleTransformReference is what you need if you want to create multiple instances of the same scene.

1 Like

To expand:

  • TCastleScene.Cache = true already clones the underlying X3D scene graph underneath. The optimization offered by TCastleScene.Cache = true is that the model doesn’t need to be read from disk and parsed (from X3D, glTF, etc.) multiple times at loading. So you get faster loading time. But this doesn’t offer less memory usage.

  • To decrease memory usage, for non-animated scenes, TCastleTransformReference is great. This means that there’s really one scene, just referenced and rendered multiple times. See Optimization and profiling | Manual | Castle Game Engine (section " 2.8.1. Reuse the same TCastleScene instance many times") for links to more docs and examples using this. The demo is using this exactly to instantiate a number of houses :slight_smile:

In the future, this should be better. I have a task on roadmap Roadmap | Manual | Castle Game Engine " 27. Allow animating selected node graph properties, without changing the graph, to be able to reuse graphs". One this is done, then TCastleScene.Cache = true will be much more powerful (will also conserve memory) and could even be just done by default, no need to toggle it. But it will take time before I implement it.

1 Like

Thanks guys! The buildings are not animated, so this is perfect for them. Someday I will get back to my neglected animated animals, but think I will be diving into car physics first.

Is there a way to use a transform from another viewport? I have the model in my tool button that places the buildings, so that would be the easy place to get a model to reference. But it throws exception because it isn’t same view. Figuring out whether there is a building to reference adds complexity.

Ok, I have it search the scene to see if there is already a house. If one is not found it creates it. If one is found then it creates a TCastleTransformReference to the one it found. This seems to be working. However when I then select a house which causes it to set RenderOptions.WireFrameEffect := weSilhouette … it does that to all the houses. I guess there is no way to update the render on a single one since they are all the same?

That’s indeed a limitation, and it’s deliberate: a TCastleTransform cannot be present in two viewports (more precisely, in two TCastleRootTransform trees) simultaneously. Trying to support that in the past was really hard, and it was only useful for some special cases, so we had to drop it.

Indeed the TCastleScene is just referenced multiple times, so when you change the RenderOptions there, you change it for all scene instances.

To overcome this in the easiest way, you need to show selection in a different way, that adds things “outside” of shared objects. E.g. use TDebugTransformBox and attach it as TCastleTransformReference child (TCastleTransformReference child, but not inside TCastleTransformReference.Reference, so it is not shared).

I thought about a more involved solution, that would allow to toggle RenderOptions.WireFrameEffect on/off depending on whether we’re in the “selected subtree” but that’s not so easy since all the shapes are collected for further rendering (to enable cross-scene batching and blending). So I don’t yet have a straightforward solution to exactly allow to tweak RenderOptions.WireFrameEffect only when the scene is in a selected subtree (and without resigning from benefits of TCastleTransformReference sharing). But let me know if you want me to think about solution to it more :), if you definitely want to use RenderOptions.WireFrameEffect to show the selected items.

I prefer a selection look that is specific to the object… as opposed to just a box around it. If would be cool if one could propagate the render settings from above the reference and have it only affect the one reference and not all references. But maybe that is a tall order.

Maybe I can clone just the selection and display its wireframe on top of or instead of the reference model.

For the selection you could use a single dedicated Scene with same Url as target and place it as a child. Render it with WireFrameMode, and remove it from Children list afterwards/ or set Exists flag to false. To select anything else use the same Scene, just reassign Url if needed and placement (or setting as Child)