lilith3d

 

Engine

Documentation

Notes

Architecture

Lilith3D

Lilith3D is the main class of the system. It manages the TerrainMesh, MOBs (mobile objects), and particles. It has methods to draw, get access to the weather, camera, particle systems, and much more functionality.

  • Get a pointer to the Lilith3D object: Instance()
  • Drawing
    • BeginDraw()
    • Draw()
    • EndDraw()
    • usually followed by SDL_GL_SwapBuffers()
  • Access other key control objects
    • GetTerrainMesh()
    • GetTerrainDecor()
    • GetTimeClock()
  • Add a sequence
  • Query the weather
  • Control rendering options
    • RenderMode()
    • RenderFoliage()
    • RenderShadows()
    • PerfDataDisplay()
    • MapSize()
    • SetInfoDisplay()
  • ScreenCapture()
  • Intersection*() functions
  • Query particle systems
  • Move the camera

Camera

With version 1.1.0, Lilith has a very flexible quaternion camera. It's interface is specified in yaw and pitch ("human" coordinates) but all interpolation is done with full rotation matrices and quaternions. The following basic design applies to the camera:

  • Lilith uses a right handed coordinate system for everything, including the camera
  • The terrain is in the XY plain, and height is positive Z
  • The default camera view is looking down the positive X axis. Left is the positive Y axis, and up is the positive Z axis.

When positioning the camera, human coordinates are used. Under the covers it's all quaternions, and if you need to access them directly, it is straightforward.

  • "Yaw" is rotation around the Z axis. A positive yaw is to the left, a negative to the right. Yaw is always measured around the Z axis even after it has been transformed.
  • "Pitch" is rotation around the local Y axis. up & down rotation. A positive pitch is forward (down) and a negative pitch is backward (up).

TerrainMesh

The TerrainMesh is the core of the engine. All the other classes assume the existence of terrain.

The basic unit of measurement of terrain is a "grid". The grid size is a power of 2 - in the demo, the grid size is 256. Image a giant chessboard of 256 by 256 squares, and that is the game world to lilith. The corner of each square has a height.

At its heart then, the terrain mesh is a height field. For a grid of 256x256, it uses 257x257 vertex heights. In order to cut down on rendering time (and pathing time), the engine dynamically changes the level of detail to meet a consistent quality criteria. Lilith will use as many polygons as needed to hit the quality threshold; therefore, smoother terrains use fewer polys that jaggy terrains do.

LOD

In version 1.5+

Lilith3D 1.5 uses a simple system for LOD. It groups 4 grids (2x2) into a "patch", and can render a patch with 4-8 polygons, as needed. When RENDER_LOD is on, the color now reflects the number of tris in a patch.

Why switch to a simpler system from the previous system?

  1. Easier to animate. It's hard to get smooth animation while changing up LOD drastically.
  2. Pathing. This was really the death knell of the prior systems. Pathing over variably sized patches is a nightmare to compute, and then you end up with paths that don't look very good. Also, reserving areas for buildings was complex.
  3. Code complexity. The prior system was too hard to change, add features, and work with the pathing. I needed a more flexible solution.

What's the performance impact? None, anymore. The initial

Prior to 1.4

Lilith uses a level of detail system to maintain a constant quality. The target level of quality can be set in worlddefine.h.

A view of the terrain. This particular section is created to achieve an artificially high LOD reduction in order to test the engine.
The exact same view, this time colored to show the LOD. Error is consistent: red takes the most polygons to achieve acceptable quality, yellow less, green even less, and blue very few.

The exact same view, this time showing the outlines of the triangles. Here you can see the LOD, and the subdivision used to avoid cracks in the mesh.

Note that neighboring polygons can be at any level of detain with respect to one another.

 

Why not use ROAM? I started with a ROAM algorithm, and it had problems, for this application, that I just wasn't happy with:

  1. Popping. ROAM terrain "pops" as the level of detain changes. This situation is exasperated by Lilith's use of dynamic terrain (sand/snow/grass) and lighting which made the popping more noticeable.
  2. What is the real height? To accurately position models on the terrain, Lilith computes the terrain height from the LOD mesh, not the height field. With ROAM, modes (and trees and buildings) jumped up and down over distance.

There's more that could be done in Lilith to have more terrain in the far distance.

As terrain changes, in response to terrain morphs, the polygons are changed to keep a consistent level of detail. The engine updates the smallest area of the world possible.

Terrain Textures

There are several approaches to texturing the terrain. Lilith repeats small textures over the terrain. (As opposed to the common approach of stretching a big texture over the whole terrain.)

Shaders are just wonderful. Lilith3D uses a GLSL shader program to generate the terrain, compute the light, and mix the textures. GLSL support is required for Lilith3D to run, and now is the exclusive terrain rendering option.

(In prior versions Lilith3D supported a multi-pass renderer on the fixed pipeline. It was an interesting experiment to sync up the two systems, but was just too much code to keep in sync.)

Pather

The pather is based on an A* algorithm. A walking MOB moves across the world, and can move across polygons that are above water. Objects move slower over snow and steep slopes, and the pather accounts for this.

As a MOB walks the terrain, it speeds up or slows down based on how flat the terrain is, and whether there is snow.

A typical chunk of terrain.

A view of the terrain that shows passable triangles (blue) and impassable ones (red). Most triangle are impassible due to high slopes.

 

A path - minimum distance - between 2 points on the terrain.

Archived Notes

Older version info:

Tree Rendering