After many days of labor, here's a very rough structural layout of an MDL file. It's incomplete and I'd need to sift through many more MDL files to find all the other structures. And right now, I no longer have the time to continue doing that...
I say "structural layout" since I can't (easily) check what that non-structural data (e.g. vertices, normals, texture info, etc.) does. I pieced all this info just by looking at the hex of MDL files and using the following two sites as reference:
http://home.comcast.net/~cchargin/kotor/mdl_info.html) (documents KoToR 1/2's MDL format)
http://web.archive.org/web/20041021050414/www.torlack.com/index.html?topics=nwndata_binmdl) (documents NWN1's MDL format)
The result is that although I can guess at the data types and structures that MDL contains, I can't tell what what those structures are exactly for, unless that structure is very similar to a structure from the old MDL formats. For example, I can tell if something is a floating point value, but I may have no clue what that FP value is for.
---------------------------------------------------------------
- unless otherwise noted, number of bytes per item is 4
- item numbers and floating point numbers are given in decimal
- all other numbers are given in hex (which means "a" is 10, "10" is 16, etc.)
- if x is a model ptr, it refers to offset (x + 14); null model ptr = 00000000
- short and long values are given in big-endian form
- all numbers in big-endian form are always written as 8 digits
- tree of nodes are in pre-order
- floats, longs, null ptrs all have the same 0 value: 00000000
- function ptrs are the memory addresses (datatype long) of functions once the game's binary code is loaded into memory
MDL file
1) file header
2) model header
3) animation blocks; number of blocks is model header data's item 4
4) model nodes
5) unknown array 1 (if it exists)
file header
loc 0
1) 00008700
2) offset to raw data or end of file if no raw data (torlack); never seen any raw data
4) MDX part 1 size
5) MDX part 2 size (item 4 + item 5 = MDX total size)
6) 00000000?
size 14
model header
loc 14
1) geometry header block
2) model header data block
3) names array
size dc (items 1 to 2)
model header data
loc 64
1) long? does torlack's info apply here?
2) 00000000?
3) model ptr to animation ptr array
4) number of animations
5) same as item 4
6) long or float? seen 0, (cb90020 or 2.85e-31)
7) bounding box min x? (cchargin)
8) bounding box min y? (cchargin)
9) bounding box min z? (cchargin)
10) bounding box max x? (cchargin)
11) bounding box max y? (cchargin)
12) bounding box max z? (cchargin)
13) radius? (cchargin)
14) long? seen values of 1 and 2 so far
15) float? animation scale? (torlack)
16) supermodel name (20-len null-terminated string) (cchargin)
17) model ptr to a node, typically but not always the model root node
18) 00000000?
19) same as file header item 4
20) same as file header item 5
21) 00000000?
22) model ptr to names array
23) number of names
24) same as item 23
25) long? seen 0, 80100, cdcdcd00 (probably junk)
26) model ptr to unknown array 1 (or end of file if block doesn't exist?)
27) number of items in array specified at item 26
28) same as 27
size 8c
geometry header
1) function ptr
2) function ptr
3) model/animation name (20-len null-terminated string)
4) model ptr to model/animation's root node
5) number of nodes in model/animation (recursively includes nodes in super model + 1)? (torlack)
6) 6 00000000's?
7) reference count? seen only 0 (torlack)
8) geometry type (char) (torlack)
9) 3 chars padding? (torlack)
size 50
names array
loc f0
1) model ptrs to the strings in item 2; number of model ptrs is model header data's item 27
2) strings delimited by null chars; number of model ptrs is model header data's item 27
animation ptr array
1) model ptrs to animation headers; number of model ptrs is model header data's item 4
animation block
1) animation header block
2) event array
3) animation nodes
animation header
1) geometry header block
2) animation length (float)? (cchargin)
3) trans time (float)? (cchargin)
4) short? seen only 0, 101, 1
5) model name or part name (20?-len null-terminated string)
6) padding (short)? seen 4, 0
7) model ptr to event array or null if no events
8) number of events
9) same as item 8
10) 00000000?
size (items 1 to 10) 8c
size (items 2 to 10) 3c
event array
1) events; number of events is animation header's item 8
event
1) activation time? (float) (cchargin)
2) event name (20-len null-terminated string (cchargin)
3) 00000000?
size 28
node
1) node header block
2) subheader block (depends on node header's item 1 and apparently also node header's item 2?); can be nonexistent
3) data (depends on node header's item 1); can be nonexistent
4) child node array (if any children)
node header
1) node type (short) (torlack)
2) super node number (short)? (cchargin)
3) node/part number (short)? (cchargin) all values are unique within a model geometry/animation geometry block, generally increasing
4) n where node is n-th node of model node tree laid out in pre-order; if two different node header's have the same item 3, they also have the same item 4 (this applies for both model and animation node trees)
5) model ptr to parent animation header or null if no such parent
6) model ptr to parent node or null if no such parent
7) position X? (float) (cchargin)
8) position Y? (float) (cchargin)
9) position Z? (float) (cchargin)
10) rotation W? (float) (cchargin)
11) rotation X? (float) (cchargin)
12) rotation Y? (float) (cchargin)
13) rotation Z? (float) (cchargin)
14) model ptr to array of child node ptrs (or end of node if no children)
15) number of child nodes
16) float? seen 1.0
17) float? usually 1.0e10, seen 10.0, 30.0
size 3c
child node array
1) model ptrs to nodes; number of model ptrs is node header's item 15
mesh node subheader (type 0021)
1) 3 00000000's?
2) a floats
3) 00000000?
4) long? seen 10
5) 20 bytes that seem to vary in format (not sure what determines format):
5a) 10 shorts?
5b) 8 floats
5c) 10-len null-terminated string + 4 floats
6) if item 7 is not 0, number of items in array specified at item 7; otherwise, some long? seen 2e8, 321, f72, 954 (can't be model ptr since it can be larger than mdl file size)
7) 00000000 or model ptr to mesh node data array
8) -1 (long) if item 7 is 0?; otherwise, seen 61 and 62 (can't be index into array since it can be larger than array size)
9) long? seen 3 and 4
10) c bytes that seem to vary in format (not sure what determines format):
10a) 1 long and 4 shorts? or 6 shorts?
10b) 3 floats
11) long? seen 1c, 20, 24, 10, 34
12) long? seen 6b, 63, 27, 21, 823
13) 00000000?
14) long? seen c
15) long? seen 10, -1
16) long? seen 14, 10, -1
17) long? seen 18, -1
18) long? seen 1c, -1
19) long? seen -1
20) long? seen -1
21) long? seen -1
22) long? seen -1
23) long? seen -1
24) long? seen -1, 10
25) long or 2 shorts?? seen 2083d, 1017a, 11099, 10229, 2002e, 18, 10270 (can't be model ptr or offset in MDX file since it can be too large)
26) long?? seen 0, 7088, 43cb, 740, 180 (can't be model ptr since it can be larger than mdl file size)
27) long or 2 shorts?? seen 91fa0f8, 7690178, 76adc08, 76833a8, 76834d8, 0, abbcb10
28) long?? seen 3ccd, 3922, 3920, 4a92, 391c, -1, 443a (can't be model ptr since it can be larger than mdl file size)
29) long? seen 1
30) float? seen 0.0, 1.0
31) float? seen 0.0, 1.0
32) float? seen 0.0, 1.0
30) float; seen 1.0, 0.9
31) 00000000?
32) long or 2 shorts?? seen 91f7fe8, 7684fa0, 859ffc8, 7684b30, 0, c0affc8; difference between item 27 and 32 is relatively small (probably same "type")
33) offset in MDX file; either 0 or always past MDX part 1 (greater than MDX part 1 size); seen MDX part 1 size
34) offset from item 33?; always less than MDX part 2 size; seen MDX part 2 size
size e4
mesh node data array (type 0021)
(exists only have mesh node subheader's item 7 is not 0)
1) shorts; number of shorts is mesh node subheader's item 6
skin mesh node subheader (type 0061)
1) mesh node subheader block
2) 00000000?
3) 00000000?
4) 00000000?
5) long? seen 1c
6) long? seen 2c
7) model ptr to skin mesh node array 1 (cchargin)
8) number of items in array specified at item 7
9) model ptr to skin mesh node array 2
10) number of items in array specified at item 9
11) same as 10
12) model ptr to skin mesh node array 3
13) number of items in array specified at item 12
14) same as 13
15) model ptr to skin mesh node array 4
16) number of items in array specified at item 15
17) same as 16
18) 2c shorts? (number of shorts is same as item 6, but could be coincidence)
19) float? seen 1.0
20) float? seen 1.0
size (items 2 to 17) 74
size (items 2 to 20) d4
size (items 1 to 17) 158
size (items 1 to 20) 1b8
skin mesh node array 1
1) shorts? number of shorts is skin mesh node subheader's item 8
skin mesh node array 2
1) skin mesh node array 2 blocks; number of blocks is skin mesh node subheader's item 10
skin mesh node array 2 block
1) float?
2) float?
3) float?
4) float?
size 10
skin mesh node array 3
1) skin mesh node array 3 blocks; number of blocks is skin mesh node subheader's item 13
skin mesh node array 3 block
1) float?
2) float?
3) float?
size c
skin mesh node array 4
(only seen this array have 0 len, so don't know its structure)
light node subheader (type 0003)
1) 10 00000000's (torlack has info but I can't verify)
2) light priority (torlack)
3) ambient only flag (torlack)
4) dynamic type (torlack)
5) affect dynamic flag (torlack)
6) shadow flag (torlack)
7) generate flare flag (torlack)
8) fading light flag (torlack)
9) float? b/w 0 and 1?
10) float? b/w 0.0 and 1.0?
11) float? b/w 0.0 and 1.0?
12) float? b/w 0.0 and 1.0?
13) float? b/w 0.0 and 1.0?
14) float? seen 0.0
15) float? seen 0.0 and 1.0
16) float? seen 0.0 and 1.0
17) float? seen 0.0 and 1.0
18) float? seen 2000.0 and 500.0
19) float? seen -1.0
20) float? seen 0.0
21) float? seen 1.0
22) float? b/w 0.0 and 1.0?
23) float? b/w 0.0 and 1.0?
24) float? b/w 0.0 and 1.0?
size 9c
unknown node type 1 subheader (type 1001)
1) long? seen 0, 1
2) float? seen 0.0
3) float? seen 0.0
4) float? seen 0.0
5) float? seen 1.0
6) float? seen 1.0
7) float? seen 1.0
size 1c
unknown node type 2 subheader (type 0001 + super node 0002)
1) float?
2) float?
3) float?
4) float?
5) float?
6) float? seen 2.4138735e-9
7) float?
8) float?
9) float?
10) 00000000?
11) 00000000?
12) 00000000?
13) 00000000?
14) 00000000?
15) model ptr to array of child node ptrs or next node? same as node header's item 14?
16) same as node header's item 15? only seen 00000000 and the nodes had no children
17) 00000000?
18) 00000000?
size 48
unknown node type 3 subheader (type 0001 + super node 0004)
1) node type of corresponding node under model geometry (there's a node with the same node number in the node tree whose root's offset is specified in model header's geometry header's item 4)? (short)
2) model ptr to controller array or null if no controllers
3) number of controllers
4) same as item 3
5) model ptr to unknown node type 3 array 1 or null if no array
6) number of items in array specified at item 5; = sum of all controller's item 3's (i.e. total number of time keys)?
7) model ptr to controller data array or null if no controller data
8) number of controller data items
9) long? seen 6, 15, 16, 17
size 24
controller array?
1) controller blocks; number of blocks is unknown node type 3 subheader's item 3
controller?
1) controller type (long)? seen 8 (position), 14 (orientation)
2) short? = item 1 + 8?? seen 10, 1c
3) number of rows (and hence, number of time keys) (short)?
4) index into array specified at unknown node type 3 subheader's item 5? sum of all previous controller's # rows (item 3) or 0 if no previous controllers
5) index into controller data array (short)? sum of all previous controller's [# rows (item 3) * (# columns (derived from item 6) + 1)] or 0 is no previous controllers
6) column type (char)? seen 2 (2 columns), 5 (1 columns), 4 (0 columns)
7) char? seen 5, b3
8) short? seen 12, 4c (both multiples of 12...)
size 10
unknown node type 3 array 1
1) shorts that are related to time keys? number of shorts is unknown node type 3 subheader's item 6; seen values uniformly b/w 0 and 155 (larger values no doubt exist); typically x0, x5, or xa, where x is any digit(s)
controller data array?
1) the array is partitioned into controller data blocks that correspond to each controller; number of blocks is number of total floats/4-bytes is unknown node type 3 subheader's item 8;
controller data block
1) time keys? number of keys is controller's # rows (controller's item 3) (not sure if this is just another column since unknown node type 3 array 1 seems to contain integral versions of the time keys
2) controller data block items; number of items is controller's # rows * # columns; item data type seems to depend on unknown node type 3 subheader's item 1
controller data block item?
1) float? all 4 bytes almost always non-00, but the numbers can be extremely small or large (e.g. -1.9581039E22, 2.1989652E-16, even 4.0277763E-38)
controller data array item (controller node type (unknown node type 3 subheader's item 1) = 1001 and last 10 bytes of controller data)??
1) 2 shorts?
(when I see node type is 1001 with column type 5, the controller always has 2 rows, and the controller data always looks like this: 00020080 00001000 00020080 00001000; I also see this if node type is 1001 and no controllers are specified)
unknown array 1
1) unknown array 1 blocks; number of blocks is unknown node type 3 subheader's item 6
unknown array 1 block
1) model ptr to a node; denote as node A
2) model ptr to a node; denote as node B
3) 7 floats? 7 = node B's part number - node A's node's part number?
MDX file
1) MDX part 1
2) MDX part 2
MDX part 1
?
MDX part 2
1) function ptr?
2) long? seen 5 and 6 so far
3) 0018?
4) char?
5) char? usually 4x or 5x where x is any digit
6) array of shorts, adjacent values are usually have very small difference
7) 00000000?
8) 00000000?