// 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)
int16: signed 16-bit integer (int16_t)
// Length-prefixed string
typedef struct {
int32 length; // The length of the string
char[length] string; // The ASCII-encoded string
} p_char;
// RGBA colour
typedef struct {
byte[4] rgba; // One byte each for red, green, blue and alpha channel
} Color;
// 3D Vector
typedef struct {
float x;
float y;
float z;
} Vector3;
// 2D Vector
typedef struct {
float x;
float y;
} Vector2;
// Editor flags
enum JmfFlags
{
None = 0x00,
PointBased = 0x01, // Or maybe 'HasOrigin'?
Selected = 0x02,
Hidden = 0x08,
RenderMode = 0x10, // Any other render mode than 'normal'
IsWorld = 0x20, // worldspawn entity
WeaponOrItem = 0x40, // weapon* and item_* entities
PathEntity = 0x80, // path* entities
Unknown = 0x8000, // Unknown purpose, appears to be related to models, may have been introduced in file format v122
}
typedef struct {
char[4] magic; // File format magic number, "JHMF" in ASCII encoding
int32 version; // File format version (only version 121 is documented here)
int32 ep_count; // Number of recent export paths
p_char[ep_count] export_paths; // Recent export paths
int32 group_count; // Number of groups in the map
Group[group_count] groups; // Group objects
int32 visgroup_count; // Number of VisGroups
VisGroup[visgroup_count] visgroups; // VisGroups objects
Vector3 cordon_min; // Minimum corner of the Cordon box
Vector3 cordon_max; // Maximum corner of the Cordon box
int32 camera_count; // Number of Camera objects
Camera[camera_count] cameras; // Camera objects
int32 path_count; // Number of path objects
Path[path_count] paths; // Path objects (created with the Path tool)
Entity[] entities; // All entities including worldspawn, read until the end of the file
} Jmf;
All world brushes are stored within the worldspawn entity. The entities
array is read until the end of file.
typedef struct {
int32 group_id; // The ID number of this group
int32 group_parent_id; // ID of the group this group is nested within
int32 flags; // Editor flags
int32 count; // Number of objects in the group
Color color; // Editor color of the object
} Group;
typedef struct {
p_char name; // VisGroup name
int32 visgroup_id; // VisGroup's ID number
Color color; // Editor color of the VisGroup
byte visible; // Whether the VisGroup is visible or not
} VisGroup;
typedef struct {
Vector3 eye_position; // The position of the camera in world coordinates
Vector3 lookat_position; // The target position in world coordinates the camera will look at
int32 flags; // Editor flags
Color color; // Editor color of the Camera
} Camera;
typedef struct {
p_char key; // Key of the property
p_char value; // Value of the property
} KeyValue;
path_
entities manually. It works similar to the Path tool in Hammer although can offer a "preview" in the 3D viewport of a camera travelling along the path with the speed specified by each node. One can read more about this in the J.A.C.K VDKManual.
typedef struct {
p_char classname; // Typically path_corner or path_track
p_char path_name; // The base name for this path
int32 path_type; // The direction of the path
int32 flags; // Editor flags
Color color; // Editor color 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_path
, my_path_1
, 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 {
p_char name_override; // Name to use instead of auto-generated one
p_char fire_on_pass; // Trigger this target when this node has been reached
Vector3 position; // The node's position in world coordinates
Vector3 angles; // The node's angles
int32 flags; // Entity spawnflags
int32 kv_count; // Number of node's key-value pairs
KeyValue[kv_count] keyvalues; // Node's key-value pairs (properties)
} Node;
typedef struct {
p_char[] classname; // The entity's classname
Vector3 origin; // The origin if it's a point entity
int32 flags; // Editor flags
int32 group_id; // ID of the group this entity belongs to
int32 root_group_id; // The top-most group this entity is nested within
Color color; // Editor color of the Path
p_char[13] special_keys; // The names of various special attributes used by J.A.C.K
int32 sp_spawnflags; // Entity spawnflags
Vector3 sp_angles;
int32 sp_rendering;
Color sp_fx_color;
int32 sp_rendermode;
int32 sp_render_fx;
int16 sp_body;
int16 sp_skin;
int32 sp_sequence;
float sp_framerate;
float sp_scale;
float sp_radius;
byte[28] unknown;
int32 kv_count; // Number of entity's key-value pairs
KeyValue[kv_count] keyvalues; // Entity's key-value pairs (properties)
int32 vg_count; // Number of VisGroups
KeyValue[vg_count] visgroup_ids; // The ID numbers of the VisGroups the entity belongs to
int32 brush_count; // Number of brushes
Solid[brush_count] brushes; // The brushes making up this entity (empty if point entity)
} Entity;
The special attributes section is a bit of a mystery. The fields and their data types here just reflect how they're described in MESS and should not be taken as a definite guide for parsing this part of the file. All these values are duplicated in the entity keyvalues, so it seems fairly safe to simply skip over these fields.
typedef struct {
int32 mesh_count; // Number of meshes (e.g. Quake III/Volatile patches)
int32 flags; // Editor flags
int32 group_id; // ID of the group this entity belongs to
int32 root_group_id; // The top-most group this entity is nested within
Color color; // Editor color of the Path
int32 vg_count; // Number of VisGroups
KeyValue[vg_count] visgroup_ids; // The ID numbers of the VisGroups the entity belongs to
int32 face_count; // Number of faces (polygons) making up the brush
Face[face_count] faces; // The brush's faces
Mesh[mesh_count] meshes; // The brush's meshes
} Brush;
typedef struct {
Vector3 right_axis; // The texture's projected right axis
float shift_x; // Horizontal shift of the texture
Vector3 down_axis; // The texture's projected down axis
float shift_y; // Vertical shift of the texture
Vector2 scale; // Horizontal and vertical scale multiplier
float angle; // The angle of the applied rotation
int32 texture_alignment; // Flags: 0x01 = world-aligned, 0x02 = face-aligned
byte[12] unknown;
int32 surface_flags; // Content flags for Quake 2 maps
char[64] texture_name; // Name of the texture applied to the face
} SurfaceProperties;
typedef struct {
int32 render_flags; // I'm unsure what this does. Editor flags perhaps?
int32 vertex_count; // Number of vertices in the face
SurfaceProperties surface; // The texture information of the face
Vector3 normal; // Face plane normal
float distance; // Face plane distance from origin
int32 aligned_axis; // 0 = X-axis, 1 = Y-axis, 2 = Z-axis, 3 = face normal is not axis-aligned
Vertex[vertex_count] vertices; // The vertices that make up the face
} Face;
typedef struct {
Vector3 coordinates; // Vertex coordinates
Vector2 texture_uv; // The U/V coordinates of the texture on this vertex are stored in the X/Y values of this vector
byte selection_state; // 1 = vertex is selected, 2 = midpoint between this and next vertex is selected
} Vertex;
typedef struct {
int32 width; // Mesh width (number of points)
int32 height; // Mesh height (number of points)
SurfaceProperties surface; // The texture information of the mesh
byte[4] unknown;
MeshPoint[1024] points; // Yes, every curve stores 1024 points, regardless of width/height
} Mesh;
Mesh points are stored in rows - the first point is (0, 0), the second point is (0, 1), and so on up until (0, 31), before moving onto the next row - (1, 0). Only the points where x < width
and y < height
are actually parts of the mesh, the others are to be ignored.
typedef struct {
Vector3 position;
Vector3 normal;
Vector2 texture_uv;
byte is_selected;
} MeshPoint
You must log in to post a comment. You can login or register a new account.
From what I've found so far, the new structure looks like this: and for the background image struct: