Transformation hierarchy

When organizing your world, you often want to arrange your 3D objects in a hierarchy. We have two transformation hierarchies in our engine:

  1. The "outer" tree containing scenes:

    TCastleViewport.Items is a tree containing scenes. A scene is an instance of TCastleScene class, which is probably the most important class in our engine. It represents a 3D or 2D model.

    You can group and transform the scenes using TCastleTransform. The TCastleScene is also a descendant of TCastleTransform, so you can just transform a scene directly.

    This is a very simple tree, that allows you to simply transform and group 3D objects.

    • Changing this tree dynamically has absolutely zero cost. This includes changing transformations of items (moving, rotating, scaling them), or completely rearranging the tree (adding, removing items), or hiding / showing the items (use the TCastleTransform.Exists property). It is ultimately fast and can be done as often as you need.

    • Downside: do not make this tree too deep and complicated. This tree needs to be traversed each time you render or check collisions with the 3D world. Although we successfully use it with hundreds of transformations, but be careful — at some point the processing time will become noticeable.

    • Summary: absolutely dynamic tree, but don't make it too deep and complicated.

  2. The "inner" tree inside every scene, containing X3D nodes:

    Inside TCastleScene there is a transformation hierarchy of X3D nodes, starting in TCastleSceneCore.RootNode. Loading the scene by TCastleSceneCore.Load automatically builds a tree of X3D nodes based on 3D model contents. You can also build (or process) the X3D nodes tree by code. There are various grouping and transforming nodes, most notably TTransformNode (see X3D grouping component). Everything you see is expressed as a combination of X3D nodes — meshes, materials, textures, shaders, lighting, animations, collisions...

    Each single TCastleScene has a tree of X3D nodes.

    In the simplest cases (if you load scenes using TCastleSceneCore.Load) you will create one TCastleScene instance for each 3D model file you have. But you're not limited to this approach, as you can split and merge X3D graphs freely. See an example code examples/viewport_and_scenes/combine_multiple_x3d_into_one_scene for how to load multiple 3D model files into a single X3D graph (single TX3DRootNode).

    Properties of the X3D transformation hierarchy:

    • Changing the transformations in this tree is very fast and optimized, but may have a tiny cost at some point. Rebuilding this tree right now is poorly optimized (it may be improved in the future, but there's a limit to how much it can be done).

    • Upside: you can go wild with the transformation level here (the actual rendering and many other read operations look only at flattened TCastleScene.Shapes mentioned below).

    • 3D collisions, and the "frustum culling" rendering optimization, use a tree (like an octree) to minimize the number of calculations. This is very efficient if you have a lot of 3D shapes.

    • Summary: this tree is somewhat less dynamic. It is very optimized for some changes, like changing transformations of existing objects, but poorly optimized for an arbitrary rearranging at runtime. Rendering and processing is always lighting fast, regardless of the tree depth or complication.

    A natural question is should you combine multiple loaded models into one TCastleScene (like examples/viewport_and_scenes/combine_multiple_x3d_into_one_scene example does)?

    • At the beginning, don't merge the scenes. It's more natural, and in 90% cases perfectly fast, to use one TCastleScene for each one model file you load. This allows to trivially load the model using Scene.Load and is really advised for most cases. See also the relevant section in the manual about optimization.

    • 100, or even 1000, or TCastleScene instances visible should not be a problem. You should consider merging them if you have 10 000 or more. It depends on your use-case (how complicated are the scenes, how heavy is their rendering and which optimizations matter most).

  3. For completeness, we should also mention another transformation tree.

    The X3D nodes hierarchy is automatically reflected as (a little flattened and simplified) tree of shapes in the TCastleSceneCore.Shapes property.The visible nodes of this tree are X3D Shape nodes (TShapeNode) linked with geometry nodes inside (TAbstractGeometryNode).

    This tree can be completely ignored by your code. It is automatically created and managed inside the TCastleScene. Sometimes you can use this tree to speedup some operations — instead of traversing the tree in TCastleSceneCore.RootNode, it's sometimes enough to traverse simpler tree TCastleSceneCore.Shapes.