ETM v3 design


25-01-2008 10:41:19

I think design decisions should be discussed separately from feature requests, so let's continue here.
After some more thought, I'll probably drop the separation of heightmap and terrain rendering. It just doesn't work convincingly as the heightmap needs position and orientation in space to do really useful stuff, and as such it can't be as decoupled as I would have wanted it to be. There's probably not much actual use for it, anyway.

Here is how I think I would structure ETM's renewed design (just terrain, not splatting):

  1. Array2D
    At various places ETM will accept an Array2DInterface reference which, as the name suggests, provides an interface to access data in a 2D float array. One simple implementation is Array2D which really does nothing more than actually hold that 2D array and provide access to it. There will be convenience functions to load and store arrays to disk and to interpolate values in-between.
    A SubArray2D class provides a thin wrapper to select a rectangular part of a full Array2D and do mappings of the indices accordingly.
  2. TerrainPatch
    This is the low level renderable object which will basically do what ET::Impl::Tile does now. For most cases you will not need to use these directly, but it will no longer be hidden in a nested namespace, so if you do, you can use it without hassle. TerrainPatches are constructed from an Array2DInterface and a Vector3 containing the vertex scales. Height values can be updated. There are functions to define neighbouring patches which are used for determining LOD.
    A TerrainPatch itself will most likely not be a MovableObject, if you want to use them directly, you'll have to provide the logic to actually add them to a RenderQueue.
  3. Terrain
    This is more or less what TerrainManager currently is, though the interface will be different. First of all, a Terrain is constructed from an Array2DInterface, scale and patch sizes. Furthermore, Terrain itself implements Array2DInterface by which way it directly exposes its heightmap. Updates to the heightmap will be marked, and with the next render operation the internal TerrainPatches will be updated.
    Terrain is a MovableObject, so it can be placed, rotated and scaled via SceneNodes. Ray and height queries are provided for local space and world space.
    There is a setMaterial function which sets the specified material on each Patch, however you can also access each Patch and assign a custom material which can be useful for some specialised needs.
    Terrain also has functions to set neighbours for LOD calculation. Especially important for paging solutions on top of Terrain.

    Seeing as TerrainPatch is probably not a MovableObject, Terrain is responsible for actually culling invisible TerrainPatches. Therefore, the scene manager only culls the terrain as a whole while ETM will determine which parts of the terrain to actually render. This should allow for some terrain optimised culling independent of the scene manager used. Also, there will be hooks to intercept on the culling. For example, if you are doing an RTS and have a fog of war implementation, then you can additionally cull some Patches because they are not explored yet.
  4. Brushes
    Brushes in this context are actually just plain 2D arrays except that they also have a scale.
  5. Deformation and height updates
    This functionality is provided by separate functions. There are basic deform and setHeight functions which work on Array2DInterface. Basically they update one array by another. With this you can update vertices directly like you do now.
    A more advanced set of functions will instead operate with Terrain and Brush. Here you specify the actual terrain position where you want to update, and the updates of each individual vertex will be interpolated from the Brush. So in this case, you can do non-grid updates, the Brush does not need to conform to the Terrain's array structure, it can actually have a different scale (of course, updates are still only as detailled as your terrain vertices).[/*:m][/list:u]

    Does that sound reasonable to you?


25-01-2008 18:10:49

Sounds great so far! The Array2D class will contain convenience methods to populate its data from .raw or .png images, right? The SubArray2D sounds like a good idea, it will allow users to grab sections of the heightmap data and use it for whatever purpose. (I will need to test PhysX with a full heightmap based shape, or per patch shapes. Likely depends on the size of my scene, which has not been determined yet)


25-01-2008 18:25:02

Probably not contain, they will be provided as non-member functions, just like now. Array2D will have constructors to initialise from float* and vector<float>, and these functions will use that.

I forgot to mention, but the new approach would allow to specify an update rate for the terrain, i. e. updates are only carried out every fifty milliseconds or so instead of every frame (when doing continuous deformations). Right now you have to do that yourself. That should reduce CPU overhead some.