A RenderWare Graphics's chunk ID is incorporated into the RtTOCEntry to identify the chunk that the entry refers to.
An offset, in bytes, from the beginning of the stream to the entry's chunk header is also provided in the RtTOCEntry. This enables the application to read the stream non-sequentially to find particular chunks. Since this offset is from the beginning of the stream, the stream must be closed and re-opened in order to use the offset with RwStreamSkip. Note that after the skip has been applied, the chunk should be read as if it had been found sequentually.
Since there may be multiple instances of the same chunk ID in the TOC a method of distinguishing one instance from another is required. The RtTOCEntry also carries a GUID and a gid (game ID) that can be used to this end. The RenderWare Graphics exporters assign GUIDs to assets when they are exported and their value displayed in the output window.
In this tutorial we define a callback function that takes an RtTOCEntry and either accepts or declines it. If the entry is accepted, the chunk can be read. If it is declined, the next RtTOCEntry is processed.
In the utils.h file, define this callback function type
typedef RwBool (* AcceptTOCEntryCB)( RtTOCEntry *tocEntry );
TRUE to accept it, or FALSE to decline it.
Now implement the function RwsLoadWorldFromTOC in utils.c:
RpWorld * RwsLoadWorldFromTOC( RwChar *filename, RtTOC *toc, AcceptTOCEntryCB acceptTOCEntry ) { RpWorld *world; RwInt32 idx; world = (RpWorld *)NULL; for ( idx = 0; idx < RtTOCGetNumEntries( toc ); idx += 1 ) { RtTOCEntry *tocEntry; tocEntry = RtTOCGetEntry( toc, idx ); /* we're only interested in worlds */ if ( rwID_WORLD != tocEntry->id ) { continue; } /* is this the world we want? */ if ( FALSE != acceptTOCEntry( tocEntry ) ) { RwChar *pathName; RwStream *stream; RwChunkHeaderInfo chunkHdrInfo; pathName = RsPathnameCreate( filename ); if ( NULL == pathName ) { return (RpWorld *)NULL; } stream = RwStreamOpen( rwSTREAMFILENAME, rwSTREAMREAD, pathName ); /* skip through the stream using the TOC entry's offset */ RwStreamSkip( stream, tocEntry->offset ); /* read the chunk as if we'd found it sequentially */ if ( NULL != RwStreamReadChunkHeaderInfo( stream, &chunkHdrInfo ) ) { world = RpWorldStreamRead( stream ); } RwStreamClose( stream, NULL ); RsPathnameDestroy( pathName ); break;
}
}
return world;
}
utils.h.
RwsLoadWorldFromTOC loops over the entries in the TOC, ignores non-world chunks, and for each world chunk, passes the appropriate TOC entry to the application specified callback. If the TOC entry is accepted, the world is subsequently read by opening the stream and skipping to the appropriate position.
The chunk's header can be read either by RwStreamFindChunk with the rwID_WORLD argument or, as shown above, by RwStreamReadChunkHeaderInfo that assumes the stream is positioned correctly to find a chunk header.
Now in main.c we need to write the TOC entry accept callback function, and use the TOC related functions to read the world from the stream. The callback function for this tutorial is very simple as the .rws file contains just a single world, hence the first one encountered is accepted.
static RwBool acceptFirstWorld( RtTOCEntry *tocEntry ) { return TRUE; }
RwsLoadWorld in Initialize3D with the RwsLoadWorldFromTOC function.
Initialize3D(void *param) { RtTOC *toc; if( !RsRwInitialize(param) ) { RsErrorMessage(RWSTRING("Error initializing RenderWare.")); return FALSE; } Charset = RtCharsetCreate(&ForegroundColor, &BackgroundColor); if( Charset == NULL ) { RsErrorMessage(RWSTRING("Cannot create raster charset.")); return FALSE; } /* Get the TOC from the RWS file */ toc = RwsLoadTOC( "models/tutorial5p.rws" ); if ( NULL == toc ) { /* no TOC, so just load the first world found */ World = RwsLoadWorld( "models/tutorial5p.rws" ); } else { World = RwsLoadWorldFromTOC( "models/tutorial5p.rws", toc, acceptFirstWorld ); RtTOCDestroy( toc ); } if( World == NULL ) { RsErrorMessage(RWSTRING("Cannot create world.")); return FALSE; } /* Create the lights */ CreateLights();
RwsLoadWorld function is still used if the TOC, for any reason, is not present in the .rws file.
Compile the code. Before you can link this project, you will need to add the rttoc.lib library to the project.
Put a breakpoint on the call to RwsLoadWorldFromTOC. Debug the application to test that the TOC loading code is working.
© 1993-2004 Criterion Software Limited. All rights reserved. Built Thu Feb 12 13:47:00 2004.
Send Feedback