RMT fileformat specification - version 1 changelog: 17.8.2006 - File created, mesh specs written. 17.8.2006 - 5bit accuracy removed 18.8.2006 - minor tweakings and material chunk specs written 19.8.2006 - Version added to RMT chunk, some minor tweakings with names/bitdepths 20.8.2006 - FLOATS changed to REAL32 and added a RealsAsFloats boolean property to RMT chunk. If it's false everything in the file will be integer values. 21.8.2006 - NOTE: Translation, hierarchy and pivot is left outside of the scope for now. Will be decided by need later on. 07.9.2006 - indexbuffercount removed from mesh 05.10.2006 - Endchar removed from strings. 09.10.2006 - indexbuffer accuracy depends on vertexcount, vertexcount is now INT32 RMT = Random Mesh Things RMT is simple chunk-based mesh fileformat. Every chunk start with header that has type and size. The binary data byte order in RMT files is LITTLE ENDIAN. All the chunks are optional in RMT fileformat. For example it is possible to export files that have only indexbuffers. Although parent of the chunk must be present. So if there's the INDEXBUFFERS the MESH and RMT chunks are also present. See the hierarchy below. BOOLEANS are UINT8. chunktypes: RMT - 0x5ad0 MESH - 0x1000 VERTEXBUFFER - 0x1100 NORMALBUFFER - 0x1200 UVBUFFERS - 0x1300 INDEXBUFFERS - 0x1400 VCOLBUFFER - 0x1500 MATERIAL - 0x2000 BITMAPINFO - 0x2100 SHADERINFO - 0x2200 header: type: UINT16 (Presented as 0xXXXX in here) datasize: UINT32 (Size in bytes) chunks: RMT - 0x5ad0 type: UINT16 datasize: UINT32 - mesh and material data summed up. (Filesize is this size + this header) version: UINT8 - to check if the loader is did for the same version of the file spec RealsAsFloats: BOOLEAN - UINT8 meshcount: UINT16 (9 bytes) MESH - 0x1000 type: UINT16 datasize: UINT32 - 18 bytes + meshnamesize + Vertexbuffer + normalbuffer + UVbuffers + indexbuffers + vcolbuffer meshnamesize: UINT8 - meshnames are restricted to 255 char Q_Q - no endchar meshname: UINT8 * meshnamesize meshposition: REAL32*3 (XYZ) vertexcount: INT32 - note that this one affects the accuracy of indexbuffers - presented here because you need it all-around indexbuffertype: UINT8 1: list 2: strips UVbuffercount: UINT8 - max 255 UVbuffers (24 bytes + meshnamesize + data) VERTEXBUFFER - 0x1100 type: UINT16 datasize: UINT32 - 13 bytes + vertexcount*3*VBaccuracy VBscale: REAL32*3 (XYZ) VBaccuracy: UINT8 1: INT8 (coordinates in range from -127 to 127) 2: INT16 (coordinates in range from -32767 to 32767) 3: REAL32 (coordinates in range from -2147483647 to 2147483647) - if RealsAsFloats == true: data is as it is in 3dsmax. vertexdata: vertexcount*3*VBaccuracy (19 bytes + vertexdata) NOTE: To read the right coordinates when they're size-optimized you always need to divide the value with max range (for example 127 in accuracy case of INT8) and multiply that result with VBscale. NORMALBUFFER - 0x1200 type: UINT16 datasize: UINT32 - 1 byte + vertexcount*3*NRMaccuracy NRMaccuracy: UINT8 1: INT8 - coordinates range: -127 to 127, divide with 127 to get the normal 2: INT16 - coordinates range: -32767 to 32767, divide with 32767 to get the normal 3: REAL32 - coordinates range: -2147483647 to 2147483647, divide with 2147483647 to get the normal - if RealsAsFloats == true: data is normalized normals from -1 to 1 normaldata: vertexcount*3*NRMaccuracy (7 bytes + normaldata) NOTE: To read the right values when they're size-optimized you always need to divide the value with the max range (for example 127 in accuracy case of INT8.) UVBUFFER - 0x1300 type: UINT16 datasize: UINT32 - 4 bytes + UVdata UVbufferID: UINT8 includeW: BOOLEAN - UINT8 - third dimension for vertices. if TRUE (1) the vertexdata is 3-value form UVW instead of 2-value: UV. UVscale: UINT8 - value that defines the maximum times that uv:s can tile inside single face to that direction. The scale of the UV's. - takes max value from the biggest UV-triangle UVaccuracy: UINT8 1: INT8 - coordinates range: from -127 to 127, divide with 127 and multiply with UVscale to get the coordinate. 2: INT16 - coordinates range: from -32767 to 32767, divide with 32767 and multiply with UVscale to get the coordinate. 3: REAL32 - coordinates range: from -2147483647 to 2147483647, divide with 2147483647 and multiply with UVscale to get the coordinate. if RealsAsFloats = True -> outputs the coordinates as they are in 3dsmax. Do not take UVscale in account. UVdata: vertexcount*2 or 3*UVaccuracy (10 bytes + UVdata) INDEXBUFFER - 0x1400 type: UINT16 datasize: UINT32 - 7 bytes + Ibufferdata IbufferID: UINT16 IbufferMAT: UINT8 indexcount: UINT32 - count of single indices. when list-> facecount*3 Ibufferdata: in case of: vertexcount<=256: indexcount*UINT8 256 RGBA = UINT8 2: 4bit - 16 -||- -> RGBA = UINT16 3: UINT8 - 256 -||- -> RGBA = 4*UINT8 4: REAL32 - 2147483647 -||- -> RGBA = 4*REAL32. - values between 0 and 1 if RealsAsFloats = True. VCOLdata: in VCOLaccuracy case of: 1: vertexcount 2: vertexcount*2 3: vertexcount*4 4: vertexcount*16 (7 bytes + VCOLdata) MATERIAL - 0x2000 type: UINT16 datasize: UINT32 - 11 bytes MaterialID: UINT8 shading: UINT8 1: matte - Self illumination amount >50.0 in 3dsmax 2: flat - materials faceted-option checked 3: gouraud - default blending: UINT8 1: no blend - default 2: opacity 3: add 4: substr. opacity value: UINT8 0-255 = 0-100% so -> value/255*100 persp. corr: BOOLEAN - UINT8 (checking face map property in standard material will remove perspective correction) texturemapID: UINT8 - if ZERO, no bitmap reflectionmapID: UINT8 - if ZERO, no bitmap lightmapID: UINT8 - if ZERO, no bitmap glossymapID: UINT8 - if ZERO, no bitmap normalmapID: UINT8 - if ZERO, no bitmap shaderID: UINT8 - if ZERO, no shader (16 bytes) BITMAPINFO - 0x2100 type:UINT16 datasize: UINT32 - 2 bytes + BMfilenamesize mapID: UINT8 BMfilenamesize: UINT8 - no endchar BMfilename: char*BMfilenamesize (8 bytes + BMfilenamesize) SHADERINFO - 0x2200 type: UINT16 datasize: UINT32 - 2 bytes + SHDfilenamesize shaderID: UINT8 SHDfilenamesize: UINT8 - no endchar SHDfilename: char*SHDfilenamesize (8 bytes + SHDfilenamesize)