92
Interchangeable World Format v2.0 Interchangeable World Format v2.0 Standards Documentation - Rev 0 Copyright © 2002 Daedalus Developments. All Rights Reserved. Table of Contents 1. Introduction........................................................... 3 1.1. Purpose............................................................ 3 1.2. Intended Audience.................................................. 4 1.3. Compliance......................................................... 4 1.4. Changes............................................................ 4 1.5. Definitions........................................................ 4 2. What is the Interchangeable World Format?.............................. 4 2.1. Data Chunks........................................................ 5 2.2. Chunk Hierarchy.................................................... 5 2.3. Additional Features................................................ 6 2.3.1. Compression.................................................... 6 2.3.2. Error Detection................................................ 7 2.3.3. Custom Chunk Collision Prevention.............................. 8 2.3.4. Chunk Encryption............................................... 9 2.3.5. Chunk Summary Information..................................... 10 3. IWF Structure Layout.................................................. 10 3.1. File Header....................................................... 10 3.1.1. Version System................................................ 12 3.2. Chunk Header...................................................... 12 3.2.1. Calculating and Using Chunk Sizes............................. 14 3.2.2. Using Author-IDs.............................................. 14 3.3. Chunk Data Area................................................... 16 3.4. Chunk Footer...................................................... 16 3.5. Chunk Types....................................................... 18 3.6. Putting it All Together........................................... 19 3.6.1. Providing Forward References.................................. 24 3.6.1.1. File Header - Flags...................................... 25 3.6.1.2. File Header - Checksum................................... 25 3.6.1.3. Chunk Header - ChunkLength................................ 25 3.6.1.4. Chunk Header - DataLength................................. 26 3.6.1.5. Chunk Footer - EOCValue................................... 26 3.7. Supporting Chunk Encryption....................................... 27 3.8. Supporting File Compression....................................... 27 3.9. Calculating a Valid Checksum...................................... 27 Copyright © 2002 Daedalus Developments. All Rights Reserved. Page 1 of 92.

IWF Specifications v2.0.0

Embed Size (px)

Citation preview

Page 1: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Interchangeable World Format v2.0 Standards Documentation - Rev 0

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Table of Contents

1. Introduction...........................................................3 1.1. Purpose............................................................3 1.2. Intended Audience..................................................4 1.3. Compliance.........................................................4 1.4. Changes............................................................4 1.5. Definitions........................................................4

2. What is the Interchangeable World Format?..............................4 2.1. Data Chunks........................................................5 2.2. Chunk Hierarchy....................................................5 2.3. Additional Features................................................6 2.3.1. Compression....................................................6 2.3.2. Error Detection................................................7 2.3.3. Custom Chunk Collision Prevention..............................8 2.3.4. Chunk Encryption...............................................9 2.3.5. Chunk Summary Information.....................................10

3. IWF Structure Layout..................................................10 3.1. File Header.......................................................10 3.1.1. Version System................................................12

3.2. Chunk Header......................................................12 3.2.1. Calculating and Using Chunk Sizes.............................14 3.2.2. Using Author-IDs..............................................14

3.3. Chunk Data Area...................................................16 3.4. Chunk Footer......................................................16 3.5. Chunk Types.......................................................18 3.6. Putting it All Together...........................................19 3.6.1. Providing Forward References..................................24 3.6.1.1. File Header - Flags......................................25 3.6.1.2. File Header - Checksum...................................25 3.6.1.3. Chunk Header - ChunkLength................................25 3.6.1.4. Chunk Header - DataLength.................................26 3.6.1.5. Chunk Footer - EOCValue...................................26

3.7. Supporting Chunk Encryption.......................................27 3.8. Supporting File Compression.......................................27 3.9. Calculating a Valid Checksum......................................27

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 1 of 92.

Page 2: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table of Contents (cont…) 4. Standardised Chunk Specifications.....................................28 4.1. Common Types, Structures and Processes............................28 4.1.1. Vectors.......................................................28 4.1.2. Matrices......................................................29 4.1.3. Bounding Boxes................................................30 4.1.4. Palettes, Colours and Blend Modes.............................30 4.1.5. Scripts, Shaders and Effect Files.............................34 4.1.6. Object Component Architecture.................................35

4.2. Summary Chunk.....................................................37 4.2.1. Processing Chunk Statistics...................................38

4.3. Thumbnail Chunk...................................................40 4.3.1. Palettes and Image Data Formatting............................41

4.4. Group Chunk.......................................................43 4.5. Object Meshes.....................................................45 4.6. Polygon Data......................................................49 4.7. Vertex Components.................................................54 4.7.1. Vertex Pools..................................................59 4.7.1.1. Surface Pools.............................................60 4.7.1.2. Mesh Pools................................................61 4.7.1.3. Global Pools..............................................61 4.7.1.4. Mixing Vertex Pools.......................................62

4.7.2. Vertex Arrangement............................................64 4.8. Vertex Indices....................................................68 4.8.1. Index Values..................................................70

4.9. Decal Meshes......................................................72 4.10. Entities.........................................................73 4.10.1 Standard Entity Types.........................................74 4.10.1.1. Lights...................................................75 4.10.1.2. Simple Point.............................................77 4.10.1.3. Spawn Point..............................................78

4.11. Materials........................................................80 4.12. Textures.........................................................83 4.13. Shaders..........................................................87 4.14. Coordinate System Information....................................89 4.15. Standard Chunk Arrangements......................................91 4.16. Application Compliance...........................................91

5. IWF File Toolkit Version 2.0..........................................92

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 2 of 92.

Page 3: IWF Specifications v2.0.0

Interchangeable World Format v2.0

1. Introduction

The interchangeable world format, or IWF for short, is an ‘Interchange File Format’ as it’s name suggests, in the sense that, much like Microsoft’s ® RIFF™ (Resource Interchange File Format) the IWF structure is designed to store data of any custom type, and is not strictly limited to any predefined layout or design, with the exception of the interchange structure itself.

While the format does not prohibit the introduction of custom data within the file itself, and in fact can be utilised to store data pertaining to almost any application, the primary design goal of the interchangeable world format (IWF) is to provide a convenient means by which to store and retrieve data, commonly utilised by interactive multimedia applications such as computer games and any manner of associated content creation tools. For this reason, the IWF is an ideal candidate for such a task, not only because of the inherent features within file structure itself, but also due to the fact that many objects and data types, associated with such applications, have been standardised within the specification. This provides massive potential for cross-application support and content sharing, with minimal effort.

This standards document is essentially split into three distinct sections. The

first covers the actual properties, and intended use of the IWF specification. The second covers the actual structure and layout of the IWF file itself, whilst the third focuses more on the objects and data types implemented within the standards specification.

Please bear in mind that this specification is designed as a reference to be used

alongside the example import / export source code provided. There is a vast amount of information provided here that may become overwhelming should you be

attempting to develop an import or export procedure based upon this specifications document alone.

Unless otherwise noted, all aspects of this specifications document are

Copyright © 2002 Daedalus Developments, All Rights Reserved.

1.1. Purpose

The purpose of this specification is to define a flexible means by which to store a wide variety of information, including but not limited to, that used by applications involved in the field of interactive multimedia software, such as computer games, which:

• Allows easy access to all, or simply portions, of the information stored within the file. • Defines a content standard to provide support for multiple applications between non-

associated developers. • Provides as much functionality as possible, for use within a wide range of situations. • Does not restrict developers to only that which is defined by the standard. • Provides support for constantly modernising technology.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 3 of 92.

Page 4: IWF Specifications v2.0.0

Interchangeable World Format v2.0

1.2. Intended Audience

This specification is intended for use by developers of software intending to either export to, or import from the interchangeable world format, and assumes at least a basic knowledge of programming and the development of file input / output procedures.

1.3. Compliance

Unless otherwise noted, a compliant IWF import procedure must be able to successfully import any data set that conforms to all the specifications presented within this document with the exception of the standardised data chunk types. Likewise a compliant IWF export procedure must produce data sets that conform to all the specifications presented within this document with that same exception.

Please refer to section 4.16. Application Compliance for more information about the implications of, and requirements for, building a compliant import procedure.

1.4. Changes

Revision 0. There are currently no changes to list.

1.5. Definitions

• Hex Hexadecimal. Pertaining to a number system having 16 as its base. Values specified in hexadecimal always begin with the characters ‘0x’ within this specification.

• Array A linear list of identically typed data items distinguished by their indices.

• Var Variable. An object of a certain type, used to store an arbitrary value.

2. What is the Interchangeable World Format?

The format itself is not an all encompassing multimedia file format, but is in fact a hierarchical structure, designed primarily for ease of use rather than focusing on the storage of any particular type of object or data. To speak metaphorically, this structure can be thought of as being a library full of books. Each of these books has a contents page, which contains information about exactly what is contained within that particular book and also how to access it, by page number for instance. Put in the terms used by the format itself, the file is the library, and each book is what is known as a ‘chunk’. Each chunk has a header, essentially the contents page in our previous example, which contains information about the data contained within that chunk and how it should be accessed.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 4 of 92.

Page 5: IWF Specifications v2.0.0

Interchangeable World Format v2.0

2.1. Data Chunks

Due to the fact that the structure itself is not reliant in any way on the data stored within each chunk, this allows us to essentially store any type of data we wish within the file. However, as previously mentioned, the primary design goal of this format is to provide a convenient method for storing and retrieving information, commonly utilised by interactive multimedia applications, in such a way that it can be retrieved and understood by a wide range of software, not simply the application for which it was designed. For this reason, the IWF implements the concept of Standard and Custom data chunks.

Custom data chunks are developer defined, and can contain any object or data that is required. This could be in absolutely any form ranging from image or audio data, to scripts which control characters within the world.

Standard data chunks however, are defined by the IWF standard. These chunks contain information such as mesh data, polygons, vertex information, certain types of world entities such as lights and player spawn points, height-maps and many other types of objects which relate to the creation of a three dimensional scenes. While these chunks are provided within the IWF standard, their use is not mandatory. However, should you choose not to utilise the format of this standardised information, third parties will be unable to read the information stored within the file, without making available the specifications of your own custom data chunks. This of course may be desirable; however other methods are available for protecting the data stored within an IWF file, discussed later in this document, other than using strictly custom data chunks (see section 2.3.4. Chunk Encryption).

Both types of data chunk are made up of both the actual chunk data itself and a chunk header which precedes it. This header contains various pieces of information such as a chunk type-id (i.e. is this a mesh or a piece of terrain), a signature which informs the software whether this is a standard or custom chunk, and also the various chunk data size information which allows us to iterate through, or skip over, certain chunks without having to read or understand the data stored within them. Unlike the IWF version 1.0 specification, version 2.0 is now a fully realised hierarchical file format, and for this reason data chunks now also contain a chunk footer. This footer provides us with an additional ‘End of Chunk’ code which informs the import procedure of whether there are additional chunks at this level in the hierarchy, or if it should step out of this level, and back up to the parent that owns it. While this could be achieved simply by using file position monitoring, the use of the exit code allows extremely intricate recursive procedures to be implemented with incredible ease.

2.2. Chunk Hierarchy

As mentioned, the v2.0 IWF is a hierarchical format. This means that all chunks within the file can be arranged in such a way that certain chunks can become children of other chunks. As an example, the polygon chunk may be a child of the mesh chunk, and many chunk types may be a child of the group chunk. The

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 5 of 92.

Page 6: IWF Specifications v2.0.0

Interchangeable World Format v2.0

usefulness of these hierarchical properties extends far beyond simple arrangement of individual object components however. Take a look at figure 1 below:

Hopefully, using the above diagram, you can see that even individual parts of

a character model can be arranged such that certain limb meshes are stored as children of other parent limb meshes. In the above case, we could say that the objects fingers are children of that objects hand, or that the objects mouth is a child of the objects head. Due to the fact that the objects have physically been stored in this manner, there is no requirement for any additional information outlining the parent child hierarchy of specific model components. This not only applies merely to models of course, your entire scene graph information could be stored simply by writing the graph components out in this way.

Body

Head Arms Legs

Mouth Eyes Hands Feet

Fingers Toes

Figure 1. Object Hierarchy

As we go on to discuss individual chunk types and their relationships later in

this document, it should become clear how this form of hierarchical design can be achieved easily and efficiently.

2.3. Additional Features

There are many additional features built into the v2.0 IWF specifications in addition to the benefits gained using the chunk structure system itself (not including the features built into the standardised chunk types outlined later on), just some of which include compression, write corruption / read error detection and recovery, custom chunk collision prevention, chunk encryption and chunk summary information. All of these features are of course optional, but serve to provide extremely comprehensive support, whatever the situation. Although these features will be discussed in greater detail later in this document, here is a quick summary of what these features provide:

2.3.1. Compression

The compression support built into this specification is the primary means by which to reduce the overall size of the output IWF file. As the size and content of interactive worlds increase exponentially the amount of storage required for this information also increases. However, because of the ever increasing popularity of

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 6 of 92.

Page 7: IWF Specifications v2.0.0

Interchangeable World Format v2.0

online content, this no longer means that the only consideration is storage space, we must also now take into account the amount of bandwidth required to send and receive this information. Although there are many space saving features built into the individual standardised chunk types themselves, there is only so much space which can by saved by simply rearranging and merging the information within the file. This is why compression of data is becoming more and more important within this medium.

The compression system utilised by the IWF is a lossless data-compression algorithm (very similar to that used in PKWARE’s ® PKZIP 2.x and above) and has been designed around the extremely popular ZLib library (v1.1.4) developed by Jean-loup Gailly (compression) and Mark Adler (decompression). This library is used in the creation and decoding of many popular formats such as the PNG image format and GZIP / ZIP compressed volumes. ZLib is open source under the GPL and the library used is available completely free of charge from the following address: http://www.gzip.org/zlib/

2.3.2. Error Detection

Again, due to the ever increasing popularity of online content, file corruptions are an unfortunate reality even though many safeguards exist within the various internet traffic protocols. For this reason, the early detection of file corruptions is fast becoming an even more important aspect of any import procedure, if you are to prevent application-fatal protection faults.

The IWF specification includes its own safeguards to help detect such errors, both before and during the import procedure. The first of these safeguards is a 32 bit checksum, or CRC, stored in the main header of the IWF file itself. This checksum is somewhat like a unique key, built using each individual byte of the file itself. By attempting to build this checksum again at load time, and then matching the resulting checksum against the original stored within the file, it is possible to tell whether or not the file has changed since it was written. Note: This checksum is not intended as a file content protection scheme. It is purely

optional and should not be used to verify the existence of file tampering.

As mentioned, this checksum value is optional, and may not be provided in the file header. Even if this value is provided, it may be advantageous to step through the file regardless of the fact that the checksum did not match. For this reason additional error detection is provided in the form of chunk signatures. Each chunk header and footer contains a 4 byte signature which can be examined to determine not only whether any corruption exists, but also to allow attempted recovery of the import process itself. This signature is not a checksum value however; it is intended to determine whether or not the attempted read operation of the current chunk is in fact valid.

When reading the chunk header, if this signature is invalid, it is normally

indicative of one of two things: either the chunk itself or this portion of the file is

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 7 of 92.

Page 8: IWF Specifications v2.0.0

Interchangeable World Format v2.0

entirely or partially corrupt, or an invalid value stored within the file caused the read operation to become out of sync with the file contents. Either of these two situations is of course a catastrophic event. In the case of the latter however, it is possible to attempt to recover the situation by ignoring this chunk. Even if the chunk itself is completely corrupt, or contains invalid values, it is usually the case that using the value stored in the chunk header will allow you to continue on to the next chunk. If this next chunk signature is also found to be invalid then using certain values stored in the ‘Parent Level’ chunk can allow recovery back up to the level above. This does mean however that, if the latter is the case, all chunks found at the same level as that of the corrupt chunk will have to be discarded. However this does mean that the remaining contents of the file outside of the corrupted level can be recovered.

2.3.3. Custom Chunk Collision Prevention

All chunks are identified using a single two byte value, which informs the import procedure about what type of data this chunk contains. For example, the standards defined mesh chunk has a type-id code of 0x0020(hex) which identifies it as such. Because true globally unique identification (GUID) values are so large, combined with the fact that the same chunk headers are used for both standard and custom chunks, the IWF introduces the concept of ‘Author ID’ fields.

It is commonplace for two or more non-associated developers to choose the same id code for a custom chunk. Therefore, to prevent a collision of any such custom chunks, a developer defined author-id is appended to the chunk header as a means of identifying who created the chunk itself. Far from a simple ‘watermark’ (although nonetheless very useful as such) the author-id field serves as a filter to allow an import procedure to skip over any custom chunks which are not intended for use in that application, regardless of the fact that they share the same chunk type-id code.

This is extremely useful information for a developer in many cases, where for

example ‘Application A’ is searching through the file for a custom chunk with a type-id code of 0x0100(hex) which, as far as it is concerned is an empty chunk simply used to determine if this is a file from which it can read / understand. Whereas ‘Application B’ (the software which originally exported the file), used the type-id code of 0x0100(hex) to hold a script file. Because both applications use that same type-id code, ‘Application A’ in our example will now assume that it is a valid file, and no doubt get into trouble later on. As a second example, a third-party application may well be developed which appends a custom chunk with a specific type-id code to a certain (or in fact any) IWF file. The developer of that application has no way of knowing if the developer, whose application originally exported the file, presently uses, or will at any point in the future use, a custom chunk type-id with that same code.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 8 of 92.

With the author-id field in place, chunks using the same type-id code can co-exist within the same file without issue. The author-id field can even be used to signify differing versions of that same chunk. As an example, you could provide the same information within your file, perhaps structured differently or with extra fields, for both versions 1.0 and 2.0 of your application by providing different author-id

Page 9: IWF Specifications v2.0.0

Interchangeable World Format v2.0

codes for each. Reading back in is then simply a case of filtering out the chunks not intended for that particular version, therefore providing support for all of your user-base, within the same IWF file.

2.3.4. Chunk Encryption

As mentioned in earlier sections, file content protection is possible without having to resort to strictly using custom chunks, and guarding your file specifications from being leaked (although even in this case, file format analysis procedures exist to attempt to gain that information regardless). This protection comes in the form of chunk encryption, and can be put into use where the external viewing or tampering of the file contents is to be prohibited. As an example: encryption could be used to prevent modifications to scripts for use online, in an attempt to prevent certain types of cheating for instance.

The encryption scheme utilised by the IWF specification is a symmetric

stream cipher known as ARCfour (an RC4 “derivative”). This cipher is a simple yet extremely effective algorithm used in many applications and systems today. These include various internet browsers (SSL), Lotus Notes and many cryptographic libraries.

In this system, each individual chunk’s data is encrypted as it is written, using

a variable length key provided by the developer, which must also be used to decrypt the data on import. With the exception of the author-id however, the chunk header remains ‘plaintext’. Although this is a secure system, there are various considerations which should be taken into account when using any encryption scheme. Just one of these is to bear in mind that using the same key for multiple files, increases the chance that a proficient ‘crypto-analyst’ will be able to calculate the key used to encode them, and consequently freely decode that file. Therefore choosing a random key for each file increases the security of the encryption substantially. This is a consideration you should take with all encryption schemes and is not specific to ARCfour. Note: The encryption provided by this specification is not intended to be used as a

secure transport method for sensitive data, it is merely a means to prevent the average user from being able to view or tamper with the contents of the file. The authors of this specification take no responsibility for the interception, or loss of sensitive data due to the use of the encryption provided.

In addition to this warning, please also note that there are many laws in place, in various regions, which strictly prohibit certain levels of encryption (as an example, under U.S. law, you may only ‘export’ files encrypted with ARCfour if they were encoded using keys of no more than 40 bits in length). It is your responsibility to ensure that you conform to your regions laws regarding encryption!

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 9 of 92.

Page 10: IWF Specifications v2.0.0

Interchangeable World Format v2.0

2.3.5. Chunk Summary Information

It is often advantageous to know in advance how many, of each type of object, are stored within your file prior to reading its contents. These include cases where for instance you wish to allocate memory for a certain number of light maps stored within your file, without having to reallocate storage space each time a new one is encountered.

The summary information is stored in a standard chunk and is always found at,

or near to, the end of the file. The information is stored in a table providing a chunk type-id, an author-id and a field specifying how many of these particular chunks are stored within the file. There is also a dedicated positional reference value stored within the file header itself, allowing you to seek straight to the beginning of this summary chunk, if required, prior to reading the remaining file contents.

3. IWF Structure Layout

This section of the specification details the actual layout of the various different components which go to make up the structure of the IWF itself. This includes items such as the file and chunk headers, and how they relate to one another. This section also covers exactly how each of these individual components is to be arranged, both when reading from and writing to the file.

Note: Information on the structure of the separate standardised chunks can be

found later in this document (see 4. Standardised Chunk Specifications).

3.1. File Header

The IWF File Header is the primary means by which to identify not only the format of the file itself, but also the file version number and various other pieces of related information which describe how the file is laid out. The header is always found at the beginning of the file and is mandatory. The Layout of the file header is as follows:

Table 1a. Layout – File Header Name Type Size (In Bytes)

Signature unsigned char (array) 4

Version unsigned long 4

Flags unsigned long 4

Checksum unsigned long 4

Reserved1 unsigned long 4

Reserved2 unsigned long 4

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 10 of 92.

Page 11: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 1b. Variable Descriptions – File Header

Name Description Valid Values

0x49, 0x49, 0x57, 0x46 Signature

A four byte array that stores a set of pre-defined values used to identify the file as being that of a valid IWF file. { ‘I’, ‘I’, ‘W’, ‘F’ }

0x2000000 to 0x200FFFF Version

A three component version number (Major, Minor, Revision) which has been built using the MAKEVERSION macro, outlined below. This value is used to identify which version of the IWF standard was used to create the file. 3.1.1. Version System

Flags Stores either 0, or a combination of one or more of the flags specified in Table 1c. Specifies various optional features in use within the file.

IWF_COMPRESSED IWF_CHUNKSUMMARY IWF_CRYPT_ARCFOUR

Checksum

Stores any valid 32 bit CRC checksum value, built using a polynomial of 0xEDB88320. This checksum is calculated using all of the data, within the file, which directly follows the header. This value is optional, store 0 if not in use.

3.9. Calculating a Valid Checksum

Reserved1 Four bytes of reserved space for future use. N/A

Reserved2 Four bytes of reserved space for future use. N/A

Table 1c. ‘Flags’ Definitions – File Header

Name Value Description

IWF_COMPRESSED 0x1

If this flag is specified, it signals to the import procedure that compression is currently in use within the IWF file. The file is compressed from the end of the file header onwards. For more information see 3.8. Supporting File Compression

IWF_FILESUMMARY 0x2

If this flag is specified, it signals to the import procedure that a summary chunk is available for import. For more information see 4.2. Summary Chunk

IWF_CRYPT_ARCFOUR 0x4

The presence of this flag signals to the import procedure that the physical chunk data is encrypted using the ARCfour encryption scheme. If both this, and IWF_COMPRESSED are specified, the encryption will be applied first, prior to the file being compressed. For more information see 3.7. Supporting Chunk Encryption

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 11 of 92.

Page 12: IWF Specifications v2.0.0

Interchangeable World Format v2.0

3.1.1. Version System

As mentioned above, the file header’ version variable is calculated using a macro labelled MAKEVERSION. This macro simply takes three components, namely major, minor and revision values, which are then used to build up a single 4 byte unsigned long value. For completeness, this macro is shown below.

When

is supportedthe value gefor example: // Re if (

Althoufuture versioprovide full specificationincrease thecomponentsthe following

// Re if (

This ipassed to thlinear fashio

The mor 0xFF(hex0xFFFF(hexsigned / neg

3.2. Chunk H

The Cidentifies theidentify variofollowing thecustom chunchunks are mandatory.

#define MAKEVERSION( Major, Minor, Revision ) \ ((Major & 0xFF) << 24) + \ ((Minor & 0xFF) << 16) + \ (Revision & 0xFFFF)

importing an IWF file, you can check to ensure that the version number by your application, using this macro. To do this, you simply compare nerated by this macro, with the value stored inside the file header itself,

turn if this is an unsupported version. FileHeader.Version != MAKEVERSION( 2, 0, 0 ) ) return false;

gh comparing in this manner is supported, you must bear in mind that ns of the specification may well increase this version number, and still backwards compatibility. Typically, minor modifications made to the that do not require code revising, or additional support, will simply revision value. In all other cases, the major or minor version number will be increased. Therefore, it is best to test for version support using method:

turn if this is an unsupported version. FileHeader.Version < MAKEVERSION( 2, 0, 0 ) || FileHeader.Version > MAKEVERSION( 2, 0, 65535 ) ) return false;

s made possible due to the fact that increasing any individual component e macro will increase the overall value of the final version number in a n.

ajor and minor version components both have a maximum value of 255 ), whilst the revision component has a maximum value of 65535 or ). All components have a minimum value of zero, that is to say no ative values are permitted.

eader

hunk Header is the primary means by which the import procedure contents of the chunk data area. It contains several variables used to us properties, such as the length of the data area, the type of data header and so on. This same header is used for both standard and k types, and always precedes the physical chunk data although empty

allowed. All aspects of the chunk header, unless otherwise noted, are

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 12 of 92.

Page 13: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The Layout of the chunk header is as follows:

Table 2a. Layout – Chunk Header Name Type Size (In Bytes)

Signature unsigned char (array) 4

ChunkTypeID unsigned short 2

ChunkLength unsigned long 4

DataLength unsigned long 4

AuthorIDLength unsigned char 1

AuthorID unsigned char (array) AuthorIDLength (var)

Table 2b. Variable Descriptions – Chunk Header

Name Description Valid Values

0x48, 0x45, 0x41, 0x44 Signature

A four byte array that stores a set of pre-defined values used to identify this structure as being that of a valid IWF chunk header. { ‘H’, ‘E’, ‘A’, ‘D’ }

ChunkTypeID

Used as a means of identification, this variable specifies the type of data stored within this chunk. This could be either a standard or a custom chunk type-id.

3.5. Chunk Types

ChunkLength

This variable specifies the length, if any, of this particular chunk including any children. This variable is used to skip straight to the footer belonging to this chunk.

3.2.1. Calculating and Using Chunk Sizes

DataLength

This variable specifies the length, if any, of this chunks data area only, i.e. excluding any children. This variable is used to step straight to the next ‘child-level’ chunk within the file.

As Above

AuthorIDLength

Specifies the length, if any, of the author-id which directly follows this variable. It allows the import procedure to pre-allocate any memory required, and to read in the correct amount of bytes from the file. Note: This field should have a value of zero when writing / reading standard chunks.

3.2.2. Using Author-IDs

AuthorID

A simple array of bytes or characters, defined by the developer, used to identify the author of any particular custom chunk. This field is optional. See the section regarding author-ids for more information. Note: This field should not be used when writing / reading standard chunks.

As Above

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 13 of 92.

Page 14: IWF Specifications v2.0.0

Interchangeable World Format v2.0

3.2.1. Calculating and Using Chunk Sizes

There are two sizes provided by the chunk header, the first of these being the ‘ChunkLength’ variable. The value stored within this variable describes the total length of the chunk, following the header itself, up to the start of that particular chunk’s footer. Since all children, contained within that chunk, precede the chunk footer itself; this value includes the length of any children, and allows the import procedure to seek straight to the end of that particular chunk, and on to the next, at that same hierarchy level.

The second length provided by the chunk header is the ‘DataLength’ variable. Unlike ‘ChunkLength’, this variable describes only the length of that chunk’s physical data area. This means that seeking forwards by the amount specified within that variable will result in a file position which is placed directly at the start of either: the first child’s header or, should no children exist, the footer of that particular chunk. This allows the import procedure to step into any particular chunk at will, and retrieve information from any other hierarchy level which may be available at that point. This variable also provides enormous scope for providing additional chunk data area components with future versions of the specification, without sacrificing compatibility.

Should no children exist within the current chunk; both variables will contain identical values. This is due to the fact that the current chunk’s physical data area is all that is stored prior to the chunk footer.

Both variables store a length specifying the total number of bytes to seek forwards, and are both relative to the end of the chunk header which contains them. These values are mandatory and can contain a value between 0 and any 32 bit integer number (i.e. up to 0xFFFFFFF(hex)). Note: It is important when reading an IWF file, to always seek to the next chunk

header stored within the file, rather than simply continuing to read. By seeking in this way your application will be able to skip over any additional variables that may be added to the end of a chunk’s data area in later revisions of the specification.

For information on the relationships between chunk headers, data areas and

parent / child hierarchies, please refer to section 3.6. Putting it All Together.

3.2.2. Using Author-IDs

Summary: 2.3.3. Custom Chunk Collision Prevention.

As mentioned in the section outlining the mechanism used for custom chunk collision prevention, the author-id is the primary means by which to prevent custom chunks, each of differing types and possibly defined by un-associated developers, from being misidentified should they happen to share the same chunk type-id. Even though this was its original design intention, it also has many uses outside of this

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 14 of 92.

Page 15: IWF Specifications v2.0.0

Interchangeable World Format v2.0

situation, and can be an invaluable tool even when the risk of third-party involvement is not necessarily a factor.

In its most basic form, the author-id mechanism is simply an array of bytes / characters of any description, and a variable storing the length of this corresponding set. Put into context however, this array of characters serves as a way of identifying and filtering out any custom chunk not understood by the import procedure which may encounter it. As an example, one developer may define a custom chunk which stores raw light-mapping information, whereas another developer may use the same type-id as this chunk to store game-scripts. In cases where either party’s application may be required to parse the others file, compatibility would be severely compromised. However, had these developers stored an author-id along with their custom chunks, both applications would have passed over this unrecognised data without issue, even though both custom chunks share the same type-id. It is even possible to store multiple differently-formatted custom chunks, which share the same type-id, within the same file as long as different author-id values are used for each format. This caters for a wide variety of possibilities such as differently formatted custom-chunks which technically store the same data, but may be intended for different versions of a single application.

The author-id that is chosen by the developer, when writing the file, can be anything ranging from a series of random numeric values, to an ASCII string denoting a company, or developer name, but should be as unique as possible. Technically speaking, it is entirely feasible to assign a different author-id to each individual chunk; however it is usually only necessary to use a single author-id for all custom chunks, which in turn also reduces the complexity of comparing the identifier on import. If the developer chooses not to write an author-id, within the chunk header, the ‘AuthorIDLength’ variable must be set to 0 signalling that the ‘AuthorID’ variable need not be created or initialised due to the fact that no data is available or required.

When the import procedure begins reading the IWF file, filtering out unrecognised custom chunks becomes as simple as comparing the author-id, stored within each chunks header, against the original. Any custom chunk containing an ID which does not match this original value can be passed over without further processing.

Although the author-id is purely optional, it is recommended that this information be written, if only to provide interoperability with third-party files and applications. The author-id itself, if written, must be between 1 and 255 bytes in length, although an ID of no less than 4 bytes in length is recommended.

• Standard chunks do not utilise this information, and therefore should not write any additional information after the AuthorIDLength variable, which in itself must always store a value of 0, signifying that no AuthorID is in use.

• Whilst this array is not technically designed to store a string, any value may

be assigned to each element, including ASCII character values. If a string ID is used, no terminating character need be stored. If a terminator is required, the AuthorIDLength variable must also include the length of this character.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 15 of 92.

Page 16: IWF Specifications v2.0.0

Interchangeable World Format v2.0

3.3. Chunk Data Area

This portion of the IWF is technically the single most important aspect of the format structure; in the sense that this area is reserved for storing the physical file data, of which the various headers describe. The layout of the data area itself is variable, and largely depends on whether the chunk itself is a standard or custom chunk. When this data area is written within the confines of a standard chunk, it is vitally important that the formatting of the data area follows the design set out within this specification. The data stored within a custom chunk’ data area however is entirely developer defined, and therefore no restrictions are placed upon the layout.

The chunk data area is used to store the various assets, used by the application for which it is intended, which may include objects such as meshes, entities, images, texture and lighting information or any custom data that may be required.

Whilst this area is used as the sole means by which to store data within the IWF file itself, it is often advantageous to store an empty chunk, a chunk with a zero-length data area, within the hierarchy of the file. For this reason, the chunk data area is entirely optional and may be omitted, even when that chunk may contain many children with or without their own data areas. In this case, the ‘DataLength’ variable, stored within the chunk header, would contain a value of 0. Should any such data be required, it must always be written directly following the chunk header.

3.4. Chunk Footer

The chunk footer, much like the chunk header, provides information about how the file should be processed, and is mandatory. In this particular case however, its primary function is to provide information about how the import procedure should proceed once the chunk data has been processed. It provides this information via an ‘End of Chunk’ value, which specifies whether or not any additional chunks exist at the current chunk’ hierarchy level. If additional chunks do exist, then the application can continue on, reading the next header and its associated data. If there are no further chunks at that particular hierarchy level, then the application can step back out to the parent level and continue processing there.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 16 of 92.

While this may seem technically obsolete given the presence of the various chunk sizes, provided by the chunk header, the footer itself does in fact fill other, extremely crucial, roles within the structure. The first of these is to provide information about the chunk hierarchy within the file. Many such hierarchical file formats, require the developer to know in advance whether any particular chunk type has children, and also when to step out of that level of the hierarchy. Since, within these formats, chunks are essentially sequentially positioned it can become somewhat difficult to analyse the hierarchy of the file. The chunk footer however, encloses the chunk (much like you would find with HTML tags) allowing the developer to determine easily if a particular chunk is a child or not. Should the import procedure encounter a new chunk header during the processing of another chunk, prior to that chunk being closed by the footer, we know that this newly encountered chunk is a child of the original.

Page 17: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The second benefit we gain from using chunk footers is that of being able to

design intricate recursive import systems, where each level throughout the recursion is provided with all the information it needs at the point of reading, such as when to step out of the call, and which encountered chunks are children. Because it is made much easier to design completely self-contained chunk processing functions in this way, the developer need not worry about the logistics of transferring and storing chunk information whilst children, below the current chunk, are processed. It is in fact possible, in part due to the chunk footer, to simply use the function stack to store this information until all children have been processed, at which point that function will automatically regain control and can then go on to handle the data after having been provided with all the information stored within it’s children.

The third and final major benefit we gain from the use of a chunk footer, is that of support for error detection and recovery. As mentioned in previous sections of this document, the footer contains a signature which allows the import procedure to test not only for file or chunk corruption, but also for determining whether the chunk was read correctly. If this signature does not exist, or does not contain the correct value when read, the import procedure then knows that something has gone wrong, and can act appropriately. Note: For more information on using the methods outlined above, please see

section 3.6. Putting it All Together. The layout of the chunk footer is as follows:

Table 3a. Layout – Chunk Footer Name Type Size (In Bytes)

Signature unsigned char (array) 4

EOCValue unsigned short 2

Table 3b. Variable Descriptions – Chunk Footer

Name Description Valid Values

0x46, 0x4F, 0x4F, 0x54 Signature

A four byte array that stores a set of pre-defined values used to identify this structure as being that of a valid IWF chunk footer. { ‘F’, ‘O’, ‘O’, ‘T’ }

EOCValue

The ‘End Of Chunk Value’ is used to inform the import procedure about how it should proceed, once the chunk data has been processed. May only store one of the values specified within Table 3c.

CHUNK_EOC CHUNK_EOC_EXIT

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 17 of 92.

Page 18: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 3c. ‘EOCValue’ Definitions – Chunk Footer

Name Value Description

CHUNK_EOC 0xF000

If this flag is specified, it signals to the import procedure that more chunks exist at this level in the chunk hierarchy. For more information see 3.6. Putting it All Together

CHUNK_EOC_EXIT 0xF001

If this flag is specified, it signals to the import procedure that there are no further chunks contained within this level of the chunk hierarchy, and can therefore step back out to the parent level. For more information see 3.6. Putting it All Together

3.5. Chunk Types

As mentioned there are two types of chunks, standard and custom, which are identified by a ‘ChunkTypeID’ value stored within each chunk’ header. This variable has a minimum value of 0 and a maximum of 65535 or 0xFFFF(hex). The method used to identify whether a chunk is of a standard or custom type is simple. A standard chunk always has a type-id value of between 0 and 511 or 0x01FF(hex) inclusive, whereas a custom type-id must have a type-id value of between 512 or 0x0200(hex), and that maximum value inclusive.

Because those initial 512 (0 through 511) values are reserved for standard chunks, it is extremely important that no custom chunk uses these values. Should any custom chunk contain a type-id value of less than 512, it may well be mistaken for a standard chunk, and would most likely result in the complete failure of the import process at that point.

Although the type-id itself is extremely important, it serves no higher purpose other than allowing the import procedure to identify the type of information stored within the chunk data area. It is important to understand that type-id values are not unique identifiers (i.e. one for each chunk within the structure), but are in fact only unique to a specific type of data which may occur at many points throughout the file. With the exception of standard chunks, the developer may choose any type-id they wish for a specific chunk type, as long as the value chosen does not encroach on those reserved for use with standard chunk types. As an example of this, a developer may define their own custom texture chunk as having a value of 0x20FF(hex), and then go on to write thirty of these texture chunks to the file. This would in turn mean that; during the import of this file, thirty separate chunk headers, all with type-id’s containing exactly this same value (0x20FF(hex)), would be encountered.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 18 of 92.

Page 19: IWF Specifications v2.0.0

Interchangeable World Format v2.0

3.6. Putting it All Together

This section focuses on the structure of an interchangeable world formatted file as a whole. Whilst the main focus will be on writing the structure, the information contained here is equally useful to those wishing to develop an import procedure.

In its most basic form, the IWF file itself is simply a collection of chunk

headers and footers, which may contain any arbitrary data, and can be arranged in such a way that it provides information on the hierarchical layout of any content within that file. While this is of course a simplified example, it is in essence all we need to get started. So with this on board we can move on to discussing exactly how we arrange these separate components when we are writing our IWF formatted file. First, take a look at the following diagram:

File Header

Chunk Header (A)

Chunk Data (A)

Chunk Footer (A)

Chunk Header (B)

Chunk Data (B)

Chunk Header (C)

Chunk Data (C)

Chunk Footer (C)

Chunk Footer (B)

Figure 2. File Structure Layout. Looking at the above diagram you can hopefully see more clearly what is meant by hierarchical arrangement when discussed in the context of the individual components, which go to make up chunks stored within the file. Let’s now go into more detail about exactly what the above diagram represents. As always, similar to almost every other file format, the IWF structure begins with the file header. This contains various pieces of information about the file, such as an identifying signature, and various other fields. However, we can largely disregard this area of the file for the purposes of this explanation (see 3.1. File Header for more information about writing / reading the file header). Directly following the file header we then write the chunk header belonging to the first chunk

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 19 of 92.

Page 20: IWF Specifications v2.0.0

Interchangeable World Format v2.0

we would like to store within the file. We have labelled this portion of our example file structure ‘Chunk Header (A)’. You should be able to see that chunk ‘A’, coloured orange in the above diagram, has no children or rather no child chunks. It is simply made up of the chunk header, the actual chunk data, and finally the chunk footer. Let’s just assume for a moment that chunk ‘A’ is a custom chunk, whose data area contains 100 bytes of raw image data. Given the fact that this chunk has no children, the chunk header would contain values similar to those described in the following table.

Table 4a. Example Chunk Header – Chunk ‘A’ Name Type

0x48, 0x45, 0x41, 0x44 Signature

{‘H’, ‘E’, ‘A’, ‘D’ }

0x20FF (Example) ChunkTypeID

CHUNK_CTM_IMAGERAW (Example)

ChunkLength 100

DataLength 100

AuthorIDLength 4 (Example)

0x4D, 0x59, 0x49, 0x44 (Example) AuthorID

{‘M’, ‘Y’, ‘I’, ‘D’} (Example)

Of course, many of the above values are application specific, however the two values of interest here are those contained within both the ChunkLength and DataLength variables. As described in section 3.2.1. Calculating and Using Chunk Sizes, the ChunkLength variable must specify the total length of the chunk up to, but not including, the corresponding chunk footer, whereas the DataLength variable must specify the length of the chunk data area only. Due to the fact that chunk ‘A’ has no children; the data chunk will directly precede the chunk footer and therefore both of these length variables will contain the same value. At this point, having written out the chunk header, we would then proceed onto writing out the actual chunk data in whatever form we require. In our example case, we will write out our 100 bytes of raw image data. Because there are no children to be written for this particular chunk, we would then finish by writing our chunk footer which, in a sense, closes the chunk. The footer, as previously mentioned, informs the application’s import procedure about one of two things at this point. The first is whether there are more chunks to follow at this hierarchy level and that it should continue to process, or secondly, that no more chunks exist at this hierarchy level and it can step out to the parent, or in fact finish reading the file if that chunk was at the top of the hierarchy. In our example file structure there are of course more chunks to follow at this root level, so let’s take a look at an example of what values this chunk’s footer would contain.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 20 of 92.

Page 21: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 4b. Example Chunk Footer – Chunk ‘A’ Name Type

0x46, 0x4F, 0x4F, 0x54 Signature

{ ‘F’, ‘O’, ‘O’, ‘T’ }

0xF000 EOCValue

CHUNK_EOC

As you can see, the footer contains the code CHUNK_EOC, which is designed to inform the import procedure that more chunks follow. At this point, we now move onto writing chunk ‘B’, shown in green in Figure 2 above. Chunk ‘B’ is slightly different when compared to chunk ‘A’ in that it contains a child chunk, shown in blue. We know that this is a child due to the fact that it is written prior to the footer, belonging to chunk ‘B’. Although this chunk contains a child, the same rules apply when writing our chunk header, so let’s once again assume that chunk ‘B’ is a custom chunk, but this time its data area contains 350 bytes of custom mesh data. Let’s also assume for a moment that chunk ‘C’, the child of this chunk, contains a data area of 223 bytes in length. So following those same rules regarding the length variables stored in our header, let’s take a look at the values which will be written for the header belonging to chunk ‘B’.

Table 4c. Example Chunk Header – Chunk ‘B’ Name Type

0x48, 0x45, 0x41, 0x44 Signature

{‘H’, ‘E’, ‘A’, ‘D’ }

0x2100 (Example) ChunkTypeID

CHUNK_CTM_MESH (Example)

ChunkLength 598

DataLength 350

AuthorIDLength 4 (Example)

0x4D, 0x59, 0x49, 0x44 (Example) AuthorID

{‘M’, ‘Y’, ‘I’, ‘D’} (Example)

You can see in Table 4c that the two length variables now contain different values from one another. The DataLength variable obviously stores the length of the data area only, but the ChunkLength variable contains the position in bytes, relative to the end of this chunks header, at which the current chunk’s footer will be written. It may not be immediately clear how we arrived at the number 598, so let’s take a look at exactly how we came up this seemingly arbitrary value.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 21 of 92.

Page 22: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Chunk ‘B’ Data Area 350 +

Chunk ‘C’ Header 19 +

Chunk ‘C’ Data Area 223 +

Chunk ‘C’ Footer 6

Total Size 598

Hopefully you can see now why we arrive at this value, and why each of the individual components is the size outlined above (don’t forget to include the length of the various signatures in your calculations). This value will now allow the import procedure to skip over this entire chunk including any and all children it may contain. This is extremely useful in cases where, for instance, the import procedure does not include support for this chunk type and does not wish to interpret its children in this situation, whereas; the DataLength variable allows us to step into this chunk, down to the first child, regardless of whether the import procedure can interpret this chunks data (and therefore it’s length), or not. Next in the process is chunk ‘B’s data area, which as mentioned is 350 bytes in length. Looking at our description of the process used for writing chunk ‘A’, we would then, after writing the data area, write the chunk footer, but due to the fact that chunk ‘B’ has children, this step is deferred until those children have been written.

At this point we actually begin to write chunk ‘C’, the child chunk, to the IWF file. This chunk is very much like chunk ‘A’ in that it contains no children and would be handled in much the same way, however for completeness the tables containing the various chunk components are shown below:

Table 4d. Example Chunk Header – Chunk ‘C’ Name Type

0x48, 0x45, 0x41, 0x44 Signature

{‘H’, ‘E’, ‘A’, ‘D’ }

0x2101 (Example) ChunkTypeID

CHUNK_CTM_POLYGONS (Example)

ChunkLength 223

DataLength 223

AuthorIDLength 4 (Example)

0x4D, 0x59, 0x49, 0x44 (Example) AuthorID

{‘M’, ‘Y’, ‘I’, ‘D’} (Example)

Table 4e. Example Chunk Data Area – Chunk ‘C’ Name Length

{Custom Data} 223 Bytes

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 22 of 92.

Page 23: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 4f. Example Chunk Footer – Chunk ‘C’ Name Type

0x46, 0x4F, 0x4F, 0x54 Signature

{ ‘F’, ‘O’, ‘O’, ‘T’ }

0xF001 EOCValue

CHUNK_EOC_EXIT

It should be clear by now exactly what each of these components role is and

why they contain the specified values, however; one thing that you may have noticed with regards this chunk’s footer, is that it contains the code CHUNK_EOC_EXIT, unlike chunk ‘A’s footer which contains the code CHUNK_EOC. Referring back to Table 3c - ‘EOCValue’ Definitions, you will see that this code informs the import procedure that no further chunks exist at this hierarchy level. This code allows the import procedure to step back out of this chunk, and carry on processing its parent, which in this case is chunk ‘B’.

After writing all of chunk ‘B’s children, we can now close off this chunk by

writing the corresponding chunk footer. Somewhat like chunk ‘C’, chunk ‘B’ is the last chunk at this hierarchy level, so will contain the code CHUNK_EOC_EXIT but in this case, because this chunk is at the root level, the import procedure is informed that it has finished reading the file in its entirety. For completeness, the table below shows chunk ‘B’s footer:

Table 4g. Example Chunk Footer – Chunk ‘B’ Name Type

0x46, 0x4F, 0x4F, 0x54 Signature

{ ‘F’, ‘O’, ‘O’, ‘T’ }

0xF001 EOCValue

CHUNK_EOC_EXIT

The IWF structure does of course support far more individual hierarchy levels

than the two shown in this simple example, however; implementing such a structure is no more complex than the relationship between chunk ‘B’ and chunk ‘C’ in the scenario we have given. Although we have only demonstrated the hierarchy of custom chunks, exactly the same concepts are utilised for standard chunk types. This means that it is entirely possible to mix custom and standard chunks where, for example, you may specify that a custom chunk containing additional, application specific, information is the child of a standard mesh chunk.

Note: It is vitally important to understand that any and all children belonging to a

specific chunk must strictly be written after the chunk data area itself. No child must be written inside the data area, i.e. in-between two separate variables. One thing that is taken for granted in the above examples, that doesn’t

necessarily follow within a real world situation, is that we know in advance what

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 23 of 92.

Page 24: IWF Specifications v2.0.0

Interchangeable World Format v2.0

values certain variables will contain, such as the chunk and data length variables or even the EOCValue code, when they are quite clearly describing chunks or objects which we have not yet written or processed. In some real world cases, we may not know what value each of these variables should contain until such time as we have physically written those objects, and in other, more frequent, cases it is simply more convenient to calculate these values as we actually write or process those objects or chunks. These types of variables are what we call ‘Forward References’. Tips on how best to deal with these situations, are covered in the following section.

3.6.1. Providing Forward References

There are cases, as outlined in the previous section, where the IWF chunk structure requires information which may not presently be available. We call these values ‘Forward References’ and there are five such references, within the various IWF chunk components, which contain vital information required by any import procedure. The first of these is the ‘Flags’ variable, stored within the file header (see section 3.1. File Header). This variable contains various pieces of information about how the file itself is formatted, and also whether it contains certain standard chunks types. This variable is considered to be a forward reference because it may not be known, at the point of writing the file header itself, whether these specified chunks will be written or not. The second forward reference is the ‘Checksum’ value, contained within the file header, and provides error detection information to the application. The checksum requires the entire contents of the file to be written before being calculated. The third and fourth forward references within the structure are the ‘ChunkLength’ and ‘DataLength’ variables, stored within the chunk header (see section 3.2. Chunk Header). The former specifies the length of the chunk as a whole, including all its children, whilst the latter specifies only the length of the chunk data area. The fourth and final forward reference is the code specified by the ‘EOCValue’ variable, stored within the chunk footer (see section 3.4. Chunk Footer). This variable specifies whether or not there are any further chunks at the current hierarchy level.

As you can see, all of these variables describe in some way how various

portions of the file are to be interpreted by the import procedure, and each precedes the information for which it is describing. This can present a problem during the export of the file. If we were required to determine the contents of all of these variables in advance, it would no doubt involve a complex series of iterations through various data structures, calculating sizes and working out in advance the hierarchy, which could, in some cases, greatly increase the amount of code required to write even a simple file.

Due to the fact that these variables describe information not yet written, it is

logical that we would want to write these values after that information has been written to file. The listings below describe solutions for the logistical issues involved in the calculation and export of the values contained within each of these four forward references. Note: The ‘tips’ outlined below are not part of the specification itself. It is not

required that your implementation follow these guidelines in order for the

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 24 of 92.

Page 25: IWF Specifications v2.0.0

Interchangeable World Format v2.0

application to be considered ‘compliant’. Therefore you may use any technique which works best in your given situation, as long as the output provides an accurate description of the contents stored within the interchangeable world formatted file. These guidelines are discussed merely to help provide you with solutions to certain problems which you may or may not encounter during the implementation of your IWF export procedure.

Example code, and demonstrations of the techniques outlined below are included in the IWF File Toolkit (see section 5.0. IWF File Toolkit Version 2.0).

3.6.1.1. File Header - Flags

When initially writing this variable to file, it should only contain those flags for which you know will be made available at the time of writing the header. These are normally formatting values such as the IWF_COMPRESSED flag or the encryption flag, IWF_CRYPT_ARCFOUR. It may not be known however, at the point of writing the file header, whether or not a summary chunk will be written. Therefore, it is logical that we would want to alter these set of flags should we begin to write a summary chunk to file. To do this; we must store the current file position into a 4 byte application variable (which we will refer to as ‘FilePos’) just prior to writing the summary chunk’ header. Once we have stored the current file position, we can then seek back to the ‘Flags’ variable, which will always be positioned 8 bytes from the beginning of the file. Once we are positioned at the start of the ‘Flags’ variable, we can then re-write our initial flags, combined with the IWF_CHUNKSUMMARY flag, overwriting the previously stored data. Finally we must perform an absolute seek, back to the position stored within our ‘FilePos’ application variable, and continue writing the summary chunk itself.

3.6.1.2. File Header - Checksum

For more information on when and how the checksum should be calculated, please refer to section 3.9. Calculating a Valid Checksum.

3.6.1.3. Chunk Header - ChunkLength

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 25 of 92.

When initially writing this variable to file, it should either be skipped (seek forward relatively by 4 bytes) or should contain a value of zero. Just prior to writing the header that contains this variable however, we must make sure that we store the current file position into a 4 byte application variable, which we will refer to as ‘HeaderPos’. After writing the header itself, we can now continue on writing the chunk data area and all children belonging to this chunk, as we would under normal circumstances. Once we reach the point where we are about to write the footer belonging to the current chunk, we once again store the current file position into a separate 4 byte application variable, which we will refer to as ‘FilePos’. We can now, as with our summary position, seek back to the ‘ChunkLength’ variable and write this final value. This variable will always be positioned 6 bytes forward, starting from the position we stored within our ‘HeaderPos’ variable. The actual value we store here is calculated simply by subtracting the value stored in our ‘HeaderPos’ variable from

Page 26: IWF Specifications v2.0.0

Interchangeable World Format v2.0

that stored in our ‘FilePos’ variable. Once we have written our chunk length we can then seek back to the position stored within ‘FilePos’ and continue writing the chunk footer from that point.

3.6.1.4. Chunk Header - DataLength

The process of calculating and storing the ‘DataLength’ variable is very similar to the process used for writing the chunk length. The only real difference here is that whereas previously the application variable ‘FilePos’ stored the position just prior to the chunk footer, in this case ‘FilePos’ will store the position directly following the chunk data, not including any children. Of course, if no children exist within the current chunk, these values will be identical due to the fact that the chunk data will directly precede the chunk footer, which is as we would expect given our earlier examples.

3.6.1.5. Chunk Footer - EOCValue

As mentioned throughout this specification, the ‘End of Chunk’ value, contained within all chunk footers, provides information to the import procedure about how it should proceed after reading that particular chunk. Because it is not always clear, at the point of writing the chunk footer, whether more chunks exist at that level in the hierarchy, this variable should always be written to file containing an initial value of CHUNK_EOC_EXIT. There are two steps which must be taken before writing the footer itself however, the first of these is to step back to any previous footer written at that hierarchy level, and adjust its exit code from CHUNK_EOC_EXIT, to simply CHUNK_EOC. To do this, we require a 4 byte application variable which we will refer to as ‘FooterPos’. This variable will contain the position, within the file, of any footers previously written at that hierarchy level only, the reason for which will be made clear shortly. Obviously, whenever we are writing the first footer at any particular level, there are no previous footers to be altered, so defaulting the ‘FooterPos’ variable to a value which represents this fact (such as 0 or -1) is a good idea. The second of these two steps is to update the ‘FooterPos’ variable itself with the current file position, just prior to writing the actual footer. So let’s assume we are just about to write the second chunk footer to file, at that hierarchy level. Our ‘FooterPos’ variable will currently contain the position of the previous (first) footer written to file. At this point we should store the current file position into a temporary application variable, which we will refer to as ‘TempPos’, and then seek back to the ‘EOCValue’ variable written for that previous footer. This variable will always be positioned 4 bytes forward starting from the position stored within our ‘FooterPos’ application variable. We can then overwrite that portion of the file with the altered CHUNK_EOC code. At this point we would seek forward once again to the position stored within our ‘TempPos’ variable and, finally, update ‘FooterPos’ with the current file position (assigning ‘FooterPos’ to the value stored inside our ‘TempPos’ variable will suffice). This allows us at a later stage to step back and alter this second chunk’ footer, should we actually continue on to write a third. Once we have updated our ‘FooterPos’ variable, we can then continue on writing the current chunk’ footer which will, as before, contain the code CHUNK_EOC_EXIT.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 26 of 92.

Page 27: IWF Specifications v2.0.0

Interchangeable World Format v2.0

If you followed this process through, you will hopefully see that we will be left with all of our individual chunk footers containing the value CHUNK_EOC, informing the import procedure that more chunks follow, with the exception of the last chunk at any particular hierarchy level. This final chunk footer will contain the value CHUNK_EOC_EXIT and will inform the import procedure that it can now step out of that level, and back up to the parent. The reason why it is important that you store multiple ‘FooterPos’ variables, one for each individual active hierarchy level, is due to the fact that a value of CHUNK_EOC_EXIT should occur exactly once for each run of chunks at any hierarchy level within the file. If we were to have only one ‘FooterPos’ variable for the entire file, we would in fact be stepping back and altering every single footer written, until we were left with only the last chunk in our file storing the CHUNK_EOC_EXIT code. All other chunks, at any and all levels within the file, would simply contain the value CHUNK_EOC.

Although the generic procedures used to handle all of these forward

references seem relatively complex, the practical implementations of these techniques are in fact fairly simple. For more information, including example source code, please refer to section 5.0. IWF File Toolkit Version 2.0.

3.7. Supporting Chunk Encryption

Summary: 2.3.4. Chunk Encryption.

As mentioned in the section outlining the mechanism used for chunk encryption, the method used to encrypt the data stored within each individual chunk’ data area is an ‘RC4’ derivative known as ARCFour. This technique is a very simple, efficient and yet extremely secure system which is similar to that utilised by various internet browser technologies such as the ‘Secure Sockets Layer’, more commonly referred to by its acronym ‘SSL’.

Not yet supported within revision 0.

3.8. Supporting File Compression

Summary: 2.3.1. Compression. Not yet supported within revision 0.

3.9. Calculating a Valid Checksum

Summary: 2.3.2. Error Detection. Not yet supported within revision 0.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 27 of 92.

Page 28: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4. Standardised Chunk Specifications

The following sections of the file discuss the many different types of standard chunks, provided by the current interchangeable world format specification. The standardised chunk specification includes many useful structures such as, meshes, surfaces, textures, materials, shaders, images and much more, all of which are commonly used by interactive multimedia applications today. As mentioned earlier in this document, the primary goal of this particular section of the specification, is to provide a standardised means by which to store data in such a way that it is made easy to both read and write all, or simply portions, of the file, whilst providing as much functionality as possible, for use within a wide range of situations and applications. One of the other main benefits that is gained by utilising a standardised form of storage is of course the possibility for inter-application support, between non-associated developers.

It should be made clear at this point that while making use of the standard chunk definitions set out in the following sections is recommended, it is not mandatory. It is entirely possible to use the IWF structure outlined in the previous sections, to store any arbitrary custom data chunks.

For more information on how to put all of the standardised chunks together, and how

the hierarchy should be arranged, please refer to section 4.15. Standard Chunk Arrangements.

4.1. Common Types, Structures and Processes

The following sections detail both the structures and processes commonly used within the chunk data area of several current and possibly future chunk types. More specific details about the use of each individual item can be found in the various sections which describe the chunk data area in which they are used.

4.1.1. Vectors

Vectors are commonly used to describe both positional and directional values based upon the coordinate system to which they are applied. As an example, two dimensional vectors (VECTOR2) are commonly used to describe positions or directions within a two dimensional coordinate system such as ‘Screen Space’, where the vector origin is located at the top-left hand corner of the screen.

The following structure outlines the two dimensional vector:

Table 5. Structure Layout – VECTOR2 Name Type Size (Bytes) Description

x float 4 The X axis component of the two dimensional vector.

y float 4 The Y axis component of the two dimensional vector.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 28 of 92.

Page 29: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Three dimensional vectors (VECTOR3) are used more commonly throughout the

IWF specification in general. They are primarily used to describe positions and directions within the world set out in the file as a whole. All positions and directions specified by these three dimensional vectors must always be based on the left handed Cartesian coordinate system (as used in Direct3D™ by default) unless noted otherwise. For more information on coordinate systems and how they are used within the IWF specification, please refer to section 4.14. Coordinate System Information. The following structure outlines the three dimensional vector:

Table 6. Structure Layout – VECTOR3 Name Type Size (Bytes) Description

x float 4 The X axis component of the three dimensional vector.

y float 4 The Y axis component of the three dimensional vector.

z float 4 The Z axis component of the three dimensional vector.

4.1.2. Matrices

Matrices can be used for many things, ranging from transformations (translation, rotation and scaling among others) to N-dimensional projections. The matrices used within the IWF is a two-dimensional array containing 64 elements utilising a standard 4x4 arrangement, as with most popular API’s.

As with vectors, IWF matrices must always be based on the left handed

Cartesian coordinate system (as used in Direct3D™ by default) unless noted otherwise. It is also of great importance to note that each matrix is ‘Row Major’ and is designed to be compatible with the ordering system used by the popular Microsoft® Direct3D™ API. Bearing in mind that the numbering system used for referencing elements in an array is zero based, ‘Row Major’ means that when we are referring to an individual row or column within the matrix, for example ‘third column across, second row down’, we are in fact referencing the array element [1][2] (i.e. [Row][Column]).

While all matrices used by the standard chunk types within the IWF greatly

resemble that used by Direct3D™, converting matrices to and from any coordinate system utilised by your application is usually a trivial process. For more information on coordinate systems and how they are used within the IWF specification, please refer to section 4.14. Coordinate System Information.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 29 of 92.

Page 30: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The following structure outlines the two-dimensional 4x4 matrix:

Table 7. Structure Layout – MATRIX4 Name Type Size (Bytes) Description

val float [4][4] (array) 64

The entire matrix is described as a two-dimensional array specifying a 4x4 block of floats.

4.1.3. Bounding Boxes

There are various types of bounding volumes which serve to provide a rough depiction of an objects position, size,

Figure 3.

orientation and often its shape. The most commonly used bounding volume is the bounding box, or more specifically the axis-aligned bounding box. This type of bounding volume is described as being axis-aligned due to the fact that each of the 6 planes of the ‘Box’ that it is describing, are exactly aligned to one of the world axes. Because we know that this ‘Box’ will always be axis-aligned, we can in fact describe it in as little as two

separate three-dimensional vectors, one specifying its minimum extents and the other specifying the maximum, as depicted in the above diagram. The following structure outlines the three-dimensional axis-aligned bounding box:

Table 8. Structure Layout – AA_BBOX Name Type Size (Bytes) Description

Min VECTOR3 12 The minimum, local space, extents of the axis aligned bounding box.

Max VECTOR3 12 The maximum, local space, extents of the axis aligned bounding box.

4.1.4. Palettes, Colours and Blend Modes

Most images which use an 8 bit image format use a palette as a lookup table to specify the resulting colour of any pixel when displaying that image. A palette usually consists of up to 256 entries, each of which contain the individual primary colour components, red, green and blue, which are eventually combined to produce the final colour value.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 30 of 92.

Page 31: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The following structure outlines an individual palette entry:

Table 9. Structure Layout – PAL_ENTRY Name Type Size (Bytes) Description

Red unsigned char 1 The red colour component for the final pixel value.

Green unsigned char 1 The green colour component for the final pixel value.

Blue unsigned char 1 The blue colour component for the final pixel value.

There are also many cases, where a colour value is represented by a single 32 bit unsigned long value. This format can be found in such cases as the ‘Diffuse’ and ‘Specular’ vertex colouring components (See 4.7. Vertex Components), where each colour component is specified within each byte (8 bits) contained within that value, and is usually formatted in the order ‘Alpha, Red, Green, Blue’. Let’s take a look at an example of how we would build and / or extract the individual colour values from this type of variable. In the following example, we have highlighted each individual colour component using the same colour as their matching positions within the ‘SrcColour’ value.

unsigned long SrcColour = 0xFF326C94; unsigned long DestColour = 0;

// Lets extract each individual colour component unsigned char Alpha = (SrcColour & 0xFF000000) >> 24; // 0xFF unsigned char Red = (SrcColour & 0x00FF0000) >> 16; // 0x32 unsigned char Green = (SrcColour & 0x0000FF00) >> 8; // 0x6C unsigned char Blue = (SrcColour & 0x000000FF); // 0x94

// Lets now take each of these values and rebuild it

DestColour = (Alpha << 24) | (Red << 16) | (Green << 8) | (Blue);

As you can see, the colour component is extracted simply by masking off the byte in which that component is contained, and then shifting that value to the right by the required number of bits to bring it into the range of 0 - 255. To demonstrate the reasons behind why we are masking and shifting in this manner, let’s follow up with an example of what is happening, at the bit level, when we are extracting the Red colour component. Remember that there are 8 individual bits to each byte.

We begin with the bit level definition of our SrcColor variable.

(Bit 32)...................(Bit1) SrcColour = 11111111001100100110110010010100 // 0xFF326C94

At this point in our example, we want to extract the red colour component. To do this we used the code ‘Red = (SrcColour & 0x00FF0000) >> 16’. Let’s break this down and see exactly what’s happening. First of all we mask the component out by &’ing the value with a bit mask of 0x00FF0000, so let’s do this here.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 31 of 92.

Page 32: IWF Specifications v2.0.0

Interchangeable World Format v2.0

BitMask = 00000000111111110000000000000000 // 0x00FF0000

(And)

SrcColour = 11111111001100100110110010010100 // 0xFF326C94

(Equals)

TempColour = 00000000001100100000000000000000 // 0x00320000

You can see that all we are left with after these two values have been combined, is the definition of our red colour component. All of the values contained within the alpha, green and blue components have been stripped and set to 0.

The value now stored in the variable ‘TempColour’ has a hex value of 0x00320000. We can already see that this variable contains the value we are required to extract, the number 32(hex), however we have a problem: there are still 16 empty bits to the right of our red component value. This complete hex value of course corresponds to the decimal value of 3,276,800 which is clearly far outside of the range in which we require it to be (0 - 255). So what we need to do next is move the red component so that it lines up with the bit locations 1 through 8 (the bits which describe values between 0 and 255). In our above example we do this by shifting our resulting colour value to the right by 16 places using the code ‘ >> 16 ‘, lets see what happens when we do this.

TempColour = 00000000001100100000000000000000 // 0x00320000

( >> 16 Equals )

Result = 00000000000000000000000000110010 // 0x00000032

As you can see, the green and blue components are stripped and essentially drop off the end. What we are now left with is a value of 0x00000032(hex) or 50 in decimal. This means that our red colour component specifies a value of 50.

The same operation is applied to the other three colour components. The only differences between the processes used to extract the colour components is that they each utilise unique bit masks and bit shifting values required in order to extract that component’s information. Try out the remaining three for yourself and see what you come up with.

As well as palette entries storing colour values, there are also certain objects,

such as materials and light entities, which often reference colours using floating point values. These values are usually found to be within the range of 0.0 to 1.0, however the use of floats not only allows a finer level of granularity for each colour component value, it also allow for ‘Over Brightening’ or ‘Burning’ colours (by specifying a value greater than 1.0) and, in the case of lights for instance, can even contain negative values which will result in light actually being removed from the scene. The latter method in particular is a great way to create ‘cheap’ shadowed areas when using vertex lighting.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 32 of 92.

Page 33: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The following structure outlines a floating point colour value:

Table 10. Structure Layout – COLOUR_VALUE Name Type Size (Bytes) Description

Red float 4 The red colour component for the light source, or material property.

Green float 4 The green colour component for the light source, or material property.

Blue float 4 The blue colour component for the light source, or material property.

Alpha float 4 The alpha component used by the light source, or material property.

As you can see, the above structure contains an ‘Alpha’ value. This value is commonly used by most rendering applications to specify an object or surface’s level of opacity, i.e. the lower the alpha value, the more translucent those surfaces become. This technique is known as ‘Alpha Blending’. At it’s core, alpha blending is simply a rendering technique which takes two colours, one from the source ‘image’, and another from the destination ‘image’, and blends the two together (based on a weighting / alpha value) to produce the final output colour. There are many ways in which to perform alpha blending using many different formulae which can be applied to produce differing results. For this reason, most rendering API’s allow the developer to specify various flags to exact control over which blending techniques the API should use. These ‘Blend Mode’ flags are often specified in the form of two separate ‘Source’ and ‘Destination’ modes which describe, among other things, how each colour component should be interpreted for use within the blending formulae. The IWF specification exposes the ability to store these blend modes, per surface, and is stored within the following BLEND_MODE structure. (For more information on how these blending modes are stored within the file, please refer to section 4.6. Polygon Data) The following structure outlines the storage of the two blending modes:

Table 11a. Structure Layout – BLEND_MODE Name Type Size (Bytes) Description

SrcBlendMode unsigned char 1 The source blending mode. Contains one of the values described in Table 11b.

DestBlendMode unsigned char 1 The destination blending mode. Contains one of the values described in Table 11b.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 33 of 92.

Page 34: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The following table outlines the flags used within each of the above variables: (The descriptions provided below are quoted directly from the Microsoft ® DirectX™ 8.1 SDK.)

Table 11b. ‘SrcBlendMode’ & ‘DestBlendMode’ Definitions – BLEND_MODE

Name Value Description

BLEND_NONE 0x0 No blending is to be applied.

BLEND_ZERO 0x1 Blend factor is (0, 0, 0, 0).

BLEND_ONE 0x2 Blend factor is (1, 1, 1, 1).

BLEND_SRCCOLOR 0x3 Blend factor is (Rs, Gs, Bs, As).

BLEND_INVSRCCOLOR 0x4 Blend factor is (1–Rs, 1–Gs, 1–Bs, 1–As).

BLEND_SRCALPHA 0x5 Blend factor is (As, As, As, As).

BLEND_INVSRCALPHA 0x6 Blend factor is (1–As, 1–As, 1–As, 1–As).

BLEND_DESTALPHA 0x7 Blend factor is (Ad, Ad, Ad, Ad).

BLEND_INVDESTALPHA 0x8 Blend factor is (1–Ad, 1–Ad, 1–Ad, 1–Ad).

BLEND_DESTCOLOR 0x9 Blend factor is (Rd, Gd, Bd, Ad).

BLEND_INVDESTCOLOR 0xA Blend factor is (1–Rd, 1–Gd, 1–Bd, 1–Ad).

4.1.5. Scripts, Shaders and Effect Files

With the recent surge in the use of, and API support for, pixel and vertex shaders; file based support for this information has become increasingly important. The IWF structure supports both external and internal script resources which can be referenced using the SCRIPT_REF structure. This structure is used in several places throughout the various standard chunk types that are available, in particular CHUNK_SURFACES and CHUNK_SHADERS. (Please note that the term script is used loosely, and refers to any piece of executable code such as that provided by shaders or Microsoft® Direct3D™ Effect files as well as application specific scripting files).

Although the SCRIPT_REF structure allows the application to reference script

files, it is the responsibility of the application to determine the type of script being referenced whether that script is a vertex or pixel shader or an application specific script.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 34 of 92.

Page 35: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The following structure outlines an individual script reference entry:

Table 12a. Structure Layout – SCRIPT_REF Name Type Size (Bytes) Description

ScriptSource unsigned char 1

A combination of one or more of the flags set out in Table 12b. Specifies how the following variables should be interpreted and where the script should be loaded from.

ScriptSize unsigned short 2 The length of the ‘ScriptData’ area in bytes (not characters).

ScriptData char (array) ScriptSize(var)

Contains string data which specifies either an external filename or the array contains the physical script code (compiled or otherwise). No string terminator is required, however if one is included, the ‘ScriptSize’ variable must also reflect this additional character.

Table 12b. ‘ScriptSource’ Definitions – SCRIPT_REF Name Value Description

SCRIPT_EXTERNAL 0x1

The ‘ScriptData’ array contains an external resource or file name used to reference the script, shader or effect file. This flag can be combined with the SCRIPT_COMPILED flag, but must not be combined with SCRIPT_INTERNAL.

SCRIPT_INTERNAL 0x2 The ‘ScriptData’ array contains the physical script, shader or effect code itself. This flag can be combined with the SCRIPT_COMPILED flag, but must not be combined with SCRIPT_EXTERNAL.

SCRIPT_COMPILED 0x4 This flag allows you to specify whether the external or internal script, shader or effect code is in its compiled form. If this bit is set, the code referenced is compiled, otherwise it is simply raw source.

4.1.6. Object Component Architecture

Several chunk types, such as CHUNK_MESH and CHUNK_SURFACES, adopt the object component architecture. Despite its fancy name, it is an extremely simple system which provides the ability to save large amounts of space within the file by not writing components, inside the chunk data area, that are not required instead of simply writing empty values which can take up a significant amount of space.

In its most basic form, the component system is made up of a single 4 byte

variable, contained within the layout of the chunk data area itself. This variable is always referred to with the label ‘Components’, and contains various flags specifying whether or not up to 32 individual components are available. Using CHUNK_SURFACES as an example, when reading the surfaces contained within the data area, the first thing we must do is read in any mandatory variables. In this case there is only the ‘Components’ variable. At this point we can test each bit to determine which

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 35 of 92.

Page 36: IWF Specifications v2.0.0

Interchangeable World Format v2.0

components are stored within the file. As an example, we can test to see if the surface normal is contained within the data area using the following code:

if ( Components & SCOMPONENT_NORMAL ) ReadNormal();

As you can see, if the surface normal bit is set, within the components

variable, then we know that the normal is contained within the file and can continue to read it. If the bit is not set, then we simply do nothing and continue on to the next component. Obviously when writing the components variable, the same applies. Let’s just imagine for a moment that we are only planning to write out the normal component and the render effect component. In this case, the only bits which would be set within the variable would be the normal, and effect bits:

Components = SCOMPONENT_NORMAL | SCOMPONENT_EFFECT; An alternative example is one where we would like to write all components, or

possibly all components but one. Rather than specifying every component, which can be a little laborious, we can in fact specify the components by simply modifying the relevant ‘*_ALL’ definition. The following two examples demonstrate these two cases in action:

// Example 1: We will be writing out all components Components = SCOMPONENT_ALL; // Example 2: We are writing all except the normal component. Components = SCOMPONENT_ALL; Components &= ~SCOMPONENT_NORMAL; The first example simply sets all bits, currently defined by the revision of the

standard being used, to 1. Likewise, the second example also sets all bits currently defined by the revision of the standard being used to 1, however it then sets the ‘Normal’ component bit to 0. Information on both the actual data component flags and the use of each component can be found throughout all of the various sections covering the individual chunk data areas in which they are used.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 36 of 92.

Page 37: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.2. Summary Chunk

Type Identifier Name:

CHUNK_FILESUMMARY

Type Identifier Value:

0x0002(hex) Restrictions:

• Strictly one instance of this chunk per file. • Must be written at the root hierarchy level (i.e. cannot be used as a child).

Recommendations: None. Standard Children: None. Data Area Layout:

Table 13a. Data Area Layout – CHUNK_FILESUMMARY Name Type Size (In Bytes)

EntryCount unsigned short 2

Section Repeated for N Iterations - N = ‘EntryCount’ (var)

ChunkTypeID unsigned short 2

AuthorIDLength unsigned char 1

AuthorID unsigned char (array) AuthorIDLength (var)

UsageCount unsigned long 4

End Repeat

Table 13b. Variable Descriptions – CHUNK_FILESUMMARY

Name Description Valid Values

EntryCount The number of entries stored in this chunk summary table.

4.2.1. Processing Chunk Statistics

ChunkTypeID The type identifier to which the value stored in ‘UsageCount’ applies. 3.5. Chunk Types.

AuthorIDLength Specifies the length, if any, of the author-id which directly follows this variable. 3.2.2. Using Author-IDs.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 37 of 92.

Page 38: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 13b. Variable Descriptions – CHUNK_FILESUMMARY

Name Description Valid Values

AuthorID

The author-id signature, used for correct identification of the value stored within ‘ChunkTypeID’, to which the value stored in ‘UsageCount’ applies.

As Above

UsageCount The total number of the specified chunk type found to be stored within the IWF file.

4.2.1. Processing Chunk Statistics

Description:

The file summary chunk provides information about how many of each individual standard, or custom, chunk type are stored within the IWF file. This information can be used by an application to perform many tasks, just one of which is to pre-allocate memory for a certain type of object, instead of having to resize the memory block, each time a new chunk of that type is encountered within the file. This chunk is entirely optional (due to the fact that it is possible to build this information at the point of loading by stepping through the file manually), however with large data sets this can prove to be inefficient and may increase loading times, therefore it is recommended that this information is made available.

If this chunk is to be written, then it is important to also inform the loading

application that a summary chunk exists within the file. This allows the import procedure to instantly handle any situation where the summary chunk has not been provided without first having to perform a lengthy search for a chunk containing the CHUNK_FILESUMMARY type id value. This can be achieved by adjusting the ‘Flags’ variable, stored within the file header, and combining the value stored there with the IWF_FILESUMMARY flag. For more information on this subject please refer to sections 3.1. File Header and 3.6.1. Providing Forward References.

4.2.1. Processing Chunk Statistics

Providing this summary information is relatively simple, and can be built during the export of the file. Put simply, each time a new chunk header is written, the information to be stored is compared against any summary information already built. If both ‘ChunkTypeID’ and the ‘AuthorID’ match any items entries already contained within the summary table, then the ‘UsageCount’ value for that chunk type is simply increased. If that chunk type is not currently contained within the summary table, then it is appended. It is for the above reasons that the standard summary chunk will usually be found at, or close to, the end of the file.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 38 of 92.

Page 39: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The following table demonstrates an example summary chunk:

Table 14. Example Chunk Summary Table Name Type

EntryCount 3

Entry 0

ChunkTypeID CHUNK_FILESUMMARY

AuthorIDLength 0

UsageCount 1

Entry 1

ChunkTypeID CHUNK_MESH

AuthorIDLength 0

UsageCount 12

Entry 2

ChunkTypeID CHUNK_CTM_RAWIMAGE

AuthorIDLength 4

AuthorID ‘M’, ‘Y’, ‘I’, ‘D’

UsageCount 6

This example summary consists of four entries which categorise each of the

13 standard and 6 custom chunks contained within the file being described. You can see that each entry contains the ‘ChunkTypeID’ and ‘AuthorID’ which matches the various chunk headers and that the ‘UsageCount’ variable describes how many of each chunk type was written to file.

It is important to remember to include the summary entry itself when writing the table (shown here as ‘Entry 0’) because the summary may be extracted by a third party application used to display information about the exact contents of the file. Providing this entry unifies the process of displaying this chunk information without having to implement a special case for a once only insertion of the summary chunk itself. In addition, if you are developing a third party application which may append new chunks to the IWF file, you must strip the summary information already contained there. Once the append operation is completed, you must then rebuild and write the table including the newly appended chunks. Note: An example for the implementation of this process is included in the IWF file

toolkit. For more information see 5.0. IWF File Toolkit Version 2.0.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 39 of 92.

Page 40: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.3. Thumbnail Chunk

Type Identifier Name:

CHUNK_THUMBNAIL

Type Identifier Value:

0x0003(hex) Restrictions:

• Strictly one instance of this chunk per file. • Must be written at the root hierarchy level (i.e. cannot be used as a child).

Recommendations:

• For the purposes of optimisation, it is recommended that this chunk be written as close to the beginning of the file as possible to allow an application to seek to this chunk without being required to search the entire file.

Standard Children: None. Data Area Layout:

Table 15a. Data Area Layout – CHUNK_THUMBNAIL Name Type Size (In Bytes)

Width unsigned short 2

Height unsigned short 2

BitsPerPixel unsigned short 2

Palette PAL_ENTRY (array)(8bpp only) 768 (256 Entries * 3)

ImageData unsigned char (array) (Width * Height) * (BitsPerPixel / 8)

Table 15b. Variable Descriptions – CHUNK_THUMBNAIL

Name Description Valid Values

Width Specifies the width, in pixels, of the image stored within the image data array. 0 - 65535

Height Specifies the height, in pixels, of the image stored within the image data array. 0 – 65535

BitsPerPixel

The colour resolution for the image itself. This specifies how many bits are used to describe each pixel stored within the image data array.

8 or 24

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 40 of 92.

Page 41: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 15b. Variable Descriptions – CHUNK_THUMBNAIL

Name Description Valid Values

Palette

An array of 256 individual palette entries which describe the colour of each pixel stored within the image data array. Note: This array will only be written when BitsPerPixel is set to 8, i.e. the image data array holds 8 bit palette indices.

4.3.1. Palettes and Image Data Formatting

ImageData

Stores the physical image pixel data. This array stores a series of either palette indices, or physical colour data depending on the value specified in the BitsPerPixel field.

As Above

Description:

The thumbnail chunk is a specialised chunk designed to hold image data which depicts a graphical representation of the contents of the file. This chunk is commonly used by developers who wish to display a preview image, whenever a user selects an IWF file via the applications common file open dialog, or any other file preview utility. Any image, of any size, may be stored within this chunk; however, because no image compression is applied, it is recommended that you limit the dimensions of this image to a maximum of approximately 128x128. This chunk is entirely optional.

4.3.1. Palettes and Image Data Formatting

There are two colour depth dependant image formats which can be stored within this chunk. The first of these is the 8 bit format which can store an image utilising a maximum of 256 individual colours via the use of the colour palette. If the 8 bit format is to be used, the colour palette must be written just prior to the image data itself.

The palette is made up of 256 entries with each palette entry containing 3 individual components. These components describe the colour of the palette entry by specifying each of the three primary colour values; red, green and blue. Each colour component is expressed with a value between 0 and 255 inclusive. Each palette entry uses a standard RGB colour space model where black can be described using RGB( 0, 0, 0 ) and white as RGB( 255, 255, 255 ). (Please refer to section 4.1.4. Palettes, Colours and Blend Modes for information on the layout of the PAL_ENTRY structure).

As mentioned, the palette stores 256 individual colour entries in a linear array, each element being referenced by the index value 0 through 255. When the specified image depth is set to a value of 8, each byte within the image data array stores an 8 bit index value which references the specified element within the palette and therefore the colour in which this pixel should be drawn.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 41 of 92.

Page 42: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Note: You are required to write all 256 entries regardless of the number of physical colours used within the image.

The second image format which can be contained within the thumbnail chunk,

is that used by 24 bit colour depth images. Unlike the 8 bit format, no palette information is stored prior to the image data, and each pixel in the ‘ImageData’ array occupies 3 bytes instead of 1. The colour of each pixel is expressed in much the same way as it is stored within a palette entry. In this case, the first byte within each pixel specifies the red colour component, the second specifies the green colour component and the third specifies the blue. As with the standard palette entries, this is a standard RGB colour space model.

When writing the image data array itself, it is important that your image be

written using a coordinate system whose origin is set at the top-left corner (scan lines are written from the top down). This differs from windows bitmaps for instance, whose base coordinate system originates from the bottom-left and is interpreted from the bottom upwards. This raw image data need not be padded, or aligned with any boundary; it is simply a continuous stream of scan lines whose pitch exactly matches the width of the image itself, multiplied by the number of bytes used per pixel. The following series of examples shows how the same 3x3 image is laid out in both 8 and 24 bits per pixel.

Example Palette Red Green Blue

Entry 0 0xFF 0x00 0x00

Entry 1 0x00 0xFF 0x00

Entry 2 0x00 0x00 0xFF

Example Image Data Area

Column 1 Column 2 Column 3

Row 1 Palette Entry 0 Palette Entry 1 Palette Entry 2

Row 2 Palette Entry 2 Palette Entry 0 Palette Entry 1

Figure 4. 8 bpp

Row 3 Palette Entry 1 Palette Entry 2 Palette Entry 0

Example Image Data Area

Column 1 Column 2 Column 3

255, 0, 0 0, 255, 0 0, 0, 255 Row 1

0xFF0000 0x00FF00 0x0000FF

0, 0, 255 255, 0, 0 0, 255, 0 Row 2

0x0000FF 0xFF0000 0x00FF00

0, 255, 0 0, 0, 255 255, 0, 0

Figure 5. 24 bpp

(No Palette) Row 3

0x00FF00 0x0000FF 0xFF0000

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 42 of 92.

Page 43: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.4. Group Chunk

Type Identifier Name:

CHUNK_GROUP

Type Identifier Value:

0x0010(hex) Restrictions:

• Must contain at least two children. Recommendations: None. Standard Children: Any standard chunk, including CHUNK_GROUP, unless noted otherwise. Data Area Layout:

Table 16a. Data Area Layout – CHUNK_GROUP Name Type Size (In Bytes)

NameLength unsigned char 1

Name char (array) NameLength (var)

Table 16b. Variable Descriptions – CHUNK_GROUP

Name Description Valid Values

NameLength The length, in bytes (not characters), of the string following this variable. 0 – 255

Name

The label associated with this group. No terminator is required. However should you include a terminator, the value stored within the ‘NameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 255

bytes in length.

Description:

There are many cases where multiple objects must, technically, be treated as one single object, whilst retaining their own independent properties such as position and orientation. Many design applications today support the concept of grouping multiple objects in this way. This allows the designer to, for example, easily position many objects as a whole rather than forcing them to move each individual object, which goes to make up a model, by hand.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 43 of 92.

Page 44: IWF Specifications v2.0.0

Interchangeable World Format v2.0

The same concept can be adopted within the IWF, however; its scope extends far beyond merely grouping mesh objects and can in fact be applied to many standard or custom chunk types. To group two or more chunks together, simply insert a physical group chunk and then insert, as children of the group, those chunks you wish to be grouped together.

As mentioned, groups can hold many types of chunks, standard or custom,

including other groups. This provides an easy way to create multiple level grouped hierarchies where for instance you could have a group named ‘Tank’ containing two child group chunks and a custom script chunk. The first child group could contain all of the meshes used to make up the base of the tank, and the second group contains the turret meshes. The script, contained as a custom child of the ‘Tank’ group, can then modify these two child groups independently from one another. The following diagram demonstrates this grouped chunk hierarchy, utilising the group layout mentioned above.

Group - ‘Tank’

Group - ‘Base’

Mesh - ‘Body’

Mesh - ‘Left Track’

Mesh - 'Right Track’

Group - ‘Turret’

Mesh - 'Turret Base’

Mesh – ‘Barrel’

Custom - Script

Figure 6. Example Grouped Hierarchy.

The chunk data area contains only a string label, which can be used as a form

of identification for the group itself. The additional information about what objects the group contains is gained simply by stepping into the chunk, and reading the group’s children.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 44 of 92.

Page 45: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.5. Object Meshes

Type Identifier Name:

CHUNK_MESH

Type Identifier Value:

0x0020(hex) Restrictions:

None. Recommendations: None. Standard Children:

• CHUNK_SURFACES (Required) • CHUNK_MESH (Optional) • CHUNK_DECALMESH (Optional) • CHUNK_GROUP (Optional) • CHUNK_VERTEXCOMPONENTS (Mesh Pool) (Optional)

Data Area Layout:

Table 17a. Data Area Layout – CHUNK_MESH Name Type Size (In Bytes)

NameLength unsigned char 1

Name char (array) NameLength (var)

Reserved1 unsigned long 4

Reserved2 unsigned long 4

Components unsigned long 4

ObjectMatrix MATRIX4 (optional) 64

Bounds AA_BBOX (optional) 24

Style unsigned long (optional) 4

CustomDataSize unsigned short (optional) 2

CustomData unsigned char (array)(optional) CustomDataSize (var)

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 45 of 92.

Page 46: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 17b. Variable Descriptions – CHUNK_MESH

Name Description Valid Values

NameLength The length, in bytes (not characters), of the string following this variable. 0 – 255

Name

The label associated with this mesh object. No terminator is required however, should you include a terminator, the value stored within the ‘NameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 255

bytes in length.

Reserved1 Four bytes of reserved space for future use. N/A

Reserved2 Four bytes of reserved space for future use. N/A

Components

Stores either 0, or a combination of one or more of the flags specified in Table 17c. These flags describe which components are included within the file, for this particular mesh.

Refer to Table 17c.

ObjectMatrix

This matrix describes how to transform the object, from object space, into its parent’s object space. This matrix provides a relative transformation between the parent and this object.

Any valid transformation matrix (See 4.14. Coordinate System

Information)

Bounds

An axis-aligned bounding box specifying the extents of the mesh in object space, i.e. if a world space bounding box is required, this box must be transformed along with the mesh data, or recalculated in world space.

4.1.3. Bounding Boxes

Style

Stores either 0, or a combination of one or more of the flags specified in Table 17d. Specifies various features which apply to the mesh being described.

MESH_DETAIL MESH_DYNAMIC

MESH_DESTRUCTIBLE

CustomDataSize Specifies the length, in bytes, of the ‘CustomData’ array directly following this field. 0 - 65535

CustomData

A custom data array which can be freely used to store any arbitrary information which may be relevant to the mesh object. This data area should be ignored by applications which do not have strict control over the source of the file containing this information. Child chunks are preferable however for non trivial information.

Developer Defined

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 46 of 92.

Page 47: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 17c. ‘Components’ Definitions – CHUNK_MESH

Name Value Description

MCOMPONENT_OMATRIX 0x1 If this bit is set it informs the import application that the ‘ObjectMatrix’ variable is included and should be read.

MCOMPONENT_BOUNDS 0x2 If this bit is set it informs the import application that the ‘Bounds’ variable is included and should be read.

MCOMPONENT_STYLE 0x4 If this bit is set it informs the import application that the ‘Style’ variable is included and should be read.

MCOMPONENT_CUSTOMDATA 0x8

If this bit is set it informs the import application that the ‘CustomDataSize’ variable should be read and that the ‘CustomData’ area is potentially available should ‘CustomDataSize’ contain a value greater than zero.

MCOMPONENT_ALL 0xF The definition which contains all currently defined component bits set to 1.

Table 17d. ‘Style’ Definitions – CHUNK_MESH

Name Value Description

MESH_DETAIL 0x1

Specifies that this mesh is a detail object. While having no effect on the format of the file, it can provide the application with information about which objects should or should not be considered as base architecture.

MESH_DYNAMIC 0x2

Specifies that this mesh is dynamic. While having no effect on the format of the file, it can provide the application with information about which objects should be allowed to be moved by players, scripts or external forces.

MESH_DESTRUCTIBLE 0x4

Specifies that this mesh is destructible. While having no effect on the format of the file, it can provide the application with information about which objects should be allowed to be destroyed by players, scripts or external forces.

Description:

The mesh chunk is the primary, standard, means by which to define geometry contained inside the world, set out within the file. Although this chunk does not physically contain any polygonal data itself, it defines the mesh properties and is the container for various other chunks which do. More specifically, the mesh chunk is the container for the surfaces chunk defined here with the name CHUNK_SURFACES. There can be an infinite number of individual meshes stored within the file, or as few as one mesh used to describe a single model or a generic ‘soup’ of world polygons.

As with all chunks, the mesh chunk can contain other children prior to its

footer. These children can be anything from another mesh to a custom chunk containing the physical texture image data to be applied to its parent. This is the primary means by which to provide information about mesh hierarchies within the

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 47 of 92.

Page 48: IWF Specifications v2.0.0

Interchangeable World Format v2.0

IWF file. By inserting other meshes, or groups of meshes, as children of any particular chunk you can easily specify, for instance, scene graph information.

Each mesh within the file should ideally be stored within its own local object

space, relative to its parent. Each mesh may contain a matrix which allows the import procedure to transform the mesh data to and from its parent’s object space at any point. This is a vital concept within any hierarchical scene graph where, for instance, translating the parent object would effectively translate all children as well because their own object matrix is relative to its parent’s, now translated, matrix. If your meshes are defined in world space however, the MESH_OMATRIX component should not be written.

Note: This chunk utilises the component mechanism set out in section 4.1.6. Object

Component Architecture, whereby individual surface components may be discarded to save space within the output file if those components are deemed to be redundant.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 48 of 92.

Page 49: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.6. Polygon Data

Type Identifier Name:

CHUNK_SURFACES

Type Identifier Value:

0x0030(hex) Restrictions:

• Can be used as a child of CHUNK_MESH or CHUNK_DECALMESH only. • Only one instance of this child-chunk is allowed for each parent.

Recommendations: None. Standard Children:

• CHUNK_VERTEXCOMPONENTS (Surface Pool) (Optional) • CHUNK_INDICES (Required if ‘Surface Pool’ not provided)

Data Area Layout:

Table 18a. Data Area Layout – CHUNK_SURFACES Name Type Size (In Bytes)

SurfaceCount unsigned long 4

Section Repeated for N Iterations - N = ‘SurfaceCount’ (var)

Components unsigned long 4

Normal VECTOR3 (optional) 12

ZBias unsigned char (optional) 1

Style unsigned long (optional) 4

RenderEffect SCRIPT_REF (optional) 8 + SCRIPT_REF::ScriptSize

ChannelCount unsigned char (optional) 1

TexIndices short (array)(optional) 2 * ChannelCount

MatIndices short (array)(optional) 2 * ChannelCount

ShaderIndices short (array)(optional) 2 * ChannelCount

BlendModes BLEND_MODE (array)(optional) 2 * ChannelCount

CustomDataSize unsigned short (optional) 2

CustomData unsigned char (array)(optional) CustomDataSize (var)

End Repeat

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 49 of 92.

Page 50: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 18b. Variable Descriptions – CHUNK_SURFACES

Name Description Valid Values

SurfaceCount The number of surfaces that are physically described by this chunk. 0 – 0xFFFFFFFF

Components

Stores either 0, or a combination of one or more of the flags specified in Table 18c. These flags describe which components are included within the file, for this particular surface.

Refer to Table 18c.

Normal Specifies the three-dimensional unit length vector describing the direction of the plane on which this surface lies.

Any valid unit length directional vector.

(See 4.14. Coordinate System Information)

ZBias

The Z-Bias value by which to offset this surface, specified within the range of 0 to 255. Because of this fixed range, it is possible to scale the value into whatever Z-Bias range you require, for example 0-16 when using Microsoft ® Direct3D™.

0 - 255

Style Stores either 0, or a combination of one or more of the flags specified in Table 18d. Specifies various features which apply to the surface being described.

Refer to Table 18d.

RenderEffect References a script, shader or effect file that should be used when rendering this surface.

4.1.5. Scripts, Shaders and Effect Files

ChannelCount

The number of ‘Render Pass Channels’ used by this surface. The number of channels relates to the number of stages (single or multi-pass) to be applied when rendering. For example, a simple face with a base texture and a light map would specify two separate channels. Note: Please refer to the component table below for information on when this variable should be written and / or read.

0 – 255

TexIndices

An array of one or more indices specifying an entry within the texture table (CHUNK_TEXTURES). Texture entries reference either: external texture files (by specifying a filename) or physical texture data stored within the file.

4.12. Textures

MatIndices

An array of one or more indices specifying an entry within the materials table (CHUNK_MATERIALS). Material entries reference various properties primarily based around how light is reflected.

4.11. Materials

ShaderIndices

An array of one or more indices specifying an entry within the shader table (CHUNK_SHADERS). Shader entries reference vertex and pixel shaders to be applied to each render stage of the surface.

4.13. Shaders

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 50 of 92.

Page 51: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 18b. Variable Descriptions – CHUNK_SURFACES

Name Description Valid Values

BlendModes

An array of BLEND_MODE structures, used to indicate both the source, and destination, alpha blending modes which should be applied to this surface, or this render pass.

4.1.4. Palettes, Colours and Blend Modes

CustomDataSize Specifies the length, in bytes, of the ‘CustomData’ array directly following this field. 0 – 65535

CustomData

A custom data array which can be freely used to store any arbitrary information which may be relevant to the surface. This data area should be ignored by applications which do not have strict control over the source of the file containing this information. Child chunks are preferable however for non trivial information.

Developer Defined

Table 18c. ‘Components’ Definitions – CHUNK_SURFACES

Name Value Description

SCOMPONENT_NORMAL 0x1 If this bit is set it informs the import application that the ‘Normal’ variable is included and can be read.

SCOMPONENT_ZBIAS 0x2 If this bit is set it informs the import application that the ‘ZBias’ variable is included and can be read.

SCOMPONENT_STYLE 0x4 If this bit is set it informs the import application that the ‘Style’ variable is included and can be read.

SCOMPONENT_EFFECT 0x8 If this bit is set it informs the import application that the ‘RenderEffect’ variable is included and can be read.

SCOMPONENT_TEXTURES 0x10

If this bit is set it informs the import application that the ‘TexIndices’ array is available, and can be read.

Note: If this component is included, the ‘ChannelCount’ variable must also be written.

SCOMPONENT_MATERIALS 0x20

If this bit is set it informs the import application that the ‘MatIndices’ array is available, and can be read.

Note: If this component is included, the

‘ChannelCount’ variable must also be written.

SCOMPONENT_SHADERS 0x40

If this bit is set it informs the application that the ‘ShaderIndices’ array is available, and can be read.

Note: If this component is included, the ‘ChannelCount’ variable must also be written.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 51 of 92.

Page 52: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 18c. ‘Components’ Definitions – CHUNK_SURFACES

Name Value Description

SCOMPONENT_BLENDMODES 0x80

If this bit is set it informs the import application that the ‘BlendModes’ array is available, and can be read.

Note: If this component is included, the ‘ChannelCount’ variable must also be written.

SCOMPONENT_CUSTOMDATA 0x100

If this bit is set it informs the import application that the ‘CustomDataSize’ variable should be read and that the ‘CustomData’ area is potentially available should ‘CustomDataSize’ contain a value greater than zero.

SCOMPONENT_ALL 0x1FF The definition which contains all currently defined component bits set to 1.

Table 18d. ‘Style’ Definitions – CHUNK_SURFACES

Name Value Description

SURFACE_INVISIBLE 0x1 This surface is flagged as invisible, and as such should not be rendered.

SURFACE _FULLBRIGHT 0x2 Specifies that this surface should be considered ‘Full Bright’. This means that no diffuse shading should be applied during, for instance, a light-mapping process.

SURFACE _SKYTYPE 0x4

In a lot of cases, sky surfaces must be handled differently to normal surfaces whether that’s merely during texture application, or the surface is being used as a stencil to mask off the sky areas. This flag informs the rendering application that this surface should be considered as a sky surface.

SURFACE _TWO_SIDED 0x8

This surface should be considered as being two-sided, which means that no back-face culling should be applied either within the API or by the rendering application.

Description:

The surfaces chunk itself must only be written once within any mesh or decal-mesh chunk due to the fact that it houses information about every surface which goes to make up that mesh. This is not the case with certain other chunk types where an individual chunk describes only one object. The surfaces chunk may contain one surface, which describes the entire outer hull of that particular mesh object, or could in fact contain many surfaces, with each entry describing an individual polygon.

Surfaces are the primary means by which to supply polygonal data used to

make up each individual mesh within the scene. As with the mesh chunk, this chunk does not actually contain any physical vertex data, however it does serve as the container for either the vertices themselves, or the indices into a global or mesh

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 52 of 92.

Page 53: IWF Specifications v2.0.0

Interchangeable World Format v2.0

vertex pool. (See sections 4.7. Vertex Components and 4.8. Vertex Indices for more information on vertex pools.)

As previously mentioned; each ‘CHUNK_SURFACES’ data area may contain one or more surface, used to describe the outer hull of any particular mesh. It is not a requirement that each surface describes a single coplanar polygon. In actuality, it is possible, and often desirable, to provide one or more surfaces, stored as triangle strips for instance, where each surface defines a series of non-coplanar polygons. A good example of this case is where a mesh describes a portion of terrain or landscape data. In this particular example, the terrain may be divided into several ‘patches’, each one containing many vertices. In these cases it is important that the application is informed of this fact, to allow the import procedure to split if necessary. In this example, due to the fact that the surface is not strictly coplanar, the surface normal component is redundant and would not have been included. (For more information on providing this information, refer to section 4.7. Vertex Components)

Under normal circumstances however, even where global or mesh vertex pools are in use, it is often advantageous to provide information about each individual polygon that goes to make up any particular mesh. In this case, the application would export information about each individual polygon, providing components such as surface normals and per surface texture or material information if so required. Note: This chunk utilises the component mechanism set out in section 4.1.6. Object

Component Architecture, whereby individual surface components may be discarded to save space within the output file if those components are deemed to be redundant.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 53 of 92.

Page 54: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.7. Vertex Components

Type Identifier Name:

CHUNK_VERTEXCOMPONENTS

Type Identifier Value:

0x0050(hex) Restrictions (Surface Pool):

• Can be used as a child of CHUNK_SURFACES only. • Only one instance of this chunk is allowed for each parent. • Must be written prior to any CHUNK_INDICES chunk.

Restrictions (Mesh Pool):

• Can be used as a child of CHUNK_MESH or CHUNK_DECALMESH only. • Only one instance of this chunk is allowed for each parent mesh. • Must be written prior to the CHUNK_SURFACES chunk.

Restrictions (Global Pool):

• Can be used at the root hierarchy level only. • Only one instance of this chunk is allowed within the file. • Must be written prior to any CHUNK_MESH or CHUNK_DECALMESH chunk.

Recommendations: None. Standard Children:

None. Data Area Layout:

Table 19a. Data Area Layout – CHUNK_VERTEXCOMPONENTS Name Type Size (In Bytes)

VertexPool unsigned char 1

TotalVertexCount unsigned long (VPOOL_SURFACE) 4

SurfaceCount unsigned long (VPOOL_SURFACE) 4

(VertexPool = VPOOL_SURFACE) Section Repeated for N Iterations N = ‘SurfaceCount’

(VertexPool = VPOOL_MESH or VPOOL_GLOBAL) No Repeat Occurs Once

VertexFlags unsigned char 1

VertexCount unsigned short 2

Components unsigned long 4

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 54 of 92.

Page 55: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 19a. Data Area Layout – CHUNK_VERTEXCOMPONENTS Name Type Size (In Bytes)

TexChannelCount unsigned char (optional) 1

TexCoordSize unsigned char (array)(optional) TexChannelCount (var)

Section Repeated for N Iterations - N = ‘VertexCount’ (var)

x float (optional) 4

y float (optional) 4

z float (optional) 4

rhw float (optional) 4

Normal VECTOR3 (optional) 12

PointSize float (optional) 4

Diffuse unsigned long (optional) 4

Specular unsigned long (optional) 4

Section Repeated for N Iterations - N = ‘TexChannelCount’ (var) (optional)

TexCoords float (array)(optional) TexCoordSize[N] * 4

End Repeat for (TexChannelCount)

End Repeat for (VertexCount)

End Repeat for (VertexPool = VPOOL_SURFACE) (SurfaceCount)

Table 19b. Variable Descriptions – CHUNK_VERTEXCOMPONENTS

Name Description Valid Values

VertexPool

Informs the import procedure about what type of vertex pool this chunk is describing. This variable also defines, in part, how this chunk is to be interpreted. Note: Refer to section 4.7.1. Vertex Pools for more information on this value.

VPOOL_SURFACE VPOOL_MESH VPOOL_GLOBAL

TotalVertexCount

The total number of vertices described by the individual vertex components stored inside all surfaces being described within this chunk. Note: This should not be read / written unless VertexPool contains the VPOOL_SURFACE flag.

0 – 0xFFFFFFFF

SurfaceCount

The number of surfaces, whose vertices are described by this chunk. Note: This should not be read / written unless VertexPool contains the VPOOL_SURFACE flag.

0 – 0xFFFFFFFF

VertexFlags

Informs the import procedure, among other things, about how the vertices are currently arranged within the chunk. Must contain at least one primitive flag.

4.7.2. Vertex Arrangement

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 55 of 92.

Page 56: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 19b. Variable Descriptions – CHUNK_VERTEXCOMPONENTS

Name Description Valid Values

VertexCount

Specifies the number of vertices to be read by the import procedure. Depending on the value stored within ‘VertexPool’, this variable contains the number of vertices which make up the current surface (VPOOL_SURFACE), the number of vertices which make up the entire mesh (VPOOL_MESH) or the number of vertices which make up the entire file (VPOOL_GLOBAL).

4.7.1. Vertex Pools

Components

Stores either 0, or a combination of one or more of the flags specified in Table 19c. These flags describe which components are included for this set of vertices.

Refer to Table 19c.

TexChannelCount

The number of texture-coordinate channels that are contained with each vertex currently being described. This information is generally linked with the number of render stage channels stored within the surface, and describes a set of texture coordinates for each. Both the ‘TexCoordSize’ and ‘TexCoords’ arrays will contain the amount elements specified by this variable.

0 – 255

TexCoordSize

This is an array of values which describes how many float components make up the texture coordinate in each channel. As an example, the standard U,V coordinate format utilises 2 components, whereas information pertaining to a volume texture may contain 3.

0 - 255

x

The X axis component of the vertex currently being described. This value is generally expressed in object space unless using transformed vertices, in which case this value is expressed in screen space.

4.14. Coordinate System Information

y

The Y axis component of the vertex currently being described. This value is generally expressed in object space unless using transformed vertices, in which case this value is expressed in screen space.

As Above

z

The Z axis component of the vertex currently being described. This value is generally expressed as a distance in object space, unless using transformed vertices, in which case this value is expressed as a depth value.

As Above

rhw The reciprocal homogeneous W value which is generally used to describe vertices which have already been transformed.

N/A

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 56 of 92.

Page 57: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 19b. Variable Descriptions – CHUNK_VERTEXCOMPONENTS

Name Description Valid Values

Normal

The vertex normal. This value is commonly used by modern rendering API’s to calculate diffuse lighting values. However, this vector is also used in many other techniques such as, among others, environment mapping.

Any valid unit length directional vector.

(See 4.14. Coordinate System Information)

PointSize

Specifies the size of the ‘Point Primitive’ to be rendered, in either camera space units, or screen space units when using transformed vertices. This value is generally used in conjunction with systems such as the Microsoft ® Direct3D™ point sprite mechanism, or used to specify the width of each line within a wire-frame model under OpenGL™ for example.

N/A

Diffuse

The diffuse colour component to be included in this vertex. This value is generally used in conjunction with pre-calculated lighting, or just to colour a surface in general.

4.1.4. Palettes, Colours and Blend Modes

Specular

The specular colour component to be included in this vertex. This value is generally used in conjunction with pre-calculated lighting, or just to colour a surface in general.

As Above

TexCoords

An array of texture coordinates of the type specified by the texture coordinate layout information. If no layout information is provided, this will always be a single element containing a two-dimensional coordinate (i.e. U & V).

Refer to ‘TexChannelCount’ and

‘TexCoordSize’ variables.

Table 19c. ‘Components’ Definitions – CHUNK_VERTEXCOMPONENTS

Name Value Description

VCOMPONENT_XYZ 0x1 Each of the X, Y and Z variables, stored within this chunk, are available and should be read by the import procedure.

VCOMPONENT_RHW 0x2

The RHW variable (reciprocal homogeneous W) stored within this chunk, is available and can be read by the import procedure. This is generally used in conjunction with transformed vertices.

VCOMPONENT_XYZRHW 0x3 A combination of the VCOMPONENT_XYZ and VCOMPONENT_RHW flags. This vertex component flag is provided for convenience only.

VCOMPONENT_NORMAL 0x4 Specifies that the ‘Normal’ variable associated with these vertices is available, and can be read by the import procedure.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 57 of 92.

Page 58: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 19c. ‘Components’ Definitions – CHUNK_VERTEXCOMPONENTS

Name Value Description

VCOMPONENT_POINTSIZE 0x8 Specifies that the ‘PointSize’ variable associated with these vertices is available, and can be read by the import procedure.

VCOMPONENT_DIFFUSE 0x10 Specifies that the ‘Diffuse’ variable associated with this vertex is available, and can be read by the import procedure.

VCOMPONENT_SPECULAR 0x20 Specifies that the ‘Specular’ variable associated with this vertex is available, and can be read by the import procedure.

VCOMPONENT_TEXCOORDS 0x40

Informs the import procedure that one or more texture coordinates have been written to file for these vertices.

Note: The availability of the texture coordinate layout variables is not determined using this flag.

See VCOMPONENT_TEXCOORDLAYOUT.

VCOMPONENT_TEXCOORDLAYOUT 0x80

Specifies that the texture coordinate layout information is available, and should be read by the import procedure. This information is provided in the form of the ‘TexChannelCount’ variable, and the ‘TexCoordSize’ array.

Note: You need not include this component if you are using the default layout of only 1 channel, made

up of two coordinate components (i.e. U and V).

Note: This component should not be written if no texture coordinates are included.

VCOMPONENT_ALL The definition which contains all currently defined component bits set to 1. This is provided purely for convenience.

0xFF

Description:

The ‘Vertex Components’ chunk is where all of the individual points, which serve to make up a mesh surface, are stored. As you can no doubt see by the sheer amount of individual components and variables stored within this chunk, this is by far the most intricate and complex standardised chunk within the specification. There is of course several good reasons for this, one of the most important being the vast amount of different ways in which vertices are required to be expressed by so many different applications. As an example, one application may require diffuse colour values to be stored at each vertex, whilst another application does not. If the specification were to force that application to write the diffuse value regardless, the resulting file would contain 4 bytes of wasted space per vertex which, in a file with for example 60,000 vertices, results in approximately 234kb of wasted space on just the redundant diffuse value alone. Add onto that a redundant vertex normal component of 12 bytes per vertex and you can clearly see the amount of space wasted within

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 58 of 92.

Page 59: IWF Specifications v2.0.0

Interchangeable World Format v2.0

the file would grow exponentially for an application which does not require that these components be exported.

In addition to the many ways in which a vertex can be

Figure 7.

formatted, there is also the issue of duplicated vertices. Taking a look at figure 7 to the left you can see that the front face of the cube is made up of two triangles (coloured in blue and red respectively), each of which is described by three vertices. If we were to describe each triangle separately within the file, we would be required to write all 6 vertices which go to make up the two triangles themselves. In this particular situation however, the

vertices which are used by the connecting edge of each of these two triangles share exactly the same position meaning we have two sets of duplicated vertices. If we examine a standard cube more closely, we can see that in fact we can describe all of the cubes 6 faces in as little as 8 unique vertex positions, however in the above situation we would require 36 vertices (3 vertices x 12 triangles) which means that we would be writing 28 duplicated vertices in total, which is of course unacceptable in many cases. Taking the same ratio of duplicated vertices, using a scene which only requires 10,000 unique vertex positions, would result in a scene made up of 45,000 vertices with 35,000 such vertices duplicating information already available. For this reason the IWF adopts the concept of vertex pools. This is an extremely important topic, and is the one that probably requires the most thought before deciding how you will be formatting your scene information during export. (For more information on vertex pools, please refer to section 4.7.1. Vertex Pools.) Note: This chunk utilises the component mechanism set out in section 4.1.6. Object

Component Architecture, whereby individual vertex components may be discarded to save space within the output file if those components are deemed to be redundant.

4.7.1. Vertex Pools

As mentioned in the previous section, the duplication of vertices is a complex issue which involves a great deal of forethought into how your application presents its mesh information, when stored in memory or written to file. Vertex pools are the primary method, adopted by the IWF specification, by which to reduce or eliminate this issue.

There are a total of three types of vertex pool which are available for use by

an export application, each of which serve as a container for one or more vertex components, at different locations within the scene hierarchy. The three types of vertex pools available are shown in the following table:

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 59 of 92.

Page 60: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 20. ‘VertexPool’ Definitions – CHUNK_*

Name Value Description

VPOOL_SURFACE 0x0 The vertices or vertex components stored, describe each individual surface separately, and cannot be referenced by an external source.

VPOOL_MESH 0x1

The vertices or vertex components stored, describe all surfaces contained within the mesh in which the pool is contained. Any vertex stored here may be referenced by any child surface, but cannot be referenced by external mesh objects.

VPOOL_GLOBAL 0x2

The vertices or vertex components stored, describe every surface, of every mesh, contained within the file. Any vertex stored here may be referenced by any surface belonging to any mesh.

The export procedure is not limited in any way to using just one type of vertex

pool per file. It is often desirable, for instance, to allow certain meshes to use their own mesh pool (i.e. a complex detail object), whilst other meshes may require that each surface reference their own set of vertices (i.e. base architecture). There are many ways of combining each type of vertex pool within the file to provide the maximum amount of coverage for any situation which may be required. (For more information on mixing vertex pool types within the file please refer to section 4.7.1.4. Mixing Vertex Pools)

4.7.1.1. Surface Pools

Vertex component chunks that describe a surface pool will always be written to file as a child of the CHUNK_SURFACES chunk. In this particular case it, should be written prior to any CHUNK_INDICES chunk contained there.

The surface pool form of the CHUNK_VERTEXCOMPONENTS chunk differs slightly

from that used when writing mesh and global pool types. Referring back to Table 19a within section 4.7. Vertex Components, you will notice that not only are there two additional variables contained within the layout itself (TotalVertexCount and SurfaceCount), the chunk actually consists of a unique vertex pool for each surface, as opposed to a single pool per chunk when used in conjunction with the other types. The primary reason for this pool dependant layout is to save as much space within the file as possible. If we were to write out a unique chunk for each surface, the file would soon grow to an unmanageable size where each set of vertices, for each surface, is enveloped by a chunk header and chunk footer. While this may add a relatively small amount of complexity when reading or writing surface pools, the overall space saving gained is more than worth the extra effort.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 60 of 92.

Surface pools are used to describe per surface vertex information, where the pool itself stores all of the vertices used by an individual surface alone. This means that no other surface, from either the parent or external mesh, can reference a vertex

Page 61: IWF Specifications v2.0.0

Interchangeable World Format v2.0

within this pool. Although, because of this fact, using this type of vertex pool alone throughout the file is generally considered to be wasteful and is usually avoided, the surface pool serves an absolutely crucial purpose when used in conjunction with other pool types (see section 4.7.1.4. Mixing Vertex Pools)

4.7.1.2. Mesh Pools

Vertex component chunks that describe a mesh pool will always be written to file as a child of the CHUNK_MESH or CHUNK_DECALMESH chunks. In this particular case, it should be written prior to any CHUNK_SURFACES chunk contained there.

The mesh pool is used to describe all of the vertices used by the child

surfaces of any particular mesh within the file. This is the most commonly used method of all three pool types because it allows duplicate vertex information to be kept to a minimum, whilst allowing meshes to be described in their own local object space. This is achieved by providing a set of indices, within each surface, which reference vertices stored within the mesh level vertex pool. Because all surfaces contained within the mesh have access to the vertex information contained within the parent, this allows many different surfaces to simply reference the same vertex information, for example on a shared edge, instead of being required to simply duplicate such information as would be required with a surface pool. For this reason, whenever a mesh level pool is in use the CHUNK_INDICES chunk must be provided as a child of the surfaces chunk if any of those surfaces reference vertices from the mesh’s vertex pool. (For more information on providing indices refer to section 4.8. Vertex Indices)

Although mesh pools are the recommended type for use during the export of

vertex information; there are cases where duplicating at least portions of each vertex cannot be avoided. A classic example of such a case is the vertex normal. In many cases, where smooth shading between polygons should not be applied (for example: cube faces) it is necessary to provide a different normal for each vertex belonging to two or more surfaces, even though the vertex positions are identical. In this particular scenario there are two options. The first is to resort to using surface pools for each face of the cube, duplicating the vertex position, which is of course far from satisfactory in many cases. The second, recommended, approach is to make use of the mixed vertex pool support (see section 4.7.1.4. Mixing Vertex Pools) whereby each individual vertex component may be separated into individual mesh and surface level pools. In the latter case a surface can reference all the shared vertex component information stored within the mesh pool, such as the vertex position, whilst also having access to the unique vertex normal component stored within the surface pool.

4.7.1.3. Global Pools

Vertex component chunks which describe a global pool will always be written to file at the root hierarchy level. In this particular case, it should be written prior to any CHUNK_MESH or CHUNK_DECALMESH contained either at the root or as a child of any other chunk.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 61 of 92.

Page 62: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Global vertex pools are used to describe all the vertices, used by all surfaces

of every mesh, stored within the IWF file as a whole. This type of pool is very similar to the mesh pool, with the exception that all vertices stored here must be expressed in world-space. For this reason, global vertex pools are probably the least used of the three pool types, mainly due to the fact that this type of restriction is generally unsuitable for scene-graph style hierarchies in particular.

Although the space saving gained by using this type of pool over the standard

mesh pool is at best negligible, there are in fact cases where the use of a global vertex pool can certainly be advantageous. As an example of one such case, imagine for a moment that the exported information is used to describe terrain data. In this case the global vertex pool may contain all of the vertices used to describe the terrain geometry itself, with each mesh simply indexing a small portion or ‘patch’ of that terrain for level of detail calculations.

As with the mesh chunk, whenever a global pool is in use the CHUNK_INDICES

chunk must be provided as a child of the surfaces chunk if any of those surfaces reference vertices from the file’s global vertex pool. (For more information on providing indices refer to section 4.8. Vertex Indices)

4.7.1.4. Mixing Vertex Pools

As mentioned in previous sections, it is possible to mix the different types of vertex pools utilised by the different components stored within the exported IWF file. The classic example, as demonstrated earlier, is that of being required to provide more than one vertex normal for a single vertex position when flat shading of surfaces is required, even when gouraud shading is in use. Let’s go into a little more detail with this example now to demonstrate exactly what components would be required in that situation.

Shown in figure 8, to the left, there are four

perv

Figure 8. Vertex Components

physical vertex locations depicted by the labels A, B, C & D. Focusing specifically on vertex A for the moment, we can see that this vertex is used by each of the three cube faces labelled 1, 2 & 3 respectively. In order to render the cube correctly however, we may in fact be required to provide one vertex normal for each of the three surfaces that reference vertex A. If we were to use only a mesh pool in this situation, we would be limited to just one vertex normal. When this type of ‘multi-component’ support is required, we can in fact split the vertex components up into separate vertex pools. In this

articular case for example, we would store the vertex normals, required to render ach face correctly, within a surface pool, with all other vertex components emaining in tact within the mesh pool. This in fact allows us to specify per-surface ertex component information, without having to duplicate all other vertex

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 62 of 92.

Page 63: IWF Specifications v2.0.0

Interchangeable World Format v2.0

components. Smooth vs. Flat shading issues are of course only one of the problems which may require vertex components to be provided on a per-surface level. Another example of this type of situation is where different textures are applied to each surface of a mesh. In this case, we often require multiple texture coordinates for faces which are connected at a shared vertex. To demonstrate this, refer back once again to figure 8 above. Looking at the top edge of surface 3, we can imagine that we might need to specify texture coordinates whose ‘U’ component ranges from 0.0f at the left-most vertex, to 1.0f at vertex A. When rendering surface 1 however, the ‘U‘ texture coordinate component of vertex A may well be expected to contain a value of 0.0f, with vertex B containing the value 1.0f. This is of course extremely difficult to achieve without requiring duplicate copies of vertex A to be stored within either surface 1 or 3. Add into the mix the ‘V’ component, let alone all the other vertices and surfaces, and we find that the only realistic way to represent all this information with one pool alone would be to duplicate each vertex 3 times, once for each face that references it. However, once again, by using mixed vertex pools we can store, for example, the texture coordinate information (along with anything else that may be required) within the surface pool, leaving all other vertex components to be shared between all surfaces within the parent mesh’s vertex pool.

The process of mixing the vertex pools used within a surface is relatively

simple, the first thing we have to do is write our indices which reference the primary vertex components within the mesh level pool, specifying VPOOL_MESH within our indices ‘VertexPool’ variable. This will allow the import procedure to determine exactly which vertices are being referenced, and in which order. Once the CHUNK_INDICES chunk has been written, we can then proceed onto writing the surface pool. In this case the import procedure determines which vertex, from the surface pool, belongs to which vertex, in the mesh pool, based on the order in which they are contained within the surfaces CHUNK_VERTEXCOMPONENTS child.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 63 of 92.

As an example, let’s imagine for a moment that the mesh contains a surface which is made up of 4 vertices whose vertex positions alone are stored within the mesh pool. The mesh pool in itself may contain many vertices, used by other surfaces within the mesh, and for this reason the surface itself is required to store a set of indices which reference the correct vertices from that mesh pool. For the moment, let’s assume that the indices, contained within the surface, reference vertices 3, 6, 8 & 12 from our mesh pool, which allows our import procedure to reference the four vertex positions which make up the topology of the surface. In addition to the vertex coordinates, each vertex may be required to contain, for instance, a vertex normal which is specific to a particular surface, many of which may be referencing the same vertex (i.e. 3, 6, 8 & 12 in our example) within the mesh. Since this is not possible by using a mesh pool alone, our surface will be required to store the various vertex normal components itself by writing out a matching CHUNK_VERTEXCOMPONENTS chunk directly preceding the indices chunk. As mentioned earlier, the order in which the additional vertex components are written within the surface pool is critical, because the import procedure needs to know which vertices in the surface pool, match up with which vertices in the mesh pool. In our example, the indices stored within the surface, reference the mesh pool vertices 3, 6, 8 & 12 respectively. This means that the vertex normal component, that will be written to the surface pool, should be stored in the same order, that is the normal

Page 64: IWF Specifications v2.0.0

Interchangeable World Format v2.0

associated with vertex 3 followed by the normal associated with vertex 6, then vertex 8 and finally vertex 12. On import, this now allows us to step through both the indices, to determine the ordering and position of each vertex used within the surface, and also to obtain the additional vertex components associated with the surface, simply by stepping through the information stored within the surface pool.

Although mixed pools are fairly complex in nature, especially when the import

procedure is required to cater for any and all situations which may arise, the amount of space saved, when mixing vertex pools in this manner, is more often than not worth the additional effort required.

4.7.2. Vertex Arrangement

There are several ways of arranging vertices, within a surface, in order to both specify how a surface’s vertex information should be interpreted and also to ensure that the most efficient method possible is used for either storage or rendering purposes. Take a look at the following table which describes the flags which can be used in conjunction with the vertex component chunks’ ‘VertexFlags’ variable.

Table 21. ‘VertexFlag’ Definitions – CHUNK_VERTEXCOMPONENTS

Name Value Description

VERTICES_NON_PLANAR 0x1 Descriptor Flag: Specifies that the vertices contained within this chunk cannot be guaranteed as being coplanar with one another. This flag can be combined with all other flags.

VERTICES_INDEXED 0x2 Primitive Type Flag: Specifies that there is no particular order to the vertices stored, and that they can only be referenced by the indices contained within each surface.

VERTICES_TRISTRIP 0x4 Primitive Type Flag: The ‘primitives’ specified by the vertices in the following array utilise triangle strip ordering.

VERTICES_TRILIST 0x8 Primitive Type Flag: The ‘primitives’ specified by the vertices in the following array utilise triangle list ordering.

VERTICES_TRIFAN 0x10 Primitive Type Flag: The ‘primitives’ specified by the vertices in the following array utilise triangle fan ordering.

VERTICES_LINESTRIP 0x20 Primitive Type Flag: The ‘primitives’ specified by the vertices in the following array are lines, ordered in a continuous strip.

VERTICES_LINELIST 0x40 Primitive Type Flag: The ‘primitives’ specified by the vertices in the following array are lines, ordered into lists.

VERTICES_POINTLIST 0x80 Primitive Type Flag: The ‘primitives’ specified by the vertices in the following array are rendered as separate points.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 64 of 92.

As you can see, this table consists primarily of the various primitive types which are exposed through many of today’s popular three-dimensional rendering pipelines such as the one provided by the Microsoft® Direct3D™ API. In case you are not familiar with the vertex arrangements commonly associated with each of

Page 65: IWF Specifications v2.0.0

Interchangeable World Format v2.0

these primitive types, the following examples show the ordering in which the vertices should be written and also how many are required for each type:

Figure 9a. VERTICES_TRILIST The diagram, shown to the left, demonstrates the primitive type known as the ‘Triangle List’. This type of primitive is quite literally a list of vertices, which describe each individual triangle that makes up the surface being rendered. The first triangle in this relatively simple diagram (depicted using red arrows) is made up of the vertices 0, 1 & 2, whilst the second (depicted using yellow arrows) is made up of vertices 3, 4 & 5. The reason why the vertices which share identical positions are shown with differing vertex numbers is due to the fact that when using a standard triangle list arrangement, all vertices making up each individual triangle are physically

separated. This means that vertices 1/3 and 2/5 are actually four separate vertices within the list. When writing the triangle list we would write the vertices in the order 0, 1, 2, 3, 4, 5 as shown in the diagram, resulting in six distinct and separate vertices. Which vertex comes first when ordering the vertices within each triangle is largely unimportant, as long as the resulting triangle’s vertices can be said to be using a clockwise winding order when viewed from its ‘Front’ (the direction in which the triangle / surface normal points). The number of triangles contained within a list of this type can be calculated simply using the formula (VertexCount / 3). Figure 9b. VERTICES_TRIFAN

This primitive type is commonly referred to as the ‘Triangle Fan’. Although, based on the first diagram shown to the left, it may not be entirely clear exactly where this primitive type gets its name; the diagram directly underneath however, shows an octagon and its resulting triangles, at which point the reason for its name should become abundantly clear. The individual triangles, described by any primitive arranged as a triangle fan, each ‘fan out’ from, or more specifically share, a single vertex (depicted in both of these diagrams as vertex 0).

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 65 of 92.

Focusing on the upper diagram for the moment, we can see that this surface is made up of only four vertices, as opposed to the six required when using VERTICES_TRILIST. Although we are not explicitly providing two distinct triangles when writing the vertices for this surface, this primitive type still in fact describes a surface containing exactly two triangles. Because of the rules governing the arrangement of triangle fans, it can be assumed that the first of the three vertices which make up all triangles in the fan is that of the first vertex in the list (Vertex 0) and that every other vertex following, make up the second and third vertex of each triangle alternately. So, using these rules we can accurately

determine that the first triangle is made up of vertices 0, 1 & 2 whilst the second triangle uses vertices 0, 2 & 3. In our second diagram, following the same rules, we know that the first triangle is made up of vertices 0, 1 & 2, the second using 0, 2 & 3 and so on up to the last triangle which makes use of vertices 0, 6 & 7. The number of triangles contained within a fan of this type can be calculated simply using the formula (VertexCount - 2). The vertices should be written in the order shown in the above diagrams.

Page 66: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 66 of 92.

Figure 9c. VERTICES_TRISTRIP

Triangle strips are in many ways similar to triangle fans, with the exception being that no single vertex is shared between all triangles. This in fact allows for much greater scope with regards the type of surface which can be described. Most 3D rendering applications today make wide use of triangle strips because they can be used to describe complex surfaces in such a way that is extremely memory and CPU / GPU efficient. In our first diagram, you can instantly see the difference between how fans and strips are ordered. Unlike fans however, when using this primitive type, we can in fact provide one long, continuous, strip of triangles where theoretically speaking, the length of the strip is only limited by the number of vertices allowed by the rendering API, and the accuracy afforded by single precision floating points. The triangle strip in our first diagram also only requires 4 individual vertices to describe the two triangles which make up the surface. One thing which you may have noticed however is the strange ordering of the second triangle,

where the arrows would seem to be travelling in a counter clockwise direction, and in fact you’d be absolutely correct. However, as with the triangle fan, there are various fixed rules, known by the rendering API, governing the arrangement of the triangles within the list. In our first diagram, the first triangle would be interpreted as 0, 1 & 2 as we would expect, however the second triangle uses the vertices in the order 1, 3 & 2 to ensure a clockwise winding order. There is of course a distinct pattern to the order of these vertices, which can be calculated using something along the lines of the following expanded code:

for ( int i = 0; i < VertexCount - 2; i++ ) {

// Starting with triangle 0. // Is this an ‘Odd’ or ‘Even’ triangle

if ( (i % 2) == 0 ) { TriVertex[0] = Vertices[i]; TriVertex[1] = Vertices[i + 1]; TriVertex[2] = Vertices[i + 2];

} // End if ‘Even’ triangle else { TriVertex[0] = Vertices[i]; TriVertex[1] = Vertices[i + 2]; TriVertex[2] = Vertices[i + 1]; } // End if ‘Odd’ triangle // Render the triangle (clockwise ordering) RenderTriangle( TriVertex );

} // Next vertex Test this out for yourself using the second diagram as a guide. The number of triangles contained within a strip of this type can be calculated simply using the formula (VertexCount - 2) as demonstrated in the above code. The vertices should be written in the order shown in the above diagrams.

Page 67: IWF Specifications v2.0.0

Interchangeable World Format v2.0

There are four additional types shown in the above table which are not associated with triangle primitives. These are: ‘Line Lists’, ‘Line Strips’, ‘Point Lists’ and the final IWF specific primitive type named VERTICES_INDEXED. The first of these, ‘Line Lists’, is used to describe a list of straight lines to be rendered by the import application as a wire-frame portion of the mesh for instance. Much like the triangle list, this primitive type requires a separate set of vertices for each line segment where, for example, rendering 10 lines requires 20 unique vertices (one start point and one end point for each line). As with ‘Line Lists’, ‘Line Strips’ are similar in theory to the triangle strip primitive type where each line segment follows on from the last (the end point of one line is the start point of the next) where, for example, rendering 10 concurrent lines requires only 12 unique vertices. Finally, ‘Point Lists’ simply describe a set of points to be rendered in whatever form is required, either for plotting individual pixels in world space, or for use as point sprites. These primitive types are used to instruct the import application on various aspects of the vertices stored within this vertex pool. Typically the primitive type itself is used to inform the rendering API about the order in which the vertices are being passed for rasterisation. This is especially useful in cases where, for example, indices are not available within the file, or are not required by the application itself. Although the previously mentioned primitive types are commonly used within surface vertex pools, used to describe each surface to be rendered, the mesh and global vertex pools on the other hand will usually be written using the remaining primitive type: VERTICES_INDEXED. Unlike the previous flags, which are common to most rendering APIs, this primitive type is defined by the IWF specification, and is used to inform the import procedure that the vertices contained within this vertex pool are in no particular order and can only be referenced by index. This flag is typically found here due to the fact that in many cases it is not possible, or desirable, to describe an entire mesh or global vertex pool using only a single primitive list (i.e. a single strip). In these cases, the mesh vertices are usually referenced using the indices stored within the individual surfaces of the meshes themselves. (For more information on providing indices refer to section 4.8. Vertex Indices) The very last bit which may be set within the ‘VertexFlags’ variable, is the VERTICES_NON_PLANAR descriptor flag. As discussed in section 4.6. Polygon Data, it is the responsibility of the export procedure to inform the end user developer if the triangles described by the vertices within any individual vertex pool cannot be guaranteed to be entirely coplanar with one another. If this is the case, then this flag must be set within the vertex pool for which it applies. This affords the import application the chance to split the surfaces if required.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 67 of 92.

Page 68: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.8. Vertex Indices

Type Identifier Name:

CHUNK_INDICES

Type Identifier Value:

0x0040(hex) Restrictions:

• Can be used as a child of CHUNK_SURFACES only. • Only one instance of this child-chunk is allowed for each parent. • Must only be written following the parent’s CHUNK_VERTEXCOMPONENT child, if any.

Recommendations: None. Standard Children:

None. Data Area Layout:

Table 22a. Data Area Layout – CHUNK_INDICES Name Type Size (In Bytes)

TotalIndexCount unsigned long 4

SurfaceCount unsigned long 4

Section Repeated for N Iterations - N = ‘SurfaceCount’ (var)

IndexCount unsigned short 2

IndexFlags unsigned char 1

VertexPool unsigned char 1

Indices (see ‘Indices’ description) (see ‘Indices’ description) End Repeat

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 68 of 92.

Page 69: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 22b. Variable Descriptions – CHUNK_INDICES

Name Description Valid Values

TotalIndexCount Total number of indices, required by all surfaces, contained within this chunk. 0 – 0xFFFFFFFF

SurfaceCount The total number of surfaces, whose indices are described by this chunk. 0 – 0xFFFFFFFF

IndexCount The number of individual indices which are contained within the following ‘Indices’ array for the current surface.

0 - 65535

IndexFlag

Informs the application about which format the indices are provided, and also informs the import procedure about how large each individual index, stored within the ‘Indices’ array, is. This variable must contain either 0, or exactly one element size flag and one primitive type flag.

4.8.1. Index Values

Refer to Table 23.

VertexPool

Specifies the type of vertex pool, into which the following indices are referencing (See both sections 4.7.1. Vertex Pools and 4.8.1. Index Values for more information)

4.7.1. Vertex Pools

Refer to Table 20.

Indices

This array is either a 16 bit array, or a 32 bit array, based upon the values provided by the ‘IndexFlag’ variable. In the former case, each index will be stored as an ‘unsigned short’ and in the latter, each index in the array will be stored as an ‘unsigned long’. The size of this array, in bytes, is therefore dependant on the format of the array elements themselves and can be calculated using either:

‘2 * Surface::IndexCount‘ (16bits)

or ‘4 * Surface::IndexCount‘ (32bits)

4.8.1. Index Values

Description: The indices chunk stores various index values, referencing each individual vertex, contained within a surface, mesh, or global vertex pool, which may be used to make up the surface / polygon being described. Indices are extremely useful, not only for reducing the amount of overall storage space required for each surface (by allowing many surfaces to reference the same vertices), but also to allow primitive rendering to be optimised both internally by the API, and also the developer, simply by adjusting integer index values rather than manipulating the ordering of the vertices themselves. For more information on what values must be written into the ‘Indices’ array, please refer to section 4.8.1. Index Values.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 69 of 92.

Page 70: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.8.1. Index Values

In many of today’s graphics rendering APIs there are several ways in which to arrange the vertices used to make up a single surface, as discussed in section 4.7.2. Vertex Arrangement. Although this topic was primarily written with regards vertex ordering, the same mechanism by which to provide the order interpreted by the import procedure also applies to indices. Take a look at the following table which describes the flags which can be used in conjunction with the index chunks’ ‘IndexFlags’ variable:

Table 23. ‘IndexFlags’ Definitions – CHUNK_INDICES

Name Value Description

INDICES_NONE 0x0 This value alone is used should there be no indices written for this particular surface.

INDICES_16BIT 0x1

Element Size Flag: Each element within the ‘Indices’ array is stored as a 16 bit, ‘unsigned short’ integer value. This flag can be combined with all other flags, with the exception of INDICES_32BIT.

INDICES_32BIT 0x2

Element Size Flag: Each element within the ‘Indices’ array is stored as a 32 bit, ‘unsigned long’ integer value. This flag can be combined with all other flags, with the exception of INDICES_16BIT.

INDICES_TRISTRIP 0x4 Primitive Type Flag: The ‘primitives’ specified by the indices in the following array utilise triangle strip ordering.

INDICES_TRILIST 0x8 Primitive Type Flag: The ‘primitives’ specified by the indices in the following array utilise triangle list ordering.

INDICES_TRIFAN 0x10 Primitive Type Flag: The ‘primitives’ specified by the indices in the following array utilise triangle fan ordering.

INDICES_LINESTRIP 0x20 Primitive Type Flag: The ‘primitives’ specified by the indices in the following array are lines, ordered in a continuous strip.

INDICES_LINELIST 0x40 Primitive Type Flag: The ‘primitives’ specified by the indices in the following array are lines, ordered into lists.

INDICES_POINTLIST 0x80 Primitive Type Flag: The ‘primitives’ specified by the indices in the following array are rendered as separate points.

With the exception of the element size flags, the remaining primitive type

definitions hold exactly the same meaning as those provided during the export of the CHUNK_VERTEXCOMPONENTS chunk. When put in the context of the indices array however, it is the order in which the vertices are referenced by the index values themselves (based on the primitive type set within the ‘IndexFlags’ variable) which dictates the arrangement of the surface used for rendering, rather than the order in which the vertices are stored.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 70 of 92.

Page 71: IWF Specifications v2.0.0

Interchangeable World Format v2.0

As discussed in the previous section, the values stored within the ‘Indices’ array may be referencing vertices from one of three pools, either the ‘Surface Pool’, the ‘Mesh Pool’ or the ‘Global Pool’. The pool being referenced can be determined by testing the value contained within the ‘VertexPool’ variable. Each surface (of whose index information is stored within this chunk) may reference a different vertex pool independently. For example the first surface may well contain indices that reference any vertices that are stored within the vertex components chunk (CHUNK_VERTEXCOMPONENTS) stored as a child of the current surfaces chunk (CHUNK_SURFACES), whilst the second surface might reference the set of vertices stored as a child of a mesh (CHUNK_MESH).

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 71 of 92.

Page 72: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.9. Decal Meshes

Type Identifier Name:

CHUNK_DECALMESH

Type Identifier Value:

0x0021(hex) Restrictions:

None. Recommendations: None. Standard Children:

• CHUNK_SURFACES (Required) • CHUNK_MESH (Optional) • CHUNK_DECALMESH (Optional) • CHUNK_GROUP (Optional) • CHUNK_VERTEXCOMPONENTS (Mesh Pool) (Optional)

Data Area Layout: The layout of the decal mesh chunk is currently identical to that of the standard mesh chunk (CHUNK_MESH). The decal mesh is provided in a separate chunk to allow for both future enhancement, and to distinguish between the two types easily without having to step into the chunk and read. More component and style flags may be added in later revisions, however for information on the current layout of the CHUNK_DECALMESH data area, including all component and style flags, please refer to section 4.5. Object Meshes. Description:

Decal meshes are essentially standard mesh chunks which are designed primarily to store surfaces used to build decals that are to be placed within the world. These decals could be anything ranging from explosion or scorch marks, to graffiti or logos. The IWF specification uses a mesh based layout for it’s decals to provide support for as many different types of system as possible, such as that required by clipped multi-surface decals.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 72 of 92.

Page 73: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.10. Entities

Type Identifier Name:

CHUNK_ENTITY

Type Identifier Value:

0x0080(hex) Restrictions: None. Recommendations: None. Standard Children:

None. Data Area Layout:

Table 24a. Data Area Layout – CHUNK_ENTITY Name Type Size (In Bytes)

EntityTypeID unsigned short 2

NameLength unsigned char 1

Name unsigned char (array) ‘NameLength’ (var)

Reserved unsigned long 4

ObjectMatrix MATRIX4 64

DataSize unsigned long 4

DataArea unsigned char (array) 4 * ‘DataSize’ (var)

Table 24b. Variable Descriptions – CHUNK_ENTITY

Name Description Valid Values

EntityTypeID This value is used to identify the type of entity stored within this chunk data area. 4.10.1 Standard Entity Types

NameLength The length, in bytes (not characters), of the string following this variable. 0 - 255

Name

The reference name associated with this material. No terminator is required however, should you include a terminator, the value stored within the ‘NameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 255

bytes in length.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 73 of 92.

Page 74: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 24b. Variable Descriptions – CHUNK_ENTITY

Name Description Valid Values

Reserved Four bytes of reserved data. N/A

ObjectMatrix

This matrix describes how to transform the entity, from object space, into its parent’s object space. This matrix provides a relative transformation between the parent and this object.

Any valid transformation matrix (See 4.14. Coordinate System

Information)

DataSize The length, in bytes, of the entity data area array directly following this variable. 4.10.1 Standard Entity Types

DataArea

An array of bytes containing the data associated with the entity stored within this chunk. For more information on the data which may be stored within this array, please refer to section 4.10.1 Standard Entity Types

As Above

Description:

Entities are the primary means by which to store non-mesh data objects for use within the scene. These objects can be anything, ranging from light sources, particle emitters, simple point locators, player / enemy spawn points, item positions and billboards through to script triggers, door buttons, object linkage, audio sample positioning, portal entry / exit points and much more. Although there are several standardised entity types defined within this specification, there are of course many more uses for entities than is realistic to set out here. For this reason, many entities stored within IWF files in real world applications will be custom entities, designed purely for the purposes of the application for which it was designed. Custom entities, much like custom chunks, have an ‘EntityTypeID’ of 0x0200 or above. All identifier values of 0 through 0x01FF are reserved for standard entity types. For more information on the standardised entity types which are available, please refer to section 4.10.1. Standard Entity Types.

4.10.1 Standard Entity Types

There are relatively few standardised entity types contained within this specification due to the fact that most entities are extremely application specific. However, more entity types may be added to the specification in future revisions to allow a wider application base to share entity information. The following multi-use entity types are currently defined:

Table 25. ‘EntityTypeID’ Definitions – CHUNK_ENTITIES

Name Value Description

ENTITY_LIGHT 0x10 Light entities are used to describe each individual light source contained within the scene. See section 4.10.1.1. Lights for more information on this entity type.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 74 of 92.

Page 75: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 25. ‘EntityTypeID’ Definitions – CHUNK_ENTITIES

Name Value Description

ENTITY_SPAWN_POINT 0x30

Spawn points describe locations in space which can be used to spawn either player or non-player characters. They can also be used as spawn points for player items such as health packs or ammo. For more information on this entity type, see section 4.10.1.3. Spawn Point.

ENTITY_SIMPLE_POINT 0x31

Used simply to describe a simple point in space which can be referenced by name by external scripts for instance. See section 4.10.1.2. Simple Point for more information on this entity type.

4.10.1.1. Lights

Light entities are provided by the specification due to the fact that lighting information is one of the primary components required to render most scenes correctly. By ensuring that this lighting information is provided using a standard format; cross-application file rendering support is made possible for scenes which do not use other means by which to represent that information (i.e. light maps).

The structure of the data area for light entities is shown in the following table:

Table 26a. Structure Layout – LIGHT_ENTITY Name Type Size (Bytes) Description

LightType long 4 The type of light being described by the following properties. Refer to Table 26b for more information.

Diffuse COLOUR_VALUE 16 Light emits diffuse light based on this component’s colour values. Refer to 4.1.4. Palettes, Colours and Blend Modes.

Specular COLOUR_VALUE 16 Light emits specular light based on this component’s colour values. Refer to 4.1.4. Palettes, Colours and Blend Modes.

Ambient COLOUR_VALUE 16 Light emits ambient light based on this component’s colour values. Refer to 4.1.4. Palettes, Colours and Blend Modes.

Range float 4

The maximum distance from the light source position, to which the emitted light reaches. (Does not apply to directional lights)

FallOff float 4 The falloff, or gradient of the light between a spot lights inner and outer cone. (Applies to spot lights only)

Attenuation0 float 4

Single component of the lights attenuation which is used to specify how the light intensity affects the scene over distance. (Does not apply to directional lights).

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 75 of 92.

Page 76: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 26a. Structure Layout – LIGHT_ENTITY Name Type Size (Bytes) Description

Attenuation1 float 4 As Above

Attenuation2 float 4 As Above

Theta float 4 Specifies the angle of the inner cone, relative to the light direction. (Applies to spot lights only)

Phi float 4 Specifies the angle of the outer cone, relative to the light direction. (Applies to spot lights only)

Table 26b. ‘LightType’ Definitions – LIGHT_ENTITY

Name Value Description

LIGHTTYPE_POINT 0x0 The entity is a point light source. The light is simply expressed by a position, and the light effects surfaces in all directions around it.

LIGHTTYPE_SPOT 0x1

The entity is a spot light source. This type of light can be thought of like a cone of light, extending outwards from a position in space. Much like a point light source, this light type has a position, but also specifies a directional cone which restricts the light to only an area which falls inside the lights cone.

LIGHTTYPE_DIRECTIONAL 0x2

The entity is a directional light source. Directional lights are very much like point light sources, with the exception that: with point light sources, the direction is calculated between any vertex it affects, and the lights position. Directional light sources however essentially just specify the direction in which the light travels (which is the same direction used in the light calculation of all vertices), and has no position.

LIGHTTYPE_AMBIENT 0x3

Ambient light types are not commonly provided by today’s popular rendering APIs, but are in fact defined within the specification as a means to define ‘global’ ambient illumination within your scene (which can be used for different areas of the level), or for reference within a script or shader source.

As with all entities, an object matrix is provided which can specify position,

scale and orientation among other things. Most light types require at least a position and often a direction in order to correctly describe the light source itself. With light entities, this information can be extracted from the object matrix itself. This matrix is a standard transformation matrix where the translation (in this case the position) can be extracted from the bottom row, and the direction can be extracted from the 3rd column. This is extraction is demonstrated in the following code:

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 76 of 92.

Page 77: IWF Specifications v2.0.0

Interchangeable World Format v2.0

// Extract Light Position pos.x = Matrix.val[3][0]; pos.y = Matrix.val[3][1]; pos.z = Matrix.val[3][2]; // Extract Light Direction dir.x = Matrix.val[0][2]; dir.y = Matrix.val[1][2]; dir.z = Matrix.val[2][2];

(For more information on matrices, please refer to sections 4.1.2. Matrices and 4.14. Coordinate System Information)

4.10.1.2. Simple Point

The simple point entity type can be used for anything from AI waypoints, to map reference points which are linked to distinguishable meshes for display within a mini-map for instance. Although technically the information provided by this entity type does not extend much further than a simple position, reference name, and a list of items to which it is linked; scripts can easily reference these points by name for use within any process or algorithm that is required. The following structure outlines the layout of the SIMPLE_POINT entity’s data area:

Table 27a. Structure Layout – SIMPLE_POINT

Name Type Size (In Bytes)

LinkCount unsigned char 1

Section Repeated for N Iterations - N = ‘LinkCount’ (var)

NameLength unsigned char 1

Name unsigned char (array) ‘NameLength’ (var)

End Repeat

Table 27b. Variable Descriptions – SIMPLE_POINT

Name Description Valid Values

LinkCount The number of linked reference names contained within this entity data area.

NameLength The length, in bytes (not characters), of the string following this variable. 0 - 255

Name

The reference name to which this simple point locator is associated. No terminator is required however, should you include a terminator, the value stored within the ‘NameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 255

bytes in length.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 77 of 92.

Page 78: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.10.1.3. Spawn Point

The spawn point entity is used to provide the application with locations and orientations of objects and characters which must be spawned within the scene. These objects could be anything ranging from health pack or ammo items, to waves of enemy NPCs spawned in for the player to repel. These spawn points reference objects either by name, or by providing a script which is triggered at level start-up or optionally, if a respawn period is provided, each time the amount of milliseconds specified has elapsed. As with light entities, the entity object matrix is used to specify the location, orientation and optionally scale of the object being spawned. The following structure outlines the layout of the SPAWN_POINT entity’s data area:

Table 28a. Structure Layout – SPAWN_POINT

Name Type Size (In Bytes)

SpawnType unsigned short 2

Components unsigned long 4

RespawnTime unsigned long (optional) 4

RefNameLength unsigned char (optional) 1

RefName unsigned char (array) (optional) ‘NameLength’ (var)

Script SCRIPT_REF (optional) 8 + SCRIPT_REF::ScriptSize

Table 28b. Variable Descriptions – SPAWN_POINT

Name Description Valid Values

SpawnType The type of spawn point being described by this chunks data area. Refer to Table 28c.

Components

Stores either 0, or a combination of one or more of the flags specified in Table 28d. These flags describe which components are included within the file, for this particular spawn point.

Refer to Table 28d.

RespawnTime The recurring time period, in milliseconds, at which this entity will respawn the associated object.

0 – 0xFFFFFFFF

RefNameLength The length, in bytes (not characters), of the string following this variable. 0 - 255

RefName

The reference name associated with this spawn point, allows the application to determine which object should be spawned. No terminator is required however, should you include a terminator, the value stored within the ‘RefNameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 255

bytes in length.

Script A script, if any, which should be triggered when the object is spawned.

4.1.5. Scripts, Shaders and Effect Files

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 78 of 92.

Page 79: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 28c. ‘SpawnType’ Definitions – SPAWN_POINT

Name Value Description

SPAWNTYPE_RESPAWNABLE 0x1

This spawn point specifies that the referenced object / script should be respawned / triggered every time the number of milliseconds, specified by the ‘RespawnTime’ variable, has passed. Can be combined with all other flag types (The remaining flags are mutually exclusive).

SPAWNTYPE_SINGLEPLAYER 0x2 The spawn point is a single player spawn point.

SPAWNTYPE_MULTIPLAYER 0x4 The spawn point is a multiplayer spawn point.

SPAWNTYPE_NON_PLAYER 0x8 The spawn point references a non player character spawn point (NPC). The type of character spawned may be referenced by name, or by specifying a script.

SPAWNTYPE_ITEM 0x10 The spawn point references an item, i.e. health or ammo. The type of item to be spawned may be referenced by name, or by specifying a script.

Table 28d. ‘Components’ Definitions – SPAWN_POINT

Name Value Description

SPCOMPONENT_RESPAWN 0x1 If this bit is set, the ‘RespawnTime’ variable is available and should be read by the import application.

SPCOMPONENT_REFNAME 0x2 If this bit is set, both the ‘RefNameLength’ variable and ‘RefName’ array are available and should be read by the import application.

SPCOMPONENT_SCRIPT 0x4 If this bit is set, the ‘Script’ variable is available and should be read by the import application.

SPCOMPONENT_ALL 0x7 The definition which contains all currently defined component bits set to 1. This flag is provided convenience purposes only.

Note: This entity data area utilises the component mechanism set out in section

4.1.6. Object Component Architecture, whereby individual components may be discarded to save space within the output file if those components are deemed to be redundant.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 79 of 92.

Page 80: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.11. Materials

Type Identifier Name:

CHUNK_MATERIALS

Type Identifier Value:

0x0090(hex) Restrictions:

• Strictly one instance of this chunk per file. • Must be written at the root hierarchy level (i.e. cannot be used as a child). • Must be written prior to any chunk types which may reference materials stored here.

Recommendations: None. Standard Children:

None. Data Area Layout:

Table 29a. Data Area Layout – CHUNK_MATERIALS Name Type Size (In Bytes)

MaterialCount unsigned long 4

Section Repeated for N Iterations - N = ‘MaterialCount’ (var)

NameLength unsigned char 2

Name unsigned char (array) ‘NameLength’ (var)

Diffuse COLOUR_VALUE 16

Ambient COLOUR_VALUE 16

Emissive COLOUR_VALUE 16

Specular COLOUR_VALUE 16

Power float 4

End Repeat

Table 29b. Variable Descriptions – CHUNK_MATERIALS

Name Description Valid Values

MaterialCount The total number of individual material entries contained within this chunk. 0 – 0xFFFFFFFF

NameLength The length, in bytes (not characters), of the string following this variable. 0 - 255

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 80 of 92.

Page 81: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 29b. Variable Descriptions – CHUNK_MATERIALS

Name Description Valid Values

Name

The reference name associated with this material. No terminator is required however, should you include a terminator, the value stored within the ‘NameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 255

bytes in length.

Diffuse The diffuse material component which describes how the surface to which it is applied reflects diffuse light.

4.1.4. Palettes, Colours and Blend Modes

Ambient The ambient material component which describes how the surface to which it is applied reflects ambient light.

As Above

Emissive

The emissive material component which describes the colour of the light that is emitted from the surface to which it is applied.

As Above

Specular The specular material component which describes how the surface to which it is applied reflects specular light.

As Above

Power Specifies the sharpness of the specular highlights. This value must be 0 to disable specular highlights.

0 – FLOAT_MAX

Description:

Materials are often used in most rendering applications to describe how the light, contained within the scene, is reflected by any surface to which it may be applied. Diffuse light is by far the most common type of light found to be reflected by surfaces both within the real world, and within scenes designed for rendering in most of today’s interactive multimedia applications.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 81 of 92.

There are several types of material component which can be specified, that interact with the various types of light sources contained within the scene. The first such property is the diffuse component which reflects light that is often scaled based on both the angle between the surface normal and the light source, and also the distance between the two. The second property is the ambient component, which does not generally take into account range or angle of incidence, and is commonly used to set the base brightness, colour and, artistically speaking, the overall ambient mood of the scene. The emissive component differs from the other properties due to the fact that it does not generally specify how light is reflected, but does in fact specify the colour of the light emitted by the surface. When used in conjunction with standard vertex lighting however, this surface does not physically become a light source in itself (that is, other surfaces do not receive this emitted light) but can essentially be used to create objects which appear to ‘glow in the dark’ even where no light source is currently within range. The last property is the specular component. This commonly interacts with any specular light emitted by any light sources within

Page 82: IWF Specifications v2.0.0

Interchangeable World Format v2.0

range, and appears to make the surface ‘shiny’ by lightening the resulting colour, at each vertex, based upon the position and direction of the world camera. This process can be relatively computationally expensive when compared with other, fake, texture based specular map solutions and therefore is not widely used in many of today’s rendering applications. However, with the wide scale introduction of accelerated transformation and lighting hardware, specular vertex lighting is becoming an increasingly viable option.

Many surfaces stored within the file may reference one or more individual

materials, stored within this chunk, by providing a zero-based index value relative to the first material stored here. Additional unreferenced materials may also be stored here should the need arise, allowing user materials to be retained within an editing system for instance, for use during the next session.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 82 of 92.

Page 83: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.12. Textures

Type Identifier Name:

CHUNK_TEXTURES

Type Identifier Value:

0x00A0(hex) Restrictions:

• Strictly one instance of this chunk per file. • Must be written at the root hierarchy level (i.e. cannot be used as a child). • Must be written prior to any chunk types which may reference textures stored here.

Recommendations: None. Standard Children:

None. Data Area Layout:

Table 30a. Data Area Layout – CHUNK_TEXTURES Name Type Size (In Bytes)

TextureCount unsigned long 4

Section Repeated for N Iterations - N = ‘TextureCount’ (var)

TextureSource unsigned char 1

NameLength unsigned short 2

Name unsigned char (array) ‘NameLength’ (var)

TextureFormat unsigned char 1

TextureSize unsigned long 4

TextureData unsigned char (array) ‘TextureSize’ (var)

End Repeat

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 83 of 92.

Page 84: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 30b. Variable Descriptions – CHUNK_TEXTURES

Name Description Valid Values

TextureCount The total number of individual texture entries contained within this chunk. 0 – 0xFFFFFFFF

TextureSource

A combination of one or more of the flags set out in Table 30c. Specifies how the following variables should be interpreted and where the texture should be loaded from.

TEXTURE_EXTERNAL TEXTURE_INTERNAL

NameLength The length, in bytes (not characters), of the string following this variable. 0 - 65535

Name

If TEXTURE_EXTERNAL is specified within ‘TextureSource’, this variable contains the external filename by which to identify the texture. If TEXTURE_INTERNAL is specified then this variable contains any arbitrary reference name which can be used to identify this texture. No terminator is required however should you include a terminator the value stored within the ‘NameLength’ variable must reflect the existence of this extra character.

Any valid, ANSI compatible, string no greater than 65535

bytes in length.

If TEXTURE_EXTERNAL is specified, this must be a valid texture filename (which may

include a relative path if required).

TextureFormat Specifies the format of the internal texture data, if any, stored within the following variables.

Refer to Table 30d.

TextureSize The length, in bytes of the ‘TextureData’ array (if any) directly following this variable. 0 – 0xFFFFFFFF

TextureData

If the TEXTURE_INTERNAL source flag is specified, this array will contain physical texture data, written in the format specified by the ‘TextureFormat’ variable.

See Chunk Description.

Table 30c. ‘TextureSource’ Definitions – CHUNK_TEXTURES Name Value Description

TEXTURE_EXTERNAL 0x1 The ‘Name’ array contains an external resource or file name used to reference the texture file. This flag cannot be combined with TEXTURE_INTERNAL.

TEXTURE_INTERNAL 0x2 The ‘TextureData’ array contains the physical texture data itself. This flag cannot be combined with TEXTURE_EXTERNAL.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 84 of 92.

Page 85: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 30d. ‘TextureFormat’ Definitions – CHUNK_TEXTURES

Name Value Description

TEXFORMAT_RAW 0x1 The texture data contained within the ‘TextureData’ array is formatted as a simple raw, uncompressed image.

TEXFORMAT_CUSTOM 0x2

The ‘TextureData’ array contains a custom data file the format of which is defined by the end user developer. Textures of this format should be ignored by any application which does not have strict control over the source of the input file.

TEXFORMAT_BMP 0x3 Windows or OS/2 Bitmap (BMP)

TEXFORMAT_JPEG 0x4 JPEG – JFIF Compilant (JPG)

TEXFORMAT_TGA 0x5 Truevision Targa (TGA)

TEXFORMAT_PNG 0x6 Portable Network Graphics (PNG)

TEXFORMAT_PCX 0x7 ZSoft Paintbrush (PCX)

TEXFORMAT_GIF 0x8 Compuserve Graphics Interchange (GIF)

TEXFORMAT_PSD 0x9 Photoshop (PSD)

TEXFORMAT_TIFF 0xA Tagged Image File Format (TIFF)

TEXFORMAT_PPM 0xB Portable Pixelmap (PPM) Description:

Textures are often applied to surfaces within the scene to give the impression that those surfaces are detailed. Imagine a scenario where we could not use textures, and yet we wanted our scene to contain a relatively highly detailed brick wall. In this case, not only would the level designer be required to model each individual brick within the wall, but anything even remotely adventurous such as deformed or rough bricks would send the scene polygon count through the roof and consequently, our applications frame rate through the floor. If however we were to apply a brick texture to all of the walls in our scene, we can in fact get away with applying it to a single flat polygon, giving the appearance of a highly detailed scene, even where extremely low polygon counts must be enforced.

The textures chunk contains the physical texture data or more commonly,

external references to, all of the textures used by the surfaces within the scene. Many surfaces stored within the file may reference one or more individual textures, stored within this chunk, by providing a zero-based index value relative to the first texture stored here.

As mentioned, each texture stored within this chunk may contain the physical

texture data itself. This data may range from a raw uncompressed image format to internal storage of physical files such as the common Windows Bitmap, by specifying the appropriate texture format flag. The layout of the raw image data which may be stored within this chunk is very similar to the format described in the section 4.3.1. Palettes and Image Data Formatting, with the exception that within this context, you are also allowed to specify a 32 bit pixel format, which used the byte ordering: Alpha, Red, Green and Blue respectively. In addition, custom file or data structures may be

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 85 of 92.

Page 86: IWF Specifications v2.0.0

Interchangeable World Format v2.0

stored within each texture element, simply by specifying the TEXFORMAT_CUSTOM flag within the ‘TextureFormat’ variable. More commonly however, developers will write out texture data in one of the common graphics file format specified in Table 30d. In this instance, it is recommended that the ‘TextureFormat’ variable contain the associated TEXFORMAT_* flag to inform the import procedure in which format the texture data is stored, so that it can be loaded without having to determine this in advance.

Although internal storage of texture data would not commonly be used within

a large scale gaming application, where many textures may be shared between individual level files; the ability to store textures in this manner is ideal for scenes which contain and utilise associated light maps, and can also prove to be a huge advantage for the simple, rapid deployment of single file demonstrations scenes.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 86 of 92.

Page 87: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.13. Shaders

Type Identifier Name:

CHUNK_SHADERS

Type Identifier Value:

0x00B0(hex) Restrictions:

• Strictly one instance of this chunk per file. • Must be written at the root hierarchy level (i.e. cannot be used as a child). • Must be written prior to any chunk types which may reference shaders stored here.

Recommendations: None. Standard Children:

None. Data Area Layout:

Table 31a. Data Area Layout – CHUNK_SHADERS Name Type Size (In Bytes)

ShaderCount unsigned long 4

Section Repeated for N Iterations - N = ‘ShaderCount’ (var)

Components unsigned long 4

VertexShader SCRIPT_REF (optional) 4

PixelShader SCRIPT_REF (optional) 4

End Repeat

Table 31b. Variable Descriptions – CHUNK_SHADERS

Name Description Valid Values

Components

Stores either 0, or a combination of one or more of the flags specified in Table 31c. These flags describe which components are included within the file, for this particular shader.

Refer to Table 31c.

VertexShader A script reference structure which specifies a vertex shader to be used for this surface rendering pass.

4.1.5. Scripts, Shaders and Effect Files

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 87 of 92.

Page 88: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Table 31b. Variable Descriptions – CHUNK_SHADERS

Name Description Valid Values

PixelShader A script reference structure which specifies a pixel shader to be used for this surface rendering pass.

As Above

Table 31c. ‘Components’ Definitions – CHUNK_SHADERS Name Value Description

SHCOMPONENT_VSHADER 0x1 If this bit is set, the ‘VertexShader’ variable is available and should be read by the import application.

SHCOMPONENT_PSHADER 0x2 If this bit is set, the ‘PixelShader’ variable is available and should be read by the import application.

Description:

Shader files are becoming an important part of today’s rendering applications. With support for shaders becoming more prevalent in hardware, they are now becoming a viable option for developers. This chunk stores a list of all of the pixel and vertex shaders used by any surface stored within the file.

Many surfaces stored within the file may reference one or more individual

shader element, stored within this chunk, by providing a zero-based index value relative to the first element stored here. Additional unreferenced shaders may also be stored here should the need arise, allowing user shaders to be retained within an editing system for instance, for use during the next session.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 88 of 92.

Page 89: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.14. Coordinate System Information

Type Identifier Name:

CHUNK_COORDSYSINFO

Type Identifier Value:

0x00C0(hex) Restrictions:

• Strictly one instance of this chunk per file. • Must be written at the root hierarchy level (i.e. cannot be used as a child). • Must be written prior to any vertex data stored within the file.

Recommendations: None. Standard Children:

None. Data Area Layout:

Table 32a. Data Area Layout – CHUNK_COORDSYSINFO Name Type Size (In Bytes)

CoordSysMatrix MATRIX4 64

WindingOrder unsigned char 1

Table 32b. Variable Descriptions – CHUNK_COORDSYSINFO

Name Description Valid Values

CoordSysMatrix

A transformation matrix which can be used by an external application to transform vertices, normals and matrices from the coordinate system used to write these components, into the standard left handed Cartesian coordinate system.

See Chunk Description.

WindingOrder

The vertex order, used by the surfaces stored within the file, in which the vertices ‘wind’. The winding order specified within this variable describes which side of any particular surface is said to be the front.

WINDING_CCW WINDING_CW

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 89 of 92.

Page 90: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Description:

To provide inter-application compatibility, the interchangeable world format is primarily based around the left handed Cartesian coordinate system (as used by Microsoft® Direct3D™ by default) for storage of mesh vertex data. However, there are cases when this can be extremely restrictive where alternative coordinate systems may be required. Forcing an application to read and write data using a non native coordinate system can place an unnecessary load on the import / export procedures, which would consequently be required to convert between the two coordinate systems on the fly. For this reason, it is in fact possible to store the scene data using any arbitrary coordinate system, such as the right handed Cartesian coordinate system used by OpenGL, as long as the application which exports this file also writes the CHUNK_COORDSYSINFO chunk. This chunk provides any external application with information about the coordinate system in which various components within the file are expressed, such as vertex positions, surface and vertex normals and the various object matices.

The following example demonstrates the values which would be stored within the ‘CoordSysMatrix’ variable to convert between a right and left handed coordinate system (i.e. between OpenGL and Direct3D).

Table 33. Example Matrix – CHUNK_COORDSYSINFO

val[*][0] val[*][1] val[*][2] val[*][3] val[0][*] 1 0 0 0 val[1][*] 0 1 0 0 val[2][*] 0 0 -1 0 val[3][*] 0 0 0 1

The above matrix is essentially a standard identity matrix, with the exception

that the matrix element [2][2] is negated. This has the effect of swapping the sign of the Z component of any vector that is transformed using these values. As mentioned earlier, it is of great importance to note that each matrix stored within the IWF, including the coordinate system matrix, are ‘Row Major’. Bearing in mind that the numbering system used for referencing elements in an array is zero based, ‘Row Major’ means that when we are referring to an individual row or column within the matrix, for example ‘third column across, second row down’, we are in fact referencing the array element [1][2] (i.e. [Row][Column]). This means that even where the coordinate system information chunk is written, all matrices within the file should still use row major ordering. If the export application stores matrices designed for use in OpenGL for example, whose matrices are column major; these matrices must be re-ordered during the physical export of any object matrix.

On import, if this chunk has been written, the application would transform all

vertex coordinates, normals and matrices, using the ‘CoordSysMatrix’ stored here, to convert that information to the base right handed coordinate system before processing. In addition the ‘WindingOrder’ variable must be taken into account should the vertex winding order need to be adjusted for use during rendering.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 90 of 92.

Note: This chunk need not be written if the default coordinate system is adopted.

Page 91: IWF Specifications v2.0.0

Interchangeable World Format v2.0

4.15. Standard Chunk Arrangements

The following diagram serves as a reference table for common arrangements of the standard chunks specified within this standards document. Although not all combinations are contained within this table, additional information about which chunks can be used as a child of which other chunks, can be found underneath the ‘Standard Children’ header of each individual chunk’s reference section.

4.16. Application Compliance

There are many different factors which contribute to how specification compliant the import application is required to be. Although the IWF specification provides many varied ways of storing and interpreting world data, an application need only implement a minor subset of the standard assuming that no support is required for third party files. As an example, the IWF structure may be used by an editing application, to export mesh data in a particular fixed manner. If the associated rendering application is only required to support files exported by that editor, then full specification compliance will not be required.

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 91 of 92.

Page 92: IWF Specifications v2.0.0

Interchangeable World Format v2.0

Copyright © 2002 Daedalus Developments. All Rights Reserved.

Page 92 of 92.

5. IWF File Toolkit Version 2.0

Not yet finalised in this document revision. Please refer to intermediate source code included for current beta toolkit information.