Game Engine Architecture

(Ben Green) #1

296 6. Resources and the File System


We sometimes use the term composite resource to describe a self-suffi cient
cluster of interdependent resources. For example, a model is a composite re-
source consisting of one or more triangle meshes, an optional skeleton, and an
optional collection of animations. Each mesh is mapped with a material, and
each material refers to one or more textures. To fully load a composite resource
like a 3D model into memory, all of its dependent resources must be loaded
as well.

6.2.2.9. Handling Cross-References between Resources
One of the more-challenging aspects of implementing a resource manager is
managing the cross-references between resource objects and guaranteeing
that referential integrity is maintained. To understand how a resource man-
ager accomplishes this, let’s look at how cross-references are represented in
memory, and how they are represented on-disk.
In C++, a cross-reference between two data objects is usually implemented
via a pointer or a reference. For example, a mesh might contain the data mem-
ber Material* m_pMaterial (a pointer) or Material& m_material (a ref-
erence) in order to refer to its material. However, pointers are just memory
addresses—they lose their meaning when taken out of the context of the run-
ning application. In fact, memory addresses can and do change even between
subsequent runs of the same application. Clearly when storing data to a disk
fi le, we cannot use pointers to describe inter-object dependencies.

GUIDs As Cross-References
One good approach is to store each cross-reference as a string or hash code
containing the unique id of the referenced object. This implies that every re-
source object that might be cross-referenced must have a globally unique identi-
fi er or GUID.
To make this kind of cross-reference work, the runtime resource manager
maintains a global resource look-up table. Whenever a resource object is load-
ed into memory, a pointer to that object is stored in the table with its GUID as
the look-up key. Aft er all resource objects have been loaded into memory and
their entries added to the table, we can make a pass over all of the objects and
convert all of their cross-references into pointers, by looking up the address
of each cross-referenced object in the global resource look-up table via that
object’s GUID.
Pointer Fix-Up Tables
Another approach that is oft en used when storing data objects into a binary
fi le is to convert the pointers into fi le off sets. Consider a group of C structs or
C++ objects that cross-reference each other via pointers. To store this group
Free download pdf