// Types
char: 8-bit ASCII character (uint8_t)
byte: unsigned 8-bit integer (uint8_t)
float: 32-bit single-precision floating point value
int32: signed 32-bit integer (int32_t)
// Length-prefixed string
typedef struct {
byte length; // The length of the string (max 256)
char[length] string; // The ASCII-encoded string
} p_char;
// RGB colour
typedef struct {
byte[3] rgb; // One byte each for red, green and blue channel
} Color;
// RGBA colour
typedef struct {
byte[4] rgba; // One byte each for red, green, blue and alpha channel
} RgbaColor;
// 3D Vector
typedef struct {
float x;
float y;
float z;
} Vector;
typedef struct {
float version; // File format version (2.2 is the most recent version)
char[3] magic; // File format magic number, "RMF" in ASCII encoding
int32 visgroup_count; // Number of VisGroups
VisGroup[visgroup_count] visgroups; // VisGroups objects
World worldspawn; // The "CMapWorld" object which contains all other MapObjects as children objects
Docinfo docinfo; // This is optional, the file is still valid if this is not present
} Rmf;
MapObjectBase
) and the type of each object is indicated by the first field - the object type.
typedef struct {
p_char object_type; // CMapWorld, CMapSolid, CMapBrush, CMapEntity
int32 visgroup_id; // ID of the VisGroup the object belongs to
Color color; // Editor color of the object
int32 child_count; // Number of child objects
MapObject[child_count] brushes; // List of child objects
} MapObjectBase;
CMapWorld and CMapEntity also have the same layout for entity data, which we'll call EntityData
.
typedef struct {
p_char classname; // The entity's classname
byte[4] unknown1; // Unused
int32 spawnflags; // The entity's spawnflags
int32 kv_count; // Number of entity's key-value pairs
KeyValue[kv_count] keyvalues; // Entity's key-value pairs (properties)
byte[12] unknown2; // Unused
} EntityData;
typedef struct {
MapObjectBase base_data;
EntityData entity_data;
int32 path_count; // Number of path objects
Path[path_count] paths; // Path objects (created with the Path tool)
} World;
typedef struct {
MapObjectBase base_data;
int32 face_count; // Number of faces (polygons) making up the brush
Face[face_count] // The brush's faces
} Brush;
typedef struct {
MapObjectBase base_data;
EntityData entity_data;
byte[2] unknown1; // Unused
Vector origin; // The origin if it's a point entity
byte[4] unknown2; // Unused
} Entity;
typedef struct {
MapObjectBase base_data;
} Group;
typedef struct {
char[128] name; // VisGroup name (null terminated)
RgbaColor color; // Editor color of the VisGroup
int32 visgroup_id; // VisGroup's ID number
byte visible; // Whether the VisGroup is visible or not
byte[3] unknown;
} VisGroup;
angle
value is what has already been applied to the face and is reflected in the right_axis
and down_axis
. In other words, any texture projected along right_axis
and down_axis
will already be rotated. You will mostly only use this to undo the rotation done to the texture.
typedef struct {
char[260] texture_name; // Name of the texture applied to the face (null terminated)
Vector right_axis; // The texture's projected right axis
float shift_x; // Horizontal shift of the texture
Vector down_axis; // The texture's projected down axis
float shift_y; // Vertical shift of the texture
float angle; // The angle of the applied rotation
float scale_x; // Horizontal scale multiplier
float scale_y; // Vertical scale multiplier
byte[16] unknown; // Unused
int32 vertex_count; // Number of vertices in the face
Vector[vertex_count] vertices; // The vertices that make up the face
Vector[3] plane_points; // A triplet of points that define the face plane
} Face;
typedef struct {
p_char key; // Key of the property
p_char value; // Value of the property
} KeyValue;
path_
entities manually. NOTE: Hammer's method of converting paths to entities is incorrect, and this tool should generally be avoided unless using a custom tool such as hlfix to convert your RMF to .map prior to compilation.
typedef struct {
char[128] path_name; // The base name for this path (null terminated)
char[128] classname; // Typically path_corner or path_track (null terminated)
int32 path_type; // The direction of the path
int32 node_count; // Number of nodes in the path
PathNode[node_count] nodes; // The nodes that make up the path
} Path;
The path_name
will be used as the base name for the nodes belonging to this path, i.e. for a path named my_path
each node will be named my_path01
, my_path02
, etc.path_type
can have one of three different values:0
: One way (from first to last node and stops there).1
: Circular (from first to last and back to first again, as an endless loop).2
: Ping pong (from first to last and reverse direction back to first, in an endless loop).
typedef struct {
Vector position; // The node's position in world coordinates
int32 index; // The node's index in the path
char[128] name_override; // Name to use instead of auto-generated one (null terminated)
int32 kv_count; // Number of node's key-value pairs
KeyValue[kv_count] keyvalues; // Node's key-value pairs (properties)
} PathNode;
typedef struct {
char[8] docinfo; // The string "DOCINFO" with a null terminator
float docinfo_version; // Possibly version number of the docinfo/camera data - always equal to 0.2
int32 active_camera; // Index of the active camera
int32 camera_count; // Number of camera objects
Camera[camera_count]; // Camera objects
} Docinfo;
typedef struct {
Vector eye_position; // The position of the camera in world coordinates
Vector lookat_position; // The target position in world coordinates the camera will look at
} Camera;
Face
structure:
typedef struct {
char[260] texture_name;
// right_axis not present
float shift_x;
// down_axis not present
float shift_y;
float angle;
float scale_x;
float scale_y;
byte[16] unknown;
int32 vertex_count;
Vector[vertex_count] vertices;
Vector[3] plane_points;
} Face18;
right_axis
and down_axis
are no longer present, the texture axes are determined by the normal of the face using Quake logic. See TextureAxisFromPlane
in the Quake compiler tools for the implementation.
Face
structure:
typedef struct {
char[40] texture_name; // Texture name is only 40 chars
// right_axis not present
float shift_x;
// down_axis not present
float shift_y;
float angle;
float scale_x;
float scale_y;
byte[4] unknown; // Only 4 unused bytes instead of 16
int32 vertex_count;
Vector[vertex_count] vertices;
Vector[3] plane_points;
} Face18;
The texture name is only 40 characters long in this version, and the unknown data is only 4 bytes long. Texture axes are calculated using the Quake method, same as v1.8.
You must log in to post a comment. You can login or register a new account.