.z3d file format blocks identifiers

File      : API\core\io\zmIOTypes.h
Namespace : core::io
#define Z3D_ID_DECLARATION              0x4C434544 //"DECL"
#define Z3D_ID_DATA                     0x41544144 //"DATA"
#define Z3D_ID_THUMBNAIL                0x424D4854 //"THMB"
#define Z3D_ID_FILEINFO                 0x4F464E49 //"INFO"
#define Z3D_ID_SUBSTREAM                0x54534253 //"SBST"

#define Z3D_ID_END_OF_FILE              0x46444E45 //"ENDF"

// ZModeler v2.x file signature:
//#define Z3D_FILE_SIGNATURE          0x53324D5A  //ZM2S

Description

Chunk identifiers for .z3d files. These are the only chunk identifiers used, while the rest of data is encapsulated in "DATA" chunks. Each chunk starts with chunk header:

//header:
{
  DWORD     m_dwType;     //chunk ID (one of Z3D_ID_* values)
  DWORD     m_dwID;       //chunk unique ID (inside .z3d file)
  DWORD     m_dwVersion;  //chunk version (any format you like)
  DWORD     m_dwSize;     //size of data, followed by this header
};

And followed by chunk-specific data. For example, Z3D_ID_THUMBNAIL is followed by pure JPEG image data (size is m_dwSize bytes) which represents thumbnail image.

Values are
Z3D_ID_DECLARATION
Declaration block. Followed by creation mode value, String: fully-qualified class name, String: serializeable resolver for this class. Each declaration is associated with one class instance (this class instance can support multiple interfaces, of cause) and m_dwID of this declaration is then associated with controlling unknown of this class. When loading or saving .z3d file all declarations are written before any DATA chunk appears. Thus, when interfaces start to load their data, they can refer to other interfaces by their ID (these unique values are stored in .z3d to identify interfaces in a file) and be sure that all interface instances are already created.
Z3D_ID_DATA
Data for an interface with the same m_dwID value. While loading .z3d file, ISerializeable::loadData method is called to allow interface to load it's data.
Z3D_ID_THUMBNAIL
Thumbnail image chunk. It can be missing in file, but if it's present, its followed by pure JPEG image data.
Z3D_ID_FILEINFO
File information chunk. File information is used purely by ZModeler's file open/save dialog box, but you can use it too by quering core::io::IFileInfo interface on services::IOpenSaveService for currently selected file.
Z3D_ID_SUBSTREAM
Chunk that identifies a sub-streaming block. Data of this chunk can only be read by another stream interface and requried information follows after chunk header: String: [fully-qualified stream class name], and long: [dataLength for substreamed class]. Substream is created on a reading stream with subStream method, limited with length of chunk (minus sizeof(long), and size of written string: class name of a stream). The dataLength is set to substream with setLength method. See an example below.
Z3D_ID_END_OF_FILE
End of file. No data contained in this chunk and no data will be read after this chunk.

Substream example

.z3d files can contain substreams in it. The most common case is a core::io::CZIPStream substream block which encapuslates all file data into it's own single ZIPped block. Substream is limited with chunk data size and long dataLength written right after a class name is an uncompressed data size.

//
// code fragment; chunkInfo is a chunk header as shown above;
//
if (chunkInfo.m_dwType == Z3D_ID_SUBSTREAM) //substream chunk found;
{
  ZPtr<core::io::IStream> pSubst;
  long nDataLen = 0, nCLen = 0;
  ZString strClass;
  pInStream->read(&nCLen, 4); //length of classname string
  strClass.length(nCLen);
  pInStream->read((LPSTR)strClass, nCLen);
  pInStream->read(&nDataLen, 4);  //dataLength for substreamed class
  //create substream on supplied stream:
  if (ZRESULT_OK != createSharedClass(strClass, 
                                      IID_(core::io::IStream), 
                                      (void**)&pSubst))
    ::ShowMessageDirect(core::MT_ERROR, 
                        _T("Failed to create substream \"%s\"."), 
                        (LPCTSTR)strClass);
  else
    if (ZRESULT_OK != pSubst->subStream(pInStream, 
                              chunkInfo.m_dwSize-4-nCLen-4) ||
        ZRESULT_OK != pSubst->setLength(nDataLen))
      ::ShowMessageDirect(core::MT_ERROR, _T("Failed to substream."));
    else
    {
      seqSubStreaming.add(pInStream);//backup previouse stream;
      pInStream = pSubst; //set substream as current
      continue;//and read from substream
    }
}
//end code fragment;
//
See Also:
overview of namespace core::io
core::io::ISerializeable interface
services::IOpenSaveService interface