Difference between revisions of "Maps/Mesh"

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
Line 301: Line 301:
 
==Texture palettes (color)==
 
==Texture palettes (color)==
  
A set of 16 palettes, each containing 16 colors. Each color in the palette is 16 bits: 5 bits each for R, G, and B, and 1 bit for A. The bits are organized like this:
+
A set of 16 palettes, each containing 16 colors. Each color in the palette is 16 bits in little endian format.
 +
 
 +
  8B B1 => B1 8B
 +
 
 +
  1000 1011 1011 0001
 +
  ABBB BBGG GGGR RRRR
  
 
{| border="1"
 
{| border="1"
Line 318: Line 323:
  
 
If R == G == B == A == 0, then the color is transparent.
 
If R == G == B == A == 0, then the color is transparent.
 
  
 
==Light colors and positions, background gradient colors==
 
==Light colors and positions, background gradient colors==

Revision as of 19:39, 9 April 2021

The structure of a mesh file consists of a header of 196 bytes followed by a series of chunks of different kinds of data.

Header

The header serves as a table of contents for the data chunks. It is a series of 32-bit unsigned little-endian integers, each of which is either 0 (meaning that a given chunk is not present in the file) or an intra-file pointer to the byte where the chunk begins. Here's a table of what each pointer points to.

address of pointer type of chunk it points to
0x40 Primary mesh
0x44 Texture palettes (color)
0x4c Unknown (this pointer is only non-zero in MAP000.5)
0x64 Light colors and positions, background gradient colors
0x68 Terrain (tile heights, slopes, and surface types)
0x6c Texture animation instructions
0x70 Palette animation instructions
0x7c Texture palettes (grayscale)
0x8c Mesh animation instructions
0x90 Animated mesh 1
0x94 Animated mesh 2
0x98 Animated mesh 3
0x9c Animated mesh 4
0xa0 Animated mesh 5
0xa4 Animated mesh 6
0xa8 Animated mesh 7
0xac Animated mesh 8
0xb0 Polygon visibility angles

Notice that this table skips some pointers. The omitted pointers are 0 in every mesh file: they never point at anything.


Primary mesh

This chunk contains most of the polygons that make up the map. It contains XYZ coordinates for each vertex, normal vectors for each vertex, UV coordinates for each vertex, and the ID of the palette to use for each polygon's texture.

The polygons are divided into four groups: Textured triangles, textured quadrilaterals, untextured triangles, and untextured quadrilaterals. The untextured polygons are always black. They're used mostly around the edges of the map to make the map look like a solid cross-section.


Header

The mesh chunk begins with a header of 4 16-bit unsigned integers specifying how many of each type of polygon the mesh contains:

Mesh header
Width (bits) Data type Purpose Maximum Value
16 uint Number of textured triangles (N) 512
16 uint Number of textured quadrilaterals (P) 768
16 uint Number of untextured triangles (Q) 64
16 uint Number of untextured quadrilaterals (R) 256


XYZ coordinates

The next block of data consists of N sets of 3 XYZ coordinates (one XYZ coordinate for each of the triangle's points):

Triangle XYZ coordinates
Width (bits) Data type Purpose
16 int Point A, X coordinate
16 int Point A, Y coordinate
16 int Point A, Z coordinate
16 int Point B, X coordinate
16 int Point B, Y coordinate
16 int Point B, Z coordinate
16 int Point C, X coordinate
16 int Point C, Y coordinate
16 int Point C, Z coordinate


Then P sets of 4 XYZ coordinates:

Quadrilateral XYZ coordinates
Width (bits) Data type Purpose
16 int Point A, X coordinate
16 int Point A, Y coordinate
16 int Point A, Z coordinate
16 int Point B, X coordinate
16 int Point B, Y coordinate
16 int Point B, Z coordinate
16 int Point C, X coordinate
16 int Point C, Y coordinate
16 int Point C, Z coordinate
16 int Point D, X coordinate
16 int Point D, Y coordinate
16 int Point D, Z coordinate


Then Q sets of 3 XYZ coordinates (same format as triangles, above), then R sets of 4 XYZ coordinate (same format as quadrilaterals, above).


Normal vectors

Next come the normal vectors, which follow the same pattern. Instead of being integers, however, the values are stored as fixed-point numbers. They have a sign bit, then a 3-bit whole part and a 12-bit fractional part. This sounds complicated, but basically it just means you read them as signed 16-bit integers, then convert them to floating-point numbers and divide by 4096.0.

Also, there are no normal vectors for the untextured polygons, since those are always completely black.

First, there are N sets of 3 normal vectors:

Triangle normal vectors
Width (bits) Data type Purpose
16 fixed 1,3,12 Point A, nomal vector X
16 fixed 1,3,12 Point A, nomal vector Y
16 fixed 1,3,12 Point A, nomal vector Z
16 fixed 1,3,12 Point B, nomal vector X
16 fixed 1,3,12 Point B, nomal vector Y
16 fixed 1,3,12 Point B, nomal vector Z
16 fixed 1,3,12 Point C, nomal vector X
16 fixed 1,3,12 Point C, nomal vector Y
16 fixed 1,3,12 Point C, nomal vector Z


Then P sets of 4 normal vectors:

Quadrilateral normal vectors
Width (bits) Data type Purpose
16 fixed 1,3,12 Point A, nomal vector X
16 fixed 1,3,12 Point A, nomal vector Y
16 fixed 1,3,12 Point A, nomal vector Z
16 fixed 1,3,12 Point B, nomal vector X
16 fixed 1,3,12 Point B, nomal vector Y
16 fixed 1,3,12 Point B, nomal vector Z
16 fixed 1,3,12 Point C, nomal vector X
16 fixed 1,3,12 Point C, nomal vector Y
16 fixed 1,3,12 Point C, nomal vector Z
16 fixed 1,3,12 Point D, nomal vector X
16 fixed 1,3,12 Point D, nomal vector Y
16 fixed 1,3,12 Point D, nomal vector Z


Polygon texture data

This block of data is a little bit different. It has UV coordinates for each point on the textured polygons, but it also has a texture page number and palette number for the polygon as a whole. The texture page number is multiplied by 256 and then added to the V coordinate for each point on the polygon. This is because the UV coordinates are stored as bytes, but the textures are 256x1024 pixels, so effectively there are 4 texture pages. The palette number indicates which palette to apply to the polygon's texture while rendering it.

There are N triangles:

Triangle texture data
Width (bits) Data type Purpose
8 uint Point A, U coordinate
8 uint Point A, V coordinate
8 uint Palette number
8 N/A Padding/unknown
8 uint Point B, U coordinate
8 uint Point B, V coordinate
6 N/A Padding/unknown
2 uint Page number
8 N/A Padding/unknown
8 uint Point C, U coordinate
8 uint Point C, V coordinate


Followed by P quadrilaterals:

Quadrilateral texture data
Width (bits) Data type Purpose
8 uint Point A, U coordinate
8 uint Point A, V coordinate
8 uint Palette number
8 N/A Padding/unknown
8 uint Point B, U coordinate
8 uint Point B, V coordinate
6 N/A Padding/unknown
2 uint Page number
8 N/A Padding/unknown
8 uint Point C, U coordinate
8 uint Point C, V coordinate
8 uint Point D, U coordinate
8 uint Point D, V coordinate


Unknown

After the polygon texture data, there's a block of data whose purpose I don't understand. Its length is equal to 4 * Q + 4 * R.


Polygon tile locations

Next comes a block that assigns a terrain coordinate to each textured polygon. Its length is equal to 2 * N + 2 * P. This data is used when the game highlights all the tiles you can move to: It looks here to figure out which polygons to turn blue.

Textured polygon terrain coordinate data
Width (bits) Data type Purpose
7 uint Z coordinate
1 N/A Height Level
8 uint X coordinate

Sometimes, there are 2 bytes of unknown data or padding at the end of this block.

Texture palettes (color)

A set of 16 palettes, each containing 16 colors. Each color in the palette is 16 bits in little endian format.

  8B B1 => B1 8B
  
  1000 1011 1011 0001
  ABBB BBGG GGGR RRRR
Color
Width (bits) Data type Purpose
1 uint Alpha
5 uint Blue
5 uint Green
5 uint Red

If R == G == B == A == 0, then the color is transparent.

Light colors and positions, background gradient colors

Each map can have 3 directional lights and ambient light. The lighting data is stored like this:

Directional light colors
Width (bits) Data type Purpose
16 fixed 1,3,12 Light 1, red
16 fixed 1,3,12 Light 2, red
16 fixed 1,3,12 Light 3, red
16 fixed 1,3,12 Light 1, green
16 fixed 1,3,12 Light 2, green
16 fixed 1,3,12 Light 3, green
16 fixed 1,3,12 Light 1, blue
16 fixed 1,3,12 Light 2, blue
16 fixed 1,3,12 Light 3, blue


Directional light positions
Width (bits) Data type Purpose
16 int Light 1, X coordinate
16 int Light 1, Y coordinate
16 int Light 1, Z coordinate
16 int Light 2, X coordinate
16 int Light 2, Y coordinate
16 int Light 2, Z coordinate
16 int Light 3, X coordinate
16 int Light 3, Y coordinate
16 int Light 3, Z coordinate


Ambient light colors
Width (bits) Data type Purpose
8 uint Red
8 uint Green
8 uint Blue


This is immediately followed by the background gradient colors:

Background gradient colors
Width (bits) Data type Purpose
8 uint Top color, red
8 uint Top color, green
8 uint Top color, blue
8 uint Bottom color, red
8 uint Bottom color, green
8 uint Bottom color, blue


Sometimes, there are 3 bytes of unknown data or padding at the end of this chunk.


Terrain

This chunk contains data about the height, depth, slope, and surface type (grass, water, stone, etc) of each tile, as well as flags for whether you can walk on a tile or select it with the cursor.


Header

There is a two-byte header indicating the size of the X and Z dimensions of the map, in tiles. The product of X and Z must be <= 256.

Terrain header
Width (bits) Data type Purpose
8 uint Number of tiles of terrain, X dimension
8 uint Number of tiles of terrain, Z dimension


Main Block

The main block of the terrain data is divided into 2 levels. For a map with a bridge, for instance, the bridge might be on level 0 and the water below it on level 1. Each terrain level contains Z rows of X tile definitions, which look like this:

Terratin tile
Width (bits) Data type Purpose
2 N/A unknown/padding
6 uint Surface type (grass, water, stone, etc.)
8 N/A unknown/padding
8 uint Height (For sloped tiles, the height of the bottom of the slope)
3 uint Depth
5 uint Slope height (For sloped tiles, the difference between the height at the top and the height at the bottom)
8 uint Slope type
14 N/A unknown/padding
1 uint Can't walk on this tile
1 uint Can't move cursor to this tile
8 N/A unknown/padding


These tile definitions are 8 bytes long. Each terrain level always has room for 256 tiles (i.e. each one is always 256 * 8 bytes long), even if the map doesn't use them all. In other words, the terrain chunk, including its header, is always 2 + 256 * 8 * 2 bytes long, no matter how big the map is. If the map is small, there will be a lot of padding.

Slope types
Value Meaning
0x00 Flat
0x85 Incline N
0x52 Incline E
0x25 Incline S
0x58 Incline W
0x41 Convex NE
0x11 Convex SE
0x14 Convex SW
0x44 Convex NW
0x96 Concave NE
0x66 Concave SE
0x69 Concave SW
0x99 Concave NW


Sometimes, there are 2 bytes of unknown data or padding at the end of this chunk.


Texture animation instructions

There are several entries in this block, each providing the instructions for a certain animation. Each entry has a texture region to copy from, a texture coordinate where that region should be pasted, and a delay and number of times to repeat this instruction.

Texture animation instruction
Width (bits) Data type Purpose
8 uint Destination X coordinate (in 16-bit words, each of which is 4 texture pixels)
8 N/A Unknown
16 uint Destination Y coordinate (in pixels)
16 uint Width of region to copy (in 16-bit words, each of which is 4 texture pixels)
16 uint Height of region to copy (in pixels)
8 uint Source X coordinate (in 16-bit words, each of which is 4 texture pixels)
8 N/A Unknown
16 uint Source Y coordinate (in pixels)
24 N/A Unknown
8 uint Number of times to repeat
8 N/A Unknown
8 uint Delay between animation frames (in 30ths of a second, approx.)
16 N/A Unknown


Palette animation instructions

I once had a vague idea of how this section works, but I've forgotten it all.


Texture palettes (grayscale)

These are just like the color palettes, but all the colors are gray. I don't know what purpose they serve, if any.


Mesh animation instructions

I partly understand this section. More info coming later.


Animated Meshes 1-8

Each of these chunks is very similar to the primary mesh chunk.


Polygon visibility angles

This chunk tells the game when it should and shouldn't draw each polygon. Specifically, for each polygon, there's a series of bits specifying whether it's visible from the north-northeast, northeast, east-northeast, east-southeast, southeast, and so on. This data is used to remove obstructions like walls from the the camera's view, and also to avoid drawing certain polygons that are unnecessary because they're covered up by other polygons anyway.

This chunk is always 4096 bytes long. It consists of 5 blocks:

  1. A block of unknown data 896 bytes long
  2. 1024 bytes for 512 textured triangles
  3. 1536 bytes for 768 textured quads
  4. 128 bytes for 64 untextured triangles
  5. 512 bytes for 256 untextured quads

The length of each block is always the same, regardless of the number of polygons the mesh actually contains. This means that there's a lot of padding for meshes with low polygon counts. It also means there's an upper limit on the number of polygons allowed in a mesh.

The visibility data for each polygon is stored in 16 bits. More on the structure of these 16 bits later.