Solar System Demo & Transforms

Solar System Demo & Transforms

- 7 mins

Summary

Welcome to the fourth entry following the creation of a rendering abstraction layer within a custom data-driven game engine! Past entries can be found on my blog or through the links found at the bottom of this post.

As a reminder, in the last entry, I described my initial implementation of an asset management pipeline, including an implementation of a Model class that represents the physical properties of an Entity object in my engine and a Transform class to support it. This past week saw those implementations put to the test as I demonstrated rendering the solar system within the engine using DirectX11.

Solar System Demo

Solar System Demo.

Data-Driven Solar System

Utilizing the data-driven capabilities of the engine, I exposed the properties of the solar system demo through a SolarSystem class derived from Entity, allowing configuration through JSON. Below is an example of the JSON used to change the unit scale and time scale factors of the demo.

1
2
3
4
5
6
7
8
9
10
{
  "DistanceScale": {
    "type": "float",
    "value": 80.0
  },
  "TimeScale": {
    "type": "float",
    "value": 0.3
  }
}

However, the data-driven aspects did not stop there. In fact, the entire solar system hierarchy was generated from JSON, exposed through the SolarBody class, inherited from Actor to take advantage of the embedded transform.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
  "Sun": {
    "type": "SolarBody",
    "value": {

      "Mercury": {
        "type": "SolarBody",
        "value": {}
      },
      "Venus": {
        "type": "SolarBody",
        "value": {}
      },
      "Earth": {
        "type": "SolarBody",
        "value": {
          "Moon": {}
        }
      },
      "Mars": {
        "type": "SolarBody",
        "value": {}
      },
      "Jupiter": {
        "type": "SolarBody",
        "value": {}
      },
      "Saturn": {
        "type": "SolarBody",
        "value": {}
      },
      "Uranus": {
        "type": "SolarBody",
        "value": {}
      },
      "Neptune": {
        "type": "SolarBody",
        "value": {}
      },
      "Pluto": {
        "type": "SolarBody",
        "value": {}
      }

    }
  }
}

Finally, each solar body had configurable properties exposed to the reflection system to more accurately simulate the appearance, orientation, and astrological movement of each.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"Earth": {
  "type": "SolarBody",
  "value": {

    "ColorMap": {
      "type": "string",
      "value": "Textures/EarthComposite.dds"
    },
    "SpecularMap": {
      "type": "string",
      "value": "Textures/EarthSpecularMap.png"
    },
    "Diameter": {
      "type": "float",
      "value": 1.0
    },
    "OrbitalDistance": {
      "type": "float",
      "value": 1.0
    },
    "OrbitalPeriod": {
      "type": "float",
      "value": 1.0
    },
    "RotationPeriod": {
      "type": "float",
      "value": 1.0
    },
    "Tilt": {
      "type": "float",
      "value": 0.41
    },

    "Moon": {
      "type": "SolarBody",
      "value": {}
    }
  }
}

Reworked Transform Class

To support the hierarchical nature of the solar system, the Transform class was completely reworked. Previously, the class was mainly a wrapper for a OpenGL Mathematics matrix (glm::mat4x4). However, this made it difficult and inefficient to break the transform class into its separate components, translation, rotation, and scale.

So, to solve this, the class now stores these components:

This both simplifies single type transformations to just vector arithmetic, preventing unnecessary matrix transformations, and allowed for easy access to each component without requiring matrix decomposition.

However, as purely components, when a full transformation matrix was needed, matrix composition was required. While a fairly simple task given, I saw an opportunity to maintain some of the performance granted by the previous implementation.

By maintaining the inner matrix as a cache that stores the result of the last matrix composition, combined with the dirty flag pattern, I was able to still have direct access to the underlying transformation matrix as in the previous implementation, as long as no transformation has occurred, a reasonable compromise in my opinion.

Rendering API Interface

With the integration of the rendering framework from the examples created by Dr. Paul Varcholik for his book Real Time 3D Rendering with DirectX and HLSL, I reached the point where the initial implementation of the rendering abstraction layer was needed to prevent dependencies on DirectX in API agnostic engine code.

As the initial implementation, I created the RenderingManager class as an interface that declares structs and pure virtual method prototypes for wrapping rendering API data types and functionality respectively.

Then I created RenderingManager_DirectX11, as a derived class from RenderingManager that implements the structs and pure virtual methods using DirectX11 data types and functions. This derived class is then defined alongside a corresponding preprocessor definition, preventing the need for DirectX11 support in programs that cannot, or do not, wish to include it.

In practice, this allows for the World class to maintain a reference to the current RenderingManager instance. This reference can then be passed within the WorldState down the Entity hierarchy, enabling components to access the rendering interface without dependencies on DirectX.

Rendering Manager

Rendering Manager design.

Next Steps

As a next step, I plan to migrate the content manager, material, and shader system borrowed from the framework by Dr. Paul Varcholik to native engine implementations, expanding the functionality of the RenderingManager interface along the way.

Additionally, I plan on improving the Actor class to natively support local and world transforms, a limitation that became apparent when implementing the solar system demo.

Thank you for reading! I hope to see you again next week for another update.

Logan Harvell

Logan Harvell

Graduate student at UCF FIEA, M.S. in Interactive Entertainment

comments powered by Disqus