WMO: Difference between revisions

From wowdev
Jump to navigation Jump to search
No edit summary
Line 116: Line 116:
== MOGN chunk ==
== MOGN chunk ==


*'''List of group names for the groups in this map object.'''  
*'''List of group names for the groups in this map object. There are nGroups entries in this chunk.'''  


*A contiguous block of zero-terminated strings. The names are purely informational, they aren't used elsewhere (to my knowledge)
A contiguous block of zero-terminated strings. The names are purely informational, they aren't used elsewhere (to my knowledge)
*There are nGroups entries in this chunk.


==  MOGI chunk ==
==  MOGI chunk ==
Line 150: Line 149:
*'''Skybox.''' If not empty, it contains a model (M2) filename to use as a skybox. Used in: Caverns of Time, Stratholme, Dire Maul.
*'''Skybox.''' If not empty, it contains a model (M2) filename to use as a skybox. Used in: Caverns of Time, Stratholme, Dire Maul.


*The regular "stars" skybox as seen outdoors at night is hardcoded into WoW.exe.
The regular "stars" skybox as seen outdoors at night is hardcoded into WoW.exe.  
*Skyboxes are also used in-game when you die (and have the swirling green clouds around you).
Skyboxes are also used in-game when you die (and have the swirling green clouds around you).


==  MOPV chunk ==
==  MOPV chunk ==
Line 344: Line 343:
Every group file has one top-level MOGP chunk, that has a 68-byte header followed by more subchunks. So it can be effectively treated as a file with a header at 0x14 and chunks starting at 0x58.  
Every group file has one top-level MOGP chunk, that has a 68-byte header followed by more subchunks. So it can be effectively treated as a file with a header at 0x14 and chunks starting at 0x58.  


== MOGP chunk ==


 
  '''Offset Type Description'''
== WMO group header ==
  0x00 uint32 Group name (offset into MOGN chunk)
  '''Offset Type Description'''
  0x04 uint32 Descriptive group name (offset into MOGN chunk)
  0x00 uint32 Group name (offset into MOGN chunk)
  0x08 uint32 Flags
  0x04 uint32 Descriptive group name (offset into MOGN chunk)
  0x08 uint32 Flags
  0x0C float[3] Bounding box corner 1 (same as in MOGI)
  0x0C float[3] Bounding box corner 1 (same as in MOGI)
  0x18 float[3] Bounding box corner 2
  0x18 float[3] Bounding box corner 2
  0x24 uint16 Index into the MOPR chunk
  0x24 uint16 Index into the MOPR chunk
  0x26 uint16 Number of items used from the MOPR chunk
  0x26 uint16 Number of items used from the MOPR chunk
  0x28 uint16 Number of batches A
  0x28 uint16 Number of batches A
  0x2A uint16 Number of batches B
  0x2A uint16 Number of batches B
  0x2C uint32 Number of batches C
  0x2C uint32 Number of batches C
  0x30 uint8[4] Up to four indices into the WMO fog list
  0x30 uint8[4] Up to four indices into the WMO fog list
  0x34 uint32 Unknown (always 15)
  0x34 uint32 Unknown (always 15)
  0x38 uint32 WMO group ID (column 4 in WMOAreaTable.dbc)
  0x38 uint32 WMO group ID (column 4 in WMOAreaTable.dbc)
  0x3C uint32 Always 0?
  0x3C uint32 Always 0?
  0x40 uint32 Always 0?
  0x40 uint32 Always 0?


The fields referenced from the MOPR chunk indicate portals leading out of the WMO group in question.
The fields referenced from the MOPR chunk indicate portals leading out of the WMO group in question.
Line 368: Line 366:
For the "Number of batches" fields, A + B + C == the total number of batches in the WMO group (in the MOBA chunk). This might be some kind of LOD thing, or just separating the batches into different types/groups...?
For the "Number of batches" fields, A + B + C == the total number of batches in the WMO group (in the MOBA chunk). This might be some kind of LOD thing, or just separating the batches into different types/groups...?


I removed the struct definition because it seemed to be a copy of some header from the terrain data, not WMO stuff
Flags: always contain more information than flags in MOGN. I suppose MOGN only deals with topology/culling, while flags here also include rendering info.


 
  '''Flag Meaning'''
Flags: always contain more information than flags in MOGN. I suppose MOGN only deals with topology/culling, while flags here also include rendering info.
  0x1 Always set
  '''Flag Meaning'''
  0x4 Has vertex colors (MOCV chunk)
  0x1 Always set
  0x8 Outdoor
  0x4 Has vertex colors (MOCV chunk)
  0x200 Has lights (MOLR chunk)
  0x8 Outdoor
  0x800 Has doodads (MODR chunk)
  0x200 Has lights (MOLR chunk)
  0x800 Has doodads (MODR chunk)
  0x1000 Has water (MLIQ chunk)
  0x1000 Has water (MLIQ chunk)
  0x2000 Indoor
  0x2000 Indoor
  0x40000 Show skybox
  0x40000 Show skybox
   
   
==  MOPY chunk ==
==  MOPY chunk ==


*'''Material info for triangles, two bytes per triangle. So size of this chunk in bytes is twice the number of triangles in the WMO group.'''


Material info for triangles, two bytes per triangle. So size of this chunk in bytes is twice the number of triangles in the WMO group.
  '''Offset Type Description'''
  '''Offset Type Description'''
  0x00 uint8 Flags?
  0x00 uint8 Flags?
  0x01 uint8 Material ID
  0x01 uint8 Material ID


  struct SMOPoly // 03-29-2005 By ObscuR ( Maybe not accurate :p )
  struct SMOPoly ''// 03-29-2005 By ObscuR ( Maybe not accurate :p )''
  {
  {
  enum   
  enum   
Line 406: Line 401:
  /*002h*/  uint8 mtlId;
  /*002h*/  uint8 mtlId;
  };
  };
// are you sure it's 3 bytes? wowmapview uses groups of 2 :)  - Z.
// look like the lightmapTex byte is no longer present, this struct come from Alpha :) - Obs
// are you sure it's 3 bytes? wowmapview uses groups of 2 :)  - Z.
// look like the lightmapTex byte is no longer present, this struct come from Alpha :) - Obs


Frequently used flags are 0x20 and 0x40, but I have no idea what they do.
Frequently used flags are 0x20 and 0x40, but I have no idea what they do.
Line 414: Line 410:


Triangles stored here are more-or-less pre-sorted by texture, so it's ok to draw them sequentially.  
Triangles stored here are more-or-less pre-sorted by texture, so it's ok to draw them sequentially.  
   
   
== MOVI chunk ==
== MOVI chunk ==
Vertex indices for triangles. Three 16-bit integers per triangle, that are indices into the vertex list. The numbers specify the 3 vertices for each triangle, their order makes it possible to do backface culling.


*'''Vertex indices for triangles.''' Three 16-bit integers per triangle, that are indices into the vertex list. The numbers specify the 3 vertices for each triangle, their order makes it possible to do backface culling.
 
== MOVT chunk ==
== MOVT chunk ==
Vertices chunk. 3 floats per vertex, the coordinates are in (X,Z,-Y) order. It's likely that WMOs and models (M2s) were created in a coordinate system with the Z axis pointing up and the Y axis into the screen, whereas in OpenGL, the coordinate system used in WoWmapiew the Z axis points toward the viewer and the Y axis points up. Hence the juggling around with coordinates.


*'''Vertices chunk.''' 3 floats per vertex, the coordinates are in (X,Z,-Y) order. It's likely that WMOs and models (M2s) were created in a coordinate system with the Z axis pointing up and the Y axis into the screen, whereas in OpenGL, the coordinate system used in WoWmapiew the Z axis points toward the viewer and the Y axis points up. Hence the juggling around with coordinates.


==  MONR chunk ==
==  MONR chunk ==
Normals. 3 floats per vertex normal, in (X,Z,-Y) order.


*'''Normals. 3 floats per vertex normal, in (X,Z,-Y) order.'''
   
   
== MOTV chunk ==
== MOTV chunk ==


Texture coordinates, 2 floats per vertex in (X,Y) order. The values range from 0.0 to 1.0. Vertices, normals and texture coordinates are in corresponding order, of course.
*'''Texture coordinates, 2 floats per vertex in (X,Y) order.''' The values range from 0.0 to 1.0. Vertices, normals and texture coordinates are in corresponding order, of course.


== MOBA chunk ==
   
   
== MOBA chunk ==
*'''Render batches. Records of 24 bytes.'''
  struct SMOBatch // 03-29-2005 By ObscuR
 
  struct SMOBatch'' // 03-29-2005 By ObscuR''
  {
  {
  enum
  enum
Line 454: Line 451:
  ?? flags;
  ?? flags;
  };
  };
Render batches. Records of 24 bytes.


For the enUS, enGB versions, it seems to be different from the preceding struct:
For the enUS, enGB versions, it seems to be different from the preceding struct:
  '''Offset Type Description'''
  '''Offset Type Description'''
  0x00 uint32 Some color?
  0x00 uint32 Some color?
  0x04 uint32 Some color?
  0x04 uint32 Some color?
  0x08 uint32 Some color?
  0x08 uint32 Some color?
  0x0C uint32 Start index
  0x0C uint32 Start index
  0x10 uint16 Number of indices
  0x10 uint16 Number of indices
  0x12 uint16 Start vertex
  0x12 uint16 Start vertex
  0x14 uint16 End vertex
  0x14 uint16 End vertex
  0x16 uint8 0?
  0x16 uint8 0?
  0x17 uint8 Texture
  0x17 uint8 Texture
 


==  MOLR chunk ==


==  MOLR chunk ==
*'''Light references, one 16-bit integer per light reference.'''


Light references, one 16-bit integer per light reference. This is basically a list of lights used in this WMO group, the numbers are indices into the WMO root file's MOLT table.
This is basically a list of lights used in this WMO group, the numbers are indices into the WMO root file's MOLT table.


For some WMO groups there is a large number of lights specified here, more than what a typical video card will handle at once. I wonder how they do lighting properly. Currently, I just turn on the first GL_MAX_LIGHTS and hope for the best. :(  
For some WMO groups there is a large number of lights specified here, more than what a typical video card will handle at once. I wonder how they do lighting properly. Currently, I just turn on the first GL_MAX_LIGHTS and hope for the best. :(  
   
   
== MODR chunk ==
== MODR chunk ==
Doodad references, one 16-bit integer per doodad. The numbers are indices into the doodad instance table ( MODD chunk) of the WMO root file. These have to be filtered to the doodad set being used in any given WMO instance.
 
*'''Doodad references, one 16-bit integer per doodad.'''
The numbers are indices into the doodad instance table (MODD chunk) of the WMO root file. These have to be filtered to the doodad set being used in any given WMO instance.


   
   
== MOBN chunk ==
== MOBN chunk ==
Array of t_BSP_NODE.
 
*'''Array of t_BSP_NODE.'''
   
   
  struct t_BSP_NODE
  struct t_BSP_NODE
Line 496: Line 492:
  };
  };
  // The numfaces and firstface define a polygon plane.
  // The numfaces and firstface define a polygon plane.
                                         2005-4-4 by linghuye
                                         ''2005-4-4 by linghuye''


==  MOBR chunk ==
==  MOBR chunk ==


Triangle indices (in MOVI which define triangles) to describe polygon planes defined by MOBN BSP nodes.  
*'''Triangle indices (in MOVI which define triangles) to describe polygon planes defined by MOBN BSP nodes.'''


== MOCV chunk ==
== MOCV chunk ==
Vertex colors, 4 bytes per vertex (BGRA), for WMO groups using indoor lighting. I don't know if this is supposed to work together with, or replace, the lights referenced in MOLR. But it sure is the only way for the ground around the goblin smelting pot to turn red in the Deadmines. (but some corridors are, in turn, too dark - how the hell does lighting work anyway, are there lightmaps hidden somewhere?)
 
*'''Vertex colors, 4 bytes per vertex (BGRA), for WMO groups using indoor lighting.'''
I don't know if this is supposed to work together with, or replace, the lights referenced in MOLR. But it sure is the only way for the ground around the goblin smelting pot to turn red in the Deadmines. (but some corridors are, in turn, too dark - how the hell does lighting work anyway, are there lightmaps hidden somewhere?)


- I'm pretty sure WoW does not use lightmaps in it's WMOs...
- I'm pretty sure WoW does not use lightmaps in it's WMOs...
Line 512: Line 509:


==  MLIQ chunk ==
==  MLIQ chunk ==
Completely overlooked this one...
Specifies liquids inside WMOs. This is where the water from Stormwind and BFD (and probably mode) was hidden. (slime in Undercity, pool water in the Darnassus temple, some lava in IF)
This file sounds like it might link to WLQ files (World LiQuids?).
    * I wish it did, but it doesn't. In fact, nothing links to them. There's no reference to them in the entire WoW data that I know of, apart from being there in misc.mpq. Makes me wonder if they're used at all.


*'''Specifies liquids inside WMOs.'''
This is where the water from Stormwind and BFD etc. is hidden. (slime in Undercity, pool water in the Darnassus temple, some lava in IF)


Chunk header:
Chunk header:
  '''Offset Type Description'''
  '''Offset Type Description'''
  0x00 uint32 number of X vertices (xverts)
  0x00 uint32 number of X vertices (xverts)
  0x04 uint32 number of Y vertices (yverts)
  0x04 uint32 number of Y vertices (yverts)
  0x08 uint32 number of X tiles (xtiles = xverts-1)
  0x08 uint32 number of X tiles (xtiles = xverts-1)
  0x0C uint32 number of Y tiles (ytiles = yverts-1)
  0x0C uint32 number of Y tiles (ytiles = yverts-1)
  0x10 float[3] base coordinates?
  0x10 float[3] base coordinates?
  0x1C uint16 material ID
  0x1C uint16 material ID


The liquid data contains the vertex height map (xverts * yverts * 8 bytes) and the tile flags (xtiles * ytiles bytes) as descripbed in ADT files (MCLQ chunk). The length and width of a liquid tile is the same as on the map, that is, 1/8th of the length of a map chunk. (which is in turn 1/16th the length of a map tile).
The liquid data contains the vertex height map (xverts * yverts * 8 bytes) and the tile flags (xtiles * ytiles bytes) as descripbed in ADT files (MCLQ chunk). The length and width of a liquid tile is the same as on the map, that is, 1/8th of the length of a map chunk. (which is in turn 1/16th the length of a map tile).


The material ID often refers to what seems to be a "special" material in the root WMO file (special because it often has a solid color/placeholder texture, or a texture from XTextures\*) - but sometimes the material referenced seems to be not special at all, so I'm not really sure how the liquid material is obtained - such as water/slime/lava.
The material ID often refers to what seems to be a "special" material in the root WMO file (special because it often has a solid color/placeholder texture, or a texture from XTextures\*) - but sometimes the material referenced seems to be not special at all, so I'm not really sure how the liquid material is obtained - such as water/slime/lava.
Retrieved from "http://wowdev.org/wiki/index.php/WMO"
Retrieved from "http://wowdev.org/wiki/index.php/WMO"

Revision as of 13:18, 27 July 2007

WMO Files

WMO files contain world map objects. They, too, have a chunked structure just like the WDT files.

There are two types of WMO files, actually:

  • WMO root file - lists textures (BLP Files), doodads (M2 or MDX Files), etc., and orientation for the WMO groups
  • WMO group file - 3d model data for one unit in the world map object

The root file and the groups are stored with the following filenames:

  • World\wmo\path\WMOName.wmo
  • World\wmo\path\WMOName_NNN.wmo

WMO root file

The root file lists the following:

  • textures (BLP File references)
  • materials
  • models (M2 File references)
  • groups
  • visibility information
  • more data

MOHD chunk

  • Header for the map object. 64 bytes.
Offset 	Type 		Description
0x00 	uint32 		nTextures - number of textures (BLP Files)
0x04 	uint32 		nGroups - number of WMO groups
0x08 	uint32 		nPortals - number of portals
0x0C 	uint32 		nLights - number of lights
0x10 	uint32 		nModels - number of M2 models imported
0x14 	uint32 		nDoodads - number of doodads (M2 instances)
0x18 	uint32 		nSets - number of doodad sets
0x1C 	uint32 		ambient color?
0x20 	uint32 		WMO ID (column 2 in WMOAreaTable.dbc)
0x24 	float[3] 	Bounding box corner 1
0x30 	float[3] 	Bounding box corner 2
0x3C 	uint32 		always 0?
struct SMOHeader // 03-29-2005 By ObscuR
{
/*000h*/  UINT32 nTextures;		
/*004h*/  UINT32 nGroups;		
/*008h*/  UINT32 nPortals;		
/*00Ch*/  UINT32 nLights;		
/*010h*/  UINT32 nDoodadNames;		
/*014h*/  UINT32 nDoodadDefs;		
/*018h*/  UINT32 nDoodadSets;		
/*01Ch*/  float ambColor[6];		
/*020h*/ 
/*024h*/  	
/*028h*/  		
/*02Ch*/ 	
/*030h*/  float pos[2];		
/*034h*/  		
/*038h*/  		
/*03Ch*/   UINT32 wmoID;		
/*040h*/ 
};

MOTX chunk

  • List of textures (BLP Files) used in this map object. There are nTextures entries in this chunk.

A block of zero-padded, zero-terminated strings, that are complete filenames with paths. There will be further material information for each texture in the next chunk. The gaps between the filenames are padded with extra zeroes, but the material chunk does have some positional information for these strings.

MOMT chunk

  • Materials used in this map object, 64 bytes per texture (BLP file), nTextures entries.

Only the known fields are documented here.

Offset 	Type 		Description
0x00 	uint32 		Flags (?)
0x08 	uint32 		Blending: 0 for opaque, 1 for transparent
0x0C 	uint32 		Start position for the texture filename in the MOTX data block
0x18 	uint32 		End position for the texture filename in the MOTX data block
0x1C 	4 * uint8 	Looks like an RGBA color?
struct SMOMaterial // 03-29-2005 By ObscuR
{
/*000h*/  UINT32 version;		
/*004h*/  UINT32 flags;		
/*008h*/  UINT32 blendMode;		
/*00Ch*/  UINT32 diffuseNameIndex;		
/*010h*/  float sidnColor[3];		
/*014h*/  		
/*018h*/ 		
/*01Ch*/  UINT32 frameSidnColor[3];		
/*020h*/  	
/*024h*/   	
/*028h*/  UINT32 envNameIndex;
/*02Ch*/  float diffColor[3] 		
/*030h*/   		
/*034h*/  		
/*038h*/  UINT32 groundType;		
/*03Ch*/  UINT32 hMaps;		
/*040h*/ 		
}

The field that looks like a color value is green for some of the wooden textures in human buildings, so it is obviously not a texture color. So its purpose is unknown.

The flags might used to tweak alpha testing values, I'm not sure about it, but some grates and flags in IF seem to require an alpha testing threshold of 0, at other places this is greater than 0.

Flag 		Meaning
0x01 		?
0x04 		Two-sided (disable backface culling)
0x10 		Bright at night (unshaded) (used on windows and lamps in Stormwind, for example) -ProFeT: i think that is Unshaded becase external face of windows are flagged like this.
0x20 		?
0x28 		Darkned ?, the intern face of windows are flagged 0x28
0x40 		?
0x80 		?

MOGN chunk

  • List of group names for the groups in this map object. There are nGroups entries in this chunk.

A contiguous block of zero-terminated strings. The names are purely informational, they aren't used elsewhere (to my knowledge)

MOGI chunk

  • Group information for WMO groups, 32 bytes per group, nGroups entries.
Offset 	Type 		Description
0x00 	uint32 		Flags
0x04 	3 * float 	Bounding box corner 1
0x10 	3 * float 	Bounding box corner 2
0x1C 	int32 		name offset in MOGN chunk (or -1 for no name?)

Groups don't have placement or orientation information, because the coordinates for the vertices in the additional .WMO files are already correctly transformed relative to (0,0,0) which is the entire WMO's base position in model space.

The name offsets seem to be incorrect (or something else entirely?). The correct name offsets are in the WMO group file headers. (along with more descriptive names for some groups)

The flags for the groups seem to specify whether it is indoors/outdoors, probably to choose what kind of lighting to use. Not fully understood. "Indoors" and "Outdoors" are flags used to tell the client whether certain spells can be cast and abilities used. (Example: Entangling Roots cannot be used indoors).

Flag		Meaning
0x8 		Outdoor (use global lights?)
0x40		?
0x80 		?
0x2000		Indoor (use local lights?)
0x8000		Unknown, but frequently used
0x10000 	Used in Stormwind?
0x40000		Show skybox if the player is "inside" the group

MOSB chunk

  • Skybox. If not empty, it contains a model (M2) filename to use as a skybox. Used in: Caverns of Time, Stratholme, Dire Maul.

The regular "stars" skybox as seen outdoors at night is hardcoded into WoW.exe. Skyboxes are also used in-game when you die (and have the swirling green clouds around you).

MOPV chunk

  • Portal vertices, 4 * 3 * float per portal, nPortals entries.

Portals are (always?) rectangles that specify where doors or entrances are in a WMO. They could be used for visibility, but I currently have no idea what relations they have to each other or how they work.

Since when "playing" WoW, you're confined to the ground, checking for passing through these portals would be enough to toggle visibility for indoors or outdoors areas, however, when randomly flying around, this is not necessarily the case.

So.... What happens when you're flying around on a gryphon, and you fly into that arch-shaped portal into Ironforge? How is that portal calculated? It's all cool as long as you're inside "legal" areas, I suppose.

It's fun, you can actually map out the topology of the WMO using this and the MOPR chunk. This could be used to speed up the rendering once/if I figure out how.

MOPT chunk

  • Portal information. 20 bytes per portal, nPortals entries.
Offset	Type 		Description
0x00 	uint16 		Base vertex index?
0x02 	uint16 		Number of vertices (?), always 4 (?)
0x04 	3*float 	a normal vector maybe? haven't checked.
0x10 	float 		unknown
struct SMOPortal  // 04-29-2005 By ObscuR
{
  /*000h*/  UINT16 startVertex;
  /*002h*/  UINT16 count;
  /*004h*/  float  plane[4];
  /*014h*/  
};

MOPR chunk

  • Portal <> group relationship? 2*nPortals entries of 8 bytes.

I think this might specify the two WMO groups that a portal connects.

Offset 	Type 		Description
0x0 	uint16 		Portal index
0x2 	uint16 		WMO group index
0x4 	int16 		1 or -1
0x6 	uint16 		always 0
struct SMOPortalRef // 04-29-2005 By ObscuR
{
  /*000h*/  UINT16 portalIndex;
  /*000h*/  UINT16 groupIndex;
  /*004h*/  UINT16 side;
  /*006h*/  UINT16 filler;
  /*008h*/
};

MOVV chunk

  • Visible block vertices

Just a list of vertices that corresponds to the visible block list.

MOVB chunk

  • Visible block list
unsigned short firstVertex;
unsigned short count;

MOLT chunk

  • Lighting information. 48 bytes per light, nLights entries
Offset 	Type 		Description
0x00 	4 * uint8 	Flags or something? Mostly (0,1,1,1)
0x04 	4 * uint8 	Color (B,G,R,A)
0x08 	3 * float 	Position (X,Z,-Y)
0x14 	7 * float 	Unknown (light properties?)
enum LightType 
{
	OMNI_LGT,
	SPOT_LGT,
	DIRECT_LGT,
	AMBIENT_LGT
};
struct SMOLight // 04-29-2005 By ObscuR
{
  /*000h*/  UINT8 LightType; 	
  /*001h*/  UINT8 type;
  /*002h*/  UINT8 useAtten;
  /*003h*/  UINT8 pad;
  /*004h*/  UINT8 color[4];  
  /*008h*/  float position[3];
  /*014h*/  float intensity;
  /*018h*/  float attenStart;
  /*01Ch*/  float attenEnd;
  /*020h*/  float unk1;
  /*024h*/  float unk2;
  /*028h*/  float unk3;
  /*02Ch*/  float unk4;
  /*030h*/  
};

I haven't quite figured out how WoW actually does lighting, as it seems much smoother than the regular vertex lighting in my screenshots. The light paramters might be range or attenuation information, or something else entirely. Some WMO groups reference a lot of lights at once.

The WoW client (at least on my system) uses only one light, which is always directional. Attenuation is always (0, 0.7, 0.03). So I suppose for models/doodads (both are M2 files anyway) it selects an appropriate light to turn on. Global light is handled similarly. Some WMO textures (BLP files) have specular maps in the alpha channel, the pixel shader renderpath uses these. Still don't know how to determine direction/color for either the outdoor light or WMO local lights... :)

MODS chunk

  • This chunk defines doodad sets.

Doodads in WoW are M2 model files. There are 32 bytes per doodad set, and nSets entries. Doodad sets specify several versions of "interior decoration" for a WMO. Like, a small house might have tables and a bed laid out neatly in one set called "Set_$DefaultGlobal", and have a horrible mess of abandoned broken things in another set called "Set_Abandoned01". The names are only informative.

The doodad set number for every WMO instance is specified in the ADT files.

Offset 	Type 		Description
0x00 	20 * char 	Set name
0x14 	uint32 		index of first doodad instance in this set
0x18 	uint32 		number of doodad instances in this set
0x1C 	uint32 		unused? (always 0)

MODN chunk

  • List of filenames for M2 models that appear in this map tile.

A block of zero-padded, zero-terminated strings. There are nModels file names in this list.

MODD chunk

  • Information for doodad instances. 40 bytes per doodad instance, nDoodads entries.

While WMOs and models (M2s) in a map tile are rotated along the axes, doodads within a WMO are oriented using quaternions! Hooray for consistency!

I had to do some tinkering and mirroring to orient the doodads correctly using the quaternion, see model.cpp in the WoWmapview source code for the exact transform matrix. It's probably because I'm using another coordinate system, as a lot of other coordinates in WMOs and models also have to be read as (X,Z,-Y) to work in my system. But then again, the ADT files have the "correct" order of coordinates. Weird.

Offset 	Type 		Description
0x00 	uint32 		Offset to the start of the model's filename in the MODN chunk.
0x04 	3 * float 	Position (X,Z,-Y)
0x10 	float 		W component of the orientation quaternion
0x14 	3 * float 	X, Y, Z components of the orientaton quaternion
0x20 	float 		Scale factor
0x24 	4 * uint8 	(B,G,R,A) color. Unknown. It is often (0,0,0,255). (something to do with lighting maybe?)
struct SMODoodadDef // 03-29-2005 By ObscuR
{
  /*000h*/  UINT32 nameIndex
  /*004h*/  float pos[3];
  /*010h*/  float rot[4];
  /*020h*/  float scale;
  /*024h*/  UINT8 color[4];
  /*028h*/
};

MFOG chunk

  • Fog information. Made up of blocks of 48 bytes.
Offset 	Type 		Description
0x00 	uint32 		Flags
0x04 	float[3]	Position
0x10 	float 		Smaller radius
0x14 	float 		Larger radius
0x18 	float 		Fog end
0x1C 	float 		Fog start multiplier (0..1)
0x20 	uint32 		Fog color
0x24 	float 		Unknown (almost always 222.222)
0x28 	float 		Unknown (-1 or -0.5)
0x2C 	uint32 		Color 2
struct SMOFog // 03-29-2005 By ObscuR
{
  /*000h*/  UINT32 flags;		
  /*004h*/  float pos[3];		
  /*008h*/ 	
  /*00Ch*/  		
  /*010h*/  float start[3];		
  /*014h*/  		
  /*018h*/ 		
  /*01Ch*/  float end[3];			
  /*020h*/  	
  /*024h*/   	
  /*028h*/  float fogs[2];
  /*02Ch*/  	
  /*030h*/		
}

  • Fog end: This is the distance at which all visibility ceases, and you see no objects or terrain except for the fog color.
  • Fog start: This is where the fog starts. Obtained by multiplying the fog end value by the fog start multiplier.

MCVP chunk

  • Convex Volume Planes. Contains blocks of floating-point numbers.

WMO group file

WMO group files contain the actual polygon soup for a particular section of the entire WMO.

Every group file has one top-level MOGP chunk, that has a 68-byte header followed by more subchunks. So it can be effectively treated as a file with a header at 0x14 and chunks starting at 0x58.

MOGP chunk

Offset	Type		Description
0x00 	uint32 		Group name (offset into MOGN chunk)
0x04 	uint32 		Descriptive group name (offset into MOGN chunk)
0x08 	uint32 		Flags
0x0C 	float[3] 	Bounding box corner 1 (same as in MOGI)
0x18 	float[3] 	Bounding box corner 2
0x24 	uint16 		Index into the MOPR chunk
0x26 	uint16 		Number of items used from the MOPR chunk
0x28 	uint16 		Number of batches A
0x2A 	uint16 		Number of batches B
0x2C 	uint32 		Number of batches C
0x30 	uint8[4] 	Up to four indices into the WMO fog list
0x34 	uint32 		Unknown (always 15)
0x38 	uint32 		WMO group ID (column 4 in WMOAreaTable.dbc)
0x3C 	uint32 		Always 0?
0x40 	uint32 		Always 0?

The fields referenced from the MOPR chunk indicate portals leading out of the WMO group in question.

For the "Number of batches" fields, A + B + C == the total number of batches in the WMO group (in the MOBA chunk). This might be some kind of LOD thing, or just separating the batches into different types/groups...?

Flags: always contain more information than flags in MOGN. I suppose MOGN only deals with topology/culling, while flags here also include rendering info.

Flag		Meaning
0x1 		Always set
0x4 		Has vertex colors (MOCV chunk)
0x8 		Outdoor
0x200 		Has lights (MOLR chunk)
0x800 		Has doodads (MODR chunk)
0x1000 	Has water (MLIQ chunk)
0x2000		Indoor
0x40000	Show skybox

MOPY chunk

  • Material info for triangles, two bytes per triangle. So size of this chunk in bytes is twice the number of triangles in the WMO group.
Offset	Type 	Description
0x00 	uint8 	Flags?
0x01 	uint8 	Material ID
struct SMOPoly // 03-29-2005 By ObscuR ( Maybe not accurate :p )
{
	enum  
	{
		F_NOCAMCOLLIDE,
		F_DETAIL,
 		F_COLLISION,
		F_HINT,
		F_RENDER,
		F_COLLIDE_HIT,
	};
/*000h*/  uint8 flags;
/*001h*/  uint8 lightmapTex; 
/*002h*/  uint8 mtlId;
};

// are you sure it's 3 bytes? wowmapview uses groups of 2 :)  - Z.
// look like the lightmapTex byte is no longer present, this struct come from Alpha :) - Obs

Frequently used flags are 0x20 and 0x40, but I have no idea what they do.

Material ID specifies an index into the material table in the root WMO file's MOMT chunk. Some of the triangles have 0xFF for the material ID, I skip these. (but there might very well be a use for them?)

Triangles stored here are more-or-less pre-sorted by texture, so it's ok to draw them sequentially.

MOVI chunk

  • Vertex indices for triangles. Three 16-bit integers per triangle, that are indices into the vertex list. The numbers specify the 3 vertices for each triangle, their order makes it possible to do backface culling.

MOVT chunk

  • Vertices chunk. 3 floats per vertex, the coordinates are in (X,Z,-Y) order. It's likely that WMOs and models (M2s) were created in a coordinate system with the Z axis pointing up and the Y axis into the screen, whereas in OpenGL, the coordinate system used in WoWmapiew the Z axis points toward the viewer and the Y axis points up. Hence the juggling around with coordinates.

MONR chunk

  • Normals. 3 floats per vertex normal, in (X,Z,-Y) order.

MOTV chunk

  • Texture coordinates, 2 floats per vertex in (X,Y) order. The values range from 0.0 to 1.0. Vertices, normals and texture coordinates are in corresponding order, of course.

MOBA chunk

  • Render batches. Records of 24 bytes.
struct SMOBatch // 03-29-2005 By ObscuR
{
	enum
	{
		F_RENDERED
	};
	?? lightMap;
	?? texture;
	?? bx;
	?? by;
	?? bz;
	?? tx;
	?? ty;
	?? tz;
	?? startIndex;
	?? count;
	?? minIndex;
	?? maxIndex;
	?? flags;
};

For the enUS, enGB versions, it seems to be different from the preceding struct:

Offset	Type 		Description
0x00 	uint32 		Some color?
0x04 	uint32 		Some color?
0x08 	uint32 		Some color?
0x0C 	uint32 		Start index
0x10 	uint16 		Number of indices
0x12 	uint16 		Start vertex
0x14 	uint16 		End vertex
0x16 	uint8 		0?
0x17 	uint8 		Texture

MOLR chunk

  • Light references, one 16-bit integer per light reference.

This is basically a list of lights used in this WMO group, the numbers are indices into the WMO root file's MOLT table.

For some WMO groups there is a large number of lights specified here, more than what a typical video card will handle at once. I wonder how they do lighting properly. Currently, I just turn on the first GL_MAX_LIGHTS and hope for the best. :(

MODR chunk

  • Doodad references, one 16-bit integer per doodad.

The numbers are indices into the doodad instance table (MODD chunk) of the WMO root file. These have to be filtered to the doodad set being used in any given WMO instance.


MOBN chunk

  • Array of t_BSP_NODE.
struct t_BSP_NODE
{	
	short planetype;          // unsure
	short children[2];        // index of bsp child node(right in this array)   
	unsigned short numfaces;  // num of triangle faces
	unsigned short firstface; // index of the first triangle index(in  MOBR)
	short nUnk;	          // 0
	float fDist;    
};
// The numfaces and firstface define a polygon plane.
                                        2005-4-4 by linghuye

MOBR chunk

  • Triangle indices (in MOVI which define triangles) to describe polygon planes defined by MOBN BSP nodes.

MOCV chunk

  • Vertex colors, 4 bytes per vertex (BGRA), for WMO groups using indoor lighting.

I don't know if this is supposed to work together with, or replace, the lights referenced in MOLR. But it sure is the only way for the ground around the goblin smelting pot to turn red in the Deadmines. (but some corridors are, in turn, too dark - how the hell does lighting work anyway, are there lightmaps hidden somewhere?)

- I'm pretty sure WoW does not use lightmaps in it's WMOs...

After further inspection, this is it, actual pre-lit vertex colors for WMOs - vertex lighting is turned off. This is used if flag 0x2000 in the MOGI chunk is on for this group. This pretty much fixes indoor lighting in Ironforge and Undercity. The "light" lights are used only for M2 models (doodads and characters). (The "too dark" corridors seemed like that because I was looking at it in a window - in full screen it looks pretty much the same as in the game) Now THAT's progress!!!


MLIQ chunk

  • Specifies liquids inside WMOs.

This is where the water from Stormwind and BFD etc. is hidden. (slime in Undercity, pool water in the Darnassus temple, some lava in IF)

Chunk header:

Offset	Type 		Description
0x00 	uint32 		number of X vertices (xverts)
0x04 	uint32 		number of Y vertices (yverts)
0x08 	uint32 		number of X tiles (xtiles = xverts-1)
0x0C 	uint32 		number of Y tiles (ytiles = yverts-1)
0x10 	float[3] 	base coordinates?
0x1C 	uint16 		material ID

The liquid data contains the vertex height map (xverts * yverts * 8 bytes) and the tile flags (xtiles * ytiles bytes) as descripbed in ADT files (MCLQ chunk). The length and width of a liquid tile is the same as on the map, that is, 1/8th of the length of a map chunk. (which is in turn 1/16th the length of a map tile).

The material ID often refers to what seems to be a "special" material in the root WMO file (special because it often has a solid color/placeholder texture, or a texture from XTextures\*) - but sometimes the material referenced seems to be not special at all, so I'm not really sure how the liquid material is obtained - such as water/slime/lava.

Retrieved from "http://wowdev.org/wiki/index.php/WMO"