Authors: Read about the new packaged scenery
format and how to optimize scenery.
Authors: Read about how land uses work, what they look like, and what's changed with XP 6.13 and beyond!
Simply implement for yourself the functions that are declared in EnvParser.h but not EnvParser.c; they will be called when you parse a .env file.
The Env Parser itself:
EnvParser.hAll code, including support code and examples...
|Endianness of the file||1 byte||char||'a' or 'i'||Big Endian or Little Endian|
|Version||4 bytes||long int||6, 61, 631 or 650||Native Endian Version|
The header starts with a 1-byte character: lower case 'a' ("Apple") indicates Big Endian, lower case 'i' ("Intel") indicates Little Endian. Except where otherwise noted, all 2-byte and 4-byte integers and 4-byte floating point values will be in the endianness specified in hte header.
The version identifies which format the sections below will be in as well as which layout the file consists of; see the charts above for which sections are included in which file version.
NOTE: previous versions of this spec were wrong; the version is an endian
native 32-bit long int.
Every version of X-Plane 6.xx is backward compatible with previous forms
of the .env file back to the original. This chart indicates what X-Plane
application is required to read a given file version. Each version
of WorldMaker writes the most recent version of the format it knows about.
|File format Version
||Minimum Version of X-plane to read File
||Major Change from Previous Version
||Grid Size Changed to 201x151
||Land Uses, vector roads, etc.
||Vector Rivers/Streams added
X-Plane 7 reads all four version 6 .env formats listed above, but only
writes the 650 file format.
The lower left vertex corresponds to the latitude and longitude the .env file is named after. In the above example, this would be the .env tile for +42 latitude, +71 longitude. Each .env file covers one degree of latitude and longitude, with the latitude of the top vertices and longitude of the right vertices being an even degree multiple.
For custom textures and 6.06 default textures, a quad's texture is specified by the vertex that specifies its lower left corner; the upper and rightmost vertices textures are ignored. For 6.10 default textures (based on land use), the corner of each quad is separately textured by the land use of that vertex. Each vertex thus creates a 1x1 quad textured patch that is centered around the vertex.
Each version 6.06 vertex has the following structure:
|Latitude||4 Bytes||float||The vertices latitude in decimal degrees|
|Longitude||4 Bytes||float||The vertices longitude in decimal degrees|
|Altitude||4 Bytes||float||The vertices altitude in meters above sea level|
|Texture Information||4 Bytes||Integer||Texture Properties (see below)|
The latitude, longitude, and altitude are simply stored as floating point coordinates. The texture information is further encoded as decimal digits with the following interpretation:
|X||A horizontal offset into the texture.|
|Y||A vertical offset into the texture|
|S||A scaling factor to increase the texture's size, 0 = normal, 1 =
double the scale, etc.
6.13 only: for custom textures, this field is the same. For default land use, this is a join code.
|R||Rotation (1 = 90 CCW, 2 = 180 CW, 3 = 90 CW, 4 = None)|
|U||Land Use. 0 = Land, 1 = Water, 2 = City. (6.06 Only!)
0 for 6.10
|C||Custom Texture (1 = yes, 0 = default land use/texture)|
|TTT||The texture number.|
Each texture field contains a texture number between 0 and 999. For custom textures, this is a 1-based index into the custom texture table found at the end of the file. For built-in textures, this is one of the 16 default scenery codes (for 6.06) or a land-use code (for 6.10). The Custom Texture Field contains a flag, 0 or 1 to determine which kind of texture this is.
X-Plane 6.06 featured a flag that specified the "land use" for the vertex; a 1 in this field indicated that the quad to the upper right of the vertex was water. A 2 indicated that dynamic scenery shoud be drawn; this dynamic scenery was always houses except for a few special-case default textures. Since 6.10 features a wide variety of land use in the texture number field this field is not used in 6.10 and should always contain 0. 6.10 will place dynamic scenery based on land use, etc.
The rotation field specifies one of four possible orientations for the texture as specified in the table. Any custom texture may be rotated, but default textures may only be rotated in 6.06.
X-Plane can spread a texture over many quads. This is actually done by only drawing a part of the texture on each quad. To specify this behavior, a scaling factor may be applied. The scaling factor is the number of times to increase the texture's apparent size to the user minus one, e.g. 0 = no scale, 1 = double, 2 = triple, etc. This effectively reduces the amount of texture shown in the specific quad by 1/(scale+1). The X and Y offsets indicate which part of the texture to use since each quad will only show a part of it. An offset of 0 indicates the lower left corner of the texture; positive X is right and positive Y is up. The maximum value for these offsets is the scale value.
Two things should be noted about this scheme that might not be apparent from the use of WorldMaker:
A join code applies to the quad for which it is the lower-left (southwest)
corner. The join code indicates how the corners of this quad will or
won't connect if they have the same land use. The join code should be
0 if the corners are of different land use types.
|Code||Connect lower left to upper right?||Connect lower right to upper left?||Description||Picture|
|0||X-Plan decides||X-Plan decides||This code indicates that X-Plane may decide the joining pattern and is used for backward compatibility.|
|1||Yes||No||This connects one diagonal.|
|2||No||Yes||This connects the other diagonal|
|3||No||No||This keeps both diagonals disconnected.|
Join codes greater than 3 are reserved and should not be used.
The X-Plane 6.06 default texture numbers were as follows:
|0||Grass||4||Commercial||8||3/4 Grass, 1/4 Mountain||12||1/4 Grass, 3/4 Water|
|1||Mountains||5||Industrial||9||1/4 Grass, 3/4 Mountain||13||Half Grass/Residential|
|2||Water||6||Field||10||Half Grass/Water||14||3/4 Grass, 1/4 Residential|
|3||Residential||7||Half Grass/Mountains||11||3/4 Grass, 1/4 Water||15||1/4 Grass, 3/4 Residential|
A 6.10 vertex takese the following form:
|Latitude/Longitude Code||4 Bytes||Integer||An encoded latitude and longitude value.|
|Altitude||2 Bytes||Big Endian signed integer||The altitude also encoded|
|Texture Code||4 Bytes||Integer||Texture properties as described above.|
The latitude and longitude of a vertex in 6.10 are compressed using the following scheme:
The altitude is stored as meters above sea level plus 10000. This number is always big endian; it is the only part of the .env file that is like this.
The texture code for 6.10 is the same as 6.06 except that default texture numbers are land uses and the land use field is ignored.
Each object starts off with an integer type code. This is a 4-byte
signed integer in the platform-native endian format. A value of 99
indicates that this is the end of the obstacle placement section; no other
data for obstacles follows. If the value is anything other than 99,
this value is an object type code. The following fields are then read:
|Latitude||4 Bytes||Float||The latitude of the obstacle.|
|Longitude||4 Bytes||Float||The longitude of the obstacle.|
|Rotation/Heading||4 Bytes||Float||The elevation of the default obstacle in meters or the rotation of the custom obstacle in degrees.|
The following obstacle types are defined:
|Obstacle Kind||Description||Obstacle Kind||Description|
|1||Control Tower||5||Water Tower|
|2||Sky Scraper||6||Smoke Stacks|
|3||Radio Tower||7||Unused (reserved)|
|4||Power Tower||8||Custom Obstacle|
The latitude and longitude of the obstacle are in decimal degrees. The rotation/heading field is the height of the top of the obstacle above ground for the default obstacles. For a custom obstacle, it specifies the number of degrees to rotate the obstacle from its natural orientation.
For custom textures, a 150-character obstacle name follows the heading field. This field is padded with 0s and contains the name of the file (minus the .obj extension) including any partial paths using the system-native directory indicator from the Custom Objects directory. For example the string
MyFunkyTrains\SteamEnginewoudl expand to the full file path
C:\Program Files\X-System 6.10 Folder\Resources\Custom Objects\MyFunkyTrains\SteamEngine.obj
Each path consists of a series of latitude/longitude values encoded into a single integer, the same way 6.10 vertices are encoded. This integer is a 4-byte native endian int. Two special codes must be noted:
Taxiways are only present in the 6.40+ version of the file, noted by a version number of "631" on the file header. Taxiways are different than other paths. Taxiways have the following format:
||Minimum File Version
||Minimum X-Plane Version
The custom texture table simply ends at the end of file; 6.06 files must
contain empty entries (containing "Untitled" plus zero padding) for the
entire maximum size of the file; 6.10 texture tables are variable length
and may end when no textures are available. Unused entries should
contain a zero-padded "Untitled" entry. The maximum size of the texture
table may have been 100 textures in previous X-Plane revisions, but is 500
textures long in 6.10.