[info].msh structure notes

Started by tirpider, October 22, 2011, 07:38:37 PM

Previous topic - Next topic
October 22, 2011, 07:38:37 PM Last Edit: May 23, 2012, 07:24:18 PM by tirpider
Notes on SWBF .msh file structure.
I want to be able to manipulate model features and geometries without XSI. In order to do that, I need the file format.

Ande has a site dedicated to this exact information. (link: www.ande.pytalhost.eu)
If anything in this document confilcts with what he has, I would go with what he has.
Some (a lot, particularly the CLTH stuff) of the following is straight from there, as I have no way to test it.

.msh MAIN CHUNK HIERARCHY
[spoiler]
HEDR                            -Size of file from next byte to end
   +-SHVO                       -Has Shadow or not?
   +-MSH2                       -Size of file from next byte to last MODL
   |    +-SINF                  -Scene Info
   |    |    +-NAME             -Name
   |    |    +-FRAM             -Scene animation info
   |    |    +-BBOX             -Bounding Box
   |    +-CAMR                  -Camera
   |    |    +-NAME             -Camera name. Typicaly "Camera"
   |    |    +-DATA             -Camera position and direction info.
   |    |    +-ANIM             - ? Animated Camera?
   |    |    +-LGTI             - ? Light?
   |    |         +-NAME        - ? The Light's name, I assume.
   |    |         +-DATA        - ? The Light's Metrics, I assume.
   |    +-MATL                  -Material info
   |    |    +-MATD             -Material description chunk
   |    |         +-NAME        -Material name
   |    |         +-DATA        -Color information
   |    |         +-ATRB        -Attributes of Texture
   |    |         +-TX0D        -Texture name
   |    +-MODL                  -Model geometry, skeleton, nulls, ect
   |         +-MTYP             -MODL type
   |         +-MNDX             -Model index #
   |         +-NAME             -MODL name
   |         +-PRNT             -Parent MODL NAME
   |         +-FLGS             -Visible/Hidden
   |         +-TRAN             -Transform/Translation
   |         +-GEOM             -Geometry
   |         |    +-BBOX        -Bounding Box
   |         |    +-SEGM        -Standard Geometry
   |         |    |    +-SHDW   -Shadow
   |         |    |    +-MATI   -Material index #
   |         |    |    +-POSL   -Vertex locations
   |         |    |    +-WGHT   -Weights
   |         |    |    +-NRML   -Vetrex Normals
   |         |    |    +-CLRL   -Vertex color
   |         |    |    +-CLRB   -Vertex color
   |         |    |    +-UV0L   -UV map
   |         |    |    +-NDXL   -Polygons
   |         |    |    +-NDXT   -Triangles
   |         |    |    +-STRP   -Triangle strips
   |         |    +-ENVL        -Envelope references
   |         |    +-CLTH        -Cloth (special geometry)
   |         |         +-CTEX   -Texture name
   |         |         +-CPOS   -Cloth Verticies
   |         |         +-CUV0   -Cloth UV map
   |         |         +-FIDX   -Cloth envelope indexes
   |         |         +-FWGT   -Cloth Weighting
   |         |         +-CMSH   -Triangles
   |         |         +-SPRS   -Stretch Constraints
   |         |         +-CPRS   -Cross Constraints
   |         |         +-BPRS   -Bend  Constraints
   |         |         +-COLL   -Collision data
   |         +-SWCI             -Collision data
   +-SKL2                       - CRC's of bones and ?
   +-BLN2                       - CRC's of bones
   +-ANM2                       -Animation data
   |    +-CYCL                  - ?
   |    +-KFR3                  - Keyframes
   +-CL1L                       - ?(Always at eof)
[/spoiler]

.msh BONE HIERARCHY (MODL chunks)
[spoiler]
DummyRoot
   +-MESH_body
   |    +-bone_root
   |         +-root_a_spine
   |         |    +-bone_a_spine
   |         |         +-bone_b_spine
   |         |              +-bone_ribcage
   |         |                   +-eff_ribcage
   |         |                        +-root_l_clavicle
   |         |                        |    +-bone_l_clavicle
   |         |                        |        +-eff_l_clavicle
   |         |                        |            +-root_l_upperarm
   |         |                        |                +-bone_l_upperarm
   |         |                        |                    +-bone_l_forearm
   |         |                        |                        +-eff_l_forearm
   |         |                        |                            +-root_l_hand
   |         |                        |                                +-bone_l_hand
   |         |                        |                                    +-eff_l_hand
   |         |                        |                                    +-MESH_l_hand
   |         |                        +-root_r_clavicle
   |         |                        |    +-bone_r_clavicle
   |         |                        |        +-eff_r_clavicle
   |         |                        |            +-root_r_upperarm
   |         |                        |                +-bone_r_upperarm
   |         |                        |                    +-bone_r_forearm
   |         |                        |                        +-eff_r_forearm
   |         |                        |                            +-root_r_hand
   |         |                        |                                +-bone_r_hand
   |         |                        |                                    +-eff_r_hand
   |         |                        |                                    +-MESH_r_hand
   |         |                        +-root_neck
   |         |                             +-bone_neck
   |         |                                 +-bone_head
   |         |                                     +-eff_head
   |         +-bone_pelvis
   |              +-root_r_thigh
   |              |   +-bone_r_thigh
   |              |       +-bone_r_calf
   |              |           +-eff_r_calf
   |              |               +-root_r_foot
   |              |                   +-bone_r_foot
   |              |                       +-bone_r_toe
   |              |                           +-eff_r_toe
   |              +-root_l_thigh
   |                  +-bone_l_thigh
   |                      +-bone_l_calf
   |                          +-eff_l_calf
   |                              +-root_l_foot
   |                                  +-bone_l_foot
   |                                      +-bone_l_toe
   |                                         +-eff_l_toe
   +-sv_ShadowVolume_mesh
   +-MESH_head
   +-MESH_backpack
   +-MESH_jetpack
   +-MESH_belt
   +-MESH_cape

   * this is just how the bones are parented. Enveloping and weighting determine
     how it moves with the skeleton.
   * the items that start with MESH_ are pretty much options. Their NAME is only
     important for parenting.
   * To make a model override_texture compatible, it's 'body' MODL chunk's name
     should be 'override_texture'. (Don't forget to change the name in it's
     children's PRNT chunk.)
   * p_* MODLs are deliberatly ommited as I don't know if they need to strictly
     follow the heirarchy or not
   * The order of the MESH_* chunks is just an example. There are models with
     all the geometry after all the bones, or some with the sv_ near the
     DummyRoot. As long as the PRNT and ENVL entries point to the correct
     models, then the msh should be valid and pass through ModelMunge just fine.

     

[/spoiler]

.msh TAG OFFSETS AND DESCRIPTIONS
[spoiler](in hierarchal order)
(items in brackets [] are still being investigated)
(? in the length fields indicate a variable length, typically defined by the preceding field)

HEDR
   offset   length   type      contents
        0        4   char(4)   HEDR
        4        4   long      bytes to end of file
   * the size entry will be the filesize - 8 bytes.

SHVO (child of HEDR)
   offset   length   type      contents
        0        4   char(4)   SHVO
        4        4   long      byte length of section from next byte
        8        4   byte(4)   ? typicaly 1
   * could be a long integer, or a series of bytes like ATRB
   * needs more study

MSH2 (child of HEDR)
   offset   length   type      contents
        0        4   char(4)   MSH2
        4        4   long      bytes from next byte until last byte of last MODL chunk

SINF (child of MSH2)
   offset   length   type      contents
        0        4   char(4)   SINF
        4        4   long      byte length of section from next byte

NAME (child of SINF)
   offset   length   type      contents
        0        4   char(4)   NAME
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long

[FRAM] (child of SINF)
   offset   length   type      contents
        0        4   char(4)   FRAM
        4        4   long      byte length of section from next byte
        8        4   long      start of frame range
       12        4   long      end of frame range
       16        4   float     fps
   * needs more study
   * most player msh's with a KFR3 chunk only have 2 frames in the KFR3. Haven't verified this in animation MSHs yet

BBOX (child of SINF)
   offset   length   type      contents
        0        4   char(4)   BBOX
        4        4   long      byte length of section from next byte
        8       16   float(4)  Quaternion Rotation ( qx , qy , qz , qw )
       24       12   float(3)  Center ( x , y , z )
       36       12   float(3)  ( Width/2 , Height/2 , Depth/2 )
       48        4   float     Bounding Sphere Radius

CAMR (child of MSH2)
   offset   length   type      contents
        0        4   char(4)   CAMR
        4        4   long      byte length of section from next byte

NAME (child of CAMR)
   offset   length   type      contents
        0        4   char(4)   NAME
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long

[DATA] (child of CAMR)
   offset   length   type      contents
        0        4   char(4)   DATA
        4        4   long      byte length of section from next byte
        8       12   float(3)  position ( x? , y? , z? )
       20       12   float(3)  direction ( x? , y? , z? )
       32       16   float(4)  ( ? , ? , ? , ?) (a quat, perhaps?)
   * needs more study

[ANIM] (child of CAMR)
   offset   length   type      contents
        0        4   char(4)   ANIM
        4        4   long      byte length of section from next byte
        8        ?   ?         ?
   * needs more study

[LGTI] (child of CAMR)
   offset   length   type      contents
        0        4   char(4)   LGTI
        4        4   long      byte length of section from next byte
   * needs more study

NAME (child of LGTI)
   offset   length   type      contents
        0        4   char(4)   NAME
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long

[DATA] (child of LGTI)
   offset   length   type      contents
        0        4   char(4)   DATA
        4        4   long      byte length of section from next byte
        8        4   float     ?
       12        4   float     ?
       16        4   float     ?
       20        4   float     ?
       24        4   float     ?
       28        4   float     ?
       32        4   float     ?
       36        4   float     ?
   * floats work for them so far, but may be incorrect
   * needs more study

MATL (child of MSH2)
   offset   length   type      contents
        0        4   char(4)   MATL
        4        4   long      byte length of section from next byte (Including sub section sizes)
        8        4   long      number of MATD sections to follow
   * MATI references to MATD's start at 0

MATD (child of MATL)
   offset   length   type      contents
        0        4   char(4)   MATD
        4        4   long      byte length of section from next byte

NAME (child of MATD)
   offset   length   type      contents
        0        4   char(4)   NAME
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long

DATA (child of MATD)
   offset   length   type      contents
        0        4   char(4)   DATA
        4        4   long      byte length of section from next byte
        8       16   float(4)  Diffuse Color ( red? , green? , blue? , alpha?)
       24       16   float(4)  Ambient Color ( red? , green? , blue? , alpha?)
       40       16   float(4)  Specular Color ( red? , green? , blue? , alpha?)
       56        4   float     Specular Intensity
   * needs more study
   * Haven't tried to interpret the floats into proper RGBa values

[ATRB] (child of MATD)
   offset   length   type      contents
        0        4   char(4)   ATRB
        4        4   long      byte length of section from next byte
        8        1   byte      addative flag values
        9        1   byte      render type number
       10        1   byte      data0 0 - 255
       11        1   byte      data1 0 - 255
   * Inside Edit Flags (FAQ) on GT
   * I will reflect the settings here when I start bump-mapping my Tuskens.

TX0D (TX1D, TX2D, ect. ) (child of MATD)
   offset   length   type      contents
        0        4   char(4)   TX0D
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long
   *some of the attributes require extra TX?D entries

MODL (child of MSH2)
   offset   length   type      contents
        0        4   char(4)   MODL
        4        4   long      byte length of section from next byte (Including sub section sizes)

[MTYP] (child of MODL)
   offset   length   type      contents
        0        4   char(4)   MTYP (model type)
        4        4   long      byte length of section from next byte
        8        4   long      0=null      1=skin    2= ?
                               3=envelope  4=static  6=shadow
   * offset 8 info from the Riley pages. The absense of 2 makes me believe there is more to this.
   * I havent figured out which one, but there is an exporter that spells this incorrectly as MYTP.
   * needs more study

MNDX (child of MODL)
   offset   length   type      contents
        0        4   char(4)   MNDX (model index #)
        4        4   long      byte length of section from next byte
        8        4   long      model index #
   * These are reffrenced by the ENVL chunks.

NAME (child of MODL)
   offset   length   type      contents
        0        4   char(4)   NAME
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long

PRNT (child of MODL)
   offset   length   type      contents
        0        4   char(4)   PRNT
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes
   *it will always be a multiple of 4 bytes long

[FLGS] (child of MODL)
   offset   length   type      contents
        0        4   char(4)   FLGS
        4        4   long      byte length of section from next byte
        8        4   long      00 00 00 00 = visible
                               01 00 00 00 = hidden
   * could be a long integer, or a series of bytes like ATRB
   * needs more study

[TRAN] (child of MODL)
   offset   length   type      contents
        0        4   char(4)   TRAN
        4        4   long      byte length of section from next byte
        8       12   float(3)  Scale ( x , y , z )
       20       16   float(4)  Quaternion rotation  ( qx , qy , qz , qw )
       36       12   float(3)  Translation  ( x , y , z )
   * needs more study
   * these are important for keeping the bones pointed in the right direction.

GEOM (child of MODL)
   offset   length   type      contents
        0        4   char(4)   GEOM
        4        4   long      byte length of section from next byte (Including sub section sizes)

BBOX (child of GEOM)
   offset   length   type      contents
        0        4   char(4)   BBOX
        4        4   long      byte length of section from next byte
        8       16   float(4)  Quaternion Rotation ( qx , qy , qz , qw )
       24       12   float(3)  Center ( x , y , z )
       36       12   float(3)  ( Width/2 , Height/2 , Depth/2 )
       48        4   float     Bounding Sphere Radius

SEGM (child of GEOM)
   offset   length   type      contents
        0        4   char(4)   SEGM
        4        4   long      byte length of section from next byte (Including sub section sizes)

[SHDW] (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   SHDW
        4        4   long      byte length of section from next byte (Including sub section sizes)
   *all the verticies are listed first
        8        4   long      number of verticies
                12   float(3)  vertex(X, Y, Z)
   *then all the edges
                 4   long      number of edges
                 2   short     Vertex index of this edge entry. Refers to the vertex list above.
                 2   short     edge 1 (refers to another edge in this list)
                 2   short     edge 2 (refers to another edge in this list) **
                 2   short     end of edge. (65535) or (0xFFFF)
   * needs more study
   ** oddly, the vertex in the edge this refers to is always the same as the vertex in the edge that edge 1 refers to.

MATI (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   MATI
        4        4   long      byte length of section from next byte
        8        4   long      MATD reference.
   * The MATD's are indexed from 0

POSL (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   POSL
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12       12   float(3)  ( x , y , z )
   * the entry at offset 12 repeats, index( offset 8 ) times.

WGHT (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   WGHT
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 32 byte entries to follow
       12       32   (long, float)(4) (bone reference, Weight in percent)
   * the entries from offset 12 to 38 repeat, index( offset 8 ) times.
   * you can have multiple weights, they just have to add up to 100% (1.0) (XSI docs)
   * The bone is called by ENVL index.
     For example: if the first bone in ENVL is bone_neck (MNDX 34) then the WGHT reff will be 0 since it is the first bone in the ENVL.

NRML (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   NRML
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12       12   float(3)  3 floats describing Vertex normals
   * the entry at offset 12 repeats, index( offset 8 ) times.

[CLRL] (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   CLRL
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12        4   short(4)  ( red , blue , green, alpha )
   * needs more study

[CLRB] (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   CLRB
        4        4   long      byte length of section from next byte
        8        4   short(4)  ( red , blue , green, alpha )
   * Got it's structure, now what is it?
   * needs more study

UV0L (UV1L, UV2L, ect.) (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   UV0L
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 8 byte entries to follow
       12        8   float(2)  ( tx , ty )
   * the entries from offset 12 and 16 repeat, index( offset 8 ) times.
   * to see where each UV is on a texture, multiply each coordinate by the size
     of the texture.
     For example:
         if texture size = 512 x 512 and tx=0.564125 , ty=0.059709
         the points would be:
         x = tx * 512 = 0.564125 * 512 = 288.832
         y = ty * 512 = 0.059709 * 512 =  30.571008
         

[NDXL] (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   NDXL
        4        4   long      byte length of section from next byte
        8        4   long      an index. Number of polygons
       12        2   short     an index. Number of corners
       14        2   short     point ref (from POSL)
   * the entries at offset 14 repeats, index( offset 12 ) times.
   * the entries from offset 12 to (end of it's sequence) repeat, index( offset 8 ) times.
   * some software uses this info, but it will munge and play without it.
   * needs more study

[NDXT] (child of SEGM)(depriciated)
   offset   length   type      contents
        0        4   char(4)   NDXT
        4        4   long      byte length of section from next byte
        8        4   long      an index. Number of triangles
       12        2   short     point ref (from POSL)
       14        2   short     point ref (from POSL)
       16        2   short     point ref (from POSL)
   * the entries from offset 12 to 14 repeat, index( offset 8 ) times.
   * some software uses this info, but it will munge and play without it.
     (I think 3d Converter uses it to determine polys instead of the STRP.)
   * I don't know if they go clockwise or counter-clockwise.
   * needs more study

[STRP] (child of SEGM)
   offset   length   type      contents
        0        4   char(4)   STRP
        4        4   long      byte length of section from next byte
        8        4   long      an index. not certain about what it's indexing
       12        2   short     POSL vertex reffrence
   * the entry (offset 12) repeat, index( offset 8 ) times.
   * This tag lists triangle strips.
     The tringles are defined by refs to vertecies in the POSL tag.
     The strips are seperated into groups of triangle strips.
     The start of a strip is indicated by 2 entries with a high bit set.
     Basicly the vertex ref has 32768 added to it. Subtracting 32768 gives the vertex index.
     They should be listed in clockwise, counter-clockwise, clockwise order, I haven't confirmed this.
     They should be listed in   counter-clockwise,   clockwise,   counter-clockwise
     order, I haven't confirmed this.
   * needs more study

ENVL (child of GEOM)
   offset   length   type      contents
        0        4   char(4)   ENVL
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 4 byte entries to follow
       12        4   long      bone MNDX reference
   * the entry offset 12 repeats, index( offset 8 ) times.

CLTH (child of GEOM)
   offset   length   type      contents
        0        4   char(4)   CLTH
        4        4   long      byte length of section from next byte

CTEX (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   CTEX
        4        4   long      byte length of section from next byte
        8        ?   ascii     string with the end padded with 00 bytes

[CPOS] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   CPOS
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12       12   float(3)  ( x , y , z )
   * the entry at offset 12 repeats, index( offset 8 ) times.
   *same as POSL
   
[CUV0] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   CUV0
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 8 byte entries to follow
       12        8   float(2)  ( tx , ty )
   *same as UV0L

[FIDX] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   FIDX
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 4 byte entries to follow
       12        4   long      CPOS vertex indexes
   * haven't looked into this yet

[FWGT] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   FWGT
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12        4   ascii     bone names
   *assuming these are the names of the bones that the CPOS vertexes refered to in FIDX, are weighted to.

[CMSH] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   CMSH
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12       12   long(3)   CPOS vertex refferences defining a counter-clockwise triangle

[SPRS] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   SPRS Stretch Constraint
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12        4   short(2)  points sharing an edge
   *ANDEWEGET's GT post

[CPRS] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   CPRS Cross Constraint
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12        4   short(2)  points sharing a quad
   *ANDEWEGET's GT post

[BPRS] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   BPRS Bend Constraint
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12        4   short(2)  Two border-points sharing a "straight" edge over the complete cloth.
   *ANDEWEGET's GT post

[COLL] (child of CLTH)
   offset   length   type      contents
        0        4   char(4)   COLL
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12        ?   ascii     Collision object name
       ??        ?   ascii     Object this collision moves with(parent)
       ??        4   long      possible FIDX refference
       ??        4   float     for type sphere   = radius
                               for type cylynder = radius
                               for type cube     = size x/2
       ??        4   float     for type sphere   = n/a
                               for type cylynder = height
                               for type cube     = size y/2
       ??        4   float     for type sphere   = n/a
                               for type cylynder = n/a
                               for type cube     = size z/2
   *seems to work like SWCI, but for cloth
   
[SWCI] (child of MODL)
   offset   length   type      contents
        0        4   char(4)   SWCI
        4        4   long      byte length of section from next byte
        8        4   long      collision primitive type
                               0 = sphere
                               2 = cylynder
                               4 = cube
       12        4   float     for type sphere   = radius
                               for type cylynder = radius
                               for type cube     = size x (might be scaled)
       16        4   float     for type sphere   = n/a
                               for type cylynder = height
                               for type cube     = size y (might be scaled)
       20        4   float     for type sphere   = n/a
                               for type cylynder = n/a
                               for type cube     = size z (might be scaled)
   * needs more study

all of the following always appear after the last MODL chunk and their size is not included in the MSH2 value.

[SKL2] (child of HEDR)
   offset   length   type      contents
        0        4   char(4)   SKL2
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 20 byte entries to follow
       12        4   byte(4)   CRC used to refer to bone_ entries
       16        4   long      type
       20        4   float     Constrain
       24        4   float     bone length 1
       28        4   float     bone length 2
   * the entries from offset 12 to 28 repeat, index( offset 8 ) times.
   * needs more study

[BLN2] (child of HEDR)
   offset   length   type      contents
        0        4   char(4)   BLN2
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of 8 byte entries to follow
       12        4   byte(4)   CRC used to refer to bone_ entries
       16        4   float?    blend factor

ANM2 (child of HEDR)
   offset   length   type      contents
        0        4   char(4)   ANM2
        4        4   long      byte length of section from next byte (Including sub section sizes)

[CYCL] (child of ANM2)
   offset   length   type      contents
        0        4   char(4)   CYCL
        4        4   long      byte length of section from next byte
        8        4   long      an index - number of entries to follow
       12       64   char(64)  animation name
       76        4   float     frame rate
       80        4   long      play Style
       84        4   long      first Frame
       88        4   long      last Frame
   * needs more study
   ** each entry is typically 80 bytes. I'm guessing they left a long space to accomodate animation names?

[KFR3] (child of ANM2)
   offset   length   type      contents
        0        4   char(4)   KFR3
        4        4   long      byte length of section from next byte
        8        4   long      an index? - number of x byte entries to follow
       12        4   byte(4)   CRC used to refer to bone_ entries
       16        4   long      keyframe type
       20        4   long      translation count
       24        4   long      rotation count
   * all the translation entries will be listed first
       28        4   long      frame position translation index (starts at 0)
       xx        4   float     translation x
       xx        4   float     translation y
       xx        4   float     translation z
   * then all the rotation entries
       xx        4   long      frame joint rotation index (starts at 0)
       xx        4   float     quaternion qx
       xx        4   float     quaternion qy
       xx        4   float     quaternion qz
       xx        4   float     quaternion qw
   * needs more study
   * In animation msh's, this is the biggest tag,having several translation and rotation entries.

[CL1L] (child of HEDR)
   offset   length   type      contents
        0        4   char(4)   CL1L
        4        4   ?         00 00 00 00
   * I wonder if this could mean anything other than EOF

   ** the Quaternions are in the order qx,qy,qz,qw
      qw is the scalar
      qx, qy, qz are the ... vector? (I don't know how to name it. read up on quats and you will discover that everyone has a different name for them. It's no wonder we don't have a single, unified field theory. We can't even agree on how to count to 'turn left'.)

   ** ALL the CLTH tag info is directly from Ande's work. I have no way to test is as I don't have BF2.
      It's solid though, and should be easy to validate.
     
[/spoiler]

I believe the above is pretty complete for the purposes of recognizing and translating the msh data. As I run across errors, I will correct them. The code I am building is drawing directly from the info in this document.
I am now moving on to explore the next level of abstraction the data represents. Envelopes, smoothing groups, IK chains and such.

The attatched tools will br removed when I make suitable replacements for them.
They are all being re-written from the ground up to include everything I have learned in the last several months.
I haven't decided if they will be several small tools, or a single tool with several options.
I do know that none will have a GUI. All input and output will take place through the console or via txt files.

I don't think there will be much more that I can do with the raw format, utillity-wise. But I am looking into various ascii formats. Perhaps I can takea swing at, say, a msh to obj converter that doesn't loose half the msh data (like the entire skeleton.)

-next update : re-tooling the tools. (testing)

nice work.  I wish I new enough to be able to help you...
Quote from: Abraham Lincoln. on November 04, 1971, 12:34:40 PM
Don't believe everything you read on the internet

i argree certainly nice work. Good job!

February 27, 2012, 08:37:57 PM #3 Last Edit: May 20, 2012, 03:01:41 PM by tirpider
-edit
Sorry about hijacking my own post.
Ran out of room above.

.msh SPECULATIONS
[spoiler]
I've noted some interesting things about how all these pieces work together, but am not sure how to word it.
Bear with me as I work this section out.

I noticed that the eff_ (effector?) MODL chunks all have either no rotation, (-0,-0,-0,1), or an all -0 vector with a very slightly off scalar (making the quat non-normalized)
I bet these could all be 'zeroed' to , (-0,-0,-0,1), and were probably intended to be to begin with.

The MATI chunk indicates what material(MATD) is to be used when rendering the geometry defined in it's SEGM.
The MATD's are referenced in order of appearance in the MATL. Starting with 0.

To get geometry to show up in game, it needs to be in a SEGM.
That SEGM needs to contain a minimum of a POSL, NRML, UV0L, and STRP chunk.
The UV0L isn't required, but if you want your mesh to not be plain white, It must be there.

The POSL lists all the vertecies for the mesh.
All the other SEGM sections refer to vertecies by their order of appearence in POSL (starting at 0.)

Positions in the chunk for POSL, WGHT, NRML, and UV0L have a 1 to 1 relationship.
An example:
Entry 15 in POSL is a vertex.
Entry 15 in WGHT is the weight info for that vetrex.
Entry 15 in NRML is that vertex's normal info.
Entry 15 in UV0L is that vertex's UV point on the texture.

NDXL, NDXT, and STRP define polygons and edges by listing vertex references in the order needed to form the poly.
The references are their entry position in POSL.

STRP also describes strips of triangles that, once coupled with their POSL, NRML, and UV0L information, define the actual stuff that shows up in game.

Trialgle strips are appearantly easier for the machine to manipulate.

NDXL and NDXT are ignored by ModelMunge.exe, and therefore do not make it into the game.

NDXL and NDXT are used by some programs to find the edges that conect vertecies.

I have tested gathering the triangles from the STRP and replacing NDXL with them, and not only does it work, but if I sort each triangle so that the lowest index comes first, the sort the entire NDXL by that first index, I end up with the same list of tris from NDXT.

Weighting.
WGHT referes to an entry in the ENVL contained in the same GEOM chunk.
ENVL is a list of MNDX references.
There are spots for 4 weights in each WGHT entry, though most models use only 1.
(I haven't actually seen any models use more than one per vertex.)
If you do use more than one weight, then the percents for all of them must add up to 100% (1.0)

Some MODL's have no EVNL.
The examples I have seen are mostly hands.
They are positioned within the heirarchy so that their parent is the bone_*_hand.
I don't know what tells ModelMunge to weight it to the hand bone.
It could be the absence of an ENVL and it's position in the heirarchy.
Or the absence of ENVL and the PRNT entry.

The CRCs in KFR3, SKL2, and BLN2 all refer to the envelope bone MODL chunks.
There is a groovy little program in the BF2 mod tools bin that will take whatever text is on the clipboard, calculate the CRC and place the CRC on the clipboard.
I don't exactly like the manner in which it runs, but I am glad whoever wrote it, did.
The algorithm for creating these CRC's is not known at this time. (if you know, drop me a line :) )

[/spoiler]

SOURCES[spoiler]
The documentation for the BFBuilder and BF2 Mod Tools.

Ande (ANDEWGET on GT) Has been the biggest contributor to all this.
He is working on an exporter for the modern version of the XSI modtool.
Idealy, once it is done, there should be no need for all this.

The Extended Riley pages MSH File Information (extended by Ande) This guy is doing a wondefull job exploring this format. I hope, one day, that our answers mirror each other.
His site has more info and tools : Ande Projects

The Riley pages (lost to the internet ages and resurected in archives, the info is a good start, and when I move on to lvl files, the Riley pages will prove invaluble, I am sure.)

A myriad of posts on GT and SWBFGamers.com. Both of these boards have hard working and dedicated modders. As I gather more resources I will put your names and links to your research here.



(Tracking all these down is going to take time, but it will show up here, I promise.)

Blood, sweat, and tears inside the SciTE editor, the AutoIT help file, and XVI32.

Genuine curiosity for how and why the msh file format has remained a mysterious black box for over 6 years.
[/spoiler]

TOOLS USED TO FIGURE THIS OUT[spoiler]
HEX EDITOR (for looking at msh guts)
Freeware Hex Editor XVI32

TEXT EDITOR (mainly for formatting text copied in one program for pasting into another)
AEdiX Suite

SPREADSHEET (for analyzing msh guts)
OpenOffice.org - Calc

SCRIPTING LANGUAGE (for chopping and stitching msh guts)
AutoIT

3D PROGRAMS (Miscelaneous bits of information)
Ultimate Unwrap 3D - A shareware UV mapping program. It has a plugin that can load SWBF msh files. If you tell it to load all models instead of just the ones with geometry, then you can access information about the bones. Specificly relative and global rotations and positions.

3D Object Converter - A shareware 3d file viewer and converter. This program will let you browse geometry and materials. You can also unwrap the model. While the unwrap from this prog is not 100% it is definatly close enough to assist with basic reskinning. Interestinly, it gets it's polygon unwrap info from NDXL and not the STRP. (The STRP makes it through ModelMunge, while NDXT and NDXL do not)

Milkshape 3D - A shareware 3d editor. Many plugins for export and import. While it isn't directly usefull for handling MSH files, it is much more approachable as a modeling program than the big players (3d studio, XSI, Blender, ect.) For static models, exporting as VRML 2.0 then converting to MSH via the SWBF MSH Viewer is really handy. If we could get a msh exporter put together for this one, it would solve our animating and modeling problems for good. (and for less than a hundred bucks.)

SWBF MSH Viewer - If you want to see a MSH without munging it into the game or jumping through ZeroEdit's hoops, this is it. It can export your MSH as a VRML97 file. It can load VRML97 files and save as a MSH. No bones make it through this process, only the geometry gets saved. It also has a debug feature that was my starting point for decyphering the MSH structure.

EVERYTHING ELSE (Miscelaneous bits of information)
... Google, Yahoo, MSDN, various math and 3D graphics engine sites... Basicly all the dustiest, darkest, most dis-used sites on the internet...



[/spoiler]

-edits-[spoiler]
05/19/2012 -Revised some definitions and data type descriptions.
           -I'm getting ready to sync the tags with my tool source, but need to do more testing. (it's a mess right now)
           -The MSH INFO tool may go away and turn into a txt report tool. AutoIT's method of handling gui widgets makes me cross-eyed. Txt reports can be customized so much easier than that logic-defying listbox.
           
03/22/2012 -Added speculation section. Ran out of room in first post, so I hijacked my next one. I think I'll work on putting this in a doc or txt file.

02/27/2012 -Fleshed out KFR3. standard bone heirarchy example. Revising many definitions... Synced up definitions.

01/21/2012 -WGHT references envelope entries and not MNDXs like I thought.

01/20/2012 -'editor' gets it's own thread now. I have more info, but haven't got it ready yet.

12/18/2011 -Updated Screenshot of the 'editor' program I'm working on. My hopes are that it's completion will help me flesh out some of the question marks in the above notes.

12/14/2011 -Added ANIM, CLRB, MYTP, LGTI tags.
           -Files are loading fast now, but I'm running into new tags and bad file sizes.
           -The problems are with 3rd party msh's, but I'd still like to resolve them.
           -No new shots of the GUI, re-working the code first. Pretty won't fix bad code.

12/13/2011 -Found 3 new tags (ANIM,CLRB,MYTP). 2 of them disturb me. The worst is MYTP. It contains the same info and is in the same place as MTYP (Existing in place of it, almost). So it was either intentionaly misspelled, or there was a bug in whatever program made them. Doing a more intense search for msh tags now. I was only looking at BF1 models, but now I'm looking at every msh in my archive. (many thousand msh files, since everyone thats released thier source also re-released assets that were either already released or included with the mod tools.) Been at it for 2 hours and I'm a quarter through determining which ones fail a size check (un accounted for tags.)  So, new tag entries in a cpl of days...

12/02/2011 -Added SHDW tag. Courtesy of Ande. Not yet reflected in tools. It seems to only be present in 'some' static models.
           -corrected (guessed at) [/b]SWCI[/b].
           -dead wrong about CLRL structure
           
11/28/2011 -NDXL and NDXT are depriciated. I thought they were redundant, anyway since the STRP is a more efficient way to store the triangle info. Thanks to ANDEWEGET on GT for the heads up.

11/22/2011 -Updated chunk2MSH tool to update size values automaticly(see readme). inacurate SWCI qualifier removed. inacurate GEOM-BBOX parent fixed.

11/18/2011 -Started enumerating sources.
11/15/2011 -upped screenshot of tool.
11/06/2011 -Got rid of some extra words.
11/05/2011 -added basic CLTH info.
11/04/2011 -added SHVO offset info. updated tools.
11/02/2011 -Attached a zip containing src and compiled scripts from early in this process. (v1)
10/31/2011 -Got rid of some extra words. Hardened some of the known descriptions.
10/27/2011 -updated NDXL, NDXT, [STRP]
10/27/2011 -fixed WGHT (skipped one of it's fields, and made a pretty good guess at it's structure)
10/26/2011 -fixed BBOX (skipped one of it's Rotation fields.)
10/25/2011 -Fleshed out some info from the MSH Viewer. (I'l love to talk with whomever made it.)
10/24/2011 -Revised the layout a bit and expanded BBOX info.
            it makes more sense to look at each tag as it's own chunk(from a programing point of view.)
            Dead wrong about ATRB. Removed bad info.
10/23/2011 -added NRML, CLRL, UV0L, NDXL, NDXT, STRP, SWCI, BLN2, KFR3, CYCL offset info.
10/23/2011 -Revised the layout a bit and added POSL, MATI, SEGM, ENVL, SKL2 offset info. Restructured the section descriptions.
10/22/2011 -added offset info section.[/spoiler]

December 26, 2017, 03:35:53 PM #4 Last Edit: December 26, 2017, 03:38:09 PM by RepComm
CAMR -> DATA info (will edit per find):

Last two floats are camera's near and far ranges.
I am comparing values to camera data on XSI soft image. I'll keep adding values and eventually structure them when I get back to internet land..

There isn't a way for me to live test values because ZETools doesn't even export camera tags.. maybe we really do need xsiaddon to work so we can flesh the format out completely.

Awesome! I'll update the above when you post it.

I don't even know if it is a field the original xsiaddon would produce. (Going off memory so I may be wrong about this) I gathered a lot of information from ancient, exotic places online. One that comes to mind is a modding community for the old Battlezone game, they have a lot of tags that don't exist in Battlefront MSH files. So some of the stuff may be depreciated data structures that the mungers would just ignore or try to smash in with a surrounding tag.

January 21, 2018, 09:52:49 AM #6 Last Edit: January 21, 2018, 10:38:22 AM by RepComm
I'm not at my computer now, but I'm investigating fsx model format, and the documentation says it's based on the riff format, which stores tags of 4 chars and byte lengths the same as MSH https://en.m.wikipedia.org/wiki/Resource_Interchange_File_Format

http://www.fsdeveloper.com/wiki/index.php?title=MDL_file_format_(FSX)

I'm still working on these other camera data bytes, btw