For the complete documentation index, see llms.txt. This page is also available as Markdown.

PLY format (.ply)

Overview

The .ply is a chunk-based format used to store meshes in engines of the GEM family.

Each file may contain:

  • static meshes;

  • skinned meshes;

  • landscape meshes;

  • terrain grids;

  • adjacency data;

  • shadow data;

  • multiple UV channels;

  • tangent space;

  • skinning

  • materials and textures

File structure

File header

Each .ply file begins with one of the following identifiers:

Name
Type
Size
Description

EPLY

uint8[4]

4

Regular mesh with 16-bit indices

BPLY

uint8[4]

4

Landscape mesh with 32-bit indices.

PM01

uint8[4]

4

GEM3 mesh format

The starting FourCC is a file format identifier, it is not a regular chunk. After reading the starting FourCC, the parser reads the rest of the file as a sequence of chunks.

Chunk IDs

FourCC
Purpose

INDX

Mesh indices (16-bit)

IND4

Mesh indices (32-bit)

VERT

Vertex data

BAS2

Terrain grid basis

InfG

Terrain grid

BNDS

Bounding box

ADJA

Adjacency

SHDW

Shadow data

MROR

Mirrored mesh flag

MARK

Markup data

SKIN

Bone map

MESH

Legacy submesh

SBM1

GEM RTS 1.1+ submesh

SUBM (GEM RTS)

GEM3 / GEM RTS submesh

SUBM (AS2)

Assault Squad 2 submesh

Chunk ID loading loop

Chunk INDX | IND4

Data structure

Chunk INDX

Name
Type
Size
Description

FourCC

uint8[4]

4

INDX Mesh indices

index_count

int32

4

Number of indices

indices

uint16[index_count]

2

Index array. Index size is determined by the starting chunk ID

Chunk IND4

Name
Type
Size
Description

FourCC

uint8[4]

4

IND4 Mesh indices

index_count

int32

4

Number of indices

indices

uint32[index_count]

4

Index array. Index size is determined by the starting chunk ID

Chunk VERT

Name
Type
Size
Description

FourCC

uint8[4]

4

VERT

vertex_count

int32

4

Number of vertices

vertex_size

uint16

2

Size of a single vertex in bytes. The engine primarily relies on this value even if the size calculated from flags is smaller

vertex_flags

uint16

2

Vertex flag bit mask

vertices

struct[vertex_count]

Vertex array. Vertex structure depends on the submesh format

FVF

Vertex flags are combined using a bit mask.

Bit
Description

0x0001

Full color. If the flag is absent, vertex colors are multiplied by 2 after loading

0x0002

Optimized vertex order. If the flag is absent, the engine may attempt to optimize the mesh automatically after loading

0x0004

Color verified. *) Not used in GEM RTS

Vertices struct[vertex_count]

Name
Type
Size
Description

position

float[3]

12

Vertex position in local coordinates

normal

float[3]

12

Normal vector in local coordinates

tangent

float[3]

12

Tangent vector in local coordinates. Optional

uv

float[2]

8

Texture UV coordinates. Multiple UV sets are supported

bone_indices

uint8[4]

4

Indices into the local submesh bone remap

bone_weights

uint8[4]

4

Bone weights stored in UNORM8 format (0..1)

Chunk BAS2

Terrain grid basis.

Name
Type
Size
Description

FourCC

uint8[4]

4

BAS2

polygons.center

float[2]

8

Origin of the triangle generation coordinate system

polygons.axis_x

float[2]

8

X axis of the triangle generation coordinate system

polygons.axis_y

float[2]

8

Y axis of the triangle generation coordinate system

texture.center

float[2]

8

Origin of the UV coordinate system

texture.axis_x

float[2]

8

X axis of UV space

texture.axis_y

float[2]

8

Y axis of UV space

Chunk InfG

Terrain triangle grid.

Name
Type
Size
Description

FourCC

uint8[4]

4

InfG Terrain grid

grid_start_xy

int32[2]

8

Grid starting coordinates

grid_end_xy

int32[2]

8

Grid ending coordinates

face_count

uint32

4

Number of triangles

faces

uint16[face_count]

Triangle data array

Bit layout of faces

Bit
Description / Value

0x7FFF

Submesh index submesh: 15

0x8000

Invalid triangle flag invalid: 1

Chunk BNDS

Axis-aligned mesh bounding box.

Name
Type
Size
Description

FourCC

uint8[4]

4

BNDS Mesh bounding box

min

float[3]

12

Minimum XYZ coordinates

max

float[3]

12

Maximum XYZ coordinates

Chunk ADJA

Information about adjacent triangles.

*) Not used in GEM RTS.

Name
Type
Size
Description

FourCC

uint8[4]

4

ADJA Adjacency information

face_count

int32

4

Number of triangles

adjacencies

struct[face_count]

Triangle neighbour information

Adjacencies (struct)

Name
Type
Size
Description

neighbours

uint16[3]

6

Indices of neighbouring triangles. 0xFFFF means no neighbour

Chunk SHDW

Shadow information.

*) Not used in GEM RTS.

Name
Type
Size
Description

FourCC

uint8[4]

4

SHDW Shadow information

face_count

int32

4

Number of triangles

shadow_infos

uint8[face_count]

Shadow casting flags:

  • 0: does not cast shadows

  • 1: casts shadows

Chunk MROR

Mirrored mesh flag.

Name
Type
Size
Description

FourCC

uint8[4]

4

MROR Indicates a mirrored mesh

Chunk MARK

Triangle markup.

*) Not used in GEM RTS.

Name
Type
Size
Description

FourCC

uint8[4]

4

MARK

mark_size

uint32

4

Size of markup data

marks

uint8[mark_size]

Binary markup data

Chunk SKIN

Bone map for a skinned mesh.

Name
Type
Size
Description

FourCC

uint8[4]

4

SKIN

bone_count

uint32

4

Number of bones

bone_names

string8[bone_count]

Bone names

Chunk SUBM (GEM RTS, GEM3)

Submesh description format used by GEM3 and GEM RTS models.

The file must start with the PM01 format identifier.

Name
Type
Size
Description

FourCC

uint8[4]

4

SUBM

vertex_format

uint16

2

Vertex format bit mask

face_start

uint16

2

Index of the first triangle in the submesh

face_count

uint16

2

Number of triangles in the submesh

vertex_start

uint16

2

Index of the first vertex in the submesh. Not used in GEM RTS

vertex_count

uint16

2

Number of vertices in the submesh. Not used in GEM RTS

mesh_flags

uint16

2

Bit flags describing mesh properties

material_name

string8/24

1+

Material name

Bit field vertex_format

Value
Type
Comment

0x0001

float[3]

Position

0x0002

float[3]

Normal

0x0004

uint8[4]

Color 0, RGBA

0x0008

uint8[4]

Color 1, RGBA

0x0010

float[2]

Texture coordinates 0

0x0020

float[2]

Texture coordinates 1

0x0040

float[2]

Texture coordinates 2

0x0080

float[2]

Texture coordinates 3

0x0100

float[4]

Tangent

0x0200

uint8

Skinning with 2 bones

0x0400

uint8[2]

Skinning with 3 bones

0x0600

uint8[3]

Skinning with 4 bones. Both 0x0200 and 0x0400 bits are set simultaneously

0x0800

float

Wind amplitude

Bit mask for mesh_flags

Value
Description

0x0001

Double-sided mesh

0x0002

Skin

Skin data

Present only if the 0x0002 (skin) flag is set in mesh_flags.

Name
Type
Size
Description

bone_count

uint8

1

Number of bones used by the skin

bone_map

uint8[bone_count]

bone_count

Bone indices in the bone map

Vertex bone_indices reference entries in the local bone_map array rather than directly indexing the global SKIN chunk. This local remapping allows each submesh to use only the subset of bones required for its vertices.

Values of bone_map

Value
Meaning

0

Use the mesh's global transform matrix

N > 0

Use SKIN.bones[N - 1]

Chunk SBM1

GEM RTS 1.1+ submesh format used for map meshes.

Name
Type
Size
Description

FourCC

uint8[4]

4

SBM1

vertex_elements

struct[]

Vertex element descriptors

tags

struct[]

List of custom vertex tags

face_start

int32

4

Index of the first triangle in the submesh

face_count

int32

4

Number of triangles in the submesh

mesh_flags

uint32

4

Mesh bit flags

material_name

string8/24

1+

Material name

Vertex format elements

The vertex_elements[] array describes the vertex layout.

The list does not contain an element count and is read sequentially until a terminator element is encountered.

The type_usage field stores both the element type and its semantic:

  • (type_usage & 0x0F) specifies the element type.

  • (type_usage & 0xF0) >> 4 specifies the element usage.

The value 0xFF is used as the list terminator and ends vertex format parsing.

Element structure

Name
Type
Size
Description

type_usage

uint8

1

Element type and semantic

usage_index

uint8

1

Usage index

stream_index

uint8

1

Stream index

Element type

Determined by the lower four bits of type_usage.

Value
Name
Type
Comment

0

FLOAT1

float

1

FLOAT2

float[2]

2

FLOAT3

float[3]

3

FLOAT4

float[4]

4

SHORT2

int16[2]

5

BYTE4

uint8[4]

6

COLOR

uint8[4]

RGBA

7

HALF4

float[4]

Half-precision

8

BYTE4N

uint8[4]

UNORM8

Element usage

Determined by the upper four bits of type_usage.

Value
Description

0

POSITION

1

NORMAL

2

COLOR

3

TEXCOORD

4

BLEND WEIGHT

5

BLEND INDICES

6

TANGENT

Vertex tags

The tags[] list contains additional user-defined tags for vertex elements.

The list does not contain an element count and is read sequentially until a terminator element is encountered.

The value 0xFF is used as the tag list terminator.

Tag structure

Name
Type
Size
Description

tag_index

uint8

1

Vertex element index

tag_chunk

uint32

4

Tag identifier

Bit mask for mesh_flags

Value
Description

0x0001

Two-sided mesh (render without back-face culling)

0x0002

Use alpha (compatibility mode)

0x0004

Use realtime scene lighting

0x0008

Use player color lighting

0x0010

Skinned mesh

0x0020

Shadow volume mesh

0x0040

Mirrored mesh (negative scaling)

0x0080

Blend by second texture alpha

0x0100

Bump mapping (compatibility mode)

0x0200

Specular color is stored

0x0400

Uses materials instead of textures

0x0800

Sub-skin feature

0x1000

Two textures share a single texture coordinate set

0x2000

Uses VD (compatibility mode)

0x4000

Contains a lightmap

Chunk MESH

Legacy submesh format used in Faces of War and Men of War.

Name
Type
Size
Description

FourCC

uint8[4]

4

MESH Legacy submesh format

fvf

uint32

4

Vertex format bit mask

face_start

int32

4

Index of the first triangle

face_count

int32

4

Number of triangles

mesh_flags

uint32

4

Mesh bit flags

Vertex format flags (FVF)

Bit mask describing the vertex format.

The fvf field contains a uint32 bit mask. The values shown below represent vertex layouts encountered in the format. If a value not listed in the table is found in a file, it should be interpreted as a combination of the corresponding flags.

For example, the value 0x00000012 is stored in the file as the byte sequence 12 00 00 00 (Little-endian). If flags 0x00000002 and 0x00000010 correspond to position and normal, then 0x00000012 indicates that both fields are present in the vertex.

Mask
Description

0x002

position float[3]

0x006

position float[3] blend_weight uint8 blend_indices uint8[4]

0x008

position float[3] blend_weight uint8[2] blend_indices uint8[4]

0x00A

position float[3] blend_weight uint8[3] blend_indices uint8[4]

0x010

normal float[3]

0x040

diffuse_color uint8[4]

0x080

specular_color uint8[4]

0xN00

texcoord_mask N × float[2]

0x8000E000

tangent float[4]

Bit mask for mesh_flags

Value
Description

0x0001

Two-sided mesh (render without back-face culling)

0x0002

Use alpha (compatibility mode)

0x0004

Use realtime scene lighting

0x0008

Use player color lighting

0x0010

Skinned mesh

0x0020

Shadow volume mesh

0x0040

Mirrored (negative scaling)

0x0080

Blend by second texture alpha

0x0100

Bump (compatibility mode)

0x0200

Specular

0x0400

Use material

0x0800

Sub-skin feature

0x1000

Two textures with one texcoord

0x2000

Using VD (compatibility mode)

0x4000

Has lightmap

Specular color

Present if mesh_flags contains 0x0200 (specular).

Name
Type
Size
Description

specular_color

uint8[4]

4

Specular color

Material name

Present if mesh_flags contains 0x0400 (use material).

Name
Type
Size
Description

material_name

string8/24

1+

Material name

Texture data

Texture data is loaded when mesh_flags does not contain 0x0400 (use material). The structure depends on the specular, bump, number of texture coordinate sets (UV), and the two textures with one texcoord flag.

Texture data for standard material

Used when mesh_flags contains specular or bump.

Name
Type
Size
Description

diffuse

string8/24

1+

Diffuse texture name

specular_texture

string8/24

1+

Specular texture name. Present if mesh_flags contains specular

bump_texture

string8/24

1+

Normal map texture name. Present if mesh_flags contains bump

Texture data for two textures

Used if the standard material path is not used and one of the following conditions is true:

  • uv == 2

  • mesh_flags contains two textures with one texcoord

Name
Type
Size
Description

diffuse_0

string8/24

1+

Diffuse texture 0 name

diffuse_1

string8/24

1+

Diffuse texture 1 name

Texture data for one texture

Used if the standard material path is not used and the conditions for using two textures are not met.

Name
Type
Size
Description

diffuse

string8/24

1+

Diffuse texture name

Skin data

Skin data is present if mesh_flags contains skinned mesh.

Name
Type
Size
Description

bone_map_size

uint8

1

Size of the local bone remapping table

bone_map

uint8[bone_map_size]

bone_map_size

Local bone remapping table

The bone_map table is used to map submesh bones to the global bone map stored in the SKIN chunk.

Each array element contains the index of a bone from SKIN, incremented by 1.

Vertex bone_index values reference entries in the bone_map array rather than directly indexing bones in SKIN.

This allows a submesh to use only the subset of bones required by its vertices.

Values of bone_map

Value
Meaning

0

Use the mesh's global transform matrix

N > 0

Use SKIN.bones[N - 1]

Chunk SUBM (Assault Squad 2)

Submesh description format used by map meshes from Assault Squad 2. This format is used when the starting chunk is not PM01.

Name
Type
Size
Description

FourCC

uint8[4]

4

SUBM

vertex_elements

struct[]

List of vertex format elements

face_start

uint32

4

Index of the first triangle in the submesh

face_count

uint32

4

Number of triangles in the submesh

unknown[2]

uint32[2]

8

Unknown data

mesh_flags

uint32

4

Mesh bit flags

material_name

string8

1+

Material name

Vertex elements info

The vertex_elements[] list describes the vertex layout.

The list does not contain an element count and is read sequentially until a terminator element is encountered.

The type_usage field stores both the element type and its semantic.

  • (type_usage & 0x0F) determines the element type.

  • (type_usage & 0xF0) >> 4 determines the element usage.

The value 0xFF is used as the list terminator and ends vertex format parsing.

Name
Type
Size
Description

type_usage

uint8

1

Element type and semantic

Element type

Determined by the lower four bits of the type_usage field.

Value
Name
Type
Comment

0

FLOAT1

float

1

FLOAT2

float[2]

2

FLOAT3

float[3]

3

FLOAT4

float[4]

4

SHORT2

int16[2]

5

BYTE4

uint8[4]

6

COLOR

uint8[4]

RGBA

7

HALF4

float[4]

Half-precision

8

BYTE4N

uint8[4]

UNORM8

Element usage

Determined by the upper four bits of the type_usage field.

Value
Description

0

POSITION

1

NORMAL

2

COLOR

3

TEXCOORD

4

BLEND WEIGHT

5

BLEND INDICES

6

TANGENT

Bit mask for mesh_flags

Value
Description

0x0001

Two-sided mesh (render this mesh without culling)

0x0002

Use alpha (compatibility mode)

0x0004

Use realtime scene lighting

0x0008

Use player color lighting

0x0010

Skinned mesh

0x0020

Shadow volume mesh

0x0040

Mirrored (has negative scaling)

0x0080

Blend by second texture alpha

0x0100

Bump (compatibility mode)

0x0200

Specular color stored

0x0400

Format with material instead of textures

0x0800

Sub-skin feature

0x1000

Two textures with one texcoord

0x2000

Using VD (compatibility mode)

0x4000

Has lightmap

Last updated