M2: Difference between revisions

From wowdev
Jump to navigation Jump to search
m (→‎Effects: fix whitespace and tables)
Line 1: Line 1:
M2 files (also called MDX) contain model objects. Each M2 file describes the vertices, faces, materials, texture names, animations and properties of one model. M2 files don't have a chunked format like most other WoW formats.
=Effects=
 
==UV-Animations==
Models are used for doodads (decoration objects), players, monsters and really everything in the game except for Terrain and WMOs.
 
This file describes their structure in the second expansion "Wrath of the Lich King". It is up to date for build 8820 and most likely following ones. It has been made by Xayo and schlumpf. All structures have been overlooked by schlumpf. Enjoy it.
 
--[[User:Schlumpf|schlumpf_]] 00:50, 23 August 2008 (CEST)
 
==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.
 
The header can be 0x130 or 0x138 bytes big.
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="80" | Name !! width="900" | Description
|-
| 0x000 || char[4] || Magic || "MD20"
|-
| 0x004 || uint32 || Version || For Cataclysm this is 263 < version < 272. Files get handled differently depending on this!
|-
| 0x008 || uint32 || lName || Length of the model's name including the trailing \0
|-
| 0x00C || uint32 || ofsName || Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess.
|-
| 0x010 || uint32 || GlobalModelFlags || 1: tilt x, 2: tilt y, 4:, 8: add another field in header, 16: ; (no other flags as of 3.1.1); list at [[M2/WotLK/flags]]; *(p+0x11) & 1 is camera related.
|-
| 0x014 || uint32 || nGlobalSequences ||
|-
| 0x018 || uint32 || [[M2/WotLK#Global_sequences|ofsGlobalSequences]] || A list of timestamps.
|-
| 0x01C || uint32 || nAnimations ||
|-
| 0x020 || uint32 || [[M2/WotLK#Animation_sequences|ofsAnimations]] || Information about the animations in the model.
|-
| 0x024 || uint32 || nAnimationLookup ||
|-
| 0x028 || uint32 || [[M2/WotLK#Animation_Lookup|ofsAnimationLookup]] || Mapping of [[M2/WotLK#Animation_sequences|global IDs]] to the entries in the [[M2/WotLK#Animation_sequences|Animation sequences]] block.
|-
| 0x02C || uint32 || nBones ||
|-
| 0x030 || uint32 || [[M2/WotLK#Bones|ofsBones]] || Information about the bones in this model.
|-
| 0x034 || uint32 || nKeyBoneLookup ||
|-
| 0x038 || uint32 || [[M2/WotLK#Key-Bone_Lookup|ofsKeyBoneLookup]] || Lookup table for key skeletal bones.
|-
| 0x03C || uint32 || nVertices ||
|-
| 0x040 || uint32 || [[M2/WotLK#Vertices|ofsVertices]] || Vertices of the model.
|-
| 0x044 || uint32 || nViews || [[M2/WotLK#Views_.28LOD.29|Views (LOD)]] are now in [[M2/WotLK/.skin|.skins]].
|-
| 0x048 || uint32 || nSubmeshAnimations
|-
| 0x04C || uint32 || [[M2/WotLK#Submesh_Animations|ofsSubmeshAnimations]] || Submesh color and alpha animations definitions.
|-
| 0x050 || uint32 || nTextures ||
|-
| 0x054 || uint32 || [[M2/WotLK#Textures|ofsTextures]] || Textures of this model.
|-
| 0x058 || uint32 || nTransparency ||
|-
| 0x05C || uint32 || [[M2/WotLK#Transparency|ofsTransparency]] || Transparency of textures.
|-
| 0x060 || uint32 || nUVAnimation ||
|-
| 0x064 || uint32 || [[M2/WotLK#UV-Animations|ofsUVAnimation]] ||
|-
| 0x068 || uint32 || nTexReplace ||
|-
| 0x06C || uint32 || [[M2/WotLK#Replacable_texture_lookup|ofsTexReplace]] || Replaceable Textures.
|-
| 0x070 || uint32 || nRenderFlags ||
|-
| 0x074 || uint32 || [[M2/WotLK#Render_flags|ofsRenderFlags]] || Blending modes / render flags.
|-
| 0x078 || uint32 || nBoneLookupTable ||
|-
| 0x07C || uint32 || [[M2/WotLK#Bone_Lookup_Table|ofsBoneLookupTable]] || A bone lookup table.
|-
| 0x080 || uint32 || nTexLookup ||
|-
| 0x084 || uint32 || [[M2/WotLK#Texture_lookup_table|ofsTexLookup]] || The same for textures.
|-
| 0x088 || uint32 || nTexUnits ||
|-
| 0x08C || uint32 || [[M2/WotLK#Texture_unit_lookup_table|ofsTexUnits]] || And texture units. Somewhere they have to be too.
|-
| 0x090 || uint32 || nTransLookup ||
|-
| 0x094 || uint32 || [[M2/WotLK#Transparency_lookup_table|ofsTransLookup]] || Everything needs its lookup. Here are the transparencies.
|-
| 0x098 || uint32 || nUVAnimLookup ||
|-
| 0x09C || uint32 || [[M2/WotLK#UV-Animation lookup table|ofsUVAnimLookup]] ||
|-
| 0x0A0 || Vec3F[2] || VertexBox || min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height
|-
| 0x0B8 || float || VertexRadius ||
|-
| 0x0BC || Vec3F[2] || BoundingBox ||
|-
| 0x0D4 || float || BoundingRadius ||
|-
| 0x0D8 || uint32 ||  nBoundingTriangles ||
|-
| 0x0DC || uint32 || [[M2/WotLK#Triangles|ofsBoundingTriangles]] || Our bounding volumes. Similar structure like in the old ofsViews.
|-
| 0x0E0 || uint32 || nBoundingVertices ||
|-
| 0x0E4 || uint32 || [[M2/WotLK#Vertices_2|ofsBoundingVertices]] ||
|-
| 0x0E8 || uint32 || nBoundingNormals ||
|-
| 0x0EC || uint32 || [[M2/WotLK#Normals|ofsBoundingNormals]] ||
|-
| 0x0F0 || uint32 || nAttachments ||
|-
| 0x0F4 || uint32 || [[M2/WotLK#Block_1|ofsAttachments]] || Attachments are for weapons etc.
|-
| 0x0F8 || uint32 || nAttachLookup ||
|-
| 0x0FC || uint32 || [[M2/WotLK#Attachment_Lookup|ofsAttachLookup]] || Of course with a lookup.
|-
| 0x100 || uint32 || nEvents ||
|-
| 0x104 || uint32 || [[M2/WotLK#Events|ofsEvents]] || Used for playing sounds when dying and a lot else.
|-
| 0x108 || uint32 || nLights ||
|-
| 0x10C || uint32 || [[M2/WotLK#Lights|ofsLights]] || Lights are mainly used in loginscreens but in wands and some doodads too.
|-
| 0x110 || uint32 || nCameras || Format of Cameras changed with version 271!
|-
| 0x114 || uint32 || [[M2/WotLK#Cameras|ofsCameras]] || The cameras are present in most models for having a model in the Character-Tab.
|-
| 0x118 || uint32 || nCameraLookup ||
|-
| 0x11C || uint32 || [[M2/WotLK#Camera_lookup_table|ofsCameraLookup]] ||  And lookup-time again.
|-
| 0x120 || uint32 || nRibbonEmitters ||
|-
| 0x124 || uint32 || [[M2/WotLK#Ribbon_emitters|ofsRibbonEmitters]] || Things swirling around. See the CoT-entrance for light-trails.
|-
| 0x128 || uint32 || nParticleEmitters ||
|-
| 0x12C || uint32 || [[M2/WotLK#Particle_emitters|ofsParticleEmitters]] || Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles.
|-
| 0x130 || uint32 || nUnknown || This field is getting added in models with the 8-flag only. If that flag is not set, this field does '''not''' exist!
|-
| 0x134 || uint32 || ofsUnknown || It has a array out of shorts. Its related to renderflags.
|}
 
=Skeleton and animation=
==Standard animation block==
*'''Many values that change with time are specified using blocks like the following.'''
Please see [[Talk:M2/WotLK#On_animations|this]] for information.
 
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)
==Global sequences==
*'''nGlobalSequences 32-bit unsigned integers starting at ofsGlobalSequences.'''
A list of timestamps that act as upper limits for global sequence ranges.
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || uint32 || Timestamp || Entry
|}
==Animation sequences==
*'''nAnimations 0x40-byte records starting at ofsAnimations.'''
List of animations present in the model.
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="900" | 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. I believe this actually the length of the animation in milliseconds.
|-
| 0x08 || float || MovingSpeed || This is the speed the character moves with in this animation.
|-
| 0x0C || uint32 || Flags || See below.
|-
| 0x10 || int16 || Probability || This is used to determine how often the animation is played. For all animations of the same type, this adds up to 0x7FFF (32767).
|-
| 0x12 || uint16 || Unused ||
|-
| 0x14 || uint32 || Unknown 1 || These two are connected. Most of the time, they are 0.
|-
| 0x18 || 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.
|-
| 0x20 || float || MinimumExtent[3] || Minimum Extent
|-
| 0x2C || float || MaximumExtent[3] || MaximumExtent
|-
| 0x38 || float || BoundsRadius || The radius.
|-
| 0x3C || int16 || NextAnimation || Id of the following animation of this AnimationID, points to an Index or is -1 if none.
|-
| 0x3E || uint16 || Index || Id in the list of animations.
|}
===Flags===
''One thing I saw in the source is that "-1 animationblocks" in bones wont get parsed if 0x20 is not set.''
 
'''Animation blocks point to .anim files, if (flags & 0x30 ) == 0. Only then, .anim files are loaded.'''
{| style="background:#FCFCFC; color:black"
! width="70" | Flag !! width="500" | Description
|-
| 0x01 || Sets 0x80 when loaded. (M2Init)
|-
| 0x02 ||
|-
| 0x04 ||
|-
| 0x08 ||
|-
| 0x10 ||
|-
| 0x20 || Looped animation.
|-
| 0x40 ||
|-
| 0x80 ||
|}
=== Animation Lookup===
*'''nAnimationLookup in  16-bit shorts starting at ofsAnimationLookup.'''
Lookup table for Animations in [[AnimationData.dbc]].
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="900" | Description
|-
| 0x00 || uint16 || AnimationID || Index at [[M2/WotLK#Animation_sequences|ofsAnimations]] which represents the animation in [[AnimationData.dbc]]. -1 if none.
|}
==  Bones ==
*'''nBones records of 0x58 bytes starting at ofsBones.''' (M2Array<M2CompBone>)
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="700" | Description
|-
| 0x00 || int32 || KeyBoneID || Back-reference to [[M2/WotLK#Key-Bone_Lookup|the key bone lookup table]]. -1 if this is no key bone.
|-
| 0x04 || uint32 || Flags || Only known flags: 8 - billborded and 512 - transformed
|-
| 0x08 || int16 || ParentBone || Parent bone ID or -1 if there is none.
|-
| 0x0A || uint16 || Unknown[3] || The first one might be related to the parts of the bodies.
|-
| 0x10 || [[M2/WotLK#Standard_animation_block|ABlock]] || Translation || An animationblock for translation. Should be 3*floats.
|-
| 0x24 || [[M2/WotLK#Standard_animation_block|ABlock]] || Rotation || An animationblock for rotation. Should be 4*shorts, see [[Quaternion_values_and_2.x|Quaternion values and 2.x]].
|-
| 0x38 || [[M2/WotLK#Standard_animation_block|ABlock]] || Scaling || An animationblock for scaling. Should be 3*floats.
|-
| 0x4C || float || PivotPoint[3] || The pivot point of that bone. Its a vector.
|}
The bone indices in the vertex definitions seem to index into this data.
 
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.
===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.
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || uint16 || Bone || Which bone. -1 if there is none.
|}
===Key-Bone Lookup===
*'''nKeyBoneLookup 16-bit shorts starting at ofsKeyBoneLookup.'''
Its a lookup table for key skeletal bones like hands, arms, legs, etc. nKeyBoneLookup is 27 for the most models. At static models it is mostly 1.
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || uint16 || Bone || Which bone. -1 if there is none.
|}
Official list:
*00 "ArmL"
*01 "ArmR"
*02 "ShoulderL"
*03 "ShoulderR"
*04 "SpineLow"
*05 "Waist"
*06 "Head"
*07 "Jaw"
*08 "IndexFingerR"
*09 "MiddleFingerR"
*10 "PinkyFingerR"
*11 "RingFingerR"
*12 "ThumbR"
*13 "IndexFingerL"
*14 "MiddleFingerL"
*15 "PinkyFingerL"
*16 "RingFingerL"
*17 "ThumbL"
*18 "$BTH"
*19 "$CSR"
*20 "$CSL"
*21 "_Breath"
*22 "_Name"
*23 "_NameMount"
*24 "$CHD"
*25 "$CCH"
*26 "Root"
*27 "Wheel1"
*28 "Wheel2"
*29 "Wheel3"
*30 "Wheel4"
*31 "Wheel5"
*32 "Wheel6"
*33 "Wheel7"
*34 "Wheel8"
 
=Geometry and rendering=
==Vertices==
*'''nVertices entries of 48 bytes per vertex (at ofsVertices)'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || float || Position[3] || A vector to the position of the vertex.
|-
| 0x0C || uint8 || BoneWeight[4] || The vertex weight for 4 bones.
|-
| 0x10 || uint8 || BoneIndices[4] || Which are referenced here.
|-
| 0x14 || float || Normal[3] || A normal vector.
|-
| 0x20 || float || TextureCoords[2] || Coordinates for a texture.
|-
| 0x28 || float || Unknown[2] || Null?
|}
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).
==Views (LOD)==
Since there is no ofsViews anymore, this data is now stored in .skin files. More information about them here: [[M2/WotLK/.skin]].
==Render flags==
*'''nRenderFlags (uint16, uint16) pairs starting at ofsRenderFlags'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="200" | Description
|-
| 0x00 || uint16 || Flags
|-
| 0x02 || uint16 || Blending mode
|}
*'''Flags:'''
{| style="background:#FCFCFC; color:black"
! width="70" | Flag !! width="300" | Meaning
|-
| 0x01 || Unlit
|-
| 0x02 || Unfogged?
|-
| 0x04 || Two-sided (no backface culling if set)
|-
| 0x08 || ? (probably billboarded)
|-
| 0x10 || Disable z-buffer?
|}
*'''Blending mode'''
{| style="background:#FCFCFC; color:black"
! width="70" | Value !! width="100" | Mapped to !! width="1000" | Meaning
|-
| 0 || 0 || Combiners_Opaque (Blend disabled)
|-
| 1 || 1 || Combiners_Mod (Blend enabled, Src = ONE, Dest = ZERO, SrcAlpha = ONE, DestAlpha = ZERO)
|-
| 2 || 1 || Combiners_Decal (Blend enabled, Src = SRC_ALPHA, Dest = INV_SRC_ALPHA, SrcAlpha = SRC_ALPHA, DestAlpha = INV_SRC_ALPHA )
|-
| 3 || 1 || Combiners_Add (Blend enabled, Src = SRC_COLOR, Dest = DEST_COLOR, SrcAlpha = SRC_ALPHA, DestAlpha = DEST_ALPHA )
|-
| 4 || 1 || Combiners_Mod2x (Blend enabled, Src = SRC_ALPHA, Dest = ONE, SrcAlpha = SRC_ALPHA, DestAlpha = ONE )
|-
| 5 || 4 || Combiners_Fade (Blend enabled, Src = SRC_ALPHA, Dest = INV_SRC_ALPHA, SrcAlpha = SRC_ALPHA, DestAlpha = INV_SRC_ALPHA )
|-
| 6 || 4 || Used in the Deeprun Tram subway glass, supposedly (Blend enabled, Src = DEST_COLOR, Dest = SRC_COLOR, SrcAlpha = DEST_ALPHA, DestAlpha = SRC_ALPHA )
|}
''*Blend values are taken from D3D11 debugging of the client
===Unknown new block===
If this block is present (globalflags&8) and the "shading" flags of a textureunit wont be &0x8000, blending modes wont get mapped to the values above but to the ones in this block.
 
Instead of Mapping[renderflags->blendingmode] it will be UnknownBlock[textureunit->Shading].
 
As shading is not &0x8000 and (in their code) needs to be above 0, this may only touch Diffuse_T1.
==Texture unit lookup table==
*'''nTexUnits 16-bit integers starting at ofsTexUnits.'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || int16 || Unit || Values are -1, 0 or 1. See below.
|}
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 nTexUnits 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==
===Submesh Animations===
*'''nSubmeshAnimations records starting at ofsSubmeshAnimations, followed by data referenced in these records.'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || [[M2/WotLK#Standard_animation_block|ABlock]] || Color || Three floats. representing the vertex color change.
|-
| 0x14 || [[M2/WotLK#Standard_animation_block|ABlock]] || Alpha || A short for the alpha value. 0 - transparent, 0x7FFF - opaque. Normaly NonInterp
|}
This block is the M2 equivalent to the GEOA chunk in MDX files, it represents the vertex color and visibility animations for meshes. Referenced from the Texture Unit blocks in the [[M2/WotLK/.skin|*.skin]]. If a texunit belonging to a submesh has a value of -1 then the submesh doesnot use this block. Contains a separate timeline for transparency values. If no animation is used, the given value is constant.
===Transparency===
*'''nTransparency AnimationBlocks at ofsTransparency, followed by data referenced in these records.
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || [[M2/WotLK#Standard_animation_block|ABlock]] || Alpha || A short for the alpha value. 0 - transparent, 0x7FFF - opaque.
|}
Specifies global transparency values in addition to the values given in the Color block. I assume these are multiplied together eventually.
====Transparency lookup table====
*'''nTransLookup 16-bit integers starting at ofsTransLookup.'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || uint16 || TransparencyId || Array indices (0 to n-1).
|}
Contains indices into the Transparency block. Used by the texture unit definitions in the LOD block.
==Textures==
*'''Textures are defined globally in a list''', additionally, a lookup table is given, referenced during rendering, to select textures.
*'''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, which seems to have the same structure like the MOTX-Chunk in WMOs(see [[WMO]]), the "empty aligtments" are just the zeros were non "0 - hardcoded" type textures point too.
{| style="background:#FCFCFC; color:black"
|-
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || uint32 || Type || The type of the texture. See below.
|-
| 0x04 || uint32 || Flags || Textures have some flags. See below too.
|-
| 0x08 || uint32 || lenFilename || Here is the length of the filename, if the type is not "0 - hardcoded" then it's just 1 and points to a zero
|-
| 0x0C || uint32 || ofsFilename || And the offset to the filename.
|}
====Texture Types====
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)
{| style="background:#FCFCFC; color:black"
! width="70" | Value !! width="800" | Meaning
|-
| 0 || Texture given in filename
|-
| 1 || Body + clothes
|-
| 2 || Item, Capes ("Item\ObjectComponents\Cape\*.blp")
|-
| 3 || Unknown - Used on several models but not used in the client as far as I see. Armor Reflect?
|-
| 6 || Hair, beard
|-
| 8 || Tauren fur
|-
| 9 || Used on inventory art M2s (1): inventoryartgeometry.m2 and inventoryartgeometryold.m2
|-
| 10 || Only used in quillboarpinata.m2. I can't even find something referencing that file. Oo Is it used?
|-
| 11 || Skin for creatures or gameobjects #1
|-
| 12 || Skin for creatures or gameobjects #2
|-
| 13 || Skin for creatures or gameobjects #3
|-
| 14 || Used on inventory art M2s (2): ui-buffon.m2 and forcedbackpackitem.m2 (LUA::Model:ReplaceIconTexture("texture"))
|}
====Flags====
{| style="background:#FCFCFC; color:black"
! width="70" | Value !! width="200" | Meaning
|-
| 1 || Texture wrap X
|-
| 2 || Texture wrap Y
|}
====Texture lookup table====
*'''nTexLookup items starting at ofsTexLookup.'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || uint16 || TextureId || Array indices (0 to n-1).
|}
====Replacable texture lookup====
*'''nTexReplace 16-bit integers starting at ofsTexReplace.'''
{| style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|-
| 0x00 || int16 || TextureID || Array indices (0 to n-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.
 
The table may look like this:
{| style="background:#FCFCFC; color:black"
! width="150" | Type !! width="70" | TextureID
|-
| HARDCODED || 0
|-
| BODY || -1
|-
| ITEM || -1
|-
| UNKNOWN3 || -1
|-
| UNKNOWN4 || -1
|-
| UNKNOWN5 || -1
|-
| HAIRBEARD || -1
|-
| UNKNOWN7 || -1
|-
| TAURENFUR || -1
|-
| UNKNOWN9 || -1
|-
| UNKNOWN10 || -1
|-
| CREATURESKIN1 || 2
|-
| CREATURESKIN2 || 1
|-
| CREATURESKIN3 || -1
|}
Its strange, that HARDCODED is in the list, as a model can have more than one of course. Its just the last one written to the file.
 
One should investigate the unknown types. Maybe they are usable for something nice.
 
Effects =
 
 
== UV-Animations ==
*'''This block contains definitions for texture animations,''' for example, flowing water or lava in some models. The keyframe values are used in the texture transform matrix.
*'''This block contains definitions for texture animations,''' for example, flowing water or lava in some models. The keyframe values are used in the texture transform matrix.
nTexAnims records of 0x3C bytes starting at ofsTexAnims, followed by data referenced in these records.
nTexAnims records of 0x3C bytes starting at ofsTexAnims, followed by data referenced in these records.
{|style="background:#FCFCFC; color:black"
{| style="background:#FCFCFC; color:black"
|
! width="70" | Offset !! width="120" | Type !! width="500" | Description
! width="70" | Offset
! width="120" | Type
! width="500"| Description
|-
|-
|||0x00||ABlock (float[3])||Translation
| 0x00 || ABlock (float[3]) || Translation
|-
|-
|||0x14||ABlock (short[4])||Rotation
| 0x14 || ABlock (short[4]) || Rotation
|-
|-
|||0x28||ABlock (float[3])||Scaling
| 0x28 || ABlock (float[3]) || Scaling
|}
|}
The three subrecords specify uv-transforms. Translation seems to work, producing nice flowing lava and waterfalls.
The three subrecords specify uv-transforms. Translation seems to work, producing nice flowing lava and waterfalls.
====UV-Animation lookup table ====
====UV-Animation lookup table ====
*'''nTexAnimLookup items starting at ofsTexAnimLookup.'''
*'''nTexAnimLookup items starting at ofsTexAnimLookup.'''
 
{| style="background:#FCFCFC; color:black"
{|style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="70" | Type !! width="90" | Name !! width="500" | Description
|
! width="70" | Offset
! width="70" | Type
! width="90" | Name
! width="500"| Description
|-
|-
|||0x00||uint16||AnimatedTextureId||Array indices (0 to n-1). -1 for a static texture.
| 0x00 || uint16 || AnimatedTextureId || Array indices (0 to n-1). -1 for a static texture.
|}
|}
== Ribbon emitters ==
== Ribbon emitters ==
*'''nRibbonEmitters records of 0xB0 bytes starting at ofsRibbonEmitters, followed by data referenced in these records.'''
*'''nRibbonEmitters records of 0xB0 bytes starting at ofsRibbonEmitters, followed by data referenced in these records.'''
The records have the following structure:
The records have the following structure:
{|style="background:#FCFCFC; color:black"
{| style="background:#FCFCFC; color:black"
|
! width="70" | Offset !! width="90" | Type !! width="120" |Name !! width="800" | Description
! width="70" | Offset
! width="90" | Type
! width="120"|Name
! width="500"| Description
|-
|-
|||0x00|| uint32||Unknown ||Always (as I have seen): -1.
| 0x00 || uint32 || Unknown || Always (as I have seen): -1.
|-
|-
|||0x04|| uint32 ||BoneID || A bone to attach to.
| 0x04 || uint32 || BoneID || A bone to attach to.
|-
|-
|||0x08||float||Position[3]|| And a position, relative to that bone.
| 0x08 || float || Position[3] || And a position, relative to that bone.
|-  
|-  
|||0x14|| int32|| nTextures|| Number of referenced textures.
| 0x14 || int32 || nTextures || Number of referenced textures.
|-
|-
|||0x18|| int32|| ofsTextures|| Offset to the referenced textures.
| 0x18 || int32 || ofsTextures || Offset to the referenced textures.
|-
|-
|||0x1C|| int32|| nBlendRef ||Number of some referenced integers,which look like the blending for the texture
| 0x1C || int32 || nBlendRef || Number of some referenced integers,which look like the blending for the texture
|-
|-
|||0x20|| int32|| ofsBlendRef|| Offset to the blending-integers.
| 0x20 || int32 || ofsBlendRef || Offset to the blending-integers.
|-
|-
|||0x24|| [[M2/WotLK#Standard_animation_block|ABlock]]||Color||A color in three floats.
| 0x24 || [[M2/WotLK#Standard_animation_block|ABlock]] || Color || A color in three floats.
|-
|-
|||0x38|| [[M2/WotLK#Standard_animation_block|ABlock]]||Opacity|| And an alpha value in a short, where: 0 - transparent, 0x7FFF - opaque.
| 0x38 || [[M2/WotLK#Standard_animation_block|ABlock]] || Opacity || And an alpha value in a short, where: 0 - transparent, 0x7FFF - opaque.
|-
|-
|||0x4C|| [[M2/WotLK#Standard_animation_block|ABlock]] ||Above||The height above.  
| 0x4C || [[M2/WotLK#Standard_animation_block|ABlock]] || Above || The height above.  
|-
|-
|||0x60|| [[M2/WotLK#Standard_animation_block|ABlock]]||Below||The height below. Do not set these to the same!
| 0x60 || [[M2/WotLK#Standard_animation_block|ABlock]] || Below || The height below. Do not set these to the same!
|-
|-
|||0x74|| float||Resolution||This defines how smooth the ribbon is. A low value may produce a lot of edges.
| 0x74 || float || Resolution || This defines how smooth the ribbon is. A low value may produce a lot of edges.
|-
|-
|||0x78|| float|| Length || The length aka Lifespan.
| 0x78 || float || Length || The length aka Lifespan.
|-  
|-  
|||0x7C|| float|| Emissionangle|| use arcsin(val) to get the angle in degree
| 0x7C || float || Emissionangle || use arcsin(val) to get the angle in degree
|-
|-
|||0x80|| short|| Renderflags[2]||Perhaps the same as in renderflags
| 0x80 || short || Renderflags[2] || Perhaps the same as in renderflags
|-
|-
|||0x84|| [[M2/WotLK#Standard_animation_block|ABlock]]||UnknownABlock1|| (short)  
| 0x84 || [[M2/WotLK#Standard_animation_block|ABlock]] || UnknownABlock1 || (short)  
|-
|-
|||0x98|| [[M2/WotLK#Standard_animation_block|ABlock]]|| UnknownABlock2|| (boolean)
| 0x98 || [[M2/WotLK#Standard_animation_block|ABlock]] || UnknownABlock2 || (boolean)
|-
|-
|||0xAC|| int32||unknown||This looks much like just some Padding to the fill up the 0x10 Bytes, always 0
| 0xAC || int32 || unknown || This looks much like just some Padding to the fill up the 0x10 Bytes, always 0
|}
|}
Some 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 the energy trails in the COT (not the actual instance, but the entrance cave in Tanaris Desert). Other models with ribbon emitters are spells and effects.
Some 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 the energy trails in the COT (not the actual instance, but the entrance cave in Tanaris Desert). Other models with ribbon emitters are spells and effects.


''Parameters from the MDL format that are probably in here somewhere: emission rate, rows, cols ...?''
''Parameters from the MDL format that are probably in here somewhere: emission rate, rows, cols ...?''
 
== Particle emitters ==
== Particle emitters ==
'''This is partly wrong as hell!'''
'''This is partly wrong as hell!'''
*'''nParticleEmitters records starting at ofsParticleEmitters, followed by data referenced in these records.'''
*'''nParticleEmitters records starting at ofsParticleEmitters, followed by data referenced in these records.'''
 
{| style="background:#FCFCFC; color:black"
{|style="background:#FCFCFC; color:black"
! width="70" | Offset !! width="90" | Type !! width="120" |Name !! width="500" | Description
|
! width="70" | Offset
! width="90" | Type
! width="120" |Name
! width="800"| Description
|-
|-
|||0x000||uint32||Unknown|| Always (as I have seen): -1.
| 0x000 || uint32 || Unknown || Always (as I have seen): -1.
|-
|-
|||0x004|| uint32||Flags|| See Below
| 0x004 || uint32 || Flags || See Below
|-
|-
|||0x008|| float||Position[3]|| The position. Relative to the following bone.
| 0x008 || float || Position[3] || The position. Relative to the following bone.
|-
|-
|||0x014|| uint16||Bone|| The [[M2/WotLK#Bones|bone]] its attached to.
| 0x014 || uint16 || Bone || The [[M2/WotLK#Bones|bone]] its attached to.
|-
|-
|||0x016|| uint16||Texture || And the [[M2/WotLK#Texture_definitions|texture]] that is used.
| 0x016 || uint16 || Texture || And the [[M2/WotLK#Texture_definitions|texture]] that is used.
|-
|-
|||0x018|| uint32||lenModelFilename ||The lenght of the ModelFilename. Zeroterminated String!
| 0x018 || uint32 || lenModelFilename || The lenght of the ModelFilename. Zeroterminated String!
|-
|-
|||0x01C|| uint32||ofsModelFilename|| And the matching offset. This is used for spawning Models. *.mdx
| 0x01C || uint32 || ofsModelFilename || And the matching offset. This is used for spawning Models. *.mdx
|-
|-
|||0x020|| uint32||lenParticleFileName|| The lenght of the ParticleFilename. Zeroterminated String!
| 0x020 || uint32 || lenParticleFileName || The lenght of the ParticleFilename. Zeroterminated String!
|-
|-
|||0x024|| uint32||ofsParticleFileName||And the matching offset again.This is used for spawning particles of a model. *.mdx!
| 0x024 || uint32 || ofsParticleFileName || And the matching offset again.This is used for spawning particles of a model. *.mdx!
|-
|-
|||0x028|| uint8||BlendingType|| A blending type for the particle. See Below
| 0x028 || uint8 || BlendingType || A blending type for the particle. See Below
|-
|-
|||0x029|| uint8||EmitterType|| 1 - Plane (rectangle), 2 - Sphere, 3 - Spline? (can't be bothered to find one)
| 0x029 || uint8 || EmitterType || 1 - Plane (rectangle), 2 - Sphere, 3 - Spline? (can't be bothered to find one)
|-
|-
|||0x02A|| uint16||ParticleColorSomething|| This one is used for [[ParticleColor.dbc]]. See below.
| 0x02A || uint16 || ParticleColorSomething || This one is used for [[ParticleColor.dbc]]. See below.
|-
|-
|||0x02C|| uint8||ParticleType?|| Found below.
| 0x02C || uint8 || ParticleType? || Found below.
|-
|-
|||0x02D|| uint8||HeadorTail||0 - Head, 1 - Tail, 2 - Both
| 0x02D || uint8 || HeadorTail || 0 - Head, 1 - Tail, 2 - Both  
|-
|-
|||0x02E|| uint16||TextureTileRotation||Rotation for the texture tile. (Values: -1,0,1)
| 0x02E || uint16 || TextureTileRotation || Rotation for the texture tile. (Values: -1,0,1)  
|-
|-
|||0x030|| uint16||TextureRows|| How many different frames are on that texture? People should learn what rows and cols are.
| 0x030 || uint16 || TextureRows || How many different frames are on that texture? People should learn what rows and cols are.
|-
|-
|||0x032|| uint16||TextureCols|| Its different everywhere. I just took it random.  
| 0x032 || uint16 || TextureCols || Its different everywhere. I just took it random.  
|-
|-
|||0x034|| [[M2/WotLK#Standard_animation_block|ABlock]] ||EmissionSpeed|| All of the following blocks should be floats.
| 0x034 || [[M2/WotLK#Standard_animation_block|ABlock]] || EmissionSpeed || All of the following blocks should be floats.
|-
|-
|||0x048|| [[M2/WotLK#Standard_animation_block|ABlock]] ||SpeedVariation|| Variation in the flying-speed. (range: 0 to 1)
| 0x048 || [[M2/WotLK#Standard_animation_block|ABlock]] || SpeedVariation || Variation in the flying-speed. (range: 0 to 1)
|-
|-
|||0x05C|| [[M2/WotLK#Standard_animation_block|ABlock]] ||VerticalRange|| Drifting away vertically. (range: 0 to pi)
| 0x05C || [[M2/WotLK#Standard_animation_block|ABlock]] || VerticalRange || Drifting away vertically. (range: 0 to pi)
|-
|-
|||0x070|| [[M2/WotLK#Standard_animation_block|ABlock]] ||HorizontalRange|| They can do it horizontally too! (range: 0 to 2*pi)
| 0x070 || [[M2/WotLK#Standard_animation_block|ABlock]] || HorizontalRange || They can do it horizontally too! (range: 0 to 2*pi)
|-
|-
|||0x084|| [[M2/WotLK#Standard_animation_block|ABlock]] ||Gravity|| Fall down, apple!
| 0x084 || [[M2/WotLK#Standard_animation_block|ABlock]] || Gravity || Fall down, apple!
|-
|-
|||0x098|| [[M2/WotLK#Standard_animation_block|ABlock]] ||Lifespan|| Everyone has to die.
| 0x098 || [[M2/WotLK#Standard_animation_block|ABlock]] || Lifespan || Everyone has to die.
|-  
|-  
|||0x0AC|| uint32 ||unknownPadding || I don't know what these two values should do..
| 0x0AC || uint32 || unknownPadding || I don't know what these two values should do..
|-
|-
|||0x0B0|| [[M2/WotLK#Standard_animation_block|ABlock]] ||EmissionRate|| Stread your particles, emitter.
| 0x0B0 || [[M2/WotLK#Standard_animation_block|ABlock]] || EmissionRate || Stread your particles, emitter.
|-
|-
|||0x0C4|| uint32 ||unknownPadding2 ||It could have been an array without them..
| 0x0C4 || uint32 || unknownPadding2 || It could have been an array without them..
|-
|-
|||0x0C8|| [[M2/WotLK#Standard_animation_block|ABlock]] ||EmissionAreaLength||Well, you can do that in this area.
| 0x0C8 || [[M2/WotLK#Standard_animation_block|ABlock]] || EmissionAreaLength || Well, you can do that in this area.
|-
|-
|||0x0DC|| [[M2/WotLK#Standard_animation_block|ABlock]] ||EmissionAreaWidth
| 0x0DC || [[M2/WotLK#Standard_animation_block|ABlock]] || EmissionAreaWidth  
|-
|-
|||0x0F0|| [[M2/WotLK#Standard_animation_block|ABlock]] ||Gravity2|| A second gravity? Its strong.
| 0x0F0 || [[M2/WotLK#Standard_animation_block|ABlock]] || Gravity2 || A second gravity? Its strong.
|-
|-
|||0x104|| [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] ||ParticleColor|| (short, vec3f) This one points to 3 floats defining red, green and blue.
| 0x104 || [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] || ParticleColor || (short, vec3f) This one points to 3 floats defining red, green and blue.
|-
|-
|||0x114|| [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] ||ParticleOpacity?|| (short, short) Looks like opacity (short) --Igor; Most likely they all have 3 timestamps for {start, middle, end}.
| 0x114 || [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] || ParticleOpacity? || (short, short) Looks like opacity (short) --Igor; Most likely they all have 3 timestamps for {start, middle, end}.
|-
|-
|||0x124|| [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] ||ParticleSizes|| (short, vec2f) It carries two floats per key. (x and y scale)
| 0x124 || [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] || ParticleSizes || (short, vec2f) It carries two floats per key. (x and y scale)
|-
|-
|||0x134|| int32 ||UnknownFields[2]|| No references. Padding?
| 0x134 || int32 || UnknownFields[2] || No references. Padding?
|-
|-
|||0x13C|| [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] ||Intensity|| Some kind of intensity values seen: 0,16,17,32(if set to different it will have high intensity) (short, short)
| 0x13C || [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] || Intensity || Some kind of intensity values seen: 0,16,17,32(if set to different it will have high intensity) (short, short)
|-
|-
|||0x14C|| [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] ||UnknownReferences1|| (short, short)
| 0x14C || [[M2/WotLK#The_Fake-AnimationBlock|FBlock]] || UnknownReferences1 || (short, short)
|-
|-
|||0x15C|| float ||UnknownFloats1[3]||They have something to do with the spread.
| 0x15C || float || UnknownFloats1[3] || They have something to do with the spread.
|-
|-
|||0x168|| float ||Scale[3]|| Wheey, its the scale!
| 0x168 || float || Scale[3] || Wheey, its the scale!
|-
|-
|||0x174|| float ||Drag|| Air resistance, see below.
| 0x174 || float || Drag || Air resistance, see below.
|-
|-
|||0x178|| float ||UnknownFloats2[2]||More unknown fields.
| 0x178 || float || UnknownFloats2[2] || More unknown fields.
|-
|-
|||0x180|| float ||Rotation|| As a single value? Most likely only one axis then..
| 0x180 || float || Rotation || As a single value? Most likely only one axis then..
|-
|-
|||0x184|| float ||UnknownFloats3[2]||More unknown fields.
| 0x184 || float || UnknownFloats3[2] || More unknown fields.
|-
|-
|||0x18C|| float ||Rot1[3]||Model Rotation 1  
| 0x18C || float || Rot1[3] || Model Rotation 1  
|-
|-
|||0x198|| float ||Rot2[3]||Model Rotation 2
| 0x198 || float || Rot2[3] || Model Rotation 2
|-
|-
|||0x1A4|| float ||Trans[3]||Model Translation
| 0x1A4 || float || Trans[3] || Model Translation
|-
|-
|||0x1B0|| float ||UnknownFloats4[4]||Unknown, unknown, unknown, unknown, unknown...
| 0x1B0 || float || UnknownFloats4[4] || Unknown, unknown, unknown, unknown, unknown...
|-
|-
|||0x1C0|| uint32 ||nUnknownReference||
| 0x1C0 || uint32 || nUnknownReference ||  
|-
|-
|||0x1C4|| uint32 ||ofsUnknownReference|| Vec3D array
| 0x1C4 || uint32 || ofsUnknownReference || Vec3D array
|-
|-
|||0x1C8|| [[M2/WotLK#Standard_animation_block|ABlock]] ||EnabledIn|| (boolean) Has been in the earlier documentations. Enabled Anim Block. Appears to be used sparely now, probably there's a flag that links particles to animation sets where they are enabled.
| 0x1C8 || [[M2/WotLK#Standard_animation_block|ABlock]] || EnabledIn || (boolean) Has been in the earlier documentations. Enabled Anim Block. Appears to be used sparely now, probably there's a flag that links particles to animation sets where they are enabled.
|}
|}
About Drag: For a non-zero 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. Speed is multiplied by exp( -drag * t ). This value is also present in M3 format.
About Drag: For a non-zero 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. Speed is multiplied by exp( -drag * t ). This value is also present in M3 format.
Line 731: Line 172:


Rotation can be a float value greater or less one. Results look better if use it as a "phase shift": particle_rotate = randfloat(-sys->rotation * pi, sys->rotation * pi); --Igor
Rotation can be a float value greater or less one. Results look better if use it as a "phase shift": particle_rotate = randfloat(-sys->rotation * pi, sys->rotation * pi); --Igor
===Particle Flags===
===Particle Flags===
{|style="background:#FCFCFC; color:black"
{| style="background:#FCFCFC; color:black"
|
! width="70" | Value !! width="600" | Description
! width="70" | Value
! width="600"| Description
|-
|-
|||0x1||
| 0x1 ||  
|-
|-
||| 0x2 ||
| 0x2 ||  
|-
|-
||| 0x4||
| 0x4 ||  
|-
|-
||| 0x8||
| 0x8 ||  
|-
|-
||| 0x10||Do not Trail
| 0x10 || Do not Trail
|-
|-
||| 0x20||
| 0x20 ||  
|-
|-
||| 0x40||
| 0x40 ||  
|-
|-
||| 0x80|| Particles in Model Space
| 0x80 || Particles in Model Space
|-
|-
||| 0x100||
| 0x100 ||  
|-
|-
||| 0x200||
| 0x200 ||  
|-
|-
||| 0x400|| Pinned Particles, their quad enlarges from their creation position to where they expand.
| 0x400 || Pinned Particles, their quad enlarges from their creation position to where they expand.
|-
|-
||| 0x800||
| 0x800 ||  
|-
|-
||| 0x1000||XYQuad Particles. They align to XY axis facing Z axis direction.
| 0x1000 || XYQuad Particles. They align to XY axis facing Z axis direction.
|-
|-
||| 0x2000||
| 0x2000 ||  
|-
|-
||| 0x4000||
| 0x4000 ||  
|-
|-
||| 0x8000||
| 0x8000 ||  
|-
|-
||| 0x10000||
| 0x10000 ||  
|-
|-
||| 0x20000||  
| 0x20000 ||  
|-
|-
||| 0x40000||
| 0x40000 ||  
|}
|}
===ParticleColorSomething===
===ParticleColorSomething===
This one is used so you can assign a color to specific particles. They loop over all particles and compare +0x2A to 11, 12 and 13. If that matches, the colors from the dbc get applied.
This one is used so you can assign a color to specific particles. They loop over all particles and compare +0x2A to 11, 12 and 13. If that matches, the colors from the dbc get applied.
===Particle types===
===Particle types===
{|style="background:#FCFCFC; color:black"
{| style="background:#FCFCFC; color:black"
|
! width="70" | Value !! width="500" | Description
! width="70" | Value
! width="500"| Description
|-
|-
|||0|| "normal" particle
| 0 || "normal" particle
|-
|-
||| 1 ||large quad from the particle's origin to its position (used in Moonwell water effects)
| 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)
| 2 || seems to be the same as 0 (found some in the Deeprun Tram blinky-lights-sign thing)
|}
|}
''ParticleType is always 0 and, maybe, now (Flags & 0x40000) != 0 means "particles from origin to position". --Igor''
''ParticleType is always 0 and, maybe, now (Flags & 0x40000) != 0 means "particles from origin to position". --Igor''
''Checked and verified --BlinkHawk''
''Checked and verified --BlinkHawk''
===Particle Blendings===
===Particle Blendings===
{|style="background:#FCFCFC; color:black"
{| style="background:#FCFCFC; color:black"
|
! width="70" | Value !! width="500" | Description
! width="70" | Value
! width="500"| Description
|-
|-
|||0||glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST);
| 0 || glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST);
|-
|-
||| 1 ||glBlendFunc(GL_SRC_COLOR, GL_ONE);
| 1 || glBlendFunc(GL_SRC_COLOR, GL_ONE);
|-
|-
||| 2||glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
| 2 || glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|-
|-
||| 3||glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST);
| 3 || glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST);
|-
|-
||| 4||glBlendFunc(GL_SRC_ALPHA, GL_ONE);
| 4 || glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|}
|}
from Modelviewer source
from Modelviewer source
===The Fake-AnimationBlock===
===The Fake-AnimationBlock===
*Its pretty much like the real one but without the "header".
*Its pretty much like the real one but without the "header".
{|style="background:#FCFCFC; color:black"
{| style="background:#FCFCFC; color:black"
|
! width="70" | Offset !! width="90" | Type !! width="120" | Name !! width="500" | Description
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
|-
|||0x000||uint32||nTimestamps|| The number of timestamps.
| 0x000 || uint32 || nTimestamps || The number of timestamps.
|-
|-
|||0x004||uint32||ofsTimestamps|| And the offset to them. The timestamps are shorts! (?)
| 0x004 || uint32 || ofsTimestamps || And the offset to them. The timestamps are shorts! (?)
|-
|-
|||0x008||uint32||nKeys|| The same number again. This time its the number of Keys / Values.
| 0x008 || uint32 || nKeys || The same number again. This time its the number of Keys / Values.
|-
|-
|||0x00C||uint32||ofsKeys|| And their offset.
| 0x00C || uint32 || ofsKeys || And their offset.
|}
|}
But they're unable to change between different animations, so they directly point to the data.
But they're unable to change between different animations, so they directly point to the data.
=Miscellaneous=
==Bounding volumes==
These blocks give a simplified bounding volume for the model. Characters and creatures have just a simple box.
===Vertices===
''Complete and right as of 17-AUG-09 (3.0.9 or higher)''
*'''nBoundingVertices vertices at ofsBoundingVertices'''.
This block defines the possible points used for the model. They are referenced in the triangles block later.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00'' || Vec3F || Coordinate || This defines a vertex in x,y and z values.
|}
===Triangles===
''Complete and right as of 17-AUG-09 (3.0.9 or higher)''
*'''nBoundingTriangles/3 triples of uint16s at ofsBoundingTriangles'''.
The number in the header tells us how many uint16s there are, not how many triangles. To use this better, you should group three of them into an array. The nBoundingTriangles/3 indices will tell you which vertices are used for the triangle then.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00'' || uint16 || Index[3] || Specifies three vertices of the list above to build a triangle.
|}
The number nBoundingTriangles once again contains the number of indices used, so divide by 3 to get the number of triangles.
===Normals===
''Complete and right as of 17-AUG-09 (3.0.9 or higher)''
*'''nBoundingNormals normals at ofsBoundingNormals'''.
This one defines a normal per triangle. The vectors are normalized, but Blizzard seems to have some problems getting a simple vector normalized leading in several 0,0,0.999999999 ones. Whatever.
As each vertex has a corresponding normal vector, it should be true that nBoundingNormals = nBoundingTriangles / 3.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00'' || Vec3F || Normal || This defines the normal for each triangle.
|}
==  Lights ==
*'''nLights records of 0x9C bytes starting at ofsLights, followed by data referenced in these records.'''
The records have the following structure:
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00''|| uint16|| Type|| Types are listed below.
|-
|||  ''0x02''|| int16|| Bone || If its attached to a bone, this is the bone. Else here is a nice -1.
|-
|||  ''0x04''|| float|| Position[3] || Where is this light?
|-
||| ''0x10''|| [[M2/WotLK#Standard_animation_block|ABlock]]|| AmbientColor || The ambient color. Three floats for RGB.
|-
||| ''0x24''|| [[M2/WotLK#Standard_animation_block|ABlock]]|| AmbientIntensity|| A float for the intensity.
|-
||| ''0x38''|| [[M2/WotLK#Standard_animation_block|ABlock]]|| DiffuseColor || The diffuse color. Three floats for RGB.
|-
||| ''0x4C'' ||[[M2/WotLK#Standard_animation_block|ABlock]]|| DiffuseIntensity|| A float for the intensity again.
|-
||| ''0x60''|| [[M2/WotLK#Standard_animation_block|ABlock]]|| AttenuationStart|| This defines, where the light starts to be.
|-
||| ''0x74''|| [[M2/WotLK#Standard_animation_block|ABlock]]|| AttenuationEnd || And where it stops.
|-
||| ''0x88''|| [[M2/WotLK#Standard_animation_block|ABlock]]|| Unknown || Its an integer and usually 1.
|}
Two light types:
{|style="background:#FCFCFC; color:black"
|
! width="70" | Value
! width="200"| Description
|-
||| 0 || Directional
|-
|||1 || Point light
|}
==Cameras==
''Complete and right as of 17-AUG-09 (3.0.9 or higher)''
*'''nCameras records of 0x64 bytes starting at ofsCameras.'''
These blocks are 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. The reason that non-mainmenu and non-geometry M2s have cameras was is you can see the unit's portrait and the character info tab.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="800"| Description
|-
||| ''0x00''|| uint32 || Type || 0: potrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table.
|-
||| ''0x04''|| float|| FOV || No radians, no degrees. Multiply by 35 to get degrees.
|-
||| ''0x08''|| float|| FarClipping || Where it stops to be drawn.
|-
||| ''0x0C''|| float|| NearClipping || Far and near. Both of them.
|-
||| ''0x10'' || [[M2/WotLK#Standard_animation_block|ABlock]] || TranslationPos || How the camera's position moves. Should be 3*3 floats. (WoW parses 36 bytes = 3*3*sizeof(float))
|-
||| ''0x24''|| float || Position[3] || Where the camera is located.
|-
||| ''0x30'' || [[M2/WotLK#Standard_animation_block|ABlock]] || TranslationTar || How the target moves. Should be 3*3 floats.
|-
||| ''0x44''|| float || Target[3] || Where the camera points to.
|-
||| ''0x50''|| [[M2/WotLK#Standard_animation_block|ABlock]] || Scaling || The camera can have some roll-effect. Its 0 to 2*Pi. 3 Floats!
|}
===Camera lookup table===
''Complete and right as of 17-AUG-09 (3.0.9 or higher)''
*'''nCameraLookup 16-bit integers starting at ofsCameraLookup.'''
This block lists the different cameras existant in the model. The index in the array is also the type. CameraLookupTable[1] is always the character tab camera.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00''|| uint16 || CameraId || All cameras by type. Array indices (0 to n-1).
|}
== Attachments ==
*'''nAttachments records of the following structure starting at ofsAttachments, followed by data referenced in these records.'''
This block specifies a bunch of locations on the body - hands, shoulders, head, back, knees etc. It is used to put items on a character. This seems very likely as this block also contains positions for sheathed weapons, a shield, etc.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00''|| uint32|| Id || Just an id. Is referenced in the [[M2/WotLK#Attachment_Lookup|lookup-block]] below too.
|-
||| ''0x04''|| uint32 || Bone || Somewhere it has to be attached.
|-
|||  ''0x08''|| float|| Position[3] || Relative to that bone of course.
|-
|||  ''0x14'' || [[M2/WotLK#Standard_animation_block|ABlock]] || Data || Its an integer in the data. It has been 1 on all models I saw. Whatever.
|}
Here's the list of position slots (by ID, or index in block P) for character models:
{|style="background:#FCFCFC; color:black"
|
! width="50" | ID
! width="250" | Description
! width="50" | ID
! width="150" | Description
! width="50" | ID
! width="150" | Description
! width="50" | ID
! width="150" | Description
! width="50" | ID
! width="150" | Description
|-
||| 0 || Shield / MountMain / ItemVisual0 || 12 || Back || 24 || Special2 || 36 || Bullet || 48 || RightFoot
|-
||| 1 || HandRight / ItemVisual1 || 13 || ShoulderFlapRight || 25 || Special3 || 37 || SpellHandOmni || 49 || ShieldNoGlove
|-
||| 2 || HandLeft / ItemVisual2 || 14 || ShoulderFlapLeft || 26 || SheathMainHand || 38 || SpellHandDirected || 50 || SpineLow
|-
||| 3 || ElbowRight / ItemVisual3 || 15 || ChestBloodFront || 27 || SheathOffHand || 39 || VehicleSeat1 || 51 || AlteredShoulderR
|-
||| 4 || ElbowLeft / ItemVisual4 || 16 || ChestBloodBack || 28 || SheathShield || 40 || VehicleSeat2 || 52 || AlteredShoulderL
|-
||| 5 || ShoulderRight || 17 || Breath || 29 || PlayerNameMounted || 41 || VehicleSeat3 || 53 || BeltBuckle
|-
||| 6 || ShoulderLeft || 18 || PlayerName || 30 || LargeWeaponLeft || 42 || VehicleSeat4 || 54 || SheathCrossbow
|-
||| 7 || KneeRight || 19 || Base || 31 || LargeWeaponRight || 43 || VehicleSeat5 || ||
|-
||| 8 || KneeLeft || 20 || Head || 32 ||HipWeaponLeft || 44 || VehicleSeat6 || ||
|-
||| 9 || HipRight || 21 || SpellLeftHand || 33 || HipWeaponRight || 45 || VehicleSeat7 || ||
|-
||| 10 || HipLeft || 22 || SpellRightHand || 34 || Chest || 46 || VehicleSeat8 || ||
|-
||| 11 || Helm || 23 || Special1 || 35 || HandArrow || 47 || LeftFoot || ||
|}
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]]. They take the ids 0 to 4. Mounts take the id 0 for their rider. Breath (17) is used by CGCamera::FinishLoadingTarget() aswell as some other one. The name above the head of a Unit (CGUnit_C::GetNamePosition) looks for PlayerNameMounted (29), then PlayerName (18).
===Attachment Lookup===
*'''nAttachLookup 16-bit integers starting at ofsAttachLookup.'''
The index of the array defines, which type that attachment is of. Its the same as the list above. The lookups and the id of the animations point in a circle.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00'' ||uint16|| Attachment|| From 0 to nAttachments-1
|}
==Events==
*'''nEvents records of 0x24 bytes starting at ofsEvents, followed by timestamps referenced in these records.'''
These events are used for timing sounds for example. You can find the $DTH (death) event on nearly every model. It will play the death sound for the unit.
The events you can use depend on the way, the model is used. Dynamic objects can shake the camera, doodads shouldn't. Units can do a lot more than other objects.
Somehow there are some entries, that don't use the $... names but identifiers like "DEST" (destination), "POIN" (point) or "WHEE" (wheel). How they are used? Idk.
{|style="background:#FCFCFC; color:black"
|
! width="70" | Offset
! width="90" | Type
! width="120"| Name
! width="500"| Description
|-
||| ''0x00'' || char || Identifier[4] || This is a (actually 3 character) name for the event with a $ in front.
|-
||| ''0x04'' || uint32 || Data || This data is passed when the event is fired.
|-
||| ''0x08'' || uint32 || Bone || Somewhere it has to be attached.
|-
||| ''0x0C'' || float || Position[3] || Position: Relative to that bone of course, animated. Pivot: without animating.
|-
||| ''0x18'' || uint16 || InterpolationType || This is some fake-AnimationBlock.
|-
||| ''0x1A'' || uint16 || GlobalSequence || Built up like a real one but without timestamps(?). What the fuck?
|-
||| ''0x1C'' || uint32 || nTimestampEntries || See the documentation on [[M2/WotLK#Standard_animation_block|AnimationBlocks]] at this topic.
|-
||| ''0x20'' || uint32 || ofsTimstampList || This points to a list of timestamps for each animation given.
|}
===Possible Events===
There are a lot more of them. I did not list all up to now.
{|style="background:#FCFCFC; color:black"
! width="60" | ID
! width="60" | Type
! width="400" | seen to be fired on
! width="600"| Description
|-
| DEST || ? ||  || exploding ballista, that one has a really fucked up block. Oo
|-
| POIN || Unit || not fired || Data: ?, seen on multiple models. Basilisk for example. (6801)
|-
| WHEE || ? ||  || Data: 601+, Used on wheels at vehicles.
|-
| $tsp || Unit ||  || p is {0 to 3} (position); t is {W, S, B, F (feet) or R} (type); s is {R or L} (right or left); this is used when running through snow for example. Calls CGUnit_C::FootstepAnimEventHit.
|-
| $Fs0 || Unit || Walk, (Run), (DragonStomp), (JumpEnd), (Special2H) || Forward, s is {R or L} (right or left); There can also be the other ones of $Fsx used in here.
|-
| $Fs1 || Unit || StealthWalk, (Walk) || Forward, s is {R or L} (right or left);
|-
| $Fs2 || Unit || Walk || Forward, s is {R or L} (right or left);
|-
| $Fs3 || Unit || || Forward, s is {R or L} (right or left);
|-
| $Rs0 || Unit || Run || Run, s is {R or L} (right or left); There can also be the other ones of $Rsx used in here.
|-
| $Rs1 || Unit || Sprint, (Run) || Run, s is {R or L} (right or left);
|-
| $Rs2 || Unit || JumpLandRun, (Run) || Run, s is {R or L} (right or left);
|-
| $Rs3 || Unit || || Run, s is {R or L} (right or left);
|-
| $Ss0 || Unit || Stop, (JumpEnd), (Shuffle*) || Stop, s is {R or L} (right or left);
|-
| $Ss1 || Unit || JumpEnd, (Stop) || Stop, s is {R or L} (right or left);
|-
| $Ss2 || Unit ||  || Stop, s is {R or L} (right or left);
|-
| $Ss3 || Unit ||  || Stop, s is {R or L} (right or left);
|-
| $Bs0 || Unit || Walkbackwards || Backwards, s is {R or L} (right or left);
|-
| $Bsp || Unit || || Backwards, p is {1 to 3} (position); s is {R or L} (right or left);
|-
| $AHx || ? ||  || UnitCombat_C, x is {0 to 3}; CGUnit_C::HandleCombatAnimEvent
|-
| $CAH || Unit || Attack*, *Unarmed, ShieldBash, Special* || attack hold? CGUnit_C::HandleCombatAnimEvent
|-
| $BWP || Unit || LoadRifle, LoadBow || prepare? CGUnit_C::HandleCombatAnimEvent
|-
| $Cxx || Unit || Attack*, *Unarmed, ShieldBash, Special* || UnitCombat_C, x is {P or S}, first P, then S, then AH is fired. CSS: CGUnit_C::HandleCombatAnimEvent
|-
| $SHx || Unit || Sheath, HipSheath || x is {L or R}, "Left/right shoulder" was in the old list. CGUnit_C::ExchangeSheathedWeapon
|-
| $BRT || ? ||  || Plays some sound.
|-
| $BTH || Unit || All situations, where nothing happens or breathing. || breath, Used for bubbles or breath. ("In front of head"), Stand, Kneel, BattleRoar, Talk, Sleep, SwimIdle
|-
| $BWR || Unit || AttackRifle, AttackBow, AttackThrown || ready?, Something with bow and rifle. "shoot now"? Hell a lot of things. Attachmentthings, CM2Model::DetachFromParent sometimes.
|-
| $CCH || Unit || mostly not fired, AttackThrown || ("Bust"), CEffect::DrawFishingString needs this on the model for getting the string attachments.
|-
| $CHD || Unit || not fired || ("Head") (?)
|-
| $CSD || Unit || Emote* || Data: [[SoundEntries.dbc]], CustomSound? (emote sounds) CGUnit_C::PlayEmoteSound
|-
| $CSL || Unit || AttackRifle, SpellCast*, ChannelCast* || x is {L or R} ("Left/right hand") (?)
|-
| $CSR || Unit || AttackBow, AttackRifle, AttackThrown, SpellCast*, ChannelCast* || x is {L or R} ("Left/right hand") (?)
|-
| $CST || Unit || Attack*, *Unarmed, ShieldBash, Special*, SpellCast, Parry*, EmoteEat, EmoteRoar, Kick, ... || $CSL/R/T are also used in CGUnit_C::ComputeDefaultMissileFirePos.
|-
| $CVS || ? ||  || Data: [[SoundEntriesAdvanced.dbc]], Sound
|-
| $DSE || ? ||  ||
|-
| $DSL || ? ||  || Data: [[SoundEntries.dbc]]  Sound with something special. Use another one if you always want to have it playing..
|-
| $DSO || ? ||  || Data: [[SoundEntries.dbc]] Sound
|-
| $DTH || Unit || Death, Drown, Knockdown || "I'm dead now!", UnitCombat_C, this plays death sounds and more.
|-
| $EMV || ? ||  || MapLoad.cpp
|-
| $ESD || Unit || EmoteWork*, *UseStanding*, EmoteTrain || EmoteSound?, plays some emote sound. CGUnit_C::PlayEmoteStateSound
|-
| $EWT || ? ||  || MapLoad.cpp
|-
| $FDx || Unit || Stand (at 0) || x is {1 to 5}. CGUnit_C::HandlePlayStandSound
|-
| $FD1 || Unit || BattleRoar (at 0) || Calls some function in the Object VMT. Also plays some sound.
|-
| $FD2 || Unit || Stand (at 0) || Calls some function in the Object VMT. Also plays some sound.
|-
| $FD3 || Unit || Stand (at 0) || Calls some function in the Object VMT. Also plays some sound.
|-
| $FDx || Unit ||  || x is {6 to 9}. Calls some function in the Object VMT.
|-
| $FDX || Unit || Stand (at 0) || Should do nothing. But is existant.
|-
| $FSD || Unit || Walk, Run (multiple times), ... || Plays some sound. Footstep? Also seen at several emotes etc. where feet are moved. CGUnit_C::HandleFootfallAnimEvent
|-
| $GCx || GO || || Play gameobject custom sound referenced in [[GameObjectDisplayInfo.dbc]]. x can be from {0 to 3}: {Custom0, Custom1, Custom2, Custom3}
|-
| $GOx || GO || || Play gameobject sound referenced in [[GameObjectDisplayInfo.dbc]]. x can be from {0 to 5}: {Stand, Open, Loop, Close, Destroy, Opened}
|-
| $HIT || Unit || Attack*, *Unarmed, ShieldBash, Special* || Hit someone?
|-
| $KVS || ? || || MapLoad.cpp
|-
| $SCD || ? || || Plays some sound.
|-
| $SHK || GO || || Data: [[SpellEffectCameraShakes.dbc]], Add a camera shake
|-
| $SMD || ? || || Plays some sound.
|-
| $SMG || ? || || Plays some sound.
|-
| $SND || ? || || Data: [[SoundEntries.dbc]] Sound
|-
| $TRD || Unit || EmoteWork*, UseStanding* || Does something with a spell, a sound and a spellvisual.
|-
| $VGx || ? ||  || UnitVehicle_C, x is {0 to 8}
|-
| $VTx || ? ||  || CVehicle_C::HandleBoneAnimThrowEvent, x is {0 to 8}
|-
| $WxG || ? ||  || x is {W or N}. Calls some function in the Object VMT.
|-
| $WTx || Bow || ShowRangedWeapon || x is {B or T}, calls CDrawBowString::UnitDrawBowStringCB(CM2Model *,CM2Lighting  const*,void *). Also used in something related to WeaponTrailSetDrawing for getting the position of both, $WTB and $WTT.
|-
| $CMA || Unit || CGCamera::UpdateMountHeightOrOffset || Position is used for something. Unsure, if in mount or on character.
|-
| $CFM || Unit || CGCamera::UpdateMountHeightOrOffset || Pivot is used for something. Only z, I think. Unsure, if in mount or on character.
|-
| $AIM || Vehicles || CGUnit_C::ComputeMissileTrajectory || Position used as MissileFirePos.
|-
| $STx || Mounts || MountTransitionObject::UpdateCharacterData || x is {E and B} , sequence time is taken of both, pivot of $STB. (Also, attachment info for attachment 0)
|-
| $TRD || ? ||  || ("Crotch") (?)
|-
| $BWR || ? ||  || ("Right hand") (?)
|-
| $CAH || ? ||  ||
|-
| $ALT || ? ||  || CUnitDisplayTransition_C::UpdateState(1) or CUnitDisplayTransition_C::HandleAnimSwapEvent
|-
| $WGG || ? ||  || vtable-call (0x124)
|}
[[Category:Format]]

Revision as of 21:04, 10 August 2014

Effects

UV-Animations

  • This block contains definitions for texture animations, for example, flowing water or lava in some models. The keyframe values are used in the texture transform matrix.

nTexAnims records of 0x3C bytes starting at ofsTexAnims, followed by data referenced in these records.

Offset Type Description
0x00 ABlock (float[3]) Translation
0x14 ABlock (short[4]) Rotation
0x28 ABlock (float[3]) Scaling

The three subrecords specify uv-transforms. Translation seems to work, producing nice flowing lava and waterfalls.

UV-Animation lookup table

  • nTexAnimLookup items starting at ofsTexAnimLookup.
Offset Type Name Description
0x00 uint16 AnimatedTextureId Array indices (0 to n-1). -1 for a static texture.

Ribbon emitters

  • nRibbonEmitters records of 0xB0 bytes starting at ofsRibbonEmitters, followed by data referenced in these records.

The records have the following structure:

Offset Type Name Description
0x00 uint32 Unknown Always (as I have seen): -1.
0x04 uint32 BoneID A bone to attach to.
0x08 float Position[3] And a position, relative to that bone.
0x14 int32 nTextures Number of referenced textures.
0x18 int32 ofsTextures Offset to the referenced textures.
0x1C int32 nBlendRef Number of some referenced integers,which look like the blending for the texture
0x20 int32 ofsBlendRef Offset to the blending-integers.
0x24 ABlock Color A color in three floats.
0x38 ABlock Opacity And an alpha value in a short, where: 0 - transparent, 0x7FFF - opaque.
0x4C ABlock Above The height above.
0x60 ABlock Below The height below. Do not set these to the same!
0x74 float Resolution This defines how smooth the ribbon is. A low value may produce a lot of edges.
0x78 float Length The length aka Lifespan.
0x7C float Emissionangle use arcsin(val) to get the angle in degree
0x80 short Renderflags[2] Perhaps the same as in renderflags
0x84 ABlock UnknownABlock1 (short)
0x98 ABlock UnknownABlock2 (boolean)
0xAC int32 unknown This looks much like just some Padding to the fill up the 0x10 Bytes, always 0

Some 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 the energy trails in the COT (not the actual instance, but the entrance cave in Tanaris Desert). Other models with ribbon emitters are spells and effects.

Parameters from the MDL format that are probably in here somewhere: emission rate, rows, cols ...?

Particle emitters

This is partly wrong as hell!

  • nParticleEmitters records starting at ofsParticleEmitters, followed by data referenced in these records.
Offset Type Name Description
0x000 uint32 Unknown Always (as I have seen): -1.
0x004 uint32 Flags See Below
0x008 float Position[3] The position. Relative to the following bone.
0x014 uint16 Bone The bone its attached to.
0x016 uint16 Texture And the texture that is used.
0x018 uint32 lenModelFilename The lenght of the ModelFilename. Zeroterminated String!
0x01C uint32 ofsModelFilename And the matching offset. This is used for spawning Models. *.mdx
0x020 uint32 lenParticleFileName The lenght of the ParticleFilename. Zeroterminated String!
0x024 uint32 ofsParticleFileName And the matching offset again.This is used for spawning particles of a model. *.mdx!
0x028 uint8 BlendingType A blending type for the particle. See Below
0x029 uint8 EmitterType 1 - Plane (rectangle), 2 - Sphere, 3 - Spline? (can't be bothered to find one)
0x02A uint16 ParticleColorSomething This one is used for ParticleColor.dbc. See below.
0x02C uint8 ParticleType? Found below.
0x02D uint8 HeadorTail 0 - Head, 1 - Tail, 2 - Both
0x02E uint16 TextureTileRotation Rotation for the texture tile. (Values: -1,0,1)
0x030 uint16 TextureRows How many different frames are on that texture? People should learn what rows and cols are.
0x032 uint16 TextureCols Its different everywhere. I just took it random.
0x034 ABlock EmissionSpeed All of the following blocks should be floats.
0x048 ABlock SpeedVariation Variation in the flying-speed. (range: 0 to 1)
0x05C ABlock VerticalRange Drifting away vertically. (range: 0 to pi)
0x070 ABlock HorizontalRange They can do it horizontally too! (range: 0 to 2*pi)
0x084 ABlock Gravity Fall down, apple!
0x098 ABlock Lifespan Everyone has to die.
0x0AC uint32 unknownPadding I don't know what these two values should do..
0x0B0 ABlock EmissionRate Stread your particles, emitter.
0x0C4 uint32 unknownPadding2 It could have been an array without them..
0x0C8 ABlock EmissionAreaLength Well, you can do that in this area.
0x0DC ABlock EmissionAreaWidth
0x0F0 ABlock Gravity2 A second gravity? Its strong.
0x104 FBlock ParticleColor (short, vec3f) This one points to 3 floats defining red, green and blue.
0x114 FBlock ParticleOpacity? (short, short) Looks like opacity (short) --Igor; Most likely they all have 3 timestamps for {start, middle, end}.
0x124 FBlock ParticleSizes (short, vec2f) It carries two floats per key. (x and y scale)
0x134 int32 UnknownFields[2] No references. Padding?
0x13C FBlock Intensity Some kind of intensity values seen: 0,16,17,32(if set to different it will have high intensity) (short, short)
0x14C FBlock UnknownReferences1 (short, short)
0x15C float UnknownFloats1[3] They have something to do with the spread.
0x168 float Scale[3] Wheey, its the scale!
0x174 float Drag Air resistance, see below.
0x178 float UnknownFloats2[2] More unknown fields.
0x180 float Rotation As a single value? Most likely only one axis then..
0x184 float UnknownFloats3[2] More unknown fields.
0x18C float Rot1[3] Model Rotation 1
0x198 float Rot2[3] Model Rotation 2
0x1A4 float Trans[3] Model Translation
0x1B0 float UnknownFloats4[4] Unknown, unknown, unknown, unknown, unknown...
0x1C0 uint32 nUnknownReference
0x1C4 uint32 ofsUnknownReference Vec3D array
0x1C8 ABlock EnabledIn (boolean) Has been in the earlier documentations. Enabled Anim Block. Appears to be used sparely now, probably there's a flag that links particles to animation sets where they are enabled.

About Drag: For a non-zero 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. Speed is multiplied by exp( -drag * t ). This value is also present in M3 format.

About particle rotation: 0 for none, 1 to rotate the particle 360 degrees throughout its lifetime.

Rotation can be a float value greater or less one. Results look better if use it as a "phase shift": particle_rotate = randfloat(-sys->rotation * pi, sys->rotation * pi); --Igor

Particle Flags

Value Description
0x1
0x2
0x4
0x8
0x10 Do not Trail
0x20
0x40
0x80 Particles in Model Space
0x100
0x200
0x400 Pinned Particles, their quad enlarges from their creation position to where they expand.
0x800
0x1000 XYQuad Particles. They align to XY axis facing Z axis direction.
0x2000
0x4000
0x8000
0x10000
0x20000
0x40000

ParticleColorSomething

This one is used so you can assign a color to specific particles. They loop over all particles and compare +0x2A to 11, 12 and 13. If that matches, the colors from the dbc get applied.

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)

ParticleType is always 0 and, maybe, now (Flags & 0x40000) != 0 means "particles from origin to position". --Igor Checked and verified --BlinkHawk

Particle Blendings

Value Description
0 glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST);
1 glBlendFunc(GL_SRC_COLOR, GL_ONE);
2 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3 glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST);
4 glBlendFunc(GL_SRC_ALPHA, GL_ONE);

from Modelviewer source

The Fake-AnimationBlock

  • Its pretty much like the real one but without the "header".
Offset Type Name Description
0x000 uint32 nTimestamps The number of timestamps.
0x004 uint32 ofsTimestamps And the offset to them. The timestamps are shorts! (?)
0x008 uint32 nKeys The same number again. This time its the number of Keys / Values.
0x00C uint32 ofsKeys And their offset.

But they're unable to change between different animations, so they directly point to the data.