this is a draft and WIP
TMF Header consist of following data, laid out without padding.
- Magic - 3 bytes ([0x54,0x4d,0x46]) creating the string "TMF" used for identification
- TMF_MAJOR:little-enidian u16 - major version of format used to save file
- TMF_MINOR:little-enidian u16 - major version of format used to save file
- MIN_TMF_MAJOR:little-enidian u16 - major version of format reader required to read this file
- MIN_TMF_MINOR:little-enidian u16 - minor version of format reader required to read this file
- mesh_count: little-enidian u32 - count of meshes inside this file. After TMF Header a mesh_count meshes will follow, each beginning with the Mesh Header
Each mesh header begins with mesh name, an UTF-8 string saved as:
- str_len: little-enidian u16 - describing name length
- str_bytes: str_len bytes - making up the name UTF-8 encoded string(not null terminated!) After the name string there is one more field:
- seg_count:little-enidian u16 - specifying how many data segment this mesh has After the mesh header there is seg_count segment.
Segment header consists of:
- seg_type:little-enidian u16 - describing segment type, for specific values look at [Segment Types](#Segment Types).
- data_length:little-enidian u64 - describing the length of data in the segment(excluding the header)
- compresion_type:u8 - Describes used compression, for more info look into [CompressionTypes](#Compression Types)
- data: data_length bytes - the internal data of the segment, for what it is exactly for each segment - look into [Segment Types](#Segment Types).
value | meaning |
---|---|
0 | Invalid |
1 | VertexSegment |
2 | VertexTriangleSegment |
3 | NormalSegment |
4 | NormalTriangleSegment |
5 | UvSegment |
6 | UvTriangleSegment |
7 | MaterialInfo |
8 | Materialtriangles |
Segment is invalid, and should be ignored.
This segment stores an array of points and consists of the following data:
- vertex_count: little_enidian u64 - describes amount of vertices ths segment contains.
- min_x: little_enidian f64 - minimal x position of any point inside this segment.
- max_x: little_enidian f64 - maximal x position of any point inside this segment.
- min_y: little_enidian f64 - minimal y position of any point inside this segment.
- max_y: little_enidian f64 - maximal y position of any point inside this segment.
- min_z: little_enidian f64 - minimal z position of any point inside this segment.
- max_z: little_enidian f64 - maximal z position of any point inside this segment.
- prec_x: u8 - describes how many bits the x component of point has
- prec_y: u8 - describes how many bits the y component of point has
- prec_z: u8 - describes how many bits the z component of point has
Each vector inside of this UBA has 3 components, prec_x, prec_y and prec_z bits in size respectively. Each component is saved as a number between 0 and 2^component_precision - 1. So it should be divide by this max number to get a number between 0 and 1. This number specifies where inside of the bounding box the point shall lay, where 0 is the minimal value of this cordiante and 1 is the maximal one.
Each one of those segments stores an array of indices into the Vertex, Normal and UV Segment respectively. Those indices then create triangles. The data layout of those segments is:
- precision: u8 - describes the size of index in bits
- count: little-enidian u64 describing the amount of indices.
Each index is precision bits in size.
TODO
TODO
value | meaning |
---|---|
0 | No compression |
1 | Segment Omitted |
2 | Unaligned LZZ (not implemented, reserved) |
Uncompressed, just raw bytes.
Segment is omitted. This does not mean that mesh does not have this data, ti only means that the data can be derived from other mesh data.
Only segment that can be currently omitted is NormalTriangleSegment
If normal triangle segment is omitted, it should be assumed that it has the same amount of indices as the normal segment has normal vectors, and that each index is equal to its position. Example: [[0,1,2,3,4,5,6,7,8,9,10,...]]
Binary data in UBA-s does not align to byte boundaries and may cross them. There is no padding between data. For example a u3 and u5 may be within the same byte. A u12 crosses a byte boundary, but the next u12 may not start at the next byte, but inside the same byte the last data ended in.