Skip to content

sapphire-bt/incoming-reader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 

Repository files navigation

Incoming .IAN Reader

This is a JavaScript plugin for reading/writing .IAN files: a simple proprietary 3D model format used for the 1998 video game Incoming.

This format was reverse engineered without a debugger/disassembler; as a result there are still values whose purpose is unknown. These values aren't included in the data returned by the plugin but guesses as to what they are can be found in the source code.

A Python script is also included for batch exporting to OBJ format.

Key Features

  • File data can be used with three.js to render models in-browser:

"Light Fighter" model shown in three.js

  • Convert between IAN and OBJ, allowing for custom in-game models and model export to programs such as Blender, Maya, etc.

"Light Fighter" model shown in Blender

  • OBJ files can be converted to IAN format allowing custom models in-game:

Custom model 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:
  • face_count
  • vertex_count
  • vertices_offset
  • faces_offset
  • unknown
Every .IAN file seems to repeat this four times.
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:
  • unknown_1
  • unknown_2
  • indices
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:
  • x
  • y
  • z
  • normal
  • u
  • v
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 determined by the first four bits. One way to obtain the index is to use a bitwise AND:

0x85 & 0xF // 5
0x05 & 0xF // 5
0x86 & 0xF // 6
0x06 & 0xF // 6

Textures are zero-indexed.

The texture position is determined by the last four bits. A bitwise AND can be used here again:

0x85 & 0xF0 // 8
0x05 & 0xF0 // 0
0x86 & 0xF0 // 8
0x06 & 0xF0 // 0

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 Position 1
0x10 Position 2
0x20 Position 3
0x30 Position 4
0x40 Position 5
0x50 Position 6
0x60 Position 7
0x70 Position 8
0x80 Position 9
0x90 Position 10
0xA0 Position 11
0xB0 Position 12
0xC0 Position 13
0xD0 Position 14
0xE0 Position 15
0xF0 Position 16

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:

"Moon" heightmap wireframe "Moon" heightmap with simple texture mapping


"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.