top of page
Search
Gio Aleman

JSON Scene Loading

For game engines, it’s always useful to have a way to save a load scenes, that way it’s easier to prepare and test gameplay and to design levels. For our engine, we wanted to go with a common file format instead of using a custom one, as well as wanting something that’s easy to read and write. With these requirements in mind, we decided the best format to use would be JSON. JSON is a very simple format to understand and write, and saves us a lot of time from writing a custom format, especially since parsers for JSON already exist. After some research, we settles on the rapidjson library. This library has the advantage of parsing JSON very fast, as well as being a header only library, making it very easy to integrate.

With our library chosen, it was time to decide how the scenes will be formatted. Currently, our engine is loading meshes and materials and now needs to load scenes. Currently, each mesh contains a material. Since our engine uses the ECS design, the planned design for scenes would be to create a list of entities, add each component of the each entity, and set their data properly. Because of these requirements, it made sense to make several different types of JSON files. Scenes, materials, and meshes all have their own files, since they all rely on external resources. With this design, each scene would load the required meshes by reading their JSON file, and each mesh would load the material it uses by reading the materials JSON file. This lead to a simple structure for files, along with the benefit of some optimizations when loading resources.


THE FILE TYPES:

The material file is fairly simple one. Since we plan to use a metallic-based PBR pipeline, the material JSON file loads the five required textures: Albedo, roughness map, normal map, metallic, and ambient occlusion. Below is an example of a what a basic material file might look like.

The file simply contains five properties, one for each of the required textures. Each property contains a string for a value referring to the location the texture is located in relation to the executable. With the materials file, we can now look at what the mesh file looks like.

As you can see, the mesh file is even simpler than the mesh file. The first property is the path to the actual mesh file, in this case an FBX. The second parameter is a string containing the path of the material JSON file. This is one of the areas of optimization. Once the engine reads the material file, it stores the material in a map using the path of the material. That way, if a mesh requires the same material, there is no need to re-read the file, and the mesh can just point to the required material. Finally, there is an “instances” property that contains the number of instances of the mesh in the scene. This is another small optimization. Since our engine uses instanced rendering, the meshes need to gather all the world matrices of an object being drawn. By passing saving and reading the instances from a file, we can know the max amount of instances that the mesh will have, letting us pre-allocate the vector of world matrices, avoiding any re-allocations during runtime. Since our game won’t contain many entities that are constantly deleted and destroyed (such as bullets), there isn’t really a concern about trying to pre-allocate an array for objects that won’t exist for long.


Finally, there are scene files. Scene files are the most complex of the files, requiring a lot more information within them. Scenes are stored as a list of entities with a transform and their component. Below is an example of a scene with one entity.

As you can see, all the entities are kept in an array, similar to how they will be kept track of in the engine. Each entity is a member of the array and contains a transform, and any components it may have. In this case, the entity only contains a single render component. The transform is 16 float values that are read into the engine and decomposed to find the position, rotation, and scale of the object. The render component contains a mesh property that links to the required mesh JSON file. Similar to materials, this is a small optimization that allows us to store the loaded mesh after loading it once. If another entity requires the same mesh, the entity can point to it instead of loading it again. Currently, we only have render components in the engine, however, the format will expand with each component added, requiring the implementation to expand as well.


As we progress with our engine, we will continually need to update the format and JSON parsing. As noted, we will need to add more components to the engine in the future. However, we will also need to add the ability to have parent child relationships for our scene current. Since entities are kept in an array, our current plan is to add a “children” array for each entity that contains the index of each of the entities children.

4 views0 comments

Recent Posts

See All

Comentarios


bottom of page