@c -*-texinfo-*-
@c ----------------------------------------------------------------------------
@c Define typesetting macros for syntax production.
@c
@c    token{} represents a terminal symbol.
@c    nonterm{} represents a non-terminal symbol.
@c    production{} represents a syntactical production.  The first argument is
@c        the non-terminal symbol represented by this production, and the
@c        second argument is its expansion.
@c    prodwrap{} is used for continuation lines when a production does not fit
@c        entirely on a single line of printed output.
@c    prodnext{} is used for alternative expansions of a production which
@c        should appear on a line following the production itself.  The '|' is
@c        automatically inserted.
@c    simpleprod{} represents a production for which no expansion is given.
@c    acomma{} represent the punctuation symbol 'comma'.  It is used when a
@c        comma must appear within the expansion of a production, since one
@c        can not use an actual comma, as it would be interpreted as a macro
@c        delimeter, instead.
@c    ACOMMA{} represents a comma wrapped as a @token{}.
@c    LP{} represents a left parenthesis '(' wrapped as a @token{}.
@c    RP{} represents a right parenthesis ')' wrapped as a @token{}.
@c
@c Eric Sunshine <sunshine@sunshineco.com>                     8 September 2000
@c ----------------------------------------------------------------------------
@ifnotinfo
@macro token{a}
`@code{\a\}'
@end macro

@macro nonterm{a}
@emph{\a\}
@end macro
@end ifnotinfo

@ifinfo
@macro token{a}
`\a\'
@end macro

@macro nonterm{a}
<\a\>
@end macro
@end ifinfo

@macro production{a,b}
@noindent
@nonterm{\a\} @result{} \b\
@end macro

@macro prodwrap{b}
@noindent
@ @ @ @ @ @ @ @ \b\
@end macro

@macro prodnext{b}
@noindent
@prodwrap{| \b\}
@end macro

@macro simpleprod{a}
@noindent
@nonterm{\a\}
@end macro

@macro acomma
,
@end macro

@macro ACOMMA
@token{@acomma{}}
@end macro

@macro LP
@token{(}
@end macro

@macro RP
@token{)}
@end macro

@node Old Map File Format, Binary XML, XML File Format, Map Loader
@subsection Old Format of Map File
@cindex Old Format of Map File
@cindex Old Map File Format

@noindent
@emph{Written by Eric Sunshine, @email{sunshine@@sunshineco.com}.}

@emph{NOTE}: This document is outdated.  Map files now use @sc{xml} format
rather than the format described here.  However, some of the information here
is still useful and has not yet been transformed to the new @sc{xml} format
documentation.  @xref{XML File Format}.

The next couple sections of this document describe the format of the standard
Crystal Space map file.  The first section describes the syntax of the file.
The second section contains extra discussions and hints regarding the map file
and the objects contained within it.

The Crystal Space engine, itself, does not care about the external format of
world data, nor does it care about how that information was obtained.  It is
possible to create additional map loaders as plug-in modules which understand
world data stored in other formats, such as binary.  A map loading plug-in
module could even load maps over the network from a map file server, or
generate worlds randomly based upon some set of input properties.  There are
many possibilities.

The map file syntax described in this section, however, is that which is
understood by the standard map file loader which accompanies Crystal Space.
It deals strictly with plain-text files.

@menu
* Map File Grammar:: Grammar
* Map File Syntax:: Syntax
* Map File Hints:: Hints
@end menu

@node Map File Grammar, Map File Syntax, Old Map File Format, Old Map File Format
@subsubsection Grammar

@noindent
@emph{Written by Eric Sunshine, @email{sunshine@@sunshineco.com}.}

The syntax for the standard Crystal Space map file is specified using a
context-free grammar using a modified @sc{bnf} (@emph{Backus-Naur Form})
notation.

@dfn{Terminal} symbols (also known as @dfn{tokens}) are denoted like this,
@token{VERTEX}.  @dfn{Non-terminal} symbols are denoted in this fashion,
@nonterm{vector}.  Expressions enclosed within `[' and `]' are optional.  When
an expression is followed by the notation `@dots{}', then the expression may
appear zero or more times.  Finally, the symbol '|' appearing between
expressions indicates selection.  Either the expression to the left may be
utilized, or the one to the right, but not both.  An example follows.

@production{flip, @token{HEAD} | @token{TAIL}}@*
@production{wager, @token{WAGER} @nonterm{flip}
    @LP{} @nonterm{money} [ @ACOMMA{} @nonterm{money} @dots{} ] @RP{}}

In this example, a @samp{WAGER} may be followed by either @samp{HEAD} or
@samp{TAIL}, and then by a parenthesized list of monetary values separated by
commas.  At least one monetary value must be specified.  All subsequent values
(including the comma) are optional, as denoted by `[' and `]'.  Here are a
couple of valid expressions which satisfy the @nonterm{wager} production:

@example
WAGER HEAD (44)
WAGER TAIL (5, 39, 2)
@end example

@noindent
And here are a few invalid expressions which do not:

@example
WAGER HEAD (44,)
WAGER TAIL (,23)
WAGER TAIL ()
WAGER EITHER (81, 15)
WAGER (72, 91)
@end example

@node Map File Syntax, Map File Hints, Map File Grammar, Old Map File Format
@subsubsection Syntax

@noindent
@emph{Written by numerous Crystal Space developers.  Extensive Texinfo
typesetting performed by Eric Sunshine, @email{sunshine@@sunshineco.com}.}

@subsubheading Basic Syntax Elements

@simpleprod{number}

A general number.

@simpleprod{pos-number}

A general positive number.

@simpleprod{integer}

A general integer.

@simpleprod{pos-integer}

A positive integer (> 0).

@simpleprod{number..number}

A numeric range. For example, `0..1' represents a number between 0 and 1.

@simpleprod{name}

A name identifier.  An unquoted string provided that it contains no
punctuation or whitespace; otherwise delimited by double quotes.

@simpleprod{string}

A string delimited by double quotes. Special characters are escaped with a
backslash.

@subsubheading Number List
@production{number-list,
    @nonterm{number} [ @ACOMMA{} @nonterm{number} ] @dots{}}

@subsubheading Boolean Value
@production{yes, @token{yes} | @token{true} | @token{on} | @token{1}}@*
@production{no, @token{no} | @token{false} | @token{off} | @token{0}}@*
@production{yes-no, @nonterm{yes} | @nonterm{no}}

@subsubheading Color Description
@production{red, 0..1}@*
@production{green, 0..1}@*
@production{blue, 0..1}@*
@production{gray, 0..1}@*
@production{color-grayscale, @nonterm{gray}}@*
@production{color-general,
    @nonterm{red} @ACOMMA{} @nonterm{green} @ACOMMA{} @nonterm{blue}}@*
@production{color, @nonterm{color-grayscale} | @nonterm{color-general}}

@subsubheading Vectors and Coordinates
@noindent
Note that the x-axis points to the right, the y-axis points up, and the z-axis
points forward.

@production{x, @nonterm{number}}@*
@production{y, @nonterm{number}}@*
@production{z, @nonterm{number}}@*
@production{u, @nonterm{number}}@*
@production{v, @nonterm{number}}@*
@production{vector-2d, @nonterm{x} @ACOMMA{} @nonterm{z}}@*
@production{vector-3d, @nonterm{x} @ACOMMA{} @nonterm{y} @ACOMMA{} @nonterm{z}}@*
@production{vector-4d, @nonterm{x} @ACOMMA{} @nonterm{y} @ACOMMA{}
    @nonterm{z} @ACOMMA{} @nonterm{r} }@*
@production{vertex-idx, @nonterm{integer}}@*
@production{coordinate, @nonterm{vector-3d}}@*
@production{coordinate-2d, @nonterm{vector-2d}}@*
@production{texture-coordinate, @nonterm{u} @ACOMMA{} @nonterm{v}}

@subsubheading Object Names

@production{sector-name, @nonterm{name}}@*
@production{light-name, @nonterm{name}}@*
@production{col-name, @nonterm{name}}@*
@production{texture-name, @nonterm{name}}@*
@production{material-name, @nonterm{name}}@*
@production{mesh-name, @nonterm{name}}@*
@production{meshfact-name, @nonterm{name}}@*
@production{library-name, @nonterm{name}}@*
@production{file-name, @nonterm{name}}@*
@production{plugin-name, @nonterm{name}}@*
@production{plugin-shortname, @nonterm{name}}@*
@production{cache-name, @nonterm{name}}@*
@production{priority-name, @nonterm{name}}

@subsubheading Attributes and Numbers
@production{radius, @nonterm{pos-number}}@*
@production{angle, @nonterm{number}}@*
@production{keyname, @nonterm{string}}@*
@production{keyvalue, @nonterm{string}}

@subsubheading Visibility Culling
Sidenote: the @samp{CULLER} statement is going to be obsolete in the future.

@production{culler, @token{CULLER} @LP{} @nonterm{mesh-name} @RP{}}
@production{cullerp, @token{CULLERP} @LP{} @nonterm{plugin-name} @RP{}}

@subsubheading Key
Use the @samp{KEY} feature to attach arbitrary game data to any Crystal
Space object. Crystal Space will only store these key/value pairs with
objects but doesn't otherwise use them. You can iterate over these
keys in the code.

@production{key,
    @token{KEY} @LP{} @nonterm{keyname} @ACOMMA{} @nonterm{keyvalue} @RP{}}

@subsubheading Fog
@production{density, @nonterm{number}}@*
@production{fog-desc,
    @token{FOG} @LP{} @nonterm{color} @ACOMMA{} @nonterm{density} @RP{}}@*
@production{alpha-nr, @token{0} | @token{25} | @token{50} | @token{75}}@*
@production{alpha, @token{ALPHA} @LP{} @nonterm{alpha-nr} @RP{}}

@subsubheading Matrices, Vectors, Scalers, and Angles
@production{vector, @token{V} @LP{} @nonterm{vector-3d} @RP{}}@*
@production{matrix-scaler, @nonterm{number}}@*
@production{matrix-x-scaler, @nonterm{matrix-scaler}}@*
@production{matrix-y-scaler, @nonterm{matrix-scaler}}@*
@production{matrix-z-scaler, @nonterm{matrix-scaler}}@*
@production{stated-matrix-x-scaler,
    @token{SCALE_X} @LP{} @nonterm{matrix-x-scaler} @RP{}}@*
@production{stated-matrix-y-scaler,
    @token{SCALE_Y} @LP{} @nonterm{matrix-y-scaler} @RP{}}@*
@production{stated-matrix-z-scaler,
    @token{SCALE_Z} @LP{} @nonterm{matrix-z-scaler} @RP{}}@*
@production{complex-matrix-scaler, @nonterm{stated-matrix-x-scaler}}@*
    @prodnext{@nonterm{stated-matrix-y-scaler}}@*
    @prodnext{@nonterm{stated-matrix-z-scaler}}@*
@production{full-matrix-scaler, @nonterm{matrix-x-scaler} @ACOMMA{}
    @nonterm{matrix-y-scaler} @ACOMMA{} @nonterm{matrix-z-scaler}}@*
@production{uniform-matrix-scaler, @nonterm{matrix-scaler}}@*
@production{simple-matrix-scaler, @token{SCALE} @LP{}
    @nonterm{uniform-matrix-scaler} | @nonterm{full-matrix-scaler} @RP{}}@*
@production{compound-matrix-scaler,
    @nonterm{simple-matrix-scaler} | @nonterm{complex-matrix-scaler}}

@production{rotation-x-angle, @nonterm{angle}}@*
@production{rotation-y-angle, @nonterm{angle}}@*
@production{rotation-z-angle, @nonterm{angle}}@*
@production{rotation-x-matrix,
    @token{ROT_X} @LP{} @nonterm{rotation-x-angle} @RP{}}@*
@production{rotation-y-matrix,
    @token{ROT_Y} @LP{} @nonterm{rotation-y-angle} @RP{}}@*
@production{rotation-z-matrix,
    @token{ROT_Z} @LP{} @nonterm{rotation-z-angle} @RP{}}@*
@production{complex-rotation-matrix, @nonterm{rotation-x-matrix} |
    @nonterm{rotation-y-matrix} | @nonterm{rotation-z-matrix}}@*
@production{rotation-angles, @nonterm{rotation-x-angle} @ACOMMA{}
    @nonterm{rotation-y-angle} @ACOMMA{} @nonterm{rotation-z-angle}}@*
@production{simple-rotation-matrix,
    @token{ROT} @LP{} @nonterm{rotation-angles} @RP{}}

@production{rotation-matrix,
    @nonterm{simple-rotation-matrix} | @nonterm{complex-rotation-matrix}}@*
@production{complex-matrix,
    @nonterm{rotation-matrix} | @nonterm{compound-matrix-scaler}}@*
@production{simple-scaled-matrix, @nonterm{uniform-matrix-scaler}}@*
@production{normal-matrix, @nonterm{vector-3d} @ACOMMA{} @nonterm{vector-3d}
    @ACOMMA{} @nonterm{vector-3d}}@*
@production{identity-matrix, @token{IDENTITY}}@*
@production{matrix-type, @nonterm{identity-matrix}}@*
    @prodnext{@nonterm{normal-matrix}}@*
    @prodnext{@nonterm{simple-scaled-matrix}}@*
    @prodnext{@nonterm{complex-matrix}}@*
@production{matrix,
    @token{MATRIX} @LP{} [ @nonterm{matrix-type} @dots{} ] @RP{}}

@production{move-comp, @nonterm{matrix} | @nonterm{vector}}@*
@production{move, @token{MOVE} @LP{} [ @nonterm{move-comp} @dots{} ] @RP{}}@*
@production{hardmove,
    @token{HARDMOVE} @LP{} [ @nonterm{move-comp} @dots{} ] @RP{}}

@subsubheading Lights
It is recommended to use the new syntax for lights.

@production{dynamic-flag, @token{0} | @token{1}}@*
@production{light-oldsyntax, @nonterm{coordinate} @token{:} @nonterm{radius}
    @ACOMMA{} @nonterm{color-general} @ACOMMA{} @nonterm{dynamic-flag}}

@production{light-center, @token{CENTER} @LP{} @nonterm{coordinate} @RP{}}@*
@production{light-radius, @token{RADIUS} @LP{} @nonterm{radius} @RP{}}@*
@production{light-color, @token{COLOR} @LP{} @nonterm{color} @RP{}}@*
@production{light-dynamic, @token{DYNAMIC} @LP{} @RP{}}@*
@production{light-halo, @token{HALO} @LP{} @RP{}}@*
@production{light-comp, @nonterm{light-center}}@*
    @prodnext{@nonterm{light-radius}}@*
    @prodnext{@nonterm{light-dynamic}}@*
    @prodnext{@nonterm{light-color}}@*
    @prodnext{@nonterm{light-halo}}@*
@production{light-newsyntax, [ @nonterm{light-comp} @dots{} ]}

@production{light, @token{LIGHT} @nonterm{light-name}
    @LP{} @nonterm{light-oldsyntax} | @nonterm{light-newsyntax} @RP{}}

@subsubheading Collection Objects
Note that collection objects are NOT hierarchical objects. A collection
object is just one object that represents a group of other objects.

@production{col-mesh, @token{MESH} @LP{} @nonterm{mesh-name} @RP{}}@*
@production{col-collection,
    @token{COLLECTION} @LP{} @nonterm{col-name} @RP{}}@*
@production{col-light, @token{LIGHT} @LP{} @nonterm{light-name} @RP{}}@*
@production{col-sector, @token{SECTOR} @LP{} @nonterm{sector-name} @RP{}}@*
@production{collection-comp, @nonterm{col-collection}}@*
    @prodnext{@nonterm{col-light}}@*
    @prodnext{@nonterm{col-sector}}@*
    @prodnext{@nonterm{col-mesh}}@*
@production{collection, @token{COLLECTION} @nonterm{col-name}
    @LP{} [ @nonterm{collection-comp} @dots{} ] @RP{}}

@subsubheading Materials and Textures
@production{material, @token{MATERIAL} @LP{} @nonterm{material-name} @RP{}}@*
@production{texture, @token{TEXTURE} @LP{} @nonterm{texture-name} @RP{}}@*

@subsubheading Material and Texture Description
@production{transparent, @token{TRANSPARENT} @LP{} @nonterm{color} @RP{}}@*
@production{procedural, @token{PROCEDURAL} @LP{} @RP{}}@*
@production{tex2d, @token{FOR_2D} @LP{} @nonterm{yes-no} @RP{}}@*
@production{tex3d, @token{FOR_3D} @LP{} @nonterm{yes-no} @RP{}}@*
@production{persistent, @token{PERSISTENT} @LP{} @RP{}}@*
@production{filter, @token{FILTER} @LP{} @dots{} @RP{}}@*
@production{mipmap, @token{MIPMAP} @LP{} @nonterm{yes-no} @RP{}}@*
@production{dither, @token{DITHER} @LP{} @nonterm{yes-no} @RP{}}@*
@production{texture-file, @token{FILE} @LP{} @nonterm{file-name} @RP{}}

@production{texture-desc-comp, @nonterm{transparent}}@*
    @prodnext{@nonterm{filter}}@*
    @prodnext{@nonterm{mipmap}}@*
    @prodnext{@nonterm{dither}}@*
    @prodnext{@nonterm{file}}@*
    @prodnext{@nonterm{procedural}}@*
    @prodnext{@nonterm{tex2d}}@*
    @prodnext{@nonterm{tex3d}}@*
    @prodnext{@nonterm{persistent}}@*
@production{texture-desc, @token{TEXTURE} @nonterm{texture-name}
    @LP{} [ @nonterm{texture-desc-comp} @dots{} ] @RP{}}

@production{material-desc-comp, @nonterm{texture}}@*
    @prodnext{@token{COLOR} @LP{} @nonterm{color} @RP{}}@*
    @prodnext{@token{DIFFUSE} @LP{} @nonterm{number} @RP{}}@*
    @prodnext{@token{AMBIENT} @LP{} @nonterm{number} @RP{}}@*
    @prodnext{@token{REFLECTION} @LP{} @nonterm{number} @RP{}}@*
@production{material-desc, @token{MATERIAL} @nonterm{material-name}
    @LP{} [ @nonterm{material-desc-comp} @dots{} ] @RP{}}

@subsubheading LOD
@production{lod-level, @token{LEVEL} @LP{} @nonterm{number} @RP{}}@*
@production{lod-comp, @nonterm{lod-level}}@*
@production{lod, @token{LOD} @LP{} [ @nonterm{lod-comp} @dots{} ] @RP{}}

@subsubheading Mesh Objects
Important note! This documentation explains ONLY the basic mesh object
and factory parsing. It does NOT describe the parsing that is done by
the loader plugin itself. So this means that everything inside the
@samp{PARAMS} blocks is not documented in this document. Documentation
for this will follow later in the mesh object plugin documentation.

@production{plugin, @token{PLUGIN} @LP{} @nonterm{string} @RP{}}@*
@production{params, @token{PARAMS} @LP{} @nonterm{string} @RP{}}
@production{paramsfile, @token{PARAMSFILE} @LP{} @nonterm{file-name} @RP{}}
@production{mesh-nolighting, @token{NOLIGHTING} @LP{} @RP{}}@*
@production{mesh-noshadows, @token{NOSHADOWS} @LP{} @RP{}}@*
@production{mesh-invisible, @token{INVISIBLE} @LP{} @RP{}}@*
@production{mesh-detail, @token{DETAIL} @LP{} @RP{}}@*
@production{mesh-zfill, @token{ZFILL} @LP{} @RP{}}@*
@production{mesh-znone, @token{ZNONE} @LP{} @RP{}}@*
@production{mesh-zuse, @token{ZUSE} @LP{} @RP{}}@*
@production{mesh-ztest, @token{ZTEST} @LP{} @RP{}}@*
@production{mesh-camera, @token{CAMERA} @LP{} @RP{}}@*
@production{mesh-convex, @token{CONVEX} @LP{} @RP{}}@*
@production{mesh-priority, @token{PRIORITY} @LP{} @nonterm{priority-name} @RP{}}@*
@production{mesh-lmcache, @token{LMCACHE} @LP{} @nonterm{cache-name} @RP{}}@*

@production{mesh-comp, @nonterm{plugin}}@*
    @prodnext{@nonterm{addon}}@*
    @prodnext{@nonterm{key}}@*
    @prodnext{@nonterm{params}}@*
    @prodnext{@nonterm{paramsfile}}@*
    @prodnext{@nonterm{mesh}}@*
    @prodnext{@nonterm{move}}@*
    @prodnext{@nonterm{hardmove}}@*
    @prodnext{@nonterm{lod}}@*
    @prodnext{@nonterm{mesh}}@*
    @prodnext{@nonterm{meshref}}@*
    @prodnext{@nonterm{mesh-nolighting}}@*
    @prodnext{@nonterm{mesh-noshadows}}@*
    @prodnext{@nonterm{mesh-invisible}}@*
    @prodnext{@nonterm{mesh-detail}}@*
    @prodnext{@nonterm{mesh-zfill}}@*
    @prodnext{@nonterm{mesh-znone}}@*
    @prodnext{@nonterm{mesh-zuse}}@*
    @prodnext{@nonterm{mesh-ztest}}@*
    @prodnext{@nonterm{mesh-camera}}@*
    @prodnext{@nonterm{mesh-convex}}@*
    @prodnext{@nonterm{mesh-priority}}@*
    @prodnext{@nonterm{mesh-lmcache}}@*
@production{mesh, @token{MESHOBJ} @nonterm{mesh-name}
    @LP{} [ @nonterm{mesh-comp} @dots{} ] @RP{}}@*
@production{meshlib, @token{MESHLIB} @nonterm{mesh-name}
    @LP{} [ @nonterm{mesh-comp} @dots{} @RP{}}

@production{meshref-factory, @token{FACTORY} @LP{} @nonterm{meshfact-name} @RP{}}@*
@production{meshref-comp, @nonterm{meshref-factory}}@*
    @prodnext{@nonterm{addon}}@*
    @prodnext{@nonterm{key}}@*
    @prodnext{@nonterm{move}}@*
    @prodnext{@nonterm{hardmove}}@*
    @prodnext{@nonterm{lod}}@*
    @prodnext{@nonterm{mesh-nolighting}}@*
    @prodnext{@nonterm{mesh-noshadows}}@*
    @prodnext{@nonterm{mesh-invisible}}@*
    @prodnext{@nonterm{mesh-detail}}@*
    @prodnext{@nonterm{mesh-zfill}}@*
    @prodnext{@nonterm{mesh-znone}}@*
    @prodnext{@nonterm{mesh-zuse}}@*
    @prodnext{@nonterm{mesh-ztest}}@*
    @prodnext{@nonterm{mesh-camera}}@*
    @prodnext{@nonterm{mesh-convex}}@*
    @prodnext{@nonterm{mesh-priority}}@*
@production{meshref, @token{MESHREF} @nonterm{mesh-name}
    @LP{} [ @nonterm{meshref-comp} @dots{} ] @RP{}}

@subsubheading Mesh Object Factories
@production{meshfact-file, @token{FILE} @LP{} @nonterm{file-name} @RP{}}@*
@production{meshfact-comp, @nonterm{plugin}}@*
    @prodnext{@nonterm{addon}}@*
    @prodnext{@nonterm{params}}@*
    @prodnext{@nonterm{paramsfile}}@*
    @prodnext{@nonterm{meshfact-file}}@*
    @prodnext{@nonterm{meshfact}}@*
    @prodnext{@nonterm{move}}@*
    @prodnext{@nonterm{hardmove}}@*
    @prodnext{@nonterm{lod}}@*
    @prodnext{@nonterm{material}}@*
@production{meshfact, @token{MESHFACT} @nonterm{meshfact-name}
    @LP{} [ @nonterm{meshfact-comp} @dots{} ] @RP{}}

@subsubheading Nodes
@production{position, @token{POSITION} @LP{} @nonterm{coordinate} @RP{}}@*
@production{node-comp, @nonterm{position} | @nonterm{key}}@*
@production{node, @token{NODE} @LP{} [ @nonterm{node-comp} @dots{} ] @RP{}}

@subsubheading Sectors

@production{sector-comp, @nonterm{addon}}@*
    @prodnext{@nonterm{culler}}@*
    @prodnext{@nonterm{cullerp}}@*
    @prodnext{@nonterm{light}}@*
    @prodnext{@nonterm{mesh}}@*
    @prodnext{@nonterm{meshref}}@*
    @prodnext{@nonterm{meshlib}}@*
    @prodnext{@nonterm{fog-desc}}@*
    @prodnext{@nonterm{key}}@*
    @prodnext{@nonterm{node}}@*
@production{sector, @token{SECTOR} @nonterm{sector-name}
    @LP{} [ @nonterm{sector-comp} @dots{} ] @RP{}}

@subsubheading Texture List
@production{textures-comp, @nonterm{texture-desc}}@*
@production{textures,
    @token{TEXTURES} @LP{} [ @nonterm{textures-comp} @dots{} ] @RP{}}

@subsubheading Material List
@production{materials-comp, @nonterm{material-desc}}@*
@production{materials,
    @token{MATERIALS} @LP{} [ @nonterm{materials-comp} @dots{} ] @RP{}}

@subsubheading Material Groupings
Sometimes you want things of the same type but with different materials on it.
This is where material groupings come in handy.  The final name of a texture
in a @samp{MAT_SET} expression will be `@var{mat-set-name_texture-name}'.  The
materials will be merged into the global texture list.  You should define a
@samp{MAT_SET} after @samp{TEXTURES} since the latter command clears the
internal list first.

@production{mat-set-name, @nonterm{name}}@*
@production{material-set,
    @token{MAT_SET} @nonterm{mat-set-name} @LP{} @nonterm{materials} @RP{}}

@subsubheading Library
@production{library,
    @token{LIBRARY} @nonterm{library-name} @LP{} @nonterm{file-name} @RP{}}

@subsubheading Starting Position
@production{start-sector, @token{SECTOR} @LP{} @nonterm{sector-name} @RP{}}@*
@production{start-position, @token{POSITION} @LP{} @nonterm{coordinate} @RP{}}@*
@production{start-up, @token{UP} @LP{} @nonterm{vector-3d} @RP{}}@*
@production{start-forward, @token{FORWARD} @LP{} @nonterm{vector-3d} @RP{}}@*
@production{start-comp, @nonterm{start-sector}}@*
    @prodnext{@nonterm{start-position}}@*
    @prodnext{@nonterm{start-up}}@*
    @prodnext{@nonterm{start-forward}}@*
@production{start-newsyntax, [ @nonterm{start-comp} @dots{} ]}@*
@production{start-oldsyntax, @nonterm{sector-name} @ACOMMA{}
    @nonterm{coordinate}}@*
@production{start, @token{START}
    @LP{} @nonterm{start-oldsyntax} | @nonterm{start-newsyntax} @RP{}}

@subsubheading For Loader Plug-Ins
@production{plugin-id, @nonterm{plugin-name} | @nonterm{plugin-shortname}}@*
@production{plugin-spec, @token{PLUGIN} @LP{} @nonterm{plugin-id} @RP{}}@*
@production{plugin-params, @token{PARAMS} @LP{} @dots{} @RP{}}@*
@production{plugin-comp, @token{PLUGIN} @nonterm{plugin-shortname}
    @LP{} @nonterm{plugin-name} @RP{}}@*
@production{plugins, @token{PLUGINS} 
    @LP{} [ @nonterm{plugin-comp} @dots{} ] @RP{}}

@subsubheading Add-ons
Same remark as for mesh objects: the stuff that is inside the
@samp{PARAMS} block is not documented here.

@production{addon-comp,
    @nonterm{plugin-spec} | @nonterm{plugin-params}}@*
@production{addon, @token{ADDON} @LP{} [ @nonterm{addon-comp} @dots{} ] @RP{}}

@subsubheading Sounds
@production{sound-file, @token{FILE} @LP{} @nonterm{file-name} @RP{}}@*
@production{sound, @token{SOUND} [ @nonterm{file-name} ]
    @LP{} [ @nonterm{sound-file} ] @RP{}}@*
@production{sounds, @token{SOUNDS} @LP{} [ @nonterm{sound} @dots{} ] @RP{}}

@subsubheading Settings
@production{setting-ambient, @token{AMBIENT} @LP{} @nonterm{color} @RP{}}@*
@production{setting-clearzbuf, @token{CLEARZBUF} @LP{} @nonterm{yes-no} @RP{}}@*
@production{setting-clearscreen, @token{CLEARSCREEN} @LP{} @nonterm{yes-no} @RP{}}@*
@production{setting-lightmapcellsize, @token{LIGHTMAPCELLSIZE} @LP{} @nonterm{pos-integer} @RP{}}@*
@production{setting-maxlightmapsize, @token{MAXLIGHTMAPSIZE} @LP{} @nonterm{pos-integer} @ACOMMA{} @nonterm{pos-integer} @RP{}}@*
@production{settings-comp, @nonterm{setting-ambient}}@*
    @prodnext{@nonterm{setting-clearzbuf}}@*
    @prodnext{@nonterm{setting-clearscreen}}@*
    @prodnext{@nonterm{setting-lightmapcellsize}}@*
    @prodnext{@nonterm{setting-maxlightmapsize}}@*
@production{settings,
    @token{SETTINGS} @LP{} [ @nonterm{settings-comp} @dots{} ] @RP{}}

@subsubheading World
@production{world-comp, @nonterm{textures}}@*
    @prodnext{@nonterm{materials}}@*
    @prodnext{@nonterm{library}}@*
    @prodnext{@nonterm{addon}}@*
    @prodnext{@nonterm{material-set}}@*
    @prodnext{@nonterm{sounds}}@*
    @prodnext{@nonterm{plugins}}@*
    @prodnext{@nonterm{sector}}@*
    @prodnext{@nonterm{meshfact}}@*
    @prodnext{@nonterm{collection}}@*
    @prodnext{@nonterm{start}}@*
    @prodnext{@nonterm{key}}@*
    @prodnext{@nonterm{settings}}@*
@production{world, @token{WORLD} @LP{} [ @nonterm{world-comp} @dots{} ] @RP{}}

@subsubheading Library File
@production{library-comp, @nonterm{textures}}@*
    @prodnext{@nonterm{materials}}@*
    @prodnext{@nonterm{meshfact}}@*
    @prodnext{@nonterm{addon}}@*
    @prodnext{@nonterm{meshobj}}@*
    @prodnext{@nonterm{meshref}}@*
    @prodnext{@nonterm{sounds}}@*
    @prodnext{@nonterm{plugins}}@*
@production{library,
    @token{LIBRARY} @LP{} [ @nonterm{library-comp} @dots{} ] @RP{}}

@node Map File Hints, , Map File Syntax, Old Map File Format
@subsubsection Hints

@noindent
@emph{Written by Jorrit Tyberghein,
@email{jorrit.tyberghein@@gmail.com}.  Mathematical typesetting for
@TeX{} performed by Eric Sunshine, @email{sunshine@@sunshineco.com}.}

This section contains extra discussions and hints regarding the map file and
the objects contained within it (this documentation is a little bit outdated
but still useful for the general idea. However it should be moved to the
thing mesh object description).

First, a little explanation about @samp{LEN} and @samp{TEXLEN}.  With these
you can specify the size of the texture on the polygon.  For example, let's
say that you have a rectangular polygon which is 4 units wide and 6 units
tall.  A texture with @samp{LEN} set to 2 will be tiled 2 times horizontally
and 3 times vertically.  If this texture is 128x128 (for example) then the
final texture on the polygon will be 256x384.

Using a @samp{TEXTURE} statement inside a @samp{POLYGON} or with a
@samp{PLANE} statement you can obtain even more control over how the texture
should be scaled across the polygon.  This is most easily explained with an
example.  Say that you have a polygon like this:

@example
VERTEX (0,2,3) VERTEX (2,2,3) VERTEX (2,0,3) VERTEX (0,0,3)
POLYGON 'poly' (VERTICES (0,1,2,3))
@end example

Let's say that you want to align the texture so that its origin is at (2,2,3).
You can do this as follows:

@example
POLYGON 'poly' (
  VERTICES (0,1,2,3)
  TEXTURE (
    ORIG (2,2,3)
    FIRST (0,2,3)
    SECOND (2,0,3)
    FIRST_LEN (1)
    SECOND_LEN (1)))
@end example

With @samp{ORIG}, @samp{FIRST}, and @samp{SECOND} you specify how the u/v
coordinate system is located.  The origin of u/v is at @samp{ORIG}; the u-axis
is at @samp{FIRST-ORIG}; and the v-axis is at @samp{SECOND-ORIG}.
@samp{FIRST_LEN} and @samp{SECOND_LEN} are similar to @samp{LEN} and
@samp{TEXLEN} except that you can control the u and v scaling separately here.
Note that @samp{ORIG}, @samp{FIRST}, and @samp{SECOND} need not coincide with
vertices of the polygon.  They should just be on the same plane as the
polygon.  That way you can also create slanted textures.

@samp{TEXLEN} in a @samp{THING} or @samp{SECTOR} is the default @samp{LEN} for
all polygons following the @samp{TEXLEN} declaration.  @samp{TEXNR} in a
@samp{THING} or @samp{SECTOR} is the default @samp{TEXNR} for all following
polygons.  @emph{Note, however, that @samp{TEXNR} is considered obsolete and
its use is deprecated.}

Use of planes is recommended.  A @samp{PLANE} provides a way to assign a name
to a texture orientation.  All polygons sharing the same @samp{PLANE} will
have textures that fit perfectly at the borders.  Crystal Space will also be
able to do some optimizations on polygons that share the same plane (like
backface culling an entire set of polygons in one operation).  Note that even
if a @samp{PLANE} is only used by one polygon it does not hurt.  If you do not
specify the @samp{PLANE}, Crystal Space will create one anyway.

Currently Crystal Space assumes that there is a sector called @samp{room}.  It
will use that as a starting place, and will always start at location (0,0,0)
unless you use an @samp{ORIGIN} directive to instruct it otherwise.

Note that Sectors must be convex (unless you add a @sc{bsp} tree).  Things
need not be convex.

Vertices in a @samp{THING} are specified in local object space.  You can
translate this object space to world space with the @samp{MOVE} directive.

When a @samp{THING} or @samp{SPRITE} is defined in the @samp{WORLD} statement
and not in a @samp{SECTOR} or @samp{ROOM} then it defines a template.  This
template can then be used inside a @samp{SECTOR} or @samp{ROOM} by providing
another @samp{THING} or @samp{SPRITE} statement and using the @samp{TEMPLATE}
statement there.  It is also possible to define the @samp{THING} or
@samp{SPRITE} inside a @samp{SECTOR} or @samp{ROOM} directly, but using
templates is preferable.

With @samp{WARP} you provide a matrix which will mirror or warp space.  For
example, when you want to make a mirroring floor the warping matrix should
invert the Y-axis and leave the others intact.  So the @samp{WARP} matrix
would be:

@ifnottex
@example
/ 1  0 0 \
| 0 -1 0 |
\ 0  0 1 /
@end example
@end ifnottex
@tex
$$\pmatrix{
1 &  0 & 0 \cr
0 & -1 & 0 \cr
0 &  0 & 1 \cr
}$$
@end tex

The vector should be a vector on the plane of the mirror.  It is used to
determine exactly where mirroring should start.  For example, if the floor is
at height -1, then (0,-1,0) is a good spot.

@samp{MATRIX (.5)} is a shorthand for:

@ifnottex
@example
/ .5  0  0 \
|  0 .5  0 |
\  0  0 .5 /
@end example
@end ifnottex
@tex
$$\pmatrix{
.5 &  0 &  0 \cr
 0 & .5 &  0 \cr
 0 &  0 & .5 \cr
}$$
@end tex

Portals are unidirectional.  If you need a @samp{PORTAL} that works in two
directions (so that you can go back) then you'll also have to specify a
@samp{PORTAL} in the other sector pointing back.

Note that even though a @samp{PORTAL} does not require a texture (unless it
has alpha transparency) you still need to specify one, since Crystal Space
currently assumes that every polygon has a texture.

The @samp{ROOM} and @samp{SIXFACE} interfaces are good for human editors but
it not suited for computer generated output.  Ignore @samp{ROOM} and
@samp{SIXFACE} if you want to write an editor or converter and concentrate on
@samp{SECTOR} and @samp{THING} instead.

@unmacro nonterm
@unmacro token
@unmacro production
@unmacro simpleprod
@unmacro prodnext
@unmacro acomma
@unmacro ACOMMA
@unmacro LP
@unmacro RP
