This section describes the syntax of UTF-8-encoded, human-readable
VRML files. A more formal description of the syntax may be found in
Appendix A, "Grammar Reference." The
semantics of VRML are presented in this part of ISO/IEC 14772 in terms
of the UTF-8 encoding. Other encodings may be defined in other parts
of ISO/IEC 14772. Such encodings shall describe how to map the UTF-8
descriptions to and from the corresponding encoding elements.
For the UTF-8 encoding, the # character begins a comment. Only the
first comment (the file header) has semantic meaning. Otherwise, all
characters following a # until the next line terminator are ignored.
The only exception is within double-quoted SFString and MFString fields
where the # character is defined to be part of the string.
Commas, spaces, tabs, linefeeds, and carriage-returns are separator
characters wherever they appear outside of string fields. One or more
separator characters separate the syntactical entities in VRML files,
where necessary. The separator characters collectively are termed whitespace.
design note
Commas are treated as whitespace characters to ease the transition
from the VRML 1.0 file format syntax. Equating commas to whitespace
does not hamper parsing and allows both the VRML 1.0 syntax for multiple-valued
fields (which required commas) and the VRML 1.0 syntax for MFNode
child lists (which were a special case in VRML 1.0 and required that
the children be separated by blank/tab/newline).
Comments and separators need not be preserved. In particular, a VRML
document server may strip comments and extra separators from a VRML
file before transmitting it. WorldInfo
nodes should be used for persistent information such as copyrights or
author information.
Note: In the following paragraph, the form "0xhh" expresses
a byte as a hexadecimal number representing the bit configuration for
that byte.
Field, event, PROTO, EXTERNPROTO, and node names shall not contain
control characters (0x0-0x1f, 0x7f), space (0x20), double or single
quotes (0x22: ", 0x27: '), sharp (0x23: #), comma
(0x2c: ,), period (0x2e: .), square brackets (0x5b, 0x5d:
[]), backslash (0x5c: \) or curly braces (0x7b, 0x7d: {}).
Further, their first character must not be a digit (0x30-0x39), plus
(0x2b: +), or minus (0x2d: -) character. Otherwise, names
may contain any ISO 10646 character encoded using UTF-8. VRML is case-sensitive;
"Sphere" is different from "sphere" and "BEGIN"
is different from "begin."
tip
The following reserved keywords shall not be used for field, event,
PROTO, EXTERNPROTO, or node names:
- DEF
- EXTERNPROTO
- FALSE
- IS
- NULL
- PROTO
- ROUTE
- TO
- TRUE
- USE
- eventIn
- eventOut
- exposedField
- field
design note
All of these rules make it easier to write
a parser that reads VRML files using traditional parsing technology
such as YACC and Lex. The public domain VRML 2.0 file format parser
donated by Silicon Graphics is an example of such a parser (see http://vrml.sgi.com).
design note
The VRML 2.0 file syntax grew out of the VRML
1.0 file syntax, which came directly from the Open Inventor ASCII
file format. The original goals for the Open Inventor file format
were simplicity, ease of use, ease of parsing, and small file size.
The VRML 2.0 syntax was changed from the VRML
1.0 syntax in a number of ways based on feedback from VRML 1.0 implementors.
Most of the changes make the format more regular and easier to parse,
sometimes at the expense of making it more difficult to edit VRML
files with a text editor. Deciding where to draw the line between
ease of parsing and ease of text editing was one of the many controversial
issues debated during the VRML 2.0 design process.
At the time of this writing, a binary, compressed
file format for VRML is being defined (http://www.vrml.org/vag/BinaryRFP.html).
After the required header, a VRML file may contain
any combination of the following:
- Any number of PROTO or EXTERNPROTO statements
(see "2.8 Prototype semantics")
- Any number of root children node statements
(see "2.4.1 Root nodes" for a
description of root nodes and "2.6.5 Grouping and children nodes"
for a description of children nodes),
- Any number of USE statements (see "2.6.2 DEF/USE semantics")
- Any number of ROUTE statements (see "2.10.2 Route semantics")
A node statement consists of an optional name
for the node followed by the node's type and then the body of the node.
A node is given a name using the keyword DEF followed by the name of
the node. The node's body is enclosed in matching curly braces ("{ }").
Whitespace shall separate the DEF, name of the node, and node type,
but is not required before or after the curly braces that enclose the
node's body. See "A.3 Nodes"
for details on node grammar rules.
[DEF <name>] <nodeType> { <body> }
A node's body consists of any number of field
statements, IS statements, ROUTE statements, PROTO statements or EXTERNPROTO
statements, in any order.
See "2.3.4 Field statement syntax"
for a description of field statement syntax and "2.7 Field, eventIn, and eventOut semantics"
for a description of field statement semantics. See "2.6 Node semantics" for a description of node
statement semantics.
A field statement consists of the name of the
field followed by the field's value(s). The following ilustrates the
syntax for a single-valued field:
<fieldName> <fieldValue>
The following illustrates the syntax for a multiple-valued
field:
<fieldName> [ <fieldValues> ]
See "A.4 Fields"
for details on field statement grammar rules.
Each node type defines the names and types of
the fields that each node of that type contains. The same field name
may be used by multiple node types. See "Chapter
4, Field and Event Reference" for the definition and syntax
of specific field types.
See "2.7 Field, eventIn,
and eventOut semantics" for a description of field statement
semantics.
A PROTO statement consists of the PROTO keyword,
followed in order by the prototype name, prototype interface declaration,
and prototype definition:
PROTO <name> [ <declaration> ] { <definition> }
See "A.2 General"
for details on prototype statement grammar rules.
design note
The convention used for all nodes defined in
the VRML standard (which should be thought of as PROTO's with built-in
implementation) is that each word in a node type name begins with
a capital letter (e.g., Box, Orientation-Interpolator). Although not
enforced, you are encouraged to follow this convention when defining
your own node types using PROTO.
A prototype interface declaration consists of
eventIn, eventOut, field, and exposedField declarations (see "2.7 Field, eventIn, and eventOut semantics") enclosed in
square brackets. Whitespace is not required before or after the brackets.
EventIn declarations consist of the keyword
"eventIn" followed by an event type and a name:
eventIn <eventType> <name>
EventOut declarations consist of the keyword
"eventOut" followed by an event type and a name:
eventOut <eventType> <name>
Field and exposedField declarations consist
of either the keyword "field" or "exposedField"
followed by a field type, a name, and an initial field value of the
given field type.
field <fieldType> <name> <initial field value>
exposedField <fieldType> <name> <initial field value>
Field, eventIn, eventOut, and exposedField names
must be unique in each PROTO statement, but are not required to be unique
between different PROTO statements. If a PROTO statement contains an
exposedField with a given name (e.g., zzz), it must not
contain eventIns or eventOuts with the prefix set_ or the suffix
_changed and the given name (e.g., set_zzz or zzz_changed).
design note
Allowing nonunique field and event names in
different node types makes it much easier to reuse PROTOs defined
by different people in the same scene and doesn't make parsing VRML
significantly more difficult (because parsers must keep track of the
fields and events that are declared for each PROTO type anyway). Forcing
all field and event types to be unique between all node types would
be very annoying, even just for the nodes defined in the VRML 2.0
standard. For example, all interpolator nodes have set_fraction, key,
keyValue, and value_changed fields/events. Defining slightly different
names for fields that perform the same function would be confusing
and error prone.
A prototype definition consists of at least
one node statement and any number of ROUTE statements, PROTO statements,
and EXTERNPROTO statements in any order.
See "2.8 Prototype semantics"
for a description of prototype semantics.
The body of a node statement that is inside
a prototype definition may contain IS statements. An IS statement consists
of the name of a field, exposedField, eventIn or eventOut from the node's
public interface followed by the keyword IS followed by the name of
a field, exposedField, eventIn or eventOut from the prototype's interface
declaration:
<field/eventName> IS <field/eventName>
See "A.3 Nodes"
for details on prototype node body grammar rules. See "2.8 Prototype semantics" for a description of IS statement
semantics.
An EXTERNPROTO statement consists of the EXTERNPROTO
keyword followed in order by the prototype's name, its interface declaration,
and either one double-quoted string or zero or more double-quoted strings
enclosed in square brackets:
EXTERNPROTO <name> [ <declaration> ] URL or [ URLs ]
See "A.2 General"
for details on external prototype statement grammar rules.
An EXTERNPROTO interface declaration is the
same as a PROTO interface declaration, with the exception that field
and exposedField intitial values are not specified and the prototype
definition is specified in a separate file referred to by the URL(s).
design note
The syntax for EXTERNPROTO was carefully chosen
so that VRML browsers can continue to parse the VRML file without
fetching the EXTERNPROTO's definition. This was done for two reasons:
First, because the Internet is not a reliable network, and broken
or temporarily unavailable links are commonplace, and second, because
it is important that VRML browsers be able to delay loading pieces
of the world that are not yet needed. Interacting with a partially
loaded world while the rest of the world is being sent across the
network is an important usability feature.
VRML browsers need to know the field/event
names and types for a node type before being able to parse node types
that aren't part of the standard. Therefore, you must use a PROTO
or EXTERNPROTO declaration before instantiating any new node type.
Several other file formats deal with the problem
of new types by defining a syntax that allows them to be skipped during
parsing by defining delimiting characters or writing a byte count
as the first part of any type. However, the existence of SFNode/MFNode
fields along with DEF/USE and ROUTE makes it difficult to use such
a scheme with VRML. For example:
UnknownNode {
children [ DEF T Transform { ... } ]
}
Group {
children [ USE T ]
}
If a parser skipped everything inside the new
UnknownNode type, then it would generate a syntax error when it later
encountered the USE T statement in the Group node since the DEF T
statement had been skipped. It would be possible to redesign the node
reference mechanisms completely (by requiring all nodes be predefined
and referred to via a table of contents structure, for example), but
doing so would complicate VRML and make it significantly harder to
use. Besides, declaring all of the events and fields for new node
types is good style and makes it much easier to implement authoring
systems that can deal with new node types.
A USE statement consists of the USE keyword
followed by a node name:
USE <name>
See "A.2 General"
for details on USE statement grammar rules.
A ROUTE statement consists of the ROUTE keyword
followed in order by a node name, a period character, a field name,
the TO keyword, a node name, a period character, and a field name. Whitespace
is allowed but not required before or after the period characters:
ROUTE <name>.<field/eventName> TO <name>.<field/eventName>
See "A.2 General"
for details on ROUTE statement grammar rules.
design note
ROUTE statements are usually put at the end
of the VRML file (or the end of a PROTO definition if you are defining
routes inside a prototype; see Section 2.6, Prototypes), but it is
often convenient to put them in the middle of the file. For example:
DEF T Transform {
translation 1 1 1
ROUTE T.translation_changed TO T.set_center
center 1 1 1
}
Allowing ROUTE statements inside nodes makes
it easier to create VRML files using a text editor and doesn't make
implementing VRML much harder. Implementing parsing of ROUTE statements
is essentially equivalent to implementing USE statements, and since
USE statements can appear inside nodes that have SFNode/MFNode fields
it is not difficult to also implement ROUTE statements inside nodes.
Tools that read and write VRML files are not
required to maintain the position of ROUTE statements in the file.
They will usually either put all ROUTE statements at the end of the
file or will put them in either the source or destination node, depending
on which is written last (since a ROUTE statement must appear after
both the source and destination nodes have been DEF'ed).