16-Dec-95
Gavin Bell , Silicon Graphics, Inc.
Anthony Parisi, Intervista Software
Mark Pesce , VRML List Moderator
Mitra , WorldMaker
YON - Jan C. Hardenbergh , OKI
Tom Meyer , Brown University
Bill Martin , Headspace
Rikk Carey , SGI
Jon Marbry , Microsoft
Brian Blau , Intervista Software
The Virtual Reality Modeling Language (VRML) is a language for describing multi-participant interactive simulations -- virtual worlds networked via the global Internet and hyperlinked with the World Wide Web. All aspects of virtual world display, interaction and internetworking can be specified using VRML. It is the intention of its designers that VRML become the standard language for interactive simulation within the World Wide Web.
The first version of VRML allows for the creation of virtual worlds with limited interactive behavior. These worlds can contain objects which have hyperlinks to other worlds, HTML documents or other valid MIME types. When the user selects an object with a hyperlink, the appropriate MIME viewer is launched. When the user selects a link to a VRML document from within a correctly configured WWW browser, a VRML viewer is launched. Thus VRML viewers are the perfect companion applications to standard WWW browsers for navigating and visualizing the Web. Future versions of VRML will allow for richer behaviors, including animations, motion physics and real-time multi-user interaction.
This document specifies the features and syntax of Version 1.1 of VRML.
The history of the development of the Internet has had three distinct phases; first, the development of the TCP/IP infrastructure which allowed documents and data to be stored in a proximally independent way; that is, Internet provided a layer of abstraction between data sets and the hosts which manipulated them. While this abstraction was useful, it was also confusing; without any clear sense of "what went where", access to Internet was restricted to the class of sysops/net surfers who could maintain internal cognitive maps of the data space.
Next, Tim Berners-Lee's work at CERN, where he developed the hypermedia system known as World Wide Web, added another layer of abstraction to the existing structure. This abstraction provided an "addressing" scheme, a unique identifier (the Universal Resource Locator), which could tell anyone "where to go and how to get there" for any piece of data within the Web. While useful, it lacked dimensionality; there's no there there within the web, and the only type of navigation permissible (other than surfing) is by direct reference. In other words, I can only tell you how to get to the VRML Forum home page by saying, "http://www.wired.com/", which is not human-centered data. In fact, I need to make an effort to remember it at all. So, while the World Wide Web provides a retrieval mechanism to complement the existing storage mechanism, it leaves a lot to be desired, particularly for human beings.
Finally, we move to "perceptualized" Internetworks, where the data has been sensualized, that is, rendered sensually. If something is represented sensually, it is possible to make sense of it. VRML is an attempt (how successful, only time and effort will tell) to place humans at the center of the Internet, ordering its universe to our whims. In order to do that, the most important single element is a standard that defines the particularities of perception. Virtual Reality Modeling Language is that standard, designed to be a universal description language for multi-participant simulations.
These three phases, storage, retrieval, and perceptualization are analogous to the human process of consciousness, as expressed in terms of semantics and cognitive science. Events occur and are recorded (memory); inferences are drawn from memory (associations), and from sets of related events, maps of the universe are created (cognitive perception). What is important to remember is that the map is not the territory, and we should avoid becoming trapped in any single representation or world-view. Although we need to design to avoid disorientation, we should always push the envelope in the kinds of experience we can bring into manifestation!
This document is the living proof of the success of a process that was committed to being open and flexible, responsive to the needs of a growing Web community. Rather than re-invent the wheel, we have adapted an existing specification (Open Inventor) as the basis from which our own work can grow, saving years of design work and perhaps many mistakes. Now our real work can begin; that of rendering our noospheric space.
VRML was conceived in the spring of 1994 at the first annual World Wide Web Conference in Geneva, Switzerland. Tim Berners-Lee and Dave Raggett organized a Birds-of-a-Feather (BOF) session to discuss Virtual Reality interfaces to the World Wide Web. Several BOF attendees described projects already underway to build three dimensional graphical visualization tools which interoperate with the Web. Attendees agreed on the need for these tools to have a common language for specifying 3D scene description and WWW hyperlinks -- an analog of HTML for virtual reality. The term Virtual Reality Markup Language (VRML) was coined, and the group resolved to begin specification work after the conference. The word 'Markup' was later changed to 'Modeling' to reflect the graphical nature of VRML.
Shortly after the Geneva BOF session, the www-vrml mailing list was created to discuss the development of a specification for the first version of VRML. The response to the list invitation was overwhelming: within a week, there were over a thousand members. After an initial settling-in period, list moderator Mark Pesce of Labyrinth Group announced his intention to have a draft version of the specification ready by the WWW Fall 1994 conference, a mere five months away. There was general agreement on the list that, while this schedule was aggressive, it was achievable provided that the requirements for the first version were not too ambitious and that VRML could be adapted from an existing solution. The list quickly agreed upon a set of requirements for the first version, and began a search for technologies which could be adapted to fit the needs of VRML.
The search for existing technologies turned up a several worthwhile candidates. After much deliberation the list came to a consensus: the Open Inventor ASCII File Format from Silicon Graphics, Inc. The Inventor File Format supports complete descriptions of 3D scenes with polygonally rendered objects, lighting, materials, ambient properties and realism effects. A subset of the Inventor File Format, with extensions to support networking, forms the basis of VRML. Gavin Bell of Silicon Graphics has adapted the Inventor File Format for VRML, with design input from the mailing list. SGI has publicly stated that the file format is available for use in the open market, and have contributed a file format parser into the public domain to bootstrap VRML viewer development.
TODO: Gavin - History of clarifications etc to be added
VRML 1.0 is designed to meet the following requirements:
As with HTML, the above are absolute requirements for a network language standard; they should need little explanation here.
Early on the designers decided that VRML would not be an extension to HTML. HTML is designed for text, not graphics. Also, VRML requires even more finely tuned network optimizations than HTML; it is expected that a typical VRML scene will be composed of many more "inline" objects and served up by many more servers than a typical HTML document. Moreover, HTML is an accepted standard, with existing implementations that depend on it. To impede the HTML design process with VRML issues and constrain the VRML design process with HTML compatibility concerns would be to do both languages a disservice. As a network language, VRML will succeed or fail independent of HTML.
It was also decided that, except for the hyperlinking feature, the first version of VRML would not support interactive behaviors. This was a practical decision intended to streamline design and implementation. Design of a language for describing interactive behaviors is a big job, especially when the language needs to express behaviors of objects communicating on a network. Such languages do exist; if we had chosen one of them, we would have risked getting into a "language war." People don't get excited about the syntax of a language for describing polygonal objects; people get very excited about the syntax of real languages for writing programs. Religious wars can extend the design process by months or years. In addition, networked inter-object operation requires brokering services such as those provided by CORBA or OLE, services which don't exist yet within WWW; we would have had to invent them. Finally, by keeping behaviors out of Version 1, we have made it a much smaller task to implement a viewer. We acknowledge that support for arbitrary interactive behaviors is critical to the long-term success of VRML; they will be included in Version 2.
The language specification is divided into the following sections:
At the highest level of abstraction, VRML is just a way for objects to read and write themselves. Theoretically, the objects can contain anything -- 3D geometry, MIDI data, JPEG images, anything. VRML defines a set of objects useful for doing 3D graphics. These objects are called Nodes.
Nodes are arranged in hierarchical structures called scene graphs. Scene graphs are more than just a collection of nodes; the scene graph defines an ordering for the nodes. The scene graph has a notion of state -- nodes earlier in the scene can affect nodes that appear later in the scene. For example, a Rotation or Material node will affect the nodes after it in the scene. A mechanism is defined to limit the effects of properties ( separator nodes), allowing parts of the scene graph to be functionally isolated from other parts.
Applications that interpret VRML files need not maintain the scene graph structure internally; the scene graph is merely a convenient way of describing objects.
A node has the following characteristics:
The syntax chosen to represent these pieces of information is straightforward:
DEF objectname objecttype { fields children }
Only the object type and curly braces are required; nodes may or may not have a name, fields, and children.
Node names must not begin with a digit, and must not contain spaces or control characters, single or double quote characters, backslashes, curly braces, the plus character or the period character.
For example, this file contains a simple scene defining a view of a red cone and a blue sphere, lit by a directional light:
#VRML V1.1 utf8 Separator { DirectionalLight { direction 0 0 -1 # Light shining from viewer into scene } PerspectiveCamera { position -8.6 2.1 5.6 orientation -0.1352 -0.9831 -0.1233 1.1417 focalDistance 10.84 } Separator { # The red sphere Material { diffuseColor 1 0 0 # Red } Translation { translation 3 0 1 } Sphere { radius 2.3 } } Separator { # The blue cube Material { diffuseColor 0 0 1 # Blue } Transform { translation -2.4 .2 1 rotation 0 1 1 .9 } Cube {} } }
For easy identification of VRML files, every VRML 1.1 file must begin with the characters:
#VRML V1.1 utf8
The identifier utf8 allows for international characters to by displayed in VRML using the UTF-8 encoding of the ISO 10646 standard. Unicode is an alternate encoding of ISO 10646. UTF-8 is explained under the Text node.
Any characters after these on the same line are ignored. The line is terminated by either the ASCII newline or carriage-return characters.
The '#' character begins a comment; all characters until the next newline or carriage return are ignored. The only exception to this is within double-quoted SFString and MFString fields, where the '#' character will be part of the string.
Note: Comments and whitespace may not be preserved; in particular, a VRML document server may strip comments and extraneous whitespace from a VRML file before transmitting it. Info nodes should be used for persistent information like copyrights or author information. Info nodes could also be used for object descriptions. New uses of named info nodes for conveying syntactically meaningfull information are deprecated. Use the extension nodes mechanism instead.
Blanks, tabs, newlines and carriage returns are whitespace characters wherever they appear outside of string fields. One or more whitespace characters separates the syntactical entities in VRML files, where necessary.
After the required header, a VRML file contains exactly one VRML node. That node may of course be a group node, containing any number of other nodes.
Field names start with lower case letters, Node types start with upper case. The remainder of the characters may be any printable ascii (21H-7EH) except curly braces {}, square brackets [], single ' or double " quotes, sharp #, backslash \\ plus +, period . or ampersand &.
Node names must not begin with a digit but they may begin and contain any UTF8 character except those below 21H (control characters and white space), and the characters {} [] ' " # \\ + . and &.
VRML is case-sensitive; 'Sphere' is different from 'sphere'.
VRML uses a cartesian, right-handed, 3-dimensional coordinate system. By default, objects are projected onto a 2-dimensional device by projecting them in the direction of the positive Z axis, with the positive X axis to the right and the positive Y axis up. A camera or modeling transformation may be used to alter this default projection.
The standard unit for lengths and distances specified is meters. The standard unit for angles is radians.
VRML scenes may contain an arbitrary number of local (or "object-space") coordinate systems, defined by modelling transformations using Translate, Rotate, Scale, Transform, and MatrixTransform nodes. Given a vertex V and a series of transformations such as:
Translation { translation T } Rotation { rotation R } Scale { scaleFactor S } Coordinate3 { point V } PointSet { numPoints 1 }
the vertex is transformed into world-space to get V' by applying the transformations in the following order:
V' = T·R·S· V (if you think of vertices as column vectors) OR V' = V·S·R·T (if you think of vertices as row vectors)
Conceptually, VRML also has a "world" coordinate system as well as a viewing or "Camera" coordinate system. The various local coordinate transformations map objects into the world coordinate system. This is where the scene is assembled. The scene is then viewed through a camera, introducing another conceptual coordinate system. Nothing in VRML is specified using these coordinates. They are rarely found in optimized implementations where all of the steps are concatenated. However, having a clear model of the object, world and camera spaces will help authors.
There are two general classes of fields; fields that contain a single value (where a value may be a single number, a vector, or even an image), and fields that contain multiple values. Single-valued fields all have names that begin with "SF", multiple-valued fields have names that begin with "MF". Each field type defines the format for the values it writes.
Multiple-valued fields are written as a series of values separated by commas, all enclosed in square brackets. If the field has zero values then only the square brackets ("[]") are written. The last may optionally be followed by a comma. If the field has exactly one value, the brackets may be omitted and just the value written. For example, all of the following are valid for a multiple-valued field containing the single integer value 1:
1 [1,] [ 1 ]
TODO: SYNTAX/RULES FOR INPUTS/OUTPUTS NEED TO BE FLESHED OUT HERE!
A single-value field that contains a mask of bit flags. Nodes that use this field class define mnemonic names for the bit flags. SFBitMasks are written to file as one or more mnemonic enumerated type names, in this format:
( flag1 | flag2 | ... )
If only one flag is used in a mask, the parentheses are optional. These names differ among uses of this field in various node classes.
A field containing a single boolean (true or false) value. SFBools may be written as 0 (representing FALSE), 1, TRUE, or FALSE.
Fields containing one (SFColor) or zero or more (MFColor) RGB colors. Each color is written to file as an RGB triple of floating point numbers in ANSI C floating point format, in the range 0.0 to 1.0. For example:
[ 1.0 0. 0.0, 0 1 0, 0 0 1 ]
is an MFColor field containing the three colors red, green, and blue.
A single-value field that contains an enumerated type value. Nodes that use this field class define mnemonic names for the values. SFEnums are written to file as a mnemonic enumerated type name. The name differs among uses of this field in various node classes.
Fields that contain one (SFFloat) or zero or more (MFFloat) single-precision floating point number. SFFloats are written to file in ANSI C floating point format. For example:
[ 3.1415926, 12.5e-3, .0001 ]
is an MFFloat field containing three values.
A field that contain an uncompressed 2-dimensional color or greyscale image.
SFImages are written to file as three integers representing the width, height and number of components in the image, followed by width*height hexadecimal values representing the pixels in the image, separated by whitespace. A one-component image will have one-byte hexadecimal values representing the intensity of the image. For example, 0xFF is full intensity, 0x00 is no intensity. A two-component image puts the intensity in the first (high) byte and the transparency in the second (low) byte. Pixels in a three-component image have the red component in the first (high) byte, followed by the green and blue components (so 0xFF0000 is red). Four-component images put the transparency byte after red/green/blue (so 0x0000FF80 is semi-transparent blue). A value of 1.0 is completely transparent, 0.0 is completely opaque. Note: each pixel is actually read as a single unsigned number, so a 3-component pixel with value "0x0000FF" can also be written as "0xFF" or "255" (decimal). Pixels are specified from left to right, bottom to top. The first hexadecimal value is the lower left pixel of the image, and the last value is the upper right pixel.
For example,
1 2 1 0xFF 0x00
is a 1 pixel wide by 2 pixel high greyscale image, with the bottom pixel white and the top pixel black. And:
2 4 3 0xFF0000 0xFF00 0 0 0 0 0xFFFFFF 0xFFFF00
is a 2 pixel wide by 4 pixel high RGB image, with the bottom left pixel red, the bottom right pixel green, the two middle rows of pixels black, the top left pixel white, and the top right pixel yellow.
Fields containing one (SFLong) or zero or more (MFLong) 32-bit integers. SFLongs are written to file as an integer in decimal, hexadecimal (beginning with '0x') or octal (beginning with '0') format. For example:
[ 17, -0xE20, -518820 ]
is an MFLong field containing three values.
A field containing a transformation matrix. SFMatrices are written to file in row-major order as 16 floating point numbers separated by whitespace. For example, a matrix expressing a translation of 7.3 units along the X axis is written as:
1 0 0 0 0 1 0 0 0 0 1 0 7.3 0 0 1
... syntax is just node syntax, DEF/USE allowed, etc...
A field containing an arbitrary rotation. SFRotations are written to file as four floating point values separated by whitespace. The 4 values represent an axis of rotation followed by the amount of right-handed rotation about that axis, in radians. For example, a 180 degree rotation about the Y axis is:
0 1 0 3.14159265
Fields containing one (SFString) or zero or more (MFString) UTF-8 string (sequence of characters). Strings are written to file as a sequence of UTF-8 octets in double quotes (optional if the string doesn't contain any whitespace). Any characters (including newlines and '#') may appear within the quotes. To include a double quote character within the string, precede it with a backslash. For example:
Testing "One, Two, Three" "He said, \"Immel did it!\""
are all valid strings.
Field containing a two-dimensional vector. SFVec2fs are written to file as a pair of floating point values separated by whitespace.
Field containing a three-dimensional vector. SFVec3fs are written to file as three floating point values separated by whitespace.
Field containing a single time value. Each time value is written to file as a double-precision floating point number in ANSI C floating point format. A absolute SFTime is the number of seconds since Jan 1, 1970 GM
TODO: TBD
VRML defines several different classes of nodes. Most of the nodes can be classified into one of three categories; shape, property or group. Shape nodes define the geometry in the scene. Conceptually, they are the only nodes that draw anything. Property nodes affect the way shapes are drawn. And grouping nodes gather other nodes together, allowing collections of nodes to be treated as a single object. Some group nodes also control whether or not their children are drawn.
Nodes may contain zero or more fields. Each node type defines the type, name, and default value for each of its fields. The default value for the field is used if a value for the field is not specified in the VRML file. The order in which the fields of a node are read is not important; for example, "Cube { width 2 height 4 depth 6 }" and "Cube { height 4 depth 6 width 2 }" are equivalent.
Here are the nodes grouped by type. The first group are the shape nodes. These specify geometry:
Cone, Cube, Cylinder, ElevationGrid, IndexedFaceSet, IndexedLineSet, PointSet, Text, Sphere
The second group are the properties. These can be further grouped into properties of the geometry and its appearance, matrix or transform properties, and cameras and lights: CollideStyle, Coordinate3, DocumentInfo, FontStyle, Info, LOD, Material, MaterialBinding, NavigationInfo, Normal, NormalBinding, TextLanguage, Texture2, Texture2Transform, TextureCoordinate2, ShapeHints
MatrixTransform, Rotation, Scale, Transform, Translation
DirectionalLight, PointLight, SpotLight
These are the group nodes:
Finally, the camera, WWWInline and Background nodes do not fit neatly into any category:
OrthographicCamera, PerspectiveCamera
This node represents a simple cone whose central axis is aligned with the y-axis. By default, the cone is centered at (0,0,0) and has a size of -1 to +1 in all three directions. The cone has a radius of 1 at the bottom and a height of 2, with its apex at 1 and its bottom at -1. The cone has two parts: the sides and the bottom.
The cone is transformed by the current cumulative transformation and is drawn with the current texture and material.
If the current material binding is PER_PART or PER_PART_INDEXED, the first current material is used for the sides of the cone, and the second is used for the bottom. Otherwise, the first material is used for the entire cone.
When a texture is applied to a cone, it is applied differently to the sides and bottom. On the sides, the texture wraps counterclockwise (from above) starting at the back of the cone. The texture has a vertical seam at the back, intersecting the yz-plane. For the bottom, a circle is cut out of the texture square and applied to the cone's base circle. The texture appears right side up when the top of the cone is rotated towards the -Z axis.
PARTS SIDES The conical part BOTTOM The bottom circular face ALL All parts FILE FORMAT/DEFAULTS Cone { parts ALL # SFBitMask bottomRadius 1 # SFFloat height 2 # SFFloat }
This node defines a set of 3D coordinates to be used by a subsequent IndexedFaceSet, IndexedLineSet, or PointSet node. This node does not produce a visible result during rendering; it simply replaces the current coordinates in the rendering state for subsequent nodes to use.
FILE FORMAT/DEFAULTS Coordinate3 { point 0 0 0 # input MFVec3f }
This node represents a cuboid aligned with the coordinate axes. By default, the cube is centered at (0,0,0) and measures 2 units in each dimension, from -1 to +1. The cube is transformed by the current cumulative transformation and is drawn with the current material and texture. A cube's width is its extent along its object-space X axis, its height is its extent along the object-space Y axis, and its depth is its extent along its object-space Z axis.
If the current material binding is PER_PART, PER_PART_INDEXED, PER_FACE, or PER_FACE_INDEXED, materials will be bound to the faces of the cube in this order: front (+Z), back (-Z), left (-X), right (+X), top (+Y), and bottom (-Y).
Textures are applied individually to each face of the cube; the entire texture goes on each face. On the front, back, right, and left sides of the cube, the texture is applied right side up. On the top, the texture appears right side up when the top of the cube is tilted toward the camera. On the bottom, the texture appears right side up when the top of the cube is tilted towards the -Z axis.
FILE FORMAT/DEFAULTS Cube { width 2 # SFFloat height 2 # SFFloat depth 2 # SFFloat }
This node represents a simple capped cylinder centered around the y-axis. By default, the cylinder is centered at (0,0,0) and has a default size of -1 to +1 in all three dimensions. The cylinder has three parts: the sides, the top (y = +1) and the bottom (y = -1). You can use the radius and height fields to create a cylinder with a different size.
The cylinder is transformed by the current cumulative transformation and is drawn with the current material and texture.
If the current material binding is PER_PART or PER_PART_INDEXED, the first current material is used for the sides of the cylinder, the second is used for the top, and the third is used for the bottom. Otherwise, the first material is used for the entire cylinder.
When a texture is applied to a cylinder, it is applied differently to the sides, top, and bottom. On the sides, the texture wraps counterclockwise (from above) starting at the back of the cylinder. The texture has a vertical seam at the back, intersecting the yz-plane. For the top and bottom, a circle is cut out of the texture square and applied to the top or bottom circle. The top texture appears right side up when the top of the cylinder is tilted toward the +Z axis, and the bottom texture appears right side up when the top of the cylinder is tilted toward the -Z axis.
PARTS SIDES The cylindrical part TOP The top circular face BOTTOM The bottom circular face ALL All parts FILE FORMAT/DEFAULTS Cylinder { parts ALL # SFBitMask radius 1 # SFFloat height 2 # SFFloat }
This node defines a directional light source that illuminates along rays parallel to a given 3-dimensional vector.
A light node defines an illumination source that may affect subsequent shapes in the scene graph, depending on the current lighting style. Light sources are affected by the current transformation. A light node under a separator does not affect any objects outside that separator.
FILE FORMAT/DEFAULTS DirectionalLight { on TRUE # SFBool intensity 1 # SFFloat color 1 1 1 # SFColor direction 0 0 -1 # SFVec3f }
This node defines the current font style used for all subsequent AsciiText. Font attributes only are defined. It is up to the browser to assign specific fonts to the various attribute combinations. The size field specifies the height (in object space units) of glyphs rendered and determines the vertical spacing of adjacent lines of text.
FAMILY
SERIF Serif style (such as TimesRoman) SANS Sans Serif Style (such as Helvetica) TYPEWRITER Fixed pitch style (such as Courier) STYLE NONE No modifications to family BOLD Embolden family ITALIC Italicize or Slant family FILE FORMAT/DEFAULTS FontStyle { size 10 # SFFloat family SERIF # SFEnum style NONE # SFBitMask }
This node represents a 3D shape formed by constructing faces (polygons) from vertices located at the current coordinates. IndexedFaceSet uses the indices in its coordIndex field to specify the polygonal faces. An index of -1 indicates that the current face has ended and the next one begins.
The vertices of the faces are transformed by the current transformation matrix.
Treatment of the current material and normal binding is as follows: The PER_PART and PER_FACE bindings specify a material or normal for each face. PER_VERTEX specifies a material or normal for each vertex. The corresponding _INDEXED bindings are the same, but use the materialIndex or normalIndex indices. The DEFAULT material binding is equal to OVERALL. The DEFAULT normal binding is equal to PER_VERTEX_INDEXED; if insufficient normals exist in the state, vertex normals will be generated automatically.
Explicit texture coordinates (as defined by TextureCoordinate2) may be bound to vertices of an indexed shape by using the indices in the textureCoordIndex field. As with all vertex-based shapes, if there is a current texture but no texture coordinates are specified, a default texture coordinate mapping is calculated using the bounding box of the shape. The longest dimension of the bounding box defines the S coordinates, and the next longest defines the T coordinates. The value of the S coordinate ranges from 0 to 1, from one end of the bounding box to the other. The T coordinate ranges between 0 and the ratio of the second greatest dimension of the bounding box to the greatest dimension.
Be sure that the indices contained in the coordIndex, materialIndex, normalIndex, and textureCoordIndex fields are valid with respect to the current state, or errors will occur.
FILE FORMAT/DEFAULTS IndexedFaceSet { coordIndex 0 # MFLong materialIndex -1 # MFLong normalIndex -1 # MFLong textureCoordIndex -1 # MFLong }
This node represents a 3D shape formed by constructing polylines from vertices located at the current coordinates. IndexedLineSet uses the indices in its coordIndex field to specify the polylines. An index of -1 indicates that the current polyline has ended and the next one begins.
The coordinates of the line set are transformed by the current cumulative transformation.
Treatment of the current material and normal binding is as follows: The PER_PART binding specifies a material or normal for each segment of the line. The PER_FACE binding specifies a material or normal for each polyline. PER_VERTEX specifies a material or normal for each vertex. The corresponding _INDEXED bindings are the same, but use the materialIndex or normalIndex indices. The DEFAULT material binding is equal to OVERALL. The DEFAULT normal binding is equal to PER_VERTEX_INDEXED; if insufficient normals exist in the state, the lines will be drawn unlit. The same rules for texture coordinate generation as IndexedFaceSet are used.
FILE FORMAT/DEFAULTS IndexedLineSet { coordIndex 0 # MFLong materialIndex -1 # MFLong normalIndex -1 # MFLong textureCoordIndex -1 # MFLong }
This class defines an information node in the scene graph. This node has no effect during traversal. It is used to store information in the scene graph, typically for browser-specific purposes, copyright messages, or other strings.
Info { string "<Undefined info>" # SFString }
This node is used to allow browsers to switch between various representations of objects automatically. The children of this node typically represent the same object or objects at varying levels of detail, from highest detail to lowest. LOD acts as a Separator, not allowing properties underneath it to affect nodes that come after it in the scene.
The distance from the viewpoint (transformed into the local coordinate space of the LOD node) to the specified center point of the LOD is calculated. If the distance is less than the first value in the ranges array, then the first child of the LOD is drawn. If between the first and second values in the ranges array, the second child is drawn, etc. If there are N values in the ranges array, the LOD group should have N+1 children. Specifying too few children will result in the last child being used repeatedly for the lowest levels of detail; if too many children are specified, the extra children will be ignored. Each value in the ranges array should be less than the previous value, otherwise results are undefined. Not specifying any values in the ranges array (the default) is a special case that indicates that the browser may decide which child to draw to optimize rendering performance.
Authors should set LOD ranges so that the transitions from one level of detail to the next are barely noticeable. Browsers may adjust which level of detail is displayed to maintain interactive frame rates, to display an already-fetched level of detail while a higher level of detail (contained in a WWWInline node) is fetched, or might disregard the author-specified ranges for any other implementation-dependent reason. Authors should not use LOD nodes to emulate simple behaviors, because the results will be undefined. For example, using an LOD node to make a door appear to open when the user approaches probably will not work in all browsers.
For best results, specify ranges only where necessary, and nest LOD nodes with and without ranges. For example:
LOD { range [100, 1000] LOD { Separator { ... detailed version... } DEF LoRes Separator { ... less detailed version... } } USE LoRes Info { } # Display nothing }
In this example, nothing at all will be displayed if the viewer is farther than 1,000 meters away from the object. A low-resolution version of the object will be displayed if the viewer is between 100 and 1,000 meters away, and either a low-resolution or a high-resolution version of the object will be displayed when the viewer is closer than 100 meters from the object.
FILE FORMAT/DEFAULTS LOD { range [ ] # MFFloat center 0 0 0 # SFVec3f }
This node defines the current surface material properties for all subsequent shapes. Material sets several components of the current material during traversal. Different shapes interpret materials with multiple values differently. To bind materials to shapes, use a MaterialBinding node.
The lighting parameters defined by the Material node are the same parameters defined by the OpenGL lighting model. For a rigorous mathematical description of how these parameters should be used to determine how surfaces are lit, see the description of lighting operations in the OpenGL Specification. Note that VRML 1.1 provides no mechanism for controlling the amount of ambient light in the scene, so use of the ambientColor field is browser dependent. Several other parameters (such as light attenuation factors) are also left as implementation details in VRML. Also note that OpenGL specifies the specular exponent as a non-normalized 0-128 value, which is specified as a normalized 0-1 value in VRML (simply multiplying the VRML value by 128 to translate to the OpenGL parameter).
For rendering systems that do not support the full OpenGL lighting model, the following simpler lighting model is recommended:
A transparency value of 0 is completely opaque, a value of 1 is completely transparent. Browsers need not support partial transparency, but should support at least fully transparent and fully opaque surfaces, treating transparency values >= 0.5 as fully transparent.
Specifying only emissiveColors and zero diffuse, specular, emissive, and ambient colors is the way to specify pre-computed lighting. It is expected that browsers will be able to recognize this as a special case and optimize their computations. For example:
Material { ambientColor [] diffuseColor [] specularColor [] emissiveColor [ 0.1 0.1 0.2, 0.5 0.8 0.8 ] }Issues for Low-End Rendering Systems. Many low-end PC rendering systems are not able to support the full range of the VRML material specification. For example, many systems do not render individual red, green and blue reflected values as specified in the specularColor field. The following table describes which Material fields are typically supported in popular low-end systems and suggests actions for browser implementors to take when a field is not supported.
Field Supported? Suggested Action ambientColor No Ignore diffuseColor Yes Use specularColor No Ignore emissiveColor No Use in place of diffuseColor if != 0 0 0 shininess Yes Use transparency No Ignore
It is also expected that simpler rendering systems will be unable to support both lit and unlit objects in the same scene.
FILE FORMAT/DEFAULTS Material { ambientColor 0.2 0.2 0.2 # input MFColor diffuseColor 0.8 0.8 0.8 # input MFColor specularColor 0 0 0 # input MFColor emissiveColor 0 0 0 # input MFColor shininess 0.2 # input MFFloat transparency 0 # input MFFloat }
Material nodes may contain more than one material. This node specifies how the current materials are bound to shapes that follow in the scene graph. Each shape node may interpret bindings differently. For example, a Sphere node is always drawn using the first material in the material node, no matter what the current MaterialBinding, while a Cube node may use six different materials to draw each of its six faces, depending on the MaterialBinding.
The bindings for faces and vertices are meaningful only for shapes that are made from faces and vertices. Similarly, the indexed bindings are only used by the shapes that allow indexing.
When multiple material values are needed by a shape, the previous Material node should at least as many materials as are needed, otherwise results are undefined.
Issues for low-end rendering systems. Some renderers do not support per-vertex materials, in which case the MaterialBinding values PER_VERTEX and PER_VERTEX_INDEXED will produce upredictable results in different browsers.
BINDINGS DEFAULT Use default binding OVERALL Whole object has same material PER_PART One material for each part of object PER_PART_INDEXED One material for each part, indexed PER_FACE One material for each face of object PER_FACE_INDEXED One material for each face, indexed PER_VERTEX One material for each vertex of object PER_VERTEX_INDEXED One material for each vertex, indexed FILE FORMAT/DEFAULTS MaterialBinding { value OVERALL # SFEnum }
This node defines a geometric 3D transformation with a 4 by 4 matrix. Only matrices that are the result of rotations, translations, and non-zero (but possibly non-uniform) scales must be supported. Non-invertable matrices should be avoided.
Matrices are specified in row-major order, so, for example, a MatrixTransform representing a translation of 6.2 units along the local Z axis would be specified as:
MatrixTransform { matrix 1 0 0 0 0 1 0 0 0 0 1 0 0 0 6.2 1 } FILE FORMAT/DEFAULTS MatrixTransform { matrix 1 0 0 0 # SFMatrix 0 1 0 0 0 0 1 0 0 0 0 1 }
This node defines a set of 3D surface normal vectors to be used by vertex-based shape nodes (IndexedFaceSet, IndexedLineSet, PointSet) that follow it in the scene graph. This node does not produce a visible result during rendering; it simply replaces the current normals in the rendering state for subsequent nodes to use. This node contains one multiple-valued field that contains the normal vectors.
To save network bandwidth, it is expected that implementations will be able to automatically generate appropriate normals if none are given. However, the results will vary from implementation to implementation.
FILE FORMAT/DEFAULTS Normal { vector [ ] # input MFVec3f }
This node specifies how the current normals are bound to shapes that follow in the scene graph. Each shape node may interpret bindings differently.
The bindings for faces and vertices are meaningful only for shapes that are made from faces and vertices. Similarly, the indexed bindings are only used by the shapes that allow indexing. For bindings that require multiple normals, be sure to have at least as many normals defined as are necessary; otherwise, errors will occur.
BINDINGS DEFAULT Use default binding OVERALL Whole object has same normal PER_PART One normal for each part of object PER_PART_INDEXED One normal for each part, indexed PER_FACE One normal for each face of object PER_FACE_INDEXED One normal for each face, indexed PER_VERTEX One normal for each vertex of object PER_VERTEX_INDEXED One normal for each vertex, indexed FILE FORMAT/DEFAULTS NormalBinding { value DEFAULT # SFEnum }
An orthographic camera defines a parallel projection from a viewpoint. This camera does not diminish objects with distance, as a PerspectiveCamera does. The viewing volume for an orthographic camera is a rectangular parallelepiped (a box).
By default, the camera is located at (0,0,1) and looks along the negative z-axis; the position and orientation fields can be used to change these values. The height field defines the total height of the viewing volume.
A camera can be placed in a VRML world to specify the initial location of the viewer when that world is entered. VRML browsers will typically modify the camera to allow a user to move through the virtual world.
The results of traversing multiple cameras are undefined; to ensure consistent results, place multiple cameras underneath one or more Switch nodes, and set the Switch's whichChild fields so that only one is traversed. By convention, these non-traversed cameras may be used to define alternate entry points into the scene; these entry points may be named by simply giving the cameras a name (using DEF); see the specification of WWWAnchor for a conventional way of specifying an entry point in a URL.
Cameras are affected by the current transformation, so you can position a camera by placing a transformation node before it in the scene graph . The default position and orientation of a camera is at (0,0,1) looking along the negative z-axis, with the positive y-axis up.
The position and orientation fields of a camera are sufficient to place a camera anywhere in space with any orientation. The orientation field can be used to rotate the default view direction (looking down -z-, with +y up) so that it is looking in any direction, with any direction 'up'.
The focalDistance field defines the point the viewer is looking at, and may be used by a browser as a navigational hint to determine how fast the viewer should travel, which objects in the scene are most important, etc.
The nearDistance and farDistance are distances from the viewpoint (in the camera's coordinate system); objects closer to the viewpoint than nearDistance or farther from the viewpoint than farDistance should not be seen. Browsers may treat these values as hints, and may decide to adjust them as the viewer moves around the scene.
FILE FORMAT/DEFAULTS OrthographicCamera { position 0 0 1 # SFVec3f orientation 0 0 1 0 # SFRotation focalDistance 5 # SFFloat height 2 # SFFloat nearDistance 1 # SFFloat farDistance 10 # SFFloat }Issues for low-end rendering systems. Most low-end rendering systems do not support the concept of focalDistance. Also, cameras are global to the scene; placing a camera beneath a particular Separator is equivalent to placing it at outermost scope. For broadest compatibility, cameras should only be placed at outermost scope.
A perspective camera defines a perspective projection from a viewpoint. The viewing volume for a perspective camera is a truncated right pyramid.
By default, the camera is located at (0,0,1) and looks along the negative z-axis; the position and orientation fields can be used to change these values. The heightAngle field defines the total vertical angle of the viewing volume.
See more on cameras in the OrthographicCamera description.
FILE FORMAT/DEFAULTS PerspectiveCamera { position 0 0 1 # SFVec3f orientation 0 0 1 0 # SFRotation focalDistance 5 # SFFloat heightAngle 0.785398 # SFFloat nearDistance 1 # SFFloat farDistance 10 # SFFloat }
This node defines a point light source at a fixed 3D location. A point source illuminates equally in all directions; that is, it is omni- directional.
A light node defines an illumination source that may affect subsequent shapes in the scene graph, depending on the current lighting style. Light sources are affected by the current transformation. A light node under a separator should not affect any objects outside that separator (although some rendering systems do not currently support this).
FILE FORMAT/DEFAULTS PointLight { on TRUE # SFBool intensity 1 # SFFloat color 1 1 1 # SFColor location 0 0 1 # SFVec3f }
This node represents a set of points located at the current coordinates. PointSet uses the current coordinates in order, starting at the index specified by the startIndex field. The number of points in the set is specified by the numPoints field. A value of -1 for this field indicates that all remaining values in the current coordinates are to be used as points.
The coordinates of the point set are transformed by the current cumulative transformation. The points are drawn with the current material and texture.
Treatment of the current material and normal binding is as follows: PER_PART, PER_FACE, and PER_VERTEX bindings bind one material or normal to each point. The DEFAULT material binding is equal to OVERALL. The DEFAULT normal binding is equal to PER_VERTEX. The startIndex is also used for materials or normals when the binding indicates that they should be used per vertex.
FILE FORMAT/DEFAULTS PointSet { startIndex 0 # SFLong numPoints -1 # SFLong }Issues for low-end rendering systems. Many low-end renderers do not support the concept of per-object lighting. This means that placing a light beneath a Separator, which implies lighting only the objects beneath the Separator with that light, is not supported in all systems. For the broadest compatibility, lights should only be placed at outermost scope.
This node defines a 3D rotation about an arbitrary axis through the origin. The rotation is accumulated into the current transformation, which is applied to subsequent shapes.
FILE FORMAT/DEFAULTS Rotation { rotation 0 0 1 0 # input SFRotation }
See rotation field description for more information.
This node defines a 3D scaling about the origin. If the components of the scaling vector are not all the same, this produces a non-uniform scale.
FILE FORMAT/DEFAULTS Scale { scaleFactor 1 1 1 # input SFVec3f }
This group node performs a push (save) of the traversal state before traversing its children and a pop (restore) after traversing them. This isolates the separator's children from the rest of the scene graph. A separator can include lights, cameras, coordinates, normals, bindings, and all other properties.
Separators can also perform render culling. Render culling skips over traversal of the separator's children if they are not going to be rendered, based on the comparison of the separator's bounding box with the current view volume. Culling is controlled by the renderCulling field. These are set to AUTO by default, allowing the implementation to decide whether or not to cull.
CULLING ENUMS ON Always try to cull to the view volume OFF Never try to cull to the view volume AUTO Implementation-defined culling behavior FILE FORMAT/DEFAULTS Separator { renderCulling AUTO # SFEnum }
The ShapeHints node indicates that IndexedFaceSets are solid, contain ordered vertices, or contain convex faces.
These hints allow VRML implementations to optimize certain rendering features. Optimizations that may be performed include enabling back-face culling and disabling two-sided lighting. For example, if an object is solid and has ordered vertices, an implementation may turn on backface culling and turn off two-sided lighting. If the object is not solid but has ordered vertices, it may turn off backface culling and turn on two-sided lighting.
The ShapeHints node also affects how default normals are generated. When an IndexedFaceSet has to generate default normals, it uses the creaseAngle field to determine which edges should be smoothly shaded and which ones should have a sharp crease. The crease angle is the angle between surface normals on adjacent polygons. For example, a crease angle of .5 radians (the default value) means that an edge between two adjacent polygonal faces will be smooth shaded if the normals to the two faces form an angle that is less than .5 radians (about 30 degrees). Otherwise, it will be faceted.
Issues for low-end rendering systems. The shapeType and vertexOrdering fields are used to determine whether or not to generate back faces for each polygon in a mesh. Most low-end rendering systems do not support built-in back face generation; browsers built on these systems need to create back faces explicitly.
VERTEX ORDERING ENUMS UNKNOWN_ORDERING Ordering of vertices is unknown CLOCKWISE Face vertices are ordered clockwise (from the outside) COUNTERCLOCKWISE Face vertices are ordered counterclockwise (from the outside) SHAPE TYPE ENUMS UNKNOWN_SHAPE_TYPE Nothing is known about the shape SOLID The shape encloses a volume FACE TYPE ENUMS UNKNOWN_FACE_TYPE Nothing is known about faces CONVEX All faces are convex FILE FORMAT/DEFAULTS ShapeHints { vertexOrdering COUNTERCLOCKWISE # SFEnum shapeType SOLID # SFEnum faceType CONVEX # SFEnum creaseAngle 0 # SFFloat }
This node represents a sphere. By default, the sphere is centered at the origin and has a radius of 1. The sphere is transformed by the current cumulative transformation and is drawn with the current material and texture.
A sphere does not have faces or parts. Therefore, the sphere ignores material and normal bindings, using the first material for the entire sphere and using its own normals. When a texture is applied to a sphere, the texture covers the entire surface, wrapping counterclockwise from the back of the sphere. The texture has a seam at the back on the yz-plane.
FILE FORMAT/DEFAULTS Sphere { radius 1 # SFFloat }
This node defines a spotlight light source. A spotlight is placed at a fixed location in 3-space and illuminates in a cone along a particular direction. The intensity of the illumination drops off exponentially as a ray of light diverges from this direction toward the edges of the cone. The rate of drop-off and the angle of the cone are controlled by the dropOffRate and cutOffAngle fields.
A light node defines an illumination source that may affect subsequent shapes in the scene graph, depending on the current lighting style. Light sources are affected by the current transformation. A light node under a separator should not affect any objects outside that separator (although some rendering systems do not currently support this).
FILE FORMAT/DEFAULTS SpotLight { on TRUE # SFBool intensity 1 # SFFloat color 1 1 1 # SFVec3f location 0 0 1 # SFVec3f direction 0 0 -1 # SFVec3f dropOffRate 0 # SFFloat cutOffAngle 0.785398 # SFFloat }Issues for low-end rendering systems. Many low-end renderers do not support the concept of per-object lighting. This means that placing a light beneath a Separator, which implies lighting only the objects beneath the Separator with that light, is not supported in all systems. For the broadest compatibility, lights should only be placed at outermost scope.
This group node traverses one or none of its children. One can use this node to switch on and off the effects of some properties or to switch between different properties.
The whichChild field specifies the index of the child to traverse, where the first child has index 0. This field is an input and thus can be modified by another node.
Open issue It is expected that in a future version of VRML the Switch node will be defined to behave as a Separator node, not allowing its children to affect anything after it in the scene graph. To ensure future compatibility, it is recommended that all children of all Switch nodes be Separator nodes.
FILE FORMAT/DEFAULTS Switch { whichChild -1 # input SFLong }
This node represents one or more text strings specified using the UTF-8 encoding of the ISO10646 character set. This is described below. An important note is that ASCII is a subset of UTF-8, so any ASCII strings are also UTF-8.
The text strings can be rendered in one of four directions: right to left (RL), left to right (LR), top to bottom (TB), or bottom to top (BT). The direction field governs this.
The justification field determines where the text will be positioned in relation to the origin (0,0,0) of the object coordinate system. The values for the justification field are BEGIN, END, CENTER. For a left to right (LR) direction, these would correspond to LEFT, RIGHT, CENTER.
For the directions RL and LR, the first line of text will be positioned with its baseline (bottom of capital letters) at y = 0. The text is positioned on the positive side of the x origin for the direction LR and justification BEGIN; the same for RL END. The text is on the negative side of X for LR END and RL BEGIN. For CENTER justification and horizontal text (RL, LR), each string will be centered at x = 0.
For the directions TB and BT, the first line of text will be positioned with the left side of the glyphs along the y = 0 axis. For TB BEGIN and BT END, the text will be positioned with the top left corner at the origin; for TB END and BT BEGIN, the bottom left will be at the origin. For TB and BT CENTER, the text will be centered vertically at x = 0.
LR BEGIN LR END LR CENTER VRML VRML VRML adds a adds a adds a dimension! dimension! dimension! RL BEGIN RL END RL CENTER LMRV LMRV LMRV a sdda a sdda a sdda !noisnemid !noisnemid !noisnemid TB BEGIN TB END TB CENTER BT BEGIN BT END BT CENTER V a d d d ! L a ! ! R d i i i n M n n M d m m a m o R s o a o L s e e V d e i V d i L i n a n R d n a s d s M s s a s d s M s s n a n R d n i V d i L i L s e e V d e o R s o a o M d m m a m n M n n R d i i i ! L a ! ! V a d d d
The spacing field determines the spacing between multiple text strings. All subsequent strings advance in either x or y by -( size * spacing). See FontStyle for a description of the size field. A value of 0 for the spacing will cause the string to be in the same position. A value of -1 will cause subsequent strings to advance in the opposite direction.
The extent field will limit and scale the text string if the natural length of the string is longer than the extent. If the text string is shorter than the extent, it will not be scaled. The extent is measured horizontally for RL and LR directions; vertically for TB and BT.
UTF-8 character encodings
The 2 byte (UCS-2) encoding of ISO 10646 is identical to the Unicode standard. References for both ISO 10646 and Unicode are given in the references section at the end.
In order to avoid introducing binary data into VRML we have chosen to support the UTF-8 encoding of ISO 10646. This encoding allows ASCII text (0x0..0x7F) to appear without any changes and encodes all characters from 0x80.. 0x7FFFFFFF into a series of six or fewer bytes.
If the most significant bit of the first character is 0, then the remaining seven bits are interpretted as an ASCII character. Otherwise, the number of leading 1 bits will indicate the number of bytes following. There is always a o bit between the count bits and any data.
First byte could be one of the following. The X indicates bits available to encode the character. 0XXXXXXX only one byte 0..0x7F (ASCII) 110XXXXX two bytes Maximum character value is 0x7FF 1110XXXX three bytes Maximum character value is 0xFFFF 11110XXX four bytes Maximum character value is 0x1FFFFF 111110XX five bytes Maximum character value is 0x3FFFFFF 1111110X six bytes Maximum character value is 0x7FFFFFFF All following bytes have this format: 10XXXXXX
A two byte example. The symbol for a register trade mark is "circled R registered sign" or 174 in both ISO/Latin-1 (8859/1) and ISO 10646. In hexadecimal it is 0xAE; In HTML ®. In UTF-8 it is has the following two byte encoding 0xC2, 0xAE.
The text is transformed by the current cumulative transformation and is drawn with the current material and texture.
Textures are applied to 3D text as follows. The texture origin is at the origin of the first string, as determined by the justification. The texture is scaled equally in both S and T dimensions, with the font height representing 1 unit. S increases to the right, T increases up.
DIRECTION LR Character are drawn from left to right RL Character are drawn from right to left TB Character are drawn from top to bottom TB Character are drawn from bottom to top JUSTIFICATION BEGIN Align beginning of text to origin CENTER Align center of text to origin END Align end of text to origin FILE FORMAT/DEFAULTS Text { string "" # MFString direction LR # SFEnum justification BEGIN # SFEnum spacing 1 # SFFloat width 0 # MFFloat }
There are many languages in which the proper rendering of the text requires more than just a sequence of glyphs. The TextLanguage node allows the author to specify which, if any, language specific rendering techniques to use. For simple languages, such as English, this node may be safely ignored.
The tag used to specify languages will follow RFC1766 - Tags for the Identification of Languages. ftp://ftp.isi.edu/in-notes/rfc1766.txt. This RFC specifies that a language tag may simply be a two letter ISO 639 tag, for example "en" for English, "ja" for Japanese, and "sv" for Swedish. This may be optionally followed by a two letter country code from ISO 3166. So, Americans would be absolutely safe with "en-US". ISO does not have documents online, yet. They can be ordered.
FILE FORMAT/DEFAULTS TextLanguage { textLanguage "" # SFString }
This property node defines a texture map and parameters for that map. This map is used to apply texture to subsequent shapes as they are rendered.
The texture can be read from the URL specified by the filename field. To turn off texturing, set the filename field to an empty string (""). Implementations should support at least the JPEG image file format. Also supporting GIF and PNG formats is recommended.
If multiple URLs are presented, this expresses a descending order of preference, a browser may display a lower preference URL while the higher order file is not available. See the section on URNs.
Textures can also be specified inline by setting the image field to contain the texture data. Supplying both image and filename fields will result in undefined behavior.
Texture images may be one component (greyscale), two component (greyscale plus transparency), three component (full RGB color), or four-component (full RGB color plus transparency). An ideal VRML implementation will use the texture image to modify the diffuse color and transparency of an object's material (specified in a Material node), then performing any lighting calculations using the rest of the object's material properties with the modified diffuse color to produce the final image. The texture image modifies the diffuse color and transparency depending on how many components are in the image, as follows:
Browsers may approximate this ideal behavior to increase performance. One common optimization is to calculate lighting only at each vertex and combining the texture image with the color computed from lighting (performing the texturing after lighting). Another common optimization is to perform no lighting calculations at all when texturing is enabled, displaying only the colors of the texture image.
WRAP ENUM REPEAT Repeats texture outside 0-1 texture coordinate range CLAMP Clamps texture coordinates to lie within 0-1 range FILE FORMAT/DEFAULTS Texture2 { filename "" # SFString image 0 0 0 # SFImage wrapS REPEAT # SFEnum wrapT REPEAT # SFEnum }
This node defines a 2D transformation applied to texture coordinates. This affects the way textures are applied to the surfaces of subsequent shapes. The transformation consists of (in order) a non-uniform scale about an arbitrary center point, a rotation about that same point, and a translation. This allows a user to change the size and position of the textures on shapes.
FILE FORMAT/DEFAULTS Texture2Transform { translation 0 0 # SFVec2f rotation 0 # SFFloat scaleFactor 1 1 # SFVec2f center 0 0 # SFVec2f }
This node defines a set of 2D coordinates to be used to map textures to the vertices of subsequent PointSet, IndexedLineSet, or IndexedFaceSet objects. It replaces the current texture coordinates in the rendering state for the shapes to use.
Texture coordinates range from 0 to 1 across the texture. The horizontal coordinate, called S, is specified first, followed by the vertical coordinate, T.
FILE FORMAT/DEFAULTS TextureCoordinate2 { point 0 0 # MFVec2f }
This node defines a geometric 3D transformation consisting of (in order) a (possibly) non-uniform scale about an arbitrary point, a rotation about an arbitrary point and axis, and a translation. The transform node
Transform { translation T1 rotation R1 scaleFactor S scaleOrientation R2 center T2 }
is equivalent to the sequence:
Translation { translation T1 } Translation { translation T2 } Rotation { rotation R1 } Rotation { rotation R2 } Scale { scaleFactor S } Rotation { rotation -R2 } Translation { translation -T2 }
FILE FORMAT/DEFAULTS Transform { translation 0 0 0 # input SFVec3f rotation 0 0 1 0 # input SFRotation scaleFactor 1 1 1 # input SFVec3f scaleOrientation 0 0 1 0 # input SFRotation center 0 0 0 # input SFVec3f }
This node defines a translation by a 3D vector.
FILE FORMAT/DEFAULTS Translation { translation 0 0 0 # input SFVec3f }
The WWWAnchor group node loads a new scene into a VRML browser when one of its children is chosen. Exactly how a user "chooses" a child of the WWWAnchor is up to the VRML browser; typically, clicking on one of its children with the mouse will result in the new scene replacing the current scene. A WWWAnchor with an empty ("") name does nothing when its children are chosen. The name is an arbitrary URL.
If multiple URLs are presented, this expresses a descending order of preference, a browser may display a lower preference URL if the higher order file is not available. See the section on URNs.
WWWAnchor behaves like a Separator, pushing the traversal state before traversing its children and popping it afterwards.
The description field in the WWWAnchor allows for a friendly prompt to be displayed as an alternative to the URL in the name field. Ideally, browsers will allow the user to choose the description, the URL or both to be displayed for a candidate WWWAnchor.
The WWWAnchor's map field is an enumerated value that can be either NONE (the default) or POINT. If it is POINT then the object-space coordinates of the point on the object the user chose will be added to the URL in the name field, with the syntax "?x,y,z".
A WWWAnchor may be used to take the viewer to a particular viewpoint in a virtual world by specifying a URL ending with "#cameraName", where "cameraName" is the name of a camera defined in the world. For example:
WWWAnchor { name "http://www.school.edu/vrml/someScene.wrl#OverView" Cube { } }
specifies an anchor that puts the viewer in the "someScene" world looking from the camera named "OverView" when the Cube is chosen. If no world is specified, then the current scene is implied; for example:
WWWAnchor { name "#Doorway" Sphere { } }
will take the viewer to the viewpoint defined by the "Doorway" camera in the current world when the sphere is chosen.
MAP ENUM NONE Do not add information to the URL POINT Add object-space coordinates to URL FILE FORMAT/DEFAULTS WWWAnchor { name "" # MFString description "" # SFString map NONE # SFEnum }
The WWWInline node reads its children from anywhere in the World Wide Web. Exactly when its children are read is not defined; reading the children may be delayed until the WWWInline is actually displayed. A WWWInline with an empty name does nothing. The name is an arbitrary URL.
The effect of referring to a non-VRML URL in a WWWInline node is undefined.
If multiple URL's are specified then this expresses a descending order of preference, a browser may display a URL for a lower preference file while it is obtaining, or if it is unable to obtain, the higher preference file. See also the section on URNs.
If the WWWInline's bboxSize field specifies a non-empty bounding box (a bounding box is non-empty if at least one of its dimensions is greater than zero), then the WWWInline's object-space bounding box is specified by its bboxSize and bboxCenter fields. This allows an implementation to quickly determine whether or not the contents of the WWWInline might be visible. This is an optimization hint only; if the true bounding box of the contents of the WWWInline is different from the specified bounding box results will be undefined.
FILE FORMAT/DEFAULTS WWWInline { name "" # MFString bboxSize 0 0 0 # SFVec3f bboxCenter 0 0 0 # SFVec3f }
By providing a shaded ground plane, sky and scenic, textures, this node can be used to add substance to the void surrounding the scene. Only the first background node encountered is used, and it must be specified in the main file.
If groundColors are specified, then a ground plane is added to the scenegraph at Y = 0 in global coordinate space. If more than one color is specified, then the ground color is interpolates between colors from 0 degrees downward to 90 degrees at the horizon. Similarly, skyColors interpolate from the 90 degree mark to 180 degrees overhead.
A scene may describe a more precise atmosphere and include background scenery in the scenery field. This field is used to add a texture to the scene that is conceptually distant enough that it does not translate with respect to the eyepoint. The texture should be mapped wrapped around a cylinder so that it runs all the way around from Y=0 in global coordinate space.
If multiple URL's are specified then this expresses a descending order of preference, a browser may display a URL for a lower preference file while it is obtaining, or if it is unable to obtain, the higher preference file. See also the section on URNs.
Background{ groundColors [ ] # MFColor skyColors [ 0 0 0 ] # MFColor scenery "" # MFString }
Pros:
Issues:
This node specifies to a browser what objects in the scene should not be navigated through. It is useful to keep viewers from walking through walls in a building, for instance. Collision response is browser defined. For example, when the camera comes sufficiently close to an object to register as a collision, the browser may have the camera bounce off the object, or simply come to a stop.
Since collision with arbitrarily complex geometry is computationally expensive, one method of increasing efficiency is to be able to define an alternate geometry that could serve as a proxy for colliding against. This collision proxy could be as crude as a simple bounding box or bounding sphere, or could be more spohisticated (for example, the convex hull of a polyhedron). This proxy volume is used ONLY to calculate the collision with the viewer and is NOT used for trivial rejection during the computation process. Efficient trivial rejection can be done using hierarchical bounding boxes or some other technique, and its implementation is not specified in the language.
VRML represents collision proxy volumes for objects through the CollideStyle property node. A CollideStyle node sets the collision proxy volume for all the geometry in the scene graph that follows it upto the next CollideStyle node. Like all other properties, the current collision style would be saved and restored by Separators. Like all other shapes, the geometry is defined in object space and is transformed by the current modeling transformation.
CollideStyle contains two fields: collide (a boolean) and proxy (a node). If the value of the collide field is FALSE, then no collision is performed with the affected geometry. If the value of the collide field is TRUE, then the proxy field defines the geometry against which collision testing is done. If the proxy value is undefined or NULL, the actual geometry is collided against. If the proxy value is not NULL, then it contains the geometry that is used in collision computations.
FILE FORMAT/DEFAULTS CollideStyle { collide FALSE # SFBool proxy NULL # SFNode }
Notes/Issues:
This node defines a sound source that is located at a specific 3D location and that emits primarily along a given direction. It adds directionality to the PointSound node. Besides the direction vector, there are minAngle and maxAngle fields that specify how the intensity of the sound changes with direction. Within the cone whose apex is the sound location, whose axis is the direction vector, and whose angle is specified by minAngle, the DirectedSound behaves exactly like a PointSound. Moving along a constant radius (from the source location) from the surface of this cone to the surface of the similar cone whose angle is maxAngle, the intensity falls off to zero.
See the PointSound node for a description of all other fields.
FILE FORMAT/DEFAULTS DirectedSound { name "" # MFString description "" # SFString intensity 1 # SFFloat location 0 0 0 # SFVec3f direction 0 0 1 # SFVec3f minRange 10 # SFFloat maxRange 10 # SFFloat minAngle 0.785398 # SFFloat maxAngle 0.785398 # SFFloat loop FALSE # SFBool start 0 # input SFTime pause 0 # input SFTime }
This node creates a rectangular grid with varying heights, especially useful in modeling terrain and other space creating surfaces. The model is specified primarily by a scalar array of height values that describe the height of the surface above each point of the grid.
The verticesPerRow and verticesPerColumn fields define the number of grid points in the Z and X directions, respectively, defining a surface that contains (verticesPerRow-1) x (verticesPerColumn-1) rectangles.
The vertex locations for the rectangles are defined by the height field and the gridStep field. The vertex corresponding to the i th row and j th column is placed at (gridStep[0] * j, heights[i*verticesPerColumn+j], gridStep[1] * i) in object space, where 0<=i<=verticesPerRow, 0<=j<=verticesPerColumn.
The height field is an array of scalar values representing the height above the grid for each vertex. The height values are stored so that row 0 is first, followed by rows 1, 2, ... verticesPerRow. Within each row, the height values are stored so that column 0 is first, followed by columns 1, 2, ... verticesPerColumn. The rows have fixed Z values, with row 0 having the smallest Z value. The columns have fixed X values, with column 0 having the smallest X value.
The default texture coordinates will range from [0,0] at the first vertex to [1,1] at the far side of the diagonal. The S texture coordinate will be aligned with X and the T texture coordinate with Z.
Treatment of the current material and normal binding is as follows: The PER_PART binding specifies a material or normal for each row of the mesh. The PER_FACE binding specifies a material or normal for each quadrilateral. The _INDEXED bindings are equivalent to their non-indexed counterparts. The default material binding is OVERALL. The default normal binding is PER_VERTEX.
If any normals (or materials) are specified, it is assumed you provide the correct number of them, as indicated by the binding. You will see unexpected results if you specify fewer normals (or materials) than the shape requires. If no normals are specified, they will be generated automatically.
By default, the rectangles are defined with a counterclockwise ordering, so the Y component of the normal is positive. Setting the vertexOrdering field of the current ShapeHints node to CLOCKWISE reverses the normal direction. Backface culling can be turned on as for all shapes, by defining a ShapeHints node prior to the ElevationGrid node with the vertexOrdering field set to CLOCKWISE or COUNTERCLOCKWISE and the shapeType field set to SOLID.
FILE FORMAT/DEFAULTS ElevationGrid { verticesPerRow 0 # SFLong verticesPerColumn 0 # SFLong gridStep [] # SFVec2f height [] # MFFloat }
Pros:
This node describes global environmental attributes such as ambient lighting, light attenuation, and fog.
Ambient lighting is the amount of extra light impinging on each surface point. It is specified as an ambientColor and ambientIntensity. Light attenuation affects all subsequent lights in a scene. It is a quadratic function of distance from a light source to a surface point. The three coefficients are specified in the attenuation field. Attenuation works only for light sources with a fixed location, such as point and spot lights. The ambient lighting and attenuation calculations are defined in the OpenGL lighting model. For a description of these and other lighting calculations, see the description of lighting operations in the OpenGL Specification.
Fog has one of four types, each of which blends each surface point with the specified fog color. Each type interprets the visibility field to be the distance at which fog totally obscures objects. A visibility value of 0 (the default) causes the Environment node to set up fog so that the visibility is the distance to the far clipping plane of the current camera. For more details on the fog calculations, see the description of fog in the OpenGL Specification.
FOGTYPE NONE No fog HAZE Linear increase in opacity with distance FOG Exponential increase in opacity SMOKE Exponential squared increase in opacity FILE FORMAT/DEFAULTS Environment { ambientIntensity 0.2 # SFFloat ambientColor 1 1 1 # SFColor attenuation 0 0 1 # SFVec3f fogType NONE # SFEnum fogColor 1 1 1 # SFColor fogVisibility 0 # SFFloat }
This is a node for parametrically describing numerous families of shapes: extrusions (along an axis or an arbitrary path), surfaces of revolution, and bend/twist/taper objects.
General Cylinders are defined by four piecewise linear curves: crossSection, profile, spine and twist. Shapes are constructed as follows. The crossSection is a 2D curve that is scaled, extruded through space, and twisted by the other curves. First, the crossSection is extruded and scaled along the path of the profile curve. Second, the shape is bent and stretched so that its central axis aligns with the spine curve. Finally, the shape is twisted about the spine by angles (in radians) given by the twist curve. The twist curve is a function of angle at given parametric distances along the spine.
Surfaces of Revolution: If the crossSection is a circle and the spine is straight, then the General Cylinder will be equivalent to a surface of revolution, where the General Cylinder profile curve maps directly to that of the surface of revolution.
Cookie-Cutter Extrusions: If both the profile and spine are straight, then the crossSection acts like a cookie-cutter, with the thickness of the cookie equal to the length of the spine.
Bend/Twist/Taper objects: Shapes like this are the result of utilizing all four curves. The spine curve bends the shape, the twist curve twists it, and the profile curve tapers it.
Planar TOP and BOTTOM surfaces will be generated when the crossSection is closed (i.e., when the first and last points of the crossSection are equal). However, if the profile is also closed, the TOP and BOTTOM are not generated; this is because a closed crossSection extruded along a closed profile creates a shape that is closed without the addition of TOP and BOTTOM parts.
The parts field determines which parts are rendered. The notion of BOTTOM versus TOP is determined by the profile curve. The end of the profile curve with a lesser y value is the BOTTOM end.
The cone is transformed by the current cumulative transformation and is drawn with the current texture and material. The first material in the state is used for the entire GeneralCylinder, regardless of the current material binding.
GeneralCylinder automatically generates its own normals. NormalBinding in the state is ignored. Orientation of the normals is determined by the vertex ordering of the triangles generated by GeneralCylinder. The vertex ordering is in turn determined by the crossSection curve. If the crossSection is drawn counterclockwise, then the polygons will have counterclockwise ordering when viewed from the 'outside' of the shape (and vice versa for clockwise ordered crossSections). The General Cylinder responds to the fields of the ShapeHints node the same way as IndexedFaceSet.
Texture coordinates are automatically generated by General Cylinders. These will map textures like the label on a soup can: the coordinates will range in the u direction from 0 to 1 along the crossSection curve and in the v direction from 0 to 1 along the spine. If the TOP and/or BOTTOM exist, textures map onto them in a planar fashion.
When a texture is applied to a General Cylinder, it is applied differently to the sides, top, and bottom. On the sides, the texture wraps [0,1] of the u-direction of the texture along the crossSection from first point to last; it wraps [0,1] of the v-direction of the texture along the direction of the spine, from first point to last. When the crossSection is closed, the texture has a seam that follows the line traced by the crossSection's start/end point as it travels along the spine. For the top and bottom, the crossSection is cut out of the texture square and applied to the top or bottom circle. The top and bottom textures' u and v directions correspond to the x and z directions in which the crossSection coordinates are defined.
PARTS SIDES The extruded surface part TOP The top cross sectional face BOTTOM The bottom cross sectional face ALL All parts FILE FORMAT/DEFAULTS GeneralCylinder { spine [ 0 0 0, 0 1 0 ] # MFVec3f crossSection [ -1 1, -1 -1, 1 -1, 1 1 ] # MFVec2f profile [ 1 -1, 1 1 ] # MFVec2f twist [ 0 -1, 0 1 ] # MFVec2f parts ALL # SFBitMask }
Pros:
This node contains information for the viewer through several fields: type, speed, collisionRadius, and headlight.
The type field specifies a navigation paradigm to use. The types that all VRML viewers should support are "walk", "examiner", "fly", and "none". A "walk" viewer would constrain the user to a plane (x-z), suitable for architectural walkthroughs. An "examiner" viewer would let the user tumble the entire scene, suitable for examining single objects. A "fly" viewer would provide six degree of freedom movement. The "none" choice removes all viewer controls, forcing the user to navigate using only WWWAnchors linked to viewpoints. The type field is multi-valued so that authors can specify fallbacks in case a browser does not understand a given type.
The speed is the rate at which the viewer travels through a scene in meters per second. Since viewers may provide mechanisms to travel faster or slower, this should be the default or average speed of the viewer. In an examiner viewer, this only makes sense for panning and dollying - it should have no affect on the rotation speed.
Open issue - no consensus on collisionRadius - see CollideStyle node
The collisionRadius field specifies the smallest allowable distance between the camera position and any collision object (as specified by CollideStyle) before a collision is detected.
Open issue - no consensus on headlight field, relates to discussion on Avatars
The headlight field specifies whether a browser should turn a headlight on. A headlight is a directional light which always points in the direction the camera is looking. This effect can be had by adding a DirectionalLight in front of a Camera in the scene. Instead, setting this field to TRUE allows the browser to provide a headlight possibly with user interface controls to turn it on and off. Scenes that enlist precomputed lighting (e.g. radiosity solutions) can specify the headlight off here. The headlight should have intensity 1, color 1 1 1, and direction 0 0 -1. The effects of specifying headlight on in a NavigationInfo node are equivalent to an author adding a default DirectionalLight in front of a camera in the scene, except that using the NavigationInfo field allows a browser to provide user interface controlling the light.
FILE FORMAT/DEFAULTS NavigationInfo { type "walk" # input MFString speed 1.0 # input SFFloat collisionRadius 1.0 # SFFloat headlight TRUE # SFBool }
Notes/Issues:
This node defines a sound source located at a specific 3D location. The name field specifies a URL from which the sound is read. Implementations should support at least the ??? ??? sound file formats. Streaming sound files may be supported by browsers; otherwise, sounds should be loaded when the sound node is loaded. Browsers may limit the maximum number of sounds that can be played simultaneously.
If multiple URL's are specified then this expresses a descending order of preference, a browser may use a URL for a lower preference file while it is obtaining, or if it is unable to obtain, the higher preference file. See also the section on URNs.
The description field is a textual description of the sound, which may be displayed in addition to or in place of playing the sound.
The intensity field adjusts the volume of each sound source; an intensity of 0 is silence and an intensity of 1 is whatever intensity is contained in the sound file.
The sound source has a radius specified by the minRadius field. When the viewpoint is within this radius, the sound's intensity (volume) is constant, as indicated by the intensity field. Outside the minRadius, the intensity drops off to zero at a distance of maxRadius from the source location. If the two radii are equal, the drop-off is sharp and sudden. Otherwise, the drop-off should be proportional to the square of the distance of the viewpoint from the minRadius.
Browsers may also support spatial localizations of sound. However, within minRadius, localization should not occur, so intensity is constant in all channels. Between minRadius and maxRadius, the sound location should be the point on the minRadius sphere that is closest to the current viewpoint. This ensures a smooth change in location when the viewpoint leaves the minRadius sphere. Note also that an ambient sound can therefore be created by using a large minRadius value.
The loop field specifies whether or not the sound is constantly repeated. By default, the sound is played only once.
The start input specifies the time at which the sound should start playing. The pause input may be used to make a sound stop playing some time after it has started. If the pause time is less than the start time then it is ignored. Changing the start input while the sound is playing will result in undefined behavior; however, changing the start input after the sound is paused is well-defined and useful. If the sound is not looped, the length of time the sound plays is determined by the sound file read, and is not specified in the VRML file.
A sound's location in the scene graph determines its spatial location (the sound's location is transformed by the current transformation) and whether or not it can be heard. A sound can only be heard while it is part of the traversed scene; sound nodes underneath LOD nodes or Switch nodes will not be audible unless they are traversed. If it is later part of the traversal again, the sound picks up where it would have been had it been playing continuously.
FILE FORMAT/DEFAULTS PointSound { name "" # MFString description "" # SFString intensity 1 # SFFloat location 0 0 0 # SFVec3f minRange 10 # SFFloat maxRange 10 # SFFloat loop FALSE # SFBool start 0 # input SFTime pause 0 # input SFTime }
This node contains information about the world. The title of the world is stored in its own field, allowing browsers to display it for instance in their window border. Any other information about the world can be stored in the info field, for instance the scene author, copyright information, and public domain information.
FILE FORMAT/DEFAULTS WorldInfo { title "" # SFString info "" # MFString }
Prototyping is a mechanism that allows the set of node types to be extended from within a VRML file. It allows the encapsulation and parameterization of geometry, behaviors, or both.
A prototype is defined using the PROTO keyword, as follows:
PROTO typename [ eventIn fieldtypename name IS nodename.eventInName nodename.eventInName ... , eventOut fieldtypename name IS nodename.eventOutName nodename.eventOutName ..., field fieldtypename name IS nodename.fieldName, ... ] { node { ... } Logic and/or ROUTES }
A prototype is NOT a node; it merely defines a prototype (named 'typename') that can be used later in the same file as if it were a built-in node. The implementation of the prototype is contained in the scene graph rooted by node. That node may be followed by Logic and/or ROUTE declarations, as necessary to implement the prototype.
The eventIn and eventOut declarations export events inside the scene graph given by node. Specifying the type of each event in the prototype is intended to prevent errors when the implementation of prototypes are changed, and to provide consistency with external prototypes. Specifying a name for each event allows several events with the same name to be exported with unique names.
Fields hold the persistent state of VRML objects. Allowing a prototype to export fields allows the initial state of a prototyped object to be specified by prototype instances.
The node names specified in the event and field declarations must be DEF'ed inside the prototype implementation. The first node DEF'ed in lexical (not traversal) order will be exported. It is an error (and results are undefined) if there is no node with the given name, or the first node found does not contain a field of the appropriate type with the given field name.
Prototype declarations have file scope, and prototype names must be unique in any given file.
Only nodes DEF'ed inside the prototype may be USE'ed inside the prototype, and nodes DEF'ed inside the prototype are not visible (may note be USE'ed) outside the prototype.
A prototype is instantiated as if typename were a built-in node. A prototype instance may be DEF'ed or USE'ed. For example, a simple chair with variable colors for the leg and seat might be prototyped as:
PROTO TwoColorChair [ field SFColor legColor IS leg.diffuseColor, field SFColor seatColor IS seat.diffuseColor ] { Separator { Separator { DEF seat Material { diffuseColor .6 .6 .1 } Cube { ... } } Separator { Transform { ... } DEF leg Material { diffuseColor .8 .4 .7 } Cylinder { ... } } } # End of root Separator } # End of prototype # Prototype is now defined. Can be used like: DEF redGreenChair TwoColorChair { legColor 1 0 0 seatColor 0 1 0 } USE redGreenChair # Regular DEF/USE rules apply
We're making distinctions between fields, which can be given an initial value but cannot be changed except by the node that they're contained in, and events, which (at least for the built-in nodes) are requests to change fields. So, if we want our TwoColorChair to have colors that can be changed, we'd need to expose the leg.setDiffuseColor 'eventIn' and seat.diffuseColor 'eventIn' events. All of which may make for confusing and wordy prototype declarations. Are there ever cases where you might want to ONLY allow initial values to be set, and NOT allow them to be changed later?
Note: PROTO sort of gives people their non-instantiating DEF: PROTO foo [] Cube { } is roughly equal to DEF foo Cube { }, except that foo is now a type name instead of an instance name (and you say foo { } to get another cube instead of USE foo). Smart implementations will automatically share the unchanging stuff in prototype implementations, so the end result will be the same.
What if we wanted a prototype that could be instantiated with arbitrary geometry? For example, we might want to define a prototype chair that allowed the geometry for the legs to be defined, with the default (perhaps) being a simple cylinder.
VRML 1.1 will include the SFNode field type-- a field that contains a pointer to a node. Using SFNode, it is easy to write the first part of the PROTO definition:
PROTO Chair [ field SFNode legGeometry IS
... but then we get stuck when we try to define the IS part of the prototype. We need some way of taking an SFNode field and inserting it into the scene. This can be accomplished with a new node, the NodeReference node:
NodeReference { node NULL # SFNode field (NULL is valid syntax for SFNode) # eventIn SFNode setNode # eventOut SFNode nodeChanged }
Functionally, NodeReference is a "do-nothing" node-- it just behaves exactly like whatever 'nodeToUse' points to (unless nodeToUse is NULL, of course, in which case NodeReference does nothing). For example, this would be a verbose way to add a Sphere to the scene:
NodeReference { nodeToUse Sphere { } }
NodeReference is only interesting if its nodeToUse field is exposed in a prototype (or it receives a nodeToUse event). So, for example, our Chair with arbitrary leg geometry (with a Cylinder default if none is specified) can be filled out as:
PROTO Chair [ field SFNode legGeometry IS NR.nodeToUse ] { Separator { Separator { Transform { ... } DEF NR NodeReference { nodeToUse Cylinder { } } } Separator { Transform { ... } USE NR } ... would re-use leg with a USE NR, would have geometry for seat/back/etc... } }
Using the Chair prototype would look like:
Chair { legGeometry Separator { Coordinate3/IndexedFaceSet/etc } }
It might also make sense to share the same geometry between several prototype instances; for example, you might do:
Chair { legGeometry DEF LEG Separator { Coordinate3/IndexedFaceSet/etc } } ... somewhere later in scene... Chair { legGeometry USE LEG }
Note that SFNode fields follow the regular DEF/USE rules, and that SFNode fields contain a pointer to a node; using DEF/USE an SFNode field may contain a pointer to a node that is also a child of some node in the scene graph, is pointed to by some other SFNode field, etc.
The NodeReference node has nice, clean semantics, and allows a lot of flexibility and power for defining prototypes. It also has some nice implementation side effects:
Browsers that want to maintain a different internal representation for the scene graph can implement NodeReference so that nodeToUse is read and the different internal representation is generated. Optimizations might also be performed at the same time:
Browsers that optimize scene graphs can implement NodeReference such that whenever nodeToUse changes an optimized scene is created. When rendering, the optimized scene will be used instead of the unotimized scene.
A really smart browser will figure out that nobody is using the unoptimized scene and may free it from memory.
Something else to think about: should a prototype be allowed to expose the fields or events of an SFNode that is passed in? For example:
PROTO Foo [ field SFNode transform IS NR.nodeToUse, eventIn SFVec3f setPosition IS NR.nodeToUse.translation ] Separator { DEF NR NodeReference { nodeToUse Transform { } } Cube { } }
This could be pretty powerful, but might also be painful to implement, since the type-checking would have to be done at run-time when NR.nodeToUse changed.
A second form of the prototype syntax allows prototypes to be defined in external files:
EXTERNPROTO typename [ eventIn fieldtypename name, eventOut fieldtypename name, field fieldtypename, ... ] URL or [ URL, URL, ... ]
In this case, the implementation of the prototype is found in the given URL. The file pointed to by that URL must contain ONLY a single prototype implementation (using PROTO). That prototype is then given the name typename in this file's scope (allowing possible naming clashes to be avoided). It is an error if the eventIn/eventOut declaration in the EXTERNPROTO is not a subset of the eventIn/eventOut declaration specified in URL.
Note: The rules about allowing exporting only from files that contain a single PROTO declaration are consistent with the WWWInline rules; until we have VRML-aware protocols that can send just one object or prototype declaration across the wire, I don't think we should encourage people to put multiple objects or prototype declarations in a single file.
We need to think about scalability when using nested EXTERNPROTO's. EXTERNPROTOS don't have bounding boxes specified like WWWInlines, and they might need them. I'm starting to think that we might need to add bboxCenter/Size fields to Separator instead of having them only on WWWInline; with animations possible, pre-specifying maximum-possible bounding boxes could save a lot of work recalculating bounding boxes as things move.
Extensions to VRML are supported by supporting self-describing nodes. Nodes that are not part of standard VRML must write out a description of their fields first, so that all VRML implementations are able to parse and ignore the extensions.
This description is written just after the opening curly-brace for the node, and consists of the keyword 'fields' followed by a list of the types and names of fields used by that node, all enclosed in square brackets and separated by commas. For example, if Cube was not a standard VRML node, it would be written like this:
Cube { fields [ SFFloat width, SFFloat height, SFFloat depth ] width 10 height 4 depth 3 }
Specifying the fields for nodes that ARE part of standard VRML is not an error; VRML parsers must silently ignore the field[] specification. However, incorrectly specifying the fields of a built-in node is an error.
The fields specification must be written out with every non-standard node, whether or not that node type was previously encountered during parsing. For each instance of a non-standard node, only the fields written as part of that instance need to be described in the fields[] specification; that is, fields that aren't written because they contain their default value may be omitted from the fields[] specification. It is expected that future versions of VRML will relax this requirement, requiring only that the first non-standard node of a given type be given the fields[] specification.
Just like standard nodes, instances of non-standard nodes do not automatically share anything besides the default values of their fields, which are not specified in the VRML file but are considered part of the implementation of the non-standard nodes.
A new node type may also be a superset of an existing node that is part of the standard. In this case, if an implementation for the new node type cannot be found the new node type can be safely treated as as the existing node it is based on (with some loss of functionality, of course). To support this, new node types can define an MFString field called 'isA' containing the names of the types of which it is a superset. For example, a new type of Material called "ExtendedMaterial" that adds index of refraction as a material property can be written as:
ExtendedMaterial { fields [ MFString isA, MFFloat indexOfRefraction, MFColor diffuseColor, MFFloat transparency ] isA [ "Material" ] indexOfRefraction .34 diffuseColor .8 .54 1 }
Multiple is-a relationships may be specified in order of preference; implementations are expected to use the first for which there is an implementation.
Note that IsA and PROTO are different ways to define new nodes, they should not be used together.
Nodes instantiated with isA should not copy default values or children from the first instantiation.
To allow extension nodes to be handled gracefully by browsers that don't recognise them, a alternateRep field is supported. This is an SFNode field that specifies what to use if the extension node is not recognised, typically it will be a WWWInline of a more complex representation, or of a CGI script which can generate the node dynamically, for example:
ColoredCube { isA Cube fields [ SFColor color ] color 2 0 0 alternateRep { WWWInline { name "http://foo.com/cgi/ColoredCube/2/0/0" } } }
Check the General Syntax section of this standard for the rules on valid characters in names.
To avoid namespace collisions with nodes defined by other people, any of the following conventions should be followed.
This is a longer example of a VRML scene. It contains a simple model of a track-light consisting of primitive shapes, plus three walls (built out of polygons) and a reference to a shape defined elsewhere, both of which are illuminated by a spotlight. The shape acts as a hyperlink to some HTML text.
#VRML V1.1 utf8 Separator { Separator { # Simple track-light geometry: Translation { translation 0 4 0 } Separator { Material { emissiveColor 0.1 0.3 0.3 } Cube { width 0.1 height 0.1 depth 4 } } Rotation { rotation 0 1 0 1.57079 } Separator { Material { emissiveColor 0.3 0.1 0.3 } Cylinder { radius 0.1 height .2 } } Rotation { rotation -1 0 0 1.57079 } Separator { Material { emissiveColor 0.3 0.3 0.1 } Rotation { rotation 1 0 0 1.57079 } Translation { translation 0 -.2 0 } Cone { height .4 bottomRadius .2 } Translation { translation 0 .4 0 } Cylinder { radius 0.02 height .4 } } } SpotLight { # Light from above location 0 4 0 direction 0 -1 0 intensity 0.9 cutOffAngle 0.7 } Separator { # Wall geometry; just three flat polygons Coordinate3 { point [ -2 0 -2, -2 0 2, 2 0 2, 2 0 -2, -2 4 -2, -2 4 2, 2 4 2, 2 4 -2] } IndexedFaceSet { coordIndex [ 0, 1, 2, 3, -1, 0, 4, 5, 1, -1, 0, 3, 7, 4, -1 ] } } WWWAnchor { # A hyperlinked cow: name "http://www.foo.edu/CowProject/AboutCows.html" Separator { Translation { translation 0 1 0 } WWWInline { # Reference another object name "http://www.foo.edu/3DObjects/cow.wrl" } } } }
This section describes the file naming and MIME conventions to be used in building VRML browsers and configuring WWW browsers to work with them.
The file extension for VMRL files is .wrl (for world).
The MIME type for VRML files is defined as follows:
x-world/x-vrml
The MIME major type for 3D world descriptions is x-world. The MIME minor type for VRML documents is x-vrml. Other 3D world descriptions, such as oogl for The Geometry Center's Object-Oriented Geometry Language, or iv, for SGI's Open Inventor ASCII format, can be supported by using different MIME minor types.
It is anticipated that the official type will change to "model/vrml", at this time servers should present files as being of type x-world/x-vrml, browsers should recognise both x-world/x-vrml and model/vrml.
I want to thank three people who have been absolutely instrumental in the design process: Brian Behlendorf, whose drive (and disk space) made this process happen; and Tony Parisi and Gavin Bell, the final authors of this specification, who have put in a great deal of design work, ensuring that we have a satisfactory product. My hat goes off to all of them, and to all of you who have made this process a success.
I would like to add a personal note of thanks to Jan Hardenbergh of Oki Advanced Products for his diligent efforts to keep the specification process on track, and his invaluable editing assistance. I would also like to acknowledge Chris Marrin of Silicon Graphics for his timely contributions to the final design.
VRML 1.1 is a result of years of effort from the Inventor group at Silicon Graphics. All of the past and present members of the Inventor team deserve recognition and thanks for their excellent work over the last five years.
22-NOV-95
The draft of the ISO UTF-8 proposal is online at: http://www.stonehand.com/unicode/standard/wg2n1036.html
The draft for making HTML internationalized is online. We are not as constrained as HTML, since VRML will rarely be primarily text. We can be a little less efficient. ftp://ftp.alis.com/pub/ietf/html/draft-ietf-html-i18n-00.txt
ftp://ftp.isi.edu/in-notes/rfc1766.txt
OpenGL specification and man pages are online: http://www.sgi.com/Technology/openGL/spec.html
Addison Wesley's "The Inventor Mentor" and "Open Inventor C++ Reference Manual" are invaluable.