M2
Header
The header has mostly the layout of number-offset pairs, containing the number of a particular record in the file, and the offset. These appear at fixed places in the header. Record sizes are not specified in the file.
Offset Type Name Description 0x000 char[4] Magic "MD20" 0x004 uint32 Version 0x80100000 (first digit of the build the format was last updated) 0x008 uint32 lName Length of the model's name 0x00C uint32 ofsName Offset to the name 0x010 uint32 Type Type of the model. Connected to field 4 of CreatureModelData.dbc? 0x014 uint32 nGlobalSequences 0x018 uint32 ofsGlobalSequences A list of timestamps. 0x01C uint32 nAnimations 0x020 uint32 ofsAnimations Information about the animations in the model. 0x024 uint32 nAnimationLookup 0x028 uint32 ofsAnimationLookup Mapping of global IDs to the entries in the Animation sequences block. 0x02C uint32 nBones 0x030 uint32 ofsBones Information about the bones in this model.
--schlumpf_ 02:08, 21 August 2008 (CEST)
- Xayo and 2.x ones:
The header has mostly the layout of number-offset pairs, containing the number of a particular record in the file, and the offset. These appear at fixed places in the header. Record sizes are not specified in the file.
The unknown blocks have (mostly arbitrary) alphabetic names until we figure out what they are.
Offset Type Description 0x02C uint32 nBones - number of bones 0x030 uint32 ofsBones - offset to bones 0x034 uint32 nF - bone lookup table 0x038 uint32 ofsF 0x03C uint32 nVertices - number of vertices 0x040 uint32 ofsVertices - offset to vertices 0x044 uint32 nViews - number of views (LOD versions?) 4 for every model (0x048 uint32 ofsViews - offset to views (After the "New Pattern" it should be there but in my M2 theres just a 00 00 00 00)) 0x048 uint32 nColors - number of color definitions 0x04C uint32 ofsColors - offset to color definitions 0x050 uint32 nTextures - number of textures 0x054 uint32 ofsTextures - offset to texture definitions 0x058 uint32 nTransparency - number of transparency definitions 0x05C uint32 ofsTransparency - offset to transparency definitions 0x060 uint32 nI - always 0 0x064 uint32 ofsI 0x068 uint32 nTexReplace 0x06C uint32 ofsTexReplace 0x070 uint32 nRenderFlags - number of blending mode definitions 0x074 uint32 ofsRenderFlags - offset to blending mode definitions 0x078 uint32 nBoneLookupTable - bone lookup table 0x07C uint32 ofsBoneLookupTable 0x080 uint32 nTexLookup - number of texture lookup table entries 0x084 uint32 ofsTexLookup - offset to texture lookup table 0x088 uint32 nTexUnits - texture unit definitions? 0x08C uint32 ofsTexUnits 0x090 uint32 nTransLookup - number of transparency lookup table entries 0x094 uint32 ofsTransLookup - offset to transparency lookup table 0x098 uint32 nTexAnimLookup - number of texture animation lookup table entries 0x09C uint32 ofsTexAnimLookup - offset to texture animation lookup table 0x0A0 14 * float float values ... ? (in range -1000...1000, mostly in -20...30) 0x0D8 uint32 nBoundingTriangles 0x0DC uint32 ofsBoundingTriangles 0x0E0 uint32 nBoundingVertices 0x0E4 uint32 ofsBoundingVertices 0x0E8 uint32 nBoundingNormals 0x0EC uint32 ofsBoundingNormals 0x0F0 uint32 nAttachments 0x0F4 uint32 ofsAttachments 0x0F8 uint32 nAttachLookup 0x0FC uint32 ofsAttachLookup 0x100 uint32 nAttachments_2 0x104 uint32 ofsAttachments_2 0x108 uint32 nLights - number of lights 0x10C uint32 ofsLights - offset to lights 0x110 uint32 nCameras - number of cameras 0x114 uint32 ofsCameras - offset to cameras 0x118 uint32 nCameraLookup 0x11C uint32 ofsCameraLookup 0x120 uint32 nRibbonEmitters - number of ribbon emitters 0x124 uint32 ofsRibbonEmitters - offset to ribbon emitters 0x128 uint32 nParticleEmitters - number of particle emitters 0x12C uint32 ofsParticleEmitters - offset to particle emitters
Note: These infos are ALL not aprooved!
Skeleton and animation
Standard animation block
- Many values that change with time are specified using blocks like the following. The structure changed in WotLK. Information will come soon.
Offset Type Name Description 0x000 uint16 InterpolationType How the values are interpolated. See below. 0x002 uint16 GlobalSequenceID If its made with a global sequence, its in here. Id is it is, -1 if not. 0x004 uint32 nA Number of the first informations in the block. 0x008 uint32 infA First informations in the block. 0x00C uint32 nB Number of the second informations in the block. 0x010 uint32 infB Second informations in the block.
--schlumpf_ 02:01, 21 August 2008 (CEST)
- Old information
Offset Type Description 0x00 int16 interpolation type 0x02 int16 global sequence ID or -1 0x04 uint32 number of (int, int) interpolation ranges 0x08 uint32 offset to interpolation ranges 0x0C uint32 number of (int) timestamps 0x10 uint32 offset to timestamps 0x14 uint32 number of values 0x18 uint32 offset to values
The values can have various types depending on the kind of data required, like floats, vectors, quaternions etc.
Usually, if animation is used, interpolation ranges will be given for each animation in the global animation list. These ranges refer to keyframes that have given time and data values. The number of timestamps should therefore be equal to the number of data values.
If a global sequence is used, it means there is an implicit interpolation range across all values, and a time range from 0 to the proper global sequence timestamp.
If the interpolation type is 0, in some cases that might mean that no animation is given (like for bones), in other cases it means that a single constant data value should be used (like for colors and effect paramters)
Interpolation types:
Value Description 0 none / static value 1 linear 2 (spline?) in addition to values, in/out tangents are given
Maybe the interpolation types here are the same as the WC3 MDL files? (bezier, etc)
Global sequences
- nGlobalSequences 32-bit unsigned integers starting at ofsGlobalSequences.
A list of timestamps that act as upper limits for global sequence ranges.
Offset Type Name Description 0x00 uint32 Timestamp Entry
--schlumpf_ 02:35, 21 August 2008 (CEST)
Animation sequences
- List of animations present in the model. nAnimations 0x40-byte records starting at ofsAnimations.
Offset Type Name Description 0x00 uint16 AnimationID Animation id in AnimationData.dbc 0x02 uint16 SubAnimationID Sub-animation id: Which number in a row of animations this one is. 0x04 uint32 Length The length (timestamps) of the animation. 0x08 float MovingSpeed As 2.x says: moving speed for walk/run animations. 0x0C uint32 Flags Most likely. All flags I saw: 0b01101101 0x10 uint32 Flags 2 Only the first 4 bits are the actual flags. The rest is 1. Values are 0x*FFF. Seen flags: 0,3,6,7 0x14 uint32 Unknown 1 These two are connected. Most of the time, they are 0. 0x16 uint32 Unknown 2 But if there is data in one, there is data in both of them. 0x1C uint32 PlaybackSpeed Values: 0, 50, 100, 150, 200, 250, 300, 350, 500. Was labeled as PlaySpeed in 2.x and earlier. 0x20 float BoundingBox [6] A Bounding Box made out of 2 vectors. 0x38 float Radius The radius. 0x3C int16 NextAnimation Id of the following animation of this AnimationID, points to an Index or is -1 if there is none. 0x3E uint16 Index Id in the list of animations.
--schlumpf_ 00:28, 21 August 2008 (CEST)
Animation Lookup
- nAnimationLookup in 16-bit shorts starting at ofsAnimationLookup.
Lookup table for Animations in AnimationData.dbc.
Offset Type Name Description 0x00 uint16 AnimationID Index at ofsAnimations which represents the animation in AnimationData.dbc. -1 if none.
--schlumpf_ 00:45, 21 August 2008 (CEST)
Bones
- nBones records of 0x70 bytes starting at ofsBones, followed by data referenced in these records.
The bone indices in the vertex definitions seem to index into this data.
Offset Type Description 0x00 uint32 index into Animation sequences or -1. Or Animation ID in AnimationData.dbc 0x04 uint32 Flags 0x08 uint16 Parent bone ID or -1 0x0A uint16 geoid 0x0C uint32 unknown, found in Client 2.0 M2s 0x10 AnimationBlock (float, float, float) Animation data for translation 0x2C AnimationBlock (float, float, float, float) Animation data for rotation, see Quaternion values and 2.x 0x48 AnimationBlock (float, float, float) Animation data for scaling 0x64 float[3] Pivot point
Flags:
- 8: billboarded
- 512: transformed
The billboarding bit is used for various things:
- Light halos around lamps must always face the viewer
- The cannonball stack model (in the Deadmines or Booty Bay), where each cannonball is a crude hemisphere, they always face the viewer to create the illusion of actual cannonballs.
Geometry and rendering
Vertices
- 48 bytes per vertex (at ofsVertices [?])
Models, too, use a Z-up coordinate systems, so in order to convert to Y-up, the X, Y, Z values become (X, -Z, Y).
Offset Type Description 0x00 float[3] Position 0x0C uint8[4] Bone weights (0 to 255) 0x10 uint8[4] Bone indices (0 to nBones-1) 0x14 float[3] Normal vector 0x20 float[2] Texture coordinates 0x28 float[2] 0?
The fields marked with ? probably have to do with skeletal animation.
Considering "standard" GPU skeletal animation (matrix palette, 4 weights/bones per vertex):
- then "usually 255" should be an array of 4 unsigned chars defning the vertex weight for 4 bones
- then "vertex group" should be an Array of 4 unsigned chars indexing 4 bones ++++
-Note by Hergonan-
When I set all info for the vertices to 0 the visual part of the model didn't change but when I tried to select a model ingame by using the mouse and hovering over them I could only do that where the bones were. That means vertices are there for the mouse to react with.
Views (LOD)
Every model has four of these, at 0x2C bytes each. I'm not sure if it is LOD because each one of them has the same amount of vertices for all four data sets. (???) First I thought this might be different vertex orderings from different views, to ease polygon sorting for transparent faces, but that's not it either. Hmm.
Starting at ofsViews, there are four View (LOD?) header records followed by the data for all four.
Offset Type Description 0x00 uint32 number of elements in the index list 0x04 uint32 offset to the index list 0x08 uint32 number of elements in the triangle list (this is 3* the number of triangles to be drawn) 0x0C uint32 offset to the triangle list 0x10 uint32 number of elements in the vertex property list 0x14 uint32 offset to the vertex property list 0x18 uint32 number of elements in the submesh list 0x1C uint32 offset to the submesh list 0x20 uint32 number of elements in the texture list 0x24 uint32 offset to the texture list 0x28 uint32 LOD distance or something?
Indices
- A 16-bit unsigned integer per index, specifies vertices from the global vertex list.
Triangles
- For every triangle, three 16-bit unsigned ints. These refer to the index list given above, not the global vertex list.
Vertex properties
- 4 bytes per vertex. Usually 0? Purpose unknown.
Submeshes
- 32 bytes per submesh. 48 bytes per submesh after client 2.0 (Burning Crusade expansion)
Offset Type Description 0x00 uint32 Mesh part ID 0x04 uint16 Starting vertex number 0x06 uint16 Number of vertices 0x08 uint16 Starting triangle index (that's 3* the number of triangles drawn so far) 0x0A uint16 Number of triangle indices 0x0C uint16 Number of elements in the bone lookup table 0x0E uint16 Starting index in the bone lookup table 0x10 uint16 Unknown 0x12 uint16 root bone ? 0x14 float[3] Vector (3d) 0x20 float[4] 4 float values? (only in Client 2.0 M2s)
Mesh part ID: for character models, each hairstyle/thick armor/etc is present in the mesh, so to render a character with a specific set of looks, some of the submeshes should be ommitted based on this ID.
Reference to the bone lookup table: the base number seems to increase per LOD, and the numbers in the bone lookup table, in turn, point to bone - indices to Block E. Maybe this could be an indicator of bones used in a submesh, or an animation sequence or something?
About LOD: Creatures\AncientProtector\AncientProtector.m2 is the first model I found where the LOD levels have a significant difference. The 4th LOD level still has the same number of vertices/polygons, but it has more submeshes (more sophisticated animation/lighting or something? I dunno)
Texture units
24 bytes per record. More specifically, textures for each texture unit. Based on the current submesh number, one or two of these are used to determine the texture(s) to bind.
Offset Type Description 0x00 uint16 Flags 0x02 int16 Render order (used in skyboxes to ditch the need for depth buffering) 0x04 uint16 Submesh index 0x06 uint16 Submesh index (repeated?) 0x08 int16 Color index or -1 0x0A uint16 Index into render flags table 0x0C uint16 Texture unit number (0 or 1 - index into the texture unit lookup table) 0x0E uint16 always 1? 0x10 uint16 Texture to use (index into the texture lookup table) 0x12 uint16 Texture unit number (repeated?) 0x14 uint16 Transparency (index into transparency lookup table) 0x16 uint16 Texture animation (index into the texture animation lookup table)
Flags: usually 16 for static textures, and 0 for animated textures.
Render flags
- nRenderFlags (uint16, uint16) pairs starting at ofsRenderFlags
Offset Description 0x00 Flags 0x02 Blending mode
- Flags:
Flag Meaning 0x01 Unlit 0x02 Unfogged? 0x04 Two-sided (no backface culling if set) 0x08 ? 0x10 Disable z-buffer?
- Blending mode
Value Meaning 0 Opaque 1 Alpha testing only 2 Alpha blending 3 Additive? 4 Additive alpha? 5 Modulate? 6 Used in the Deeprun Tram subway glass, supposedly (src=dest_color, dest=src_color) (?)
Most of these blend values are taken from the MDL docs, but they sort of work (like additive blending for light shafts and such)
Texture unit lookup table
- nTexUnits 16-bit integers starting at ofsTexUnits. (values: -1, 0, 1)
For models that use multitexturing, this maps given texture unit numbers into actual texture unit numbers (0 or 1).
Values of -1 seem to mean environment mapping.
One model is of special interest, Creature/KelThuzad/KelThuzad.m2, which is the only one that has an nL of 3, and has three texture units specified for some of its submeshes. Sure enough, two of those map to 0 and 1, and one maps to -1.
More confusion thanks to my favorite "weird" model, World/Generic/Gnome/Passive Doodads/GnomeMachine/GnomeSubwayGlass.m2, which is the translucent, environment mapped glass tunnel in the Deeprun Tram. It only has a single value in this block, -1, which is used for the single texture layer in both render operations in the model. This and the magic with rendering flags/blend modes make up the neat transparent-reflective glass effect, but confuse me even more about how envmapping and such is handled. (and where it seems to get the bluish color from - is it in the model (no color blocks in this particular model), the wmo, a solid background color, or simply the result of the blending used?)
As a side note, on my (dated) system WoW does every texture unit in a single pass.
Colors and transparency
Colors
- nColors records of 0x38 bytes starting at ofsColors, followed by data referenced in these records.
For some swirling portals and volumetric lights, these define vertex colors. Referenced from the Texture Unit blocks in the LOD part. Contains a separate timeline for transparency values. If no animation is used, the given value is assumed to be constant.
Offset Type Description 0x00 AnimationBlock (float,float,float) Data for RGB color values 0x1C AnimationBlock (short) Data for opacity values
Opacity values: 32767 = opaque, 0 = transparent.
Transparency lookup table
- nTransLookup 16-bit integers starting at ofsTransLookup. (values: 0 to nH-1 ?)
Contains indices into the Transparency block. Used by the texture unit definitions in the LOD block.
Transparency
- Specifies global transparency values (in addition to the values given in the Color block - I assume these are multiplied together eventually?)
nTransparency records of 0x1C bytes starting at ofsTransparency, followed by data referenced in these records.
Offset Type Description 0x00 AnimationBlock (short) Data for transparency values
Transparency: 32767 for fully opaque, 0 for fully transparent
Textures
- Textures are defined globally in a list, additionally, a lookup table is given, referenced during rendering, to select textures.
Texture lookup table
- Just a list of 16-bit integers. nTexLookup items starting at ofsTexLookup.
Texture definitions
- First is a list of nTextures texture definition records, 16 bytes per record, starting at ofsTextures. After it comes a string block with the texture filenames.
Offset Type Description 0x00 uint32 Texture type (aka replacable id) 0x04 uint16 Unknown, usually 0 0x06 uint16 Flags 0x08 uint32 Filename length 0x0C uint32 Offset to filename
Texture type is 0 for regular textures, nonzero for skinned textures (filename not referenced in the M2 file!) For instance, in the NightElfFemale model, her eye glow is a type 0 texture and has a file name, the other 3 textures have types of 1, 2 and 6. The texture filenames for these come from client database files:
- DBFilesClient\CharSections.dbc
- DBFilesClient\CreatureDisplayInfo.dbc
- DBFilesClient\ItemDisplayInfo.dbc
- (possibly more)
- Texture Types:
Value Meaning 0 Texture given in filename 1 Body + clothes 2 Cape 6 Hair, beard 8 Tauren fur 11 Skin for creatures 12 Skin for creatures #2 13 Skin for creatures #3
- Flags:
Value Meaning 1 Texture wrap X 2 Texture wrap Y
'Nothing changed here in WotLK so far!'
Effects
Ribbon emitters
- nRibbonEmitters records of 0xDC bytes starting at ofsRibbonEmitters, followed by data referenced in these records.
These are called ribbon emitters in the strings buried in wow.exe. I guess these are some sort of ribbon-like visual effects similar to particles. In Warcraft 3 (of which the WoW engine is quite loosely based off of) there was also the possibility of ribbon-like effects in trails and flowing clothing. This is also how in WoW the feathers of the gryphons, hippogryphs, and bats flow in the wind as you rise and descend.
Note: the models that contain ribbon emitters and are viewable in the game world are: wisps in BFD, Al'ar the Phoenix in Tempest Keep(and any other phoenix models), and energy trails in the COT (not the actual instance, but the entrance cave in Tanaris Desert). The only other models with ribbon emitters are spells and effects. Gryphons/etc don't have ribbon emitters, the feathers are part of their geometry.
What about the ribbons in the model of the undead ziggurat crystals in Stratholme?
The records have the following structure:
Offset Type Description 0x00 int32 ID? always -1 0x04 int32 Bone ID 0x08 float[3] position 0x14 int32 Number of texture refs 0x18 int32 Offset to texture refs (ints) 0x1C int32 Number of ints #2 0x20 int32 Offset to list of ints #2 0x24 AnimationBlock (float, float, float) Color 0x40 AnimationBlock (short) Opacity 0x5C AnimationBlock (float) Height above 0x78 AnimationBlock (float) Height below 0x94 float Something about length/lifespan? 0x98 float Something about length/lifespan? 0x9C float Usually 0 0xA0 short[2] (blending modes maybe?) (1,1) 0xA4 AnimationBlock (int) ? (always 0) 0xC0 AnimationBlock (int) ? (always 1)
Parameters from the MDL format that are probably in here somewhere: life span, emission rate, rows, cols ...?
Particle emitters
- nparticleEmitters records of 0x1F8 bytes starting at ofsParticleEmitters, followed by data referenced in these records.
The records have the following structure:
Offset Type Description 0x000 int32 id (always -1?) 0x004 int32 flags 0x008 float[3] position 0x014 int16 Bone ID 0x016 int16 Texture ID 0x018 uint32 Number of ints referenced #1 0x01C uint32 Offset to list of ints #1 0x020 uint32 Number of ints referenced #2 0x024 uint32 Offset to list of ints #2 0x028 int16 Blending mode 0x02A int16 Emitter type 0x02C int16 Particle type 0x02E int16 Texture tile rotation (-1,0,1) 0x030 int16 Rows on texture 0x032 int16 Columns on texture 0x034 AnimationBlock (float) [10] Parameters 0x14C float[36] unknown float values - more parameters? 0x14C float Midpoint in lifespan? (0 to 1) 0x150 uint32[3] ARGB colors (start, mid, end) 0x15C float[3] Particle sizes (start, mid, end) 0x168 short[10] Indices into the tiles on the texture? 0x17C float[3] Unknown 0x188 float[3] Something about particle scaling? Hm. 0x194 float Slowdown 0x198 float Particle rotation 0x19C float[10] Unknown (usually all 0) 0x1C4 float[6] Unknown, usually (2.5, 0.7, 7, 0.9, 0, 0) 0x1DC AnimationBlock (int) unknown
About slowdown: for nonzero values, instead of travelling linearly the particles seem to slow down sooner. I can't work out the exact function but for a value of, say, 10, the particles pretty much stay in place. Not the same effect as gravity, though. Update: thanks to nsz for the formula. Speed is multiplied by exp( -slowdown * t )
About particle rotation: 0 for none, 1 to rotate the particle 360 degrees throughout its lifetime.
The ten animatable particle parameters are:
Number Description 0 Emission speed 1 Speed variation (range: 0 to 1) 2 Vertical Range (range: 0 to pi) 3 Horizontal Range (0 to 2*pi) 4 Gravity 5 Lifespan 6 Emission rate 7 Emission area length 8 Emission area width 9 Gravity? (much stronger)
Emitter types:
Value Description 1 Plane (rectangle) 2 Sphere 3 (Spline? can't be bothered to find one)
Particle types:
Value Description 0 "normal" particle 1 large quad from the particle's origin to its position (used in Moonwell water effects) 2 seems to be the same as 0 (found some in the Deeprun Tram blinky-lights-sign thing)
Flags:
Value Description 0x1000 do not billboard (used for some water wake ripple effects)
Miscellaneous
Bounding volumes
- For some models a simplified bounding volume is given. This is probably used for collision detection?
The nBoundingVertices vertices used by the bounding volume's faces start at ofsBoundingVertices. Each vertex is given by 3 floats.
The faces start at ofsBoundingTriangles. The number nBoundingTriangles once again contains the number of indices used, so divide by 3 to get the number of triangles. Each triangle is given by 3 16-bit integers that index the bounding vertices list.
Each face also has a corresponding normal vector (?), these start at ofsBoundingNormals. Therefore, it should be true that nBoundingNormals * 3 = nBoundingTriangles.
Lights
- nLights records of 0xD4 bytes starting at ofsLights, followed by data referenced in these records.
The records have the following structure:
Offset Type Description 0x00 uint16 Type 0x02 uint16 Bone ID 0x04 float[3] Coordinates 0x10 AnimationBlock (float, float, float) Ambient color 0x2C AnimationBlock (float) Ambient intensity 0x48 AnimationBlock (float, float, float) Diffuse color 0x64 AnimationBlock (float) Diffuse intensity 0x80 AnimationBlock (float) Attenuation start? 0x9C AnimationBlock (float) Attenuation end? 0xB8 AnimationBlock (int) usually 1
Some light types:
Value Description 0 Directional 1 Point light
Cameras
- These blocks seem to be present in the "flyby" camera models which completely lack geometry, and the main menu backdrop models which are supposed to have a fixed camera. Additionally, characters and monsters also have this block.
nCameras records of 0x7C bytes starting at ofsCameras, followed by data referenced in these records.
Offset Type Description 0x00 int32 ID or maybe a parent bone? usually -1 0x04 float FOV 0x08 float Far clipping plane 0x0C float Near clipping plane 0x10 AnimationBlock (float, float, float) Translation for position? 0x2C float[3] Position? 0x38 AnimationBlock (float, float, float) Translation for target? 0x54 float[3] Target? 0x60 AnimationBlock (float) Rotation or roll? (usually 0 or 2*pi)
For static cameras the animatable data items are all 0. The FOV is not in radians, but some weird scale... Multiplying by about 35 seems to give correct-ish results in degrees.
The reason that non-mainmenu and non-geometry M2s have cameras (atleast in Warcraft 3) was so you could see the unit's portrait. In WoW, these models have cameras so that when you enter the Character menu (press "C") you see your character regardless of what model you currently have. Also, I believe that one of the main menu models has two cameras in it (I believe it's the orc one...).-DG
Oh, that's right. Neat. I added menu backdrops using these cameras. Obviously it's still missing particle emitters, but that can be fixed eventually... - Z.
Camera lookup table
- Lookup table for cameras? It seems to be persent only if a camera is present too.
nCameraLookup 16-bit integers starting at ofsCameraLookup. (values: 0..nCameras-1)
Bone Lookup Table
- nBoneLookupTable 16-bit integers starting at ofsBoneLookupTable. (values: 0 to nBones-1)
Lookup table for bones that transform geometry. Referenced in the various geoset definitions.
Attachments
Block 1
- nAttachments records of 0x50 bytes starting at ofsAttachments, followed by data referenced in these records.
Offset Type Description 0x00 uint32 id (position of the record in block P) 0x04 uint32 bone 0x08 float[3] position 0x14 AnimationBlock (int) Data 0x40 float[3] Unknown Floats (rot maybe?) 0x4C AnimationBlock (int) Data
--Xayo 02:33, 21 August 2008 (CEST)
Much like Block 2 this one also specifies a bunch of locations on the body - hands, shoulders, head, back, knees etc. Maybe this one is actually used to put items on a character. This seems very likely as this block also contains positions for sheathed weapons, a shield, etc.
Here's the list of position slots (by ID, or index in block P) for character models:
ID Description ID Description ID Description 0 Left wrist / Mountpoint 12 Back 24 - 1 Right palm 13 - 25 - 2 Left palm 14 - 26 Right back sheath 3 Right elbow 15 Bust 27 Left back sheath 4 Left elbow 16 Bust 28 Middle back sheath 5 Right shoulder 17 Face 29 Belly 6 Left shoulder 18 Above character 30 Left back 7 Right knee 19 Ground 31 Right back 8 Left knee 20 Top of head 32 Left hip sheath 9 - 21 Left palm 33 Right hip sheath 10 - 22 Right palm 34 Bust 11 Helmet 23 - 35 Right palm
ID 0 is left wrist / shield for mobs and "mountpoint" for mounts.
For weapons, usually 5 of these points are present, which correspond to the 5 columns in ItemVisuals.dbc, which in turn has 5 models from ItemVisualEffects.dbc. This is for the weapon glowy effects and such. The effect ID is the last column in ItemDisplayInfo.dbc.
Attachment Lookup
- nAttachLookup 16-bit integers starting at ofsAttachLookup. (values: -1, 0 to nO-1)
Lookup table for whatever is in block 1, I guess :)
Block 2
- nAttachments_2 records of 0x2C bytes starting at ofsAttachments_2, followed by data referenced in these records.
This might be definitions for weapon attachment slots or something like that... Mostly present on characters, creatures and items.
Offset Type Description 0x00 char[4] some kind of ID, starts with '$' 0x04 uint32 database ID? 0x08 uint32 bone ID 0x0C float[3] floats (coordinates?) 0x18 int16[2] animation block header? 0x1C uint32 number of (int, int) ranges 0x20 uint32 offset to (int, int) ranges 0x24 uint32 number of (int) values 0x28 uint32 offset to (int) values
The records seem to contain a truncated animation block. The int values look like timestamps, and there are no data values. The ranges reference more integers than are given in the list (there's always 1 less item). Weird.
Each record specifies a transformation matrix for attaching another model to a certain point. By translating to the attachment position and then applying the transform matrix of the parent bone, the other model at its default origin will snap right into place. This is how weapons are affixed to the hands, helmets and shoulder armor attached, and spell effects are also positioned this way.
Some position identifiers:
ID Description $TRD Crotch $CCH Bust $BTH In front of head $CHD Head $SHL, $SHR Left/right shoulder $CSL, $CSR Left/right hand $BWP, $BWR Right hand (for weapons maybe?)
Some unknows identifiers:
ID Found at $CST Frostwurm & Dragon $CAH Frostwurm & Dragon $CPP Frostwurm & Dragon $CSS Frostwurm & Dragon $HIT Frostwurm & Dragon $DTH Frostwurm & Dragon $FSD Frostwurm & Dragon $WNG Frostwurm & Dragon $FL0, $FL1 Frostwurm & Dragon $FR0, $FR1 Frostwurm & Dragon $RL0, $RL1 Frostwurm & Dragon $RR0, $RR1 Frostwurm & Dragon
The rest are either copies of the crotch position, or down on the floor. I suppose these are used to position spell effects (like a levelup flash or something) and damage effects.
Unknown blocks
Block D
- nD records of (int16, int16) starting at ofsD
Maybe a lookup table for animations? Since the numbers happen to be in fixed positions. The first short seems to increase with the position for models with all animations (like characters), the second seems to be flags or a modifier? Or something.
Block F
- nF 16-bit integers starting at osfF (values: -1 to nBones-1)
nF is 27 for most characters/models with lots of animation. For static models it's 1. Intermediate values are rare.
Its a lookup table for Key Skeletal Bones, hands, arms, legs, etc.
Block K - Replacable texture lookup
- nK 16-bit integers starting at ofsK. (values: -1 or 0 to nTex-1)
A reverse lookup table for 'replaced' textures, mapping replacable ids to texture indices or -1. Only goes up to the maximum id used in the model.