Geometry header
#
item
offset
size (bytes)
data type
1
unknown 0
4
long?
2
unknown
4
4
long?
3
model name
8
32
null terminated string
4
location of root node
40
4
long
5
number of nodes
44
4
long
6
unknown bytes
48
28

7
geometry type?
76
1
char
8
padding?
77
3
char
Total length of geometry header: 80 bytes

Model header
#
item
offset
size (bytes)
data type
1
unknown
0
1
char
2
unknown bytes
1
2
char
3
unknown
3
1
char
4
unknown
4
4
long?
5
location of the start of animation data
8
4
long
6
number of animations
12
4
long
7
duplicate of item 6
16
4
long
8
unknown
20
4
long?
9
bounding box min. x
24
4
float
10
bounding box min. y
28
4
float
11
bounding box min. z
32
4
float
12
bounding box max. x
36
4
float
13
bounding box max. y
40
4
float
14
bounding box max. z
44
4
float
15
radius
48
4
float
16
unknown
52
4
float
17
super model
56
32
null terminated string
Total length of model header: 88 bytes

Names array header
#
item
offset
size (bytes)
data type
1
location of root node
0
4
long
2
unknown
4
4
long?
3
size of mdx data?
8
4
long
4
unknown
12
4
long?
5
location of names
16
4
long
6
number of names
20
4
long
7
duplicate of item 6
24
4
long
Total length of names array header: 28 bytes

The names are stored in the array one after the other seperated only by the null values.

Animation header
#
item
offset
size (bytes)
data type
1
animation length
0
4
float
2
trans time
4
4
float
3
model name
8
32
null terminated string
4
location of events
40
4
long
5
number of events
44
4
long
6
duplicate of item 5
48
4
long
7
unknown bytes
52
4

Total length of animation header: 56 bytes

Events structure:
#
item
offset
size (bytes)
data type
1
activation time?
0
4
float
2
event
4
32
null terminated string
Total length of 1 structure: 36 bytes

Node header
#
item
offset
size (bytes)
data type
1
node type
0
2
short
2
supernode
2
2
short
3
node number
4
2
short
4
unknown
6
2
short
5
unknown
8
4

6
location of parent node
12
4
long
7
position X (same value as position controller)
16
4
float
8
position Y (same value as position controller) 20
4
float
9
position Z (same value as position controller) 24
4
float
10
rotation W (same value as rotation controller) 28
4
float
11
rotation X (same value as rotation controller) 32
4
float
12
rotation Y (same value as rotation controller) 36
4
float
13
rotation Z (same value as rotation controller) 40
4
float
14
location of the array of child node locations
44
4
long
15
number of items in array in item 8
48
4
long
16
duplicate of item 9
52
4
long
17
location of the array of controllers
56
4
long
18
number of items in array in item 11
60
4
long
19
duplicate of item 12
64
4
long
20
location of the array of controller data
68
4
long
21
number of items in array in item 14
72
4
long
22
duplicate of item 15
76
4
long
Total length of node header: 80 bytes

The array of child node locations is simply a list of long integers.

controller structure:
#
item
offset
size (bytes)
data type
1
controller type
0
4
long
2
unknown
4
2
short
3
number of rows of controller data
6
2
short
4
offset of first time key
8
2
short
5
offset of first data byte
10
2
short
6
columns of data
12
1
char
7
unknown
13
3
char
Total length of controller structure: 16 bytes

controller data structure:
Ok, the controller data structure is not fixed.  It has to be figured out from the controller itself.

Example:
controller:    1) 8 -1 2 0 2 3
                   2) 20 -1 2 8 10 4

data: 0 1 0 0 0 1 2 3 0 1 0 0 0 1 0 0 0 1

dark green =  controller 1 time keys, light green = controller 1 data, dark red = controller 2 time keys, light red = controller 2 data

So, controller 1 is a position controller (8 = position).  It has 2 rows of data, first time key is at offset 0, first data byte is at offset 2, the data is 3 values long.
Controller 2 is an orientation controller (20 = orientation).  It has 2 rows of data, first time key is at offset 8, first data byte is at offset 10, the data is 4 values long.

Taking the data string and formatting it according to the controller info gives:
controller 1 data:
time
x position
y position
z position
0
0
0
0
1
1
2
3

controller 2 data:
time
x
y
z
w
0
0
0
0
1
1
0
0
0
1

What the heck is that x,y,z,w for orientation?  That is a quaternion.  For some models oreintation (i.e. rotation) is stored as quaternions.  Too much for me to explain, Google it.

common mesh header
#
item
offset
size (bytes)
data type
1
unknown
0
4
long
2
unknown
4
4
long
3
location of the face array
8
4
long
4
number of faces in the face array
12
4
long
5
duplicate of item 4
16
4
long
6
bounding box min X
20
4
float
7
bounding box min Y 24
4
float
8
bounding box min Z 28
4
float
9
bounding box max X 32
4
float
10
bounding box max Y
36
4
float
11
bounding box max Z
40
4
float
12
mesh radius
44
4
float
13
mesh points average X
48
4
float
14
mesh points average Y
52
4
float
15
mesh points average Z
56
4
float
16
diffuse red
60
4
float
17
diffuse green
64
4
float
18
diffuse blue
68
4
float
19
ambient red
72
4
float
20
ambient green
76
4
float
21
ambient blue
80
4
float
22
unknown
84
4
float?
23
name for texture map 1
88
32
null terminated string
24
name for texture map 2
120
32
null terminated string
25
unknown
152
24
???
26
location of number of verts
176
4
long
27
number of items in array 10 (always 1)
180
4
long
28
duplicate of item 11
184
4
long
29
location of location of verts
188
4
long
30
number of items in array 13 (always 1)
192
4
long
31
duplicate of item 14
196
4
long
32
location of unknown array
200
4
long
33
number of items in array 16 (always 1)
204
4
long
34
duplicate of item 17
208
4
long
35
unknown (always -1)
212
4
long
36
unknown (always -1)
216
4
long
37
unknown (always 0)
220
4
long
38
unknown (always 3)
224
4
long
39
unknown (always 0) 228
4
long
40
unknown (always 0) 232
4
long
41
unknown
236
16
long?
42
size of 1 MDX structure
252
4
long
43
unknown (has something to do with textures)
256
4
long
44
unknown (always 0)
260
4

45
offset to vertex normals in MDX data in bytes (always 12)
264
4
long
46
unknown (always -1)
268
4
long
47
offset to UV coordinates in MDX data in bytes (24 if present)
272
4
long
48
unknown (each value always -1)
276
28

49
number of vertices
304
2
short
50
number of textures
306
2
short
51
unknown
308
2
short
52
shadow flag (value of 256 = cast shadow)
310
2
short
53
render flag (value of 256 = render this node) 312
2
short
54
unknown 314
2
short
55
unknown 316
8
long?
56
location of this nodes data in mdx
324
4
long
57
location of vertex coordinates array
328
4
long
Total length of common mesh header: 332 bytes

skin mesh header
#
item
offset
size (bytes)
data type
1
unknown
0
20
long?
2
location of bone map array
20
4
long
3
number of items in array 2
24
4
long
4
location of an unknown array
28
4
long
5
number of items in array 4
32
4
long
6
duplicate of item 5
36
4
long
7
location of an unknown array
40
4
long
8
number of items in array 7
44
4
long
9
duplicate of item 8
48
4
long
10
location of an unknown array
52
4
long
11
number of items in array 10
56
4
long
12
duplicate of item 11
60
4
long
13
list of nodes that can affect verticies of this node (i.e. bones)
64
30
short
14
unknown
94
6
short?
Total length of skin mesh header: 100 bytes

Bone maps work like this:
-For each vertex in the MDX there are 4 bone indexes and the corresponding bone weights
-You take the bone index from the MDX and match it to an entry in the bone map array
-The entry number that matches is the node number that affects the vertex

Example:
MDX data:  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.5 0.5 0 0 1 2 -1 -1

Bone map array:
0 => 1
1 => -1
2 => -1
3 => 2

The yellow numbers in the MDX data are the weights.  The red numbers are the bone indicies. The white numbers are coordinates, uv map coordinates, etc.

We take bone index 1 from the MDX and look for it in the bone map array.  We see that it is at position 0 in the list.  This means that node 0 has a bone weight of 0.5 when affecting the vertex described in the MDX data.  Taking bone index 2 we see that it is at position 3 in the list.  So, node 3 has a bone weight of 0.5 when affecting the vertex described in the MDX data.  The remaining bone indexs in the MDX are -1, meaning no other nodes affect this vertex.  The total of  the bone weights for a vertex must equal 1.

dangly mesh header
#
item
offset
size (bytes)
data type
1
location of constraints
0
4
long
2
number of items in array 1
4
4
long
3
duplicate of item 2
8
4
long
4
displacement
12
4
float
5
tightness
16
4
float
6
period
20
4
float
7
unknown
24
4
long?
Total length of dangly mesh header: 28 bytes