Sons of Myrgard
News | Solo Strategy | Multiplayer Strategy | Solo Films
Myth Links | Myth Mapmaking | Site FAQ

Posted by Loshadh on April 12, 1998 at 13:06:51:

Well, I decided to go ahead and put up everything I know
about the mesh tag so far, instead of waiting until this
evening to do so. This is a very long post, and contains
all sorts of useful (useless?) information. I have formatted
it to match reasonably well with the structure syntax for C.

The information below has been a result of a small amount of
compilation from WWW sites (to get a rough idea of how things
are represented), a good deal of fiddling on my part, and some
wild-ass-guesses tossed in along the way. Some of this 
information is not thoroughly tested; your mileage may vary.
If anyone has any additions/subtractions by all means post 
a reply (please please please do not quote this entire post 
in your replies).

Happy mesh-ing,
Loshadh


NOTES FOR THE C IMPARIED:

This information is written so someone with C experience can easily
import it into any coding they wish to perform. I have arranged things
as best I can to allow those with little C knowledge to understand
the information as well. To that end, I am adding this little bit at
the beginning to help clear up what some of these things mean:

In this documentation, each variable has been given a separate line. On
this line will be the variable's type, the variable's name, and then 
some comments. An example is as follows:

short meshHeight; // Number of rows in the mesh [1]

The "short" is the number of bytes assigned to the variable. It also 
says what type of variable it is (in this case, a 16-bit, signed 
integer). The number of bytes allotted are as follows:

short -- 2 bytes, signed integer
long -- 4 bytes, signed integer
uint16 -- 2 bytes, unsigned integer
char -- 1 byte, unsigned integer

There are some other variable types that have been defined by us. They
are the ones that end in "TAG" (such as mediTAG, sounTAG, etc...). 
Treat these as 4 bytes, signed integers.

The "meshHeight" is the name of the variable. Ignore the semicolons
after the variable names... they are a part of C syntax. Sometimes
a variable will have a number enclosed in brackets immediately after
it (as in "unknown[191];"). The number enclosed in the brackets
tells you how many times to repeat that line; in this case, it is
saying that there are 191 repetitions of unknown variables present.
This was done to save space, and because of C array conventions.

Everything that follows the "//" on a line is a comment, describing 
a bit about the variable. If a number appears in brackets [] somewhere
in a comment line, then there are more extensive notes at the end of
the section.

Hope this helps sufficiently. A greater understanding would be obtained
by picking up a beginner's C book and reading it thoroughly.

END NOTES FOR THE C IMPAIRED


The structures for a mesh tag, so far. I have included a block diagram
showing the various parts of the whole file.

Note: The 63fx, 64fx, and 65fx files have an additional 64 bytes tacked
onto the front of them. This is what makes a plugin a plugin. I
have not included this 64 byte header in the information here.


Block diagram for a tag of type "mesh"

+-----------------------------------------------+
| |
| meshHeader |
| (1024 bytes) |
| |
| Handles things like how water will behave, |
| ambient sounds, offsets to various portions |
| of the tag, the size of the various tag |
| portions, etc. |
| |
+-----------------------------------------------+
| |
| gridData |
| (size set in meshHeader) |
| |
| Handles the altitude of each mesh grid |
| point, notes where water is and how it is |
| to be handled, and sets the passability |
| of each point in the mesh grid. Each |
| meshGridData entry is 8 bytes in length. |
| |
+-----------------------------------------------+
| |
| itemTypeData |
| (size set in meshHeader) |
| |
| This section lists all the item types that |
| are found on the level. These include |
| units, sounds, scenery, and other objects |
| (like wight pus packets and such). Each |
| itemTypeData entry is 32 bytes in length. |
| |
+-----------------------------------------------+
| |
| itemListData |
| (size set in meshHeader) |
| |
| This section details the starting location |
| (X, Y, and Z coordinates) and initial facing |
| direction, and assigns a unique item ID |
| number to each item. Each itemListData |
| entry is 64 bytes long. |
| |
+-----------------------------------------------+
| |
| actionListData |<---- I am here
| (size set in meshHeader) |
| |
| This section handles the set of predefined |
| actions that take place during a given |
| level. More data on this as I discover it. |
| |
+-----------------------------------------------+
| |
| Not sure what these next bits do... |
| |
| |


Here is the mesh header

typedef long mediTAG;
typedef long meliTAG;
typedef long sounTAG;
typedef long stliTAG;
typedef long .256TAG;
typedef long partTAG;
typedef long amsoTAG;
typedef long meshTAG;
typedef long windTAG;

struct meshHeader
{
.256TAG 256TagID; // ID code for the .256 tag used for 
// this map. (thanks Thanquol!)
mediTAG waterType1; // ID used to represent water
short meshWidth; // Number of columns in the mesh [1]
short meshHeight; // Number of rows in the mesh [1]
long unknown1; // Usually zeros
long meshLength; // Total length of the height mesh data
long unknown2; // Usually zeros
long meshOffset; // Offset from beginning of tag to the
// start of the height mesh data
long tagLength; // Total length of data from tag start
long unknown3; // Usually zeros
long itemTypeCount; // Number of item types used on map [2]
long itemTypeOffset; // Offset from start of height mesh data
long itemTypeLength; // Total length of the item type data
long unknown4; // Usually zeros
long itemCount; // Number of individual items used
long itemOffset; // Offset from start of height mesh data
long itemLength; // Total length of the item data
long unknown5; // Usually zeros
meliTAG lighting; // Lighting for the level
mediTAG waterType2; // Second ID used to represent water
short flags1; // Single/multiplayer flags [3]
short flags2; // Types of games playable on map [4]
partTAG particleEffect; // Rain and snow
long maxTeams; // Maximum number of teams on map
long unknown6; // Usually zeros
long unknown7; // Usually zeros
long unknown8; // Usually zeros
long unknown9; // Usually zeros
long unknown10; // Usually zeros
long unknown11; // Usually zeros
long unknown12; // Usually zeros
short unknown13; // No idea
short unknown14; // No idea
short unknown15; // No idea
short unknown16; // No idea
amsoTAG ambientSound; // Global ambient sound ID
long actionCount; // Number of scripted actions on level
long actionOffset; // Offset from start of height mesh data
long actionLength; // Total length of the action data
stliTAG nameID; // Name of the map (stli tag reference)
.256TAG postScreen; // Post-level screen ID (.256 tag)
.256TAG preScreen; // Pre-level screen ID (.256 tag)
.256TAG overheadMap; // Overhead map ID (.256 tag)
meshTag nextLevel; // Next level ID (mesh tag)
long unknown17; // No idea
long objectives; // In-level objectives and subtitles
long unknown18; // No idea
long unknown19; // No idea
long narrationText; // Scrolling text seen pre-level
long unknown20; // No idea
long unknown21; // No idea
long unknown22; // No idea
long ?2Offset; // Offset from start of height mesh data
long ?2Length; // Total length of ?2 data
long unknown23; // No idea
long ?3Offset; // Offset from start of height mesh data
long ?3Length; // Total length of ?3 data
long unknown24; // No idea
long unknown25; // Usually zeros
long unknown26; // Usually zeros
long unknown27; // Usually zeros
windTAG windEffects; // Wind effects, usually FFFF
long unknown28; // Usually zeros
long unknown29; // Usually zeros
long unknown30; // Usually zeros
long unknown31; // Usually zeros
long unknown32; // Usually zeros
stliTAG captions; // Captions (stli tag reference)
sounTAG narrationSound; // Narration voice (soun tag reference)
long unknown33[191]; // Spacer zeros?
}; // 1024 bytes

Notes:

[1] These are measured in 'map sections' as well, so the training map 
would be represented as 00 03 00 03 (3x3 map sections). Multiply 
these numbers by 16 to get the number of mesh points in each 
direction (48x48).

[2] Item types apparently include troops, scenery (trees and such), 
miscellaneous objects (pus packets, etc.), and sounds. There may
be others as well.

[3] These appear to be bit flags of some type or another. On single
player maps, these flags are as follows (values in hex):

00 D9 - Training Map
00 11 - Crows Bridge
00 19 - Five Champions and Silvermines
00 1C - A Long Awaited Party
00 1D - (all remaining single player maps)

On multiplayer maps, the flags are as follows:

00 12 - Desert Between Your Ears, If I Had a Trow
00 16 - (all remaining multiplayer maps)

I tried changing this flag from 00 1D to 00 12 (and 00 16) for 
"The Great Devoid". When I tried starting a multiplayer game,
it did not show up on the single player or multiplayer lists.
I believe the 2's bit is the one that controls single or
multiplayer games. When the 2's bit is set, the game is
a multiplayer one (assuming that there is at least one type
of multiplayer game available for play... see [4] for details).

[4] This piece of data contains all the flags pertaining to what types
of multiplayer games are available on a multiplayer map. They are
as follows (values in hex):

00 01 - Body Count
00 02 - Steal the Bacon
00 04 - Last Man on the Hill
00 08 - Scavenger Hunt
00 10 - Flag Rally
00 20 - Capture the Flag
00 40 - Balls on Parade
00 80 - Territories
01 00 - Captures
02 00 - King of the Hill
04 00 - Rugby
08 00 - "None" (not sure if that is "no multiplayer games 
available", or "a multiplayer game named 'none' is 
available".)

To make more than one type of game available on a map, just add the
respective flag values together. Thus, to make every game 
available, including "None", flags2 would have a value of 0F FF.

When I changed flags1 of "The Great Devoid" to 00 16 and also set
flags2 to anything other than 00 00, it showed up in the multiplayer
map section when I ran Myth. :)

The height mesh data consists of an array of entries, each 8 bytes long.
The structure for a single entry in the height mesh is detailed below:

struct gridData
{
short height; // 16 bit height map, signed integer
uint16 gradient; // 16 bit unsigned integer [1] 
char water; // Effects of water (reflections, etc)?
char passability; // Two 4-bit passability flags [2]
char unknown1; // Possibly unused, usually FF
char unknwon2; // Possibly unused, usually FF
}; // 8 bytes


[1] Gradient
This seems to be a simple gradient value, depicting the maximum
amount of elevation change between a given mesh point and the mesh 
points surrounding it. If you take the height map, convert it to 
8 bit grayscale, import it into Photoshop, and then apply a "glowing edges" filter to it, the result looks -very- similar to what you get
when you convert the gradient map to 8 bits and bring it into Photoshop.
I am not sure exactly what this gradient might be used for in Myth,
however. It might help to handle how things bounce when they strike
the mesh surface somehow.


[2] Passability is as follows:

0 Clear 8 Rocky
1 Human depth water 9 Marsh
2 Giant depth water A Snow
3 Deep water B Forest
4 Sloped C ?
5 Steep slope D ?
6 Grass E Walking impassable
7 Desert F Flying impassable

I have recently learned that each mesh "square" is tessalated into two
mesh triangles. The passability byte is split into two 4-bit nibbles.
Each of these nibbles is applied to one of the two mesh triangles in a 
mesh square. Thus we have a slightly finer resolution of passability.
As to how the mesh is tesselated (which diagonal to use per mesh 
"square"), I do not know.


The declaration of item types present on the level.

struct itemTypeData
{
short itemType; // The type of item listed [1]
short flags1; // [2]
long itemID; // The ID tag of the item type
short teamNumber; // Which team the item belongs to [3]
char unknown1[16]; // Usually zeros
short itemMax; // Number of itemType present on level [4]
short itemMax; // Max number of itemType allowed on 
// level (multiplayer) [5]
short itemRef; // Reference number used in following
// section.
}; // 32 bytes


[1] Item Types:

00 00 Camera Objects (?)
00 01 Scenery items (trees, bushes, etc)
00 03 Units
00 05 Ambient Sounds
00 06 Models (big houses, etc)
00 09 Objects affected by physics (proj tags?)
00 0A Special effects (particle generators, etc)


[2] Flags:

00 00 Shows up in unit trading list but is not tradable
00 06 Shows up in unit trading list and is tradable
00 08 Does not show up in unit trading list


[3] Team Number:

This number represents whose team the unit belongs to. On solo 
levels, your units are team 00 00, and the enemy is team 00 01. The
"Seven Gates" level may well have a second enemy team 00 02. On
multiplayer maps, each starting point has a separate team associated 
with it (ranging from 00 00 through 00 04 for "I'll dance on your 
grave", for example).


[4] Number Present:

I am still working on this one. I thought that by modifying this
number, the starting number of units of a given type would change
in multiplayer games. It didn't. I believe that this is what sets
aside memory space for the item list that follows. 


[5] Max Number Allowed:

As with [4], I am still working on this one. I thought that this
would set the maximum number of allowed units of a given type in
a multiplayer game. It didn't. I believe that this is what sets
aside memory space for the item list that follows.

The information for each individual item present on a level. 

struct itemListData
{
short unknown1; // No idea. Often it is all 0's
short initialItem; // Flag whether level starts with item
// present [1]
short itemType; // The type of item listed [2]
short itemRef; // Reference number from itemTypeData
short itemID1; // Unique ID number for this instance
// of the item
short unknown2; // No idea.
long itemPosition[3]; // (X,Y,Z) position on the mesh [3]
char unknown3; // No idea. Usually all 0's
char unknown4; // No idea. Usually all 0's
char unknown5; // No idea. Usually all 0's
char unknown6; // No idea. Usually all 0's
char unknown7; // No idea. Usually all 0's
char unknown8; // No idea. Usually all 0's
char unknown9; // No idea. Usually all 0's
char unknown10; // No idea. Usually all 0's
short facing; // Direction the item is facing [4]
char unknown11[26]; // No idea. Usually all 0's.
short itemID2; // Another unique number for each item
short itemID3; // Yet another unique number [5]
}; // 64 bytes


[1] If this is set to 00 00, the item is present at the beginning of
the level. In multiplayer games, if this is set to 00 01, the item
is not one of the pre-set units you are given... you must trade to
get any unit with a 00 01 flag. I have not delved too deeply into
any other possibilities (there might be a 00 02 or something in 
some of the solo maps). This explains the problems I was having
above with the Number Present and Max Number Allowed values.


[2] Item Type:

00 00 Camera Objects (?)
00 01 Scenery items (trees, bushes, etc)
00 03 Units
00 05 Ambient Sounds
00 06 Models (big houses, etc)
00 09 Objects affected by physics (proj tags?)
00 0A Special effects (particle generators, etc)


[3] The X, Y, and Z positions are integer positions measured in 
1024-ths of a mesh point from the northeast corner of the map. 
Thus, take the number you get in decimal from those positions, and 
divide by 1024 to get the actual mesh point location. The tutorial 
flag on the training map is located at the following coordinates:

X: 00 00 68 3E = 26686 --(convert to mesh points)--> 26.061
Y: 00 00 6B C6 = 27590 --(convert to mesh points)--> 26.943
Z: 00 00 01 FC = 508 --(convert to mesh points)--> 0.496

I checked this method against the three Forest Giant (Ent) locations 
on Forest Heart (location data unceremoniously ripped off of 
Zarquon's "Piri Reis" Markers.jpg image... I'm sneaky that way.)
Image located at http://www.smavid.com/FutureMyth/PiriReis.htm
The first Ent is found at tags.gor offset 13646544, has an 
item_number_ID of 287D = 10365, is located at X:163.857 Y:36.483
Z:-0.199. (It matches -exactly- with what Zarquon's editor 
gives... how's that for some digital magic? *grin*).


[4] I am currently guessing on this, but it looks like this might be
the direction the unit is facing, in 65536-ths of a circle. I do
not know which way 0 degrees is... I'm guessing it's north.


[5] itemID2 and itemID3 always appear to add together to yield 32768 
(80 00). I have no idea why they do this.

END OF MESH INFORMATION (FOR NOW)

[line break]

david@theresistance.net | David Shaw | http://david.theresistance.net/