Parser module
JSON serialization/deserialization, the darts plugin factory, and scene parser.
JSON
JSON is a human-readible data interchange format for expressing attribute-value pairs. You can read more about it here:
Darts relies on the great nlohmann-json C++ library for parsing and manipulating JSON data.
In darts, we will use JSON for two purposes:
- As a generic way to pass named parameters to functions
- As a way to specify and load text-based scene files
Darts already supports serializing all the basis darts data-types (such as floats, strings, Vec, Color3, etc.) to and from a JSON object. Additionally, most of the constructors for ray tracing classes in darts take a single JSON object as a parameter. This allows us to have a uniform interface for creating these structures while allowing the constructors to retrieve the necessary values from the JSON object. This dramatically simplifies our code for writing a parser for reading scene files from disk.
darts_tutorial1.cpp
provides a gentle introduction to this functionality and nlohmann-json website provides extensive documentation.
Plugins and factories
Darts relies on a Factory pattern a automatically register new plugins that extend its functionality. Dart plugins are simply classes that extend a few abstract base classes within darts, such as Material, Surface, and later we will also introduce Texture, Integrator, Sampler, and more.
Registering plugins
Whenever you are adding a new plugin to darts, you will call the macro #DARTS_REGISTER_CLASS_IN_FACTORY, which creates some code that informs a global #DartsFactory how to create objects defined by your plugin. For instance, if we were adding a hypothetical SuperAwesome Material to darts, we would include:
DARTS_REGISTER_CLASS_IN_FACTORY(Material, SuperAwesome, "super-awesome")
at the bottom of our implementation file for the plugin. This informs darts about a new #Material of type SuperAwesome, and associates the keyword super-awesome
with it. This allows us to create such a Material in other parts of darts (or from a file on disc) without ever having to #include
a header for that plugin. We can simply call the function #DartsFactory<Material>::create(). This function accepts a #json object as a parameter, and returns a shared_ptr to a Material. It determines the specific Material class to create by looking for a "type" field in the json object. If the value is "super-awesome" it will create our SuperAwesome Material for us.
More generally we will use #DartsFactory<Type>::create() with different classes for the Type, such as Surface, Texture, etc.
Registering instances
It is often necessary to have one element in a scene refer to another one by name (for instance, if we'd like to load a texture and use it to texture more than one Material). Each JSON plugin specification can therefore contain an optional "name":
field. Latter parts of the JSON file can refer to that instance by this name. To facilitate this, #DartsFactory::register_instance() allows storing previously parsed/created instances into a registry. These can later be retrieved by name using #DartsFactory::find(). The darts basecode already has an example of how to accomplish this for Materials in the #Scene::parse() function, but you may want to add similar functional for other types of plugins as you extend darts.
An example JSON specification
In addition to the "type":
and "name":
fields, plugins may require any number of additional parameters which can be specified using additional fields in the #json object. A full specification of our hypothetical SuperAwesome Material might look as follows in JSON:
"materials": [ { "type": "super-awesome", "name": "my awesome material", "fuzziness": 1.5, "color": [1, .2, .7], "awesomeness-factor": 1000 } ]
The constructor for SuperAwesome would then be responsible for retrieving the values from the #json object and appropriately initialize the material.
The darts scene parser
You will be implementing the top-level darts parser in Scene::parse(). It takes a json object which contains the contents of a json file loaded from a disc.