3.3 On-demand or View-dependent Streaming

For large models, it is sometimes desirable to stream in only those parts which either the user wants to visualise or parts in the current view. This is especially the case when the model files are shared in a network environment and are accessed by various clients with bandwidth limitations.

Implementing this functionality requires the ability to access the .hsf file randomly and the file layout information. A .hsf file dictionary is a lookup table, providing the file offsets, bounding information etc. to specified items and their variations. Before attempting to selectively stream a file, you must ensure that the file was written out with the dictionary. This is demonstrated by the following code.

// Parse the File Header (TKE_Comment) opcode first
// Parse the next opcode which is TKE_File_Info
TK_Status status = tk->ParseBuffer (stream_data, data_size, TK_Single);
if (status == TK_Complete)
{
if((tk->GetWriteFlags() & TK_Generate_Dictionary) == TK_Generate_Dictionary)
{
// dictionary present, can do selective streaming
}
}

The next task is to read the dictionary itself. To find out the location of the dictionary in the file, read the last 5 bytes of the file. The last byte of these 5 bytes is the #TKE_Termination opcode and the preceding 4 indicate the file offset of dictionary. Following source code provides an example.

// read the last 5 bytes
char data[5];
int amount_read = 0;
tk->PositionFile(-5);
tk->ReadBuffer(data, 5, &amount_read);
// minor sanity check -- last byte should be TKE_Termination
if (data[4] != TKE_Termination)
return Error ("file does not end correctly");
// get the dictionary offset
int dictionary_offset;
memcpy (&dictionary_offset, data, sizeof (int));

Having the offset of the dictionary, reading it directly is quite easy. Position to the dictionary offset and read till the end of the file. Let us discuss how the information contained in the dictionary can be used to achieve selective streaming.

// find out the offset of the entity to stream
TK_Status status = tk->LocateEntity(shell_key, lod_level);
assert(status == TK_Normal);
// get an estimate of size of entity to stream
int offset = 0;
int entity_size = 0;
status = tk->GetOffset(shell_key, lod_level, offset, entity_size);
if (entity_size != 0)
{
// read the entity data and parse it
int amount_read = 0;
char * buffer = new char[entity_size];
tk->ReadBuffer(buffer, entity_size, amount_read);
tk->ParseBuffer(buffer, entity_size, TK_Single);
}