User Tools

Site Tools

File Loading Interface

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
        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:

  • When a file is loaded via LoadFile(), a hint is passed about whether the SDK needs the returned memory block for long or short term. For example, a short term load might be a texture that's simply being uploaded to the GPU and flushed. A long term load might be an SRT file, depending on usage.
  • Note that because most of the SDK's resources use search paths, FileExists() may be called several times for a single load. This is the SDK's way of determining which of the search paths contains the requested file.
  • Use CleanPlatformFilename() to provide a filename formatted for a given platform. Some platforms, like the Xbox 360, can be very sensitive to mixed forward and backslashes, or not support “../”. This overridable function attempts to create a clean filename for the compiled platform (#ifdefs are used internally to determine the platform).

Using the Interface

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).