Skip to main content

GND

This document describes the GND file format used in the Ragnarok Online client.

Contents

GND files contain the following information:

  • The entirety of a map's surface geometry (i.e., the ground/static terrain)
  • A list of diffuse textures and texture coordinates for mapping them to the terrain
  • Vertex colors and precomputed lightmap textures to add lights and shadows
  • In later versions they can also include the configuration of the water surfaces, which were previously stored in RSW files

The file contents effectively represent the basic terrain for a given map, without 3D models, sprites, or other decoration.

Layout

Arcturus & iRO Alpha

Unversioned GND files were already used in Arcturus. They also appear in the iRO alpha client, alongside more recent versions.

FieldOffsetLengthTypeDescription
TextureCount04intNumber of diffuse texture paths
Width44intWidth of the cube grid
Height84intHeight of the cube grid
TexturePaths1280arrayTextureCount entries; all paths are null-terminated C strings
GroundMeshCubesvariable28arrayWidth * Height entries

Cube Grid

Compared to later versions of the format, the indirection from cubes to textured surfaces doesn't yet exist:

FieldOffsetLengthTypeDescription
UpwardsFacingTexture04intTexture ID of the upwards-facing GROUND surface
NorthernWallTexture44intTexture ID of the northwards-facing WALL surface
EasternWallTexture84intTexture ID of the eastwards-facing WALL surface
BottomLeftHeight124floatAltitude of the bottom left corner (in world units)
BottomRightHeight164floatAltitude of the bottom right corner (in world units)
TopLeftHeight204floatAltitude of the top left corner (in world units)
TopRightHeight244floatAltitude of the top right corner (in world units)
VertexColor284intARGB vertex color (stored as BGRA) for the bottom left vertex
TBD324intPurpose unknown, but its value seems to always be 1 (?)
TextureCoordinates3632floatDiffuse texture UVs (uses the same format as later versions)

The format used to store texture coordinates seems to be identical to the one used in GND 1.7 and later.

Version 1.5

Certain maps in the iRO alpha client use GND 1.5. These are much closer to the version used in the modern RO client.

The format is identical to GND 1.7, except that the lightmap format is stored globally instead of on a per-slice basis:

Version 1.6

Some unverified information is available for this version, but there aren't any known files that actually use it.

Version 1.7

This is the original version used for most maps in the modern RO client:

FieldOffsetLengthTypeDescription
Header04string"GRGN" as an ASCII-encoded, fixed-size string
MajorVersion41byteVersioning information
MinorVersion51byteVersioning information
Width64intWidth of the cube grid
Height104intHeight of the cube grid
Scale144floatGeometry scale factor (always 10)
TextureCount164intNumber of diffuse texture paths
TexturePathLength204intLength of each texture path string, in bytes (always 80)
TexturePaths24+80stringNull-terminated (discard garbage bytes at the end)
LightmapSliceCountvariable4intNumber of lightmap (and ambient occlusion) texture slices
LightmapSlicesvariable268structAmbient occlusion and lightmap texture bitmaps (alternating)
SurfaceCountvariable4intNumber of textured surface blueprints
SurfaceDefinitionsvariable56arrayShared texturing information (copy to each cube vertex)
GroundMeshCubesvariable28arrayWidth * Height entries

Lightmap Slices

The lightmap and ambient occlusion textures are split into small bitmaps:

FieldOffsetLengthTypeDescription and notes
PixelFormat44intEncoding of the lightmap and ambient occlusion pixels (usually 11)
Width84intWidth of each texture bitmap (always 8)
Height124intHeight of teach texture bitmap (always 8)
ShadowmapPixels1664arrayWidth * Height ambient occlusion texture pixels (intensity values)
LightmapPixels16192arrayWidth * Height lightmap texture pixels (specularity values)

Textured Surfaces

These can be used to construct the terrain geometry (vertex data):

FieldOffsetLengthTypeDescription and notes
TextureCoordinates032arrayDiffuse texture UVs (array of float values, see below)
Texture322shortID of the diffuse texture to apply to this surface (-1 means "none")
LightmapSlice362ushortID of the lightmap (and ambient occlusion) slice to apply to the surface
VertexColor4016arrayBGRA-ordered color (byte values) of the surface's bottom left vertex

Texture Coordinates

Texture coordinates are stored in the following order:

  1. bottomLeftU
  2. bottomRightU
  3. topLeftU
  4. topRightU
  5. bottomLeftV
  6. bottomRightV
  7. topLeftV
  8. topRightV

The direction is always relative to the cube that the surface belongs to, i.e., bottomLeft is south-west and topRight is north-east.

Cube Grid

FieldOffsetLengthTypeDescription
BottomLeftHeight04floatAltitude of the bottom left corner (in world units)
BottomRightHeight44floatAltitude of the bottom right corner (in world units)
TopLeftHeight84floatAltitude of the top left corner (in world units)
TopRightHeight124floatAltitude of the top right corner (in world units)
UpwardsFacingSurface164intUpwards-facing surface ID
NorthernWallSurface204intSurface ID of the northwards-facing wall
EasternWallSurface244intSurface ID of the eastwards-facing wall

Version 1.8

The water plane configuration that was previously part of the RSW file has been moved to the GND file instead.

All the information stored in version 1.7 is still present (and unchanged), plus the water plane configuration (appended).

Water Plane Configuration

In theory, this GND version supports multiple water planes. But in practice, all maps that use it only feature a single one.

FieldOffsetLengthTypeDescription
WaterLevel04floatHeight of the default water plane (there's always at least one)
WaterType44intTexture ID that's applied to the water plane (tiled)
WaveHeight84floatAmplitude of the water plane's animation curve
WaveSpeed124floatPhase of the water plane's animation curve
WavePitch164floatSurface curvature in degrees (origin of the curve)
TextureCyclingInterval204intAfter how many frames the next texture should be swapped in

This is the basic water configuration, as present in both RSW (pre-2.6) and the next GND version.

The configuration for the other planes follows after the above, and is (in this version) always of the following form:

  1. NumWaterPlanesU (int value): How many water planes there are in the horizontal dimension (always 1)
  2. NumWaterPlanesV (int value): How many water planes there are in the vertical dimension (always 1)
  3. A float defining the WaterLevel (altitude) of this plane. It's always identical to the water level above, since there's only one.

If there were multiple values here, it would likely be the WateLlevel of each plane (assuming the presence of u * v planes), but since that doesn't happen (and there's already a new GND version available) it seems unlikely that this would ever be used.

Version 1.9

All the information stored in version 1.7, plus the water plane configuration (appended). The latter consists of the same information as is present in 1.8, but the format for defining multiple water planes has changed (and they are in fact used in some of the episode 19 maps I've seen, such as icecastle.gnd):

  1. NumWaterPlanesU (int value): How many water planes there are in the horizontal dimension (NOT always 1)
  2. NumWaterPlanesV (int value): How many water planes there are in the vertical dimension (NOT always 1)
  3. The same structure as defined for the original water plane (see table above), repeated u * v times

I'm not quite sure what the original configuration is still used for, but I'm guessing it would serve as a fallback in case the numbers (u, v) are both zero (i.e., there aren't any water planes defined in this section). More research is needed.

References

Footnotes

  1. This value appears to be ignored; the actual pixel format should always be 8-bit RGBA (stored as ARGB).