Incoming .IAN Reader
This is a JavaScript plugin for reading/writing .IAN files - a proprietary 3D model format used by the 1998 video game Incoming.
This format was reverse engineered and as a result there are still values whose meaning are unknown. These values aren't included in the data returned by the plugin, but guesses to what they are/notes can be found in the source code.
Key Features
- File data can be used with three.js to render models in-browser:
- Convert between IAN and OBJ, allowing for custom in-game models and model export to programs such as Blender, Maya, etc.
- OBJ files can be converted to IAN format allowing custom models in-game:
How to Use
Include incoming-reader.js in the page and pass an ArrayBuffer of the .IAN file to the global IncomingReader function:
<input type="file" id="file-input" />
<script src="incoming-reader.js"></script>
<script>
document.getElementById("file-input").addEventListener("input", function() {
for (const file of this.files) {
const fileReader = new FileReader();
fileReader.onload = function() {
const incomingReader = new IncomingReader(this.result);
}
fileReader.readAsArrayBuffer(file);
}
})
</script>Methods
readIAN() returns Object
Returns an object containing the following:
| Name | Type | Description |
|---|---|---|
mesh_info |
Array | Contains four identical objects, each containing:
|
unknown_end_data_count |
Number | Appears to be a count of data at the end of the file. These values may be bounding box vertices, but I'm not sure. The count also appears to be occasionally incorrect, e.g. tree7.ian reads 18, but the actual count is 16. |
unknown_end_data_offset |
Number | Offset to unknown end data. |
faces_offset |
Number | Offset to face indices (same value as repeated four times in mesh_info). |
name |
String | Model name. Not always descriptive (e.g. "Object01"). |
faces |
Array | An array of objects, each containing:
indices is an array of three indices into the vertices data. The two unknown values are usually 3, or 3 and 7. They do not appear to affect the model if set to null. |
vertices |
Array | An array of objects, each containing:
normal is an array containing 3 values, e.g. [0, -1, 0]. |
unknown_end_data |
Array | See above. |
writeIAN(filename : String)
Converts an OBJ file to IAN format.
Pass an OBJ file ArrayBuffer to the plugin and call incomingReader.writeIAN("my_model"). This will prompt a download from a Blob object URL.
It is recommended to export a default IAN file and keep your model to roughly the same size.
writeOBJ(filename : String)
Converts an IAN file to OBJ format.
Pass an IAN file ArrayBuffer to the plugin and call incomingReader.writeOBJ("my_model"). This will prompt a download from a Blob object URL.
Additional Information
Overview
The game assets are contained in the following folders (typically located at C:\Program Files (x86)\Incoming):
Incoming/
├── asc/
├── pcobject/
├── ppm/
└── wavs/
See the sections below for further details on each folder.
"asc" Folder
Contains several files related to the levels of the game, each contained in its own folder. The folder for the first level, Africa, contains:
Incoming/
└── asc/
└── africa/
├── africa.mdl
├── africa.odl
├── africa.wdl
├── africa_action.mdl
├── africa_virus.mdl
├── africa_virus.odl
├── city2tc.bin
└── tland1.bin
A brief overview of the file types:
| File | Description |
|---|---|
*.mdl |
A series of procedures describing each mission, including spawn positions of enemies, camera positions, and which speech files to play. |
*.odl |
A list of permitted models (vehicles and scenery) for this level. Basic values for the environment are also present such as RGB and fog values for the sky, as well as a list of terrain textures. |
*.wdl |
A list of level scenery and where to spawn the models. |
city2tc.bin |
Texture positions/properties for each square tile of the level (see below). |
tland1.bin |
A heightmap for the terrain (see below). |
city2tc.bin
These files consist of 128 blocks of 256 bytes. Each block corresponds to one column of the terrain, starting from north west, going across. Two bytes are used to describe the texture information for each square, which means each level is a 128×128 grid.
An excerpt from Africa's file, split into rows of two bytes:
85 00
05 00
86 00
06 00
The first byte contains two values: the texture index, and its position. Levels use eight textures for terrain which are specified inside the .odl file.
The texture index is always the last digit of the first byte, i.e. 5, 5, 6, 6 for the bytes shown above, and can be quickly calculated using the modulus operator:
0x85 % 0x10 // 5
0x05 % 0x10 // 5
0x86 % 0x10 // 6
0x06 % 0x10 // 6Textures are zero-indexed.
The texture position is determined from the remainder of the modulus operation. Terrain textures are 256×256px, however only a quarter (128×128px) segment is shown per tile. There are 16 possible positions (highlighted by the red square):
| Value | Position |
|---|---|
0x00 |
![]() |
0x10 |
![]() |
0x20 |
![]() |
0x30 |
![]() |
0x40 |
![]() |
0x50 |
![]() |
0x60 |
![]() |
0x70 |
![]() |
0x80 |
![]() |
0x90 |
![]() |
0xA0 |
![]() |
0xB0 |
![]() |
0xC0 |
![]() |
0xD0 |
![]() |
0xE0 |
![]() |
0xF0 |
![]() |
The second byte is a bitmask of texture properties, such as rotation/mirroring:
| Value | Description |
|---|---|
0x01 |
Flip horizontally. |
0x02 |
Flip vertically. |
0x04 |
Rotate 90° clockwise. |
0x08 |
Rotate 180° clockwise. |
0x10 |
Unknown; may be used for tiles which should contain water in the oceanic level. |
0x20 |
Unknown; used heavily in the oceanic level. |
0x40 |
No visible effect. |
0x80 |
No visible effect. |
tland1.bin
As mentioned, this file solely consist of height values for the terrain which is used to modify a flat plane. Each height value is a 16-bit signed integer, resulting in a 513×513 grid of values. Height values seem to be negative in Incoming, so these values would need to be inverted if used for drawing terrain.
An example applying the Moon level's values to a plane using three.js is shown below:
"pcobject" Folder
Contains all model files. Alien models are stored in "cweapons" whereas allied models can be found in "pweapons".
LOD meshes can be found within "low" folders in each directory.
Models displaying different levels of damage are separated into folders corresponding to the amount of damage (ranging from 1-3, with 3 being the most damaged).
"ppm" Folder
Contains all texture files. Textures are encoded as PPM files, an open-source bitmap format.
"wavs" Folder
Contains all sound files. Sounds are stored in WAV format. All sounds appear to be monophonic 22.05 kHz / 16-bit.
Unknown
Yet to be figured out is the purpose of the .ctl files inside the Incoming\asc\pads\ folder. As the name indicates, these may be related to healing pads.

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.





















