The SpeedTree SDK makes several reads from the host platform's file system (e.g. reading textures, tree models, and shaders), but every access is routed through an overrideable interface, giving the client application a chance to intercept the request and provide the file data through a custom implementation (while it is not ideal for a middleware product to make direct I/O calls, this can prove useful during early stage of development). Most commonly, games may have one or more large files that house a conglomeration of different files, compiled together when packaging the game's assets.
Specifically, the following class interface is available to be overridden:
/////////////////////////////////////////////////////////////////////// // class CFileSystem class CFileSystem { public: enum ETermHint { SHORT_TERM, LONG_TERM }; virtual st_bool FileExists(const st_char* pFilename); virtual size_t FileSize(const st_char* pFilename); // returns size in bytes virtual st_byte* LoadFile(const st_char* pFilename, ETermHint eTermHint = SHORT_TERM); virtual void Release(st_byte* pBuffer); virtual CFixedString CleanPlatformFilename(const st_char* pFilename); };
By default, the SDK provides definitions for these functions that implement standard file read()/open()-level functionality.
Some notes about this interface class:
The reference application contains a full example of how to override the CFileSystem interface in MyFileSystem.h. Once the class is defined, as in CMyFileSystem in the reference application, the SDK can be notified of it using the following approach:
// create an object of the derived file system CMyFileSystem g_cMyFileSystem; // pass that object into the SDK's CFileSystemInterface SpeedTree::CFileSystemInterface g_cFileSystemInterface(&g_cMyFileSystem);
A global variable is normally used like this to ensure that the interface is established as early as possible (before main() is invoked).