Data Manager

The data manager is also a singleton in the HOOPS Luminate cluster, like the resource manager is. The data manager is directly accessed from the resource manager using RED::IResourceManager::GetDataManager.

The data manager implements the RED::IDataManager interface and is in charge of controlling the life cycle of all data loaded through .red files. It’s not used for any other purpose than managing loaded scenes and data from .red files. Details on loading .red files can be found here: Loading .red Files.

Data Manager Contexts

The data manager operates using contexts. Contexts are retrieved after loading .red files using the RED::IREDFile interface. Any RED::IREDFile::Load method returns a list of contexts corresponding to the loaded file contents: this list of contexts is the foundation of all operations with the RED::IDataManager.

All data manager access methods will use a source context.

A context in the data manager is just a number. An unsigned int. However, to ease the manipulation of a context, an ID can be associated to a context to provide it a name as this can be done for any RED::Object. The RED::IDataManager::SetContextID, RED::IDataManager::GetContextID, and RED::IDataManager::FindContext provide all the necessary tools to perform an association between a context number and an application ID.

A data manager context is used to retrieve the data loaded from a .red file. It retrieves all the data that were associated to the context at the time the .red file was written. Therefore, for a single .red file, several contexts can be returned (this is always the case for animated .red files). On loading several .red files, each file will receive different context numbers, depending on what was loaded before and on the contents of the file.

Therefore, context numbers are not persistent. Loading several files in a different order will lead to different context numbers returned for each of these files.

Multi Threaded Data Manager Usage

The data manager should be used from the application writer thread, and only from that thread. Of course caution must be taken if .red file loading has to occur in parallel to a draw. In this case, the RED::StreamingPolicy::SetLocalImages must be activated to avoid having image loading operations that take place in parallel with the draw (which will result in RED_WORKFLOW_ERROR returned by the RED::IREDFile::Load method).

Data Stored by a Context

The context number can be used to query the data manager to retrieve all the contents that were recorded for it. This includes:

  • Animation tracks

  • Images

  • Fonts

  • Materials

  • Cameras

  • Scene graphs

  • Miscellaneous objects

API methods are quite straightforward for all categories listed above but for animations that are detailed below.

Accessing Animated Data

The .red file can store animated data. Scene graph animations, object deformations are covered by the storage capabilities of the .red file format. Therefore, the RED::IDataManager delivers methods to replay an animation:

Replaying an Animation using the Data Manager

// Access the cluster's resource manager:
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();
const RED::State& state = iresmgr->BeginState();

// Access the data manager:
RED::Object* datamgr = iresmgr->GetDataManager();
RED::IDataManager* idatamgr = datamgr->As< RED::IDataManager >();

// Load a file ('ifile' is our RED::IREDFile handler, assuming we have saved one animated scene graph in it):
RED::StreamingPolicy policy;
RED::FileHeader fheader;
RED::FileInfo finfo;
RED::Vector< unsigned int > context;
RC_TEST( ifile->Load( "./my_file.red", iresmgr->GetState(), policy, fheader, finfo, context ) );

// Access the scene graph at frame 0, and add it to a camera:
RED::Object* root;
RC_TEST( idatamgr->GetSceneRoot( root, context[0], 0, state, 0 ) );
RC_TEST( icamera->AddShape( root, state ) );

// Query the length of the animation:
unsigned int frames_count;
RC_TEST( idatamgr->GetFramesCount( frames_count, context[0] ) );

// Access the scene graph for each frame of the animation. 'root' is modified in-place and does not
// need to be reassigned into 'icamera'. The engine will update the scene graph automatically:
for( unsigned int i = 1; i < frames_count; i++ )
{
    RC_TEST( idatamgr->GetSceneRoot( root, context[0], 0, state, i ) );
}

The loaded .red file returns the context number to be used by the application. In the example, we assume that we have one context in ‘context[0]’ that corresponds to our loaded animated scene graph. Once the scene graph root has been retrieved and added to a viewpoint for the display, updating the animated scene graph is simply performed by accessing the scene graph root again, but using another frame counter indicator.

Note

This task does not cover hierarchical imbricated animations for which a RED::IDataManager::RestoreTracksHierarchy call needs to occur.

Releasing a Context

The RED::IDataManager::ReleaseContext method can be used to free all the loaded informations from memory. This is a transactional operation, that will release all shapes, fonts, images, and other resources using the public HOOPS Luminate APIs. Therefore, this means that images released by the context are immediately destroyed. This don’t cause any problem, as all objects that were using these images are also released with the context destruction operation.

Nevertheless, if the calling application still points onto loaded data after the RED::IDataManager::ReleaseContext call, the application may crash.