Chapter
2 Key Concepts
2.1 Intro
2.1.1 Overview
2.1.2 TOC
2.1.3 Conventions
2.2 Overview
2.2.1 File Structure
2.2.2 Header
2.2.3 Scene graph
2.2.4 Prototypes
2.2.5 Routing
2.2.6 Generating files
2.2.7 Presentation
& Interaction
2.2.8 Profiles
2.3 UTF-8 syntax
2.3.1 Clear text
2.3.2 Statements
2.3.3 Node
2.3.4 Field
2.3.5 PROTO
2.3.6 IS
2.3.7 EXTERNPROTO
2.3.8 USE
2.3.9 ROUTE
2.4 Scene graph
2.4.1 Root nodes
2.4.2 Hierarchy
2.4.3 Descendants
& ancestors
2.4.4 Hierarchy
2.4.5 Units & coord sys
2.5 VRML & WWW
2.5.1 MIME type
2.5.2 URLs
2.5.3 Relative URLs
2.5.4 data:
2.5.5 Scripting protocols
2.5.6 URNs
2.6 Nodes
2.6.1 Intro
2.6.2 DEF/USE
2.6.3 Geometry
2.6.4 Bboxes
2.6.5 Grouping & children
2.6.6 Lights
2.6.7 Sensors
2.6.8 Interpolators
2.6.9 Time nodes
2.6.10 Bindable children
2.6.11 Textures
2.7 Field, eventIn,
& eventOut
2.8 PROTO
2.8.1 Declaration
2.8.2 Definition
2.8.3 Scoping
2.9 EXTERNPROTO
2.9.1 Interface
2.9.2 URL
2.9.3 Extensions
2.10 Events
2.10.1 Intro
2.10.2 Routes
2.10.3 Execution
2.10.4 Loops
2.10.5 Fan-in & fan-out
2.11 Time
2.11.1 Intro
2.11.2 Origin
2.11.3 Discrete/cont
2.12 Scripting
2.12.1 Intro
2.12.2 Execution
2.12.3 Initialize/shutdown
2.12.4 eventsProcessed
2.12.5 Direct outputs
2.12.6 Asynchronous
2.12.7 Languages
2.12.8 EventIns
2.12.9 fields & events
2.12.10 Browser interface
2.13 Navigation
2.13.1 Intro
2.13.2 Navigation
2.13.3 Viewing
2.13.4 Collisions
2.14 Lighting
2.14.1 Intro
2.14.2 'off'
2.14.3 'on'
2.14.4 Equations
2.14.5 References
|
The PROTO statement defines a new node type
in terms of already defined (built-in or prototyped) node types. Once
defined, prototyped node types may be instantiated in the scene graph
exactly like the built-in node types.
Node type names must be unique in each VRML
file. Defining a prototype with the same name as a previously defined
prototype or a built-in node type is an error.
TECHNICAL
NOTE: Prototypes have many possible uses and can be thought
of as:
- An extensibility
mechanism that allows a new node type to be defined in terms
of other, predefined nodes. Prototypes replace the VRML 1.0
extension features (isA and fields[]) with a single, more general
mechanism.
- A protection
mechanism that allows an author to limit what can be done to
an object. The only way to violate the interface defined by
a prototype is to make a copy of its implementation and modify
the copy.
- A method
of defining a library of reusable objects
- An object-definition
mechanism that allows someone to impose application--specific
policies on top of the general VRML scene structure
- A convenience
mechanism that allows geometry and/or behavior to be packaged
in an easy-to-use way
- An optimization
mechanism that allows browsers to reason about which objects
can and cannot be changed
- A bandwidth-saving
mechanism that allows the definition of a world structure to
be defined once and reused multiple times, and allows the creation
of abbreviations for commonly used nodes
- An alternative
to DEF/USE instancing
Prototypes
give VRML 2.0 much of its flexibility. Many arguments about the
details of the VRML design were ended by pointing out that the
feature in question can be implemented using the prototyping mechanism
and the built-in nodes.
|
The prototype interface defines the fields,
eventIns, and eventOuts for the new node type. The interface declaration
includes the types and names for the eventIns and eventOuts of the prototype,
as well as the types, names, and default values for the prototype's
fields.
The interface declaration may contain exposedField
declarations, which are a convenient way of defining an eventIn, field,
and eventOut at the same time. If an exposedField named zzz is
declared, it is equivalent to declaring a field named zzz, an
eventIn named set_zzz, and an eventOut named zzz_changed.
Each prototype instance can be considered to
be a complete copy of the prototype, with its own fields, events, and
copy of the prototype definition. A prototyped node type is instantiated
using standard node syntax. For example, the following prototype (which
has an empty interface declaration):
PROTO Cube [ ] { Box { } }
may be instantiated as follows:
Shape { geometry Cube { } }
It is recommended that user-defined field or
event names defined in PROTO interface declarations statements follow
the naming conventions described in "2.7 Fields, eventIns, and eventOuts semantics."
TECHNICAL
NOTE: The prototype declaration defines its interface--how
the prototype communicates with the rest of the scene and what parameters
may be set for each instance of the prototype. |
TECHNICAL
NOTE: VRML's
prototyping mechanism is not equivalent to the object-oriented notion
of inheritance. Object-oriented notions such as superclass and subclass
are consciously kept out of the VRML specification, although many
of the node classes are designed to make an object-oriented implementation
straightforward. For example, the Transform node can be implemented
as a subclass of the Group node, and all of the interpolator nodes
can share much of their code in a common base class. Anticipating
implementation needs but not requiring any particular implementation
was another of the many design constraints on VRML. Because
the second and subsequent root nodes in a PROTO definition are not
part of the scene's transformation hierarchy, only the following
node types should be used there: Script, TimeSensor, and interpolators.
Using any of the other node types as the second or subsequent root
of a PROTO is never useful, but is not prohibited because there
were no compelling reasons to do so. |
A prototype definition consists of one or more
root nodes, nested PROTO statements, and ROUTE statements. The first
node found in the prototype definition is used to define the node type
of this prototype. This first node type determines how instantiations
of the prototype can be used in a VRML file. An instantiation is created
by filling in the parameters of the prototype declaration and inserting
copies of the first node (and its scene graph) wherever the prototype
instantiation occurs. For example, if the first node in the prototype
definition is a Material node, instantiations of the prototype can be
used wherever a Material can be used. Any other nodes and accompanying
scene graphs are not part of the transformation hierarchy, but may be
referenced by ROUTE statements or Script nodes in the prototype definition.
TECHNICAL
NOTE: The prototype definition is the implementation of the
prototype, defining exactly what the prototype does in terms of
other prototypes and built-in node |
Nodes in the prototype definition may have their
fields, eventIns, or eventOuts associated with the fields, eventIns,
and eventOuts of the prototype interface declaration. This is accomplished
using IS statements in the body of the node. When prototype instances
are read from a VRML file, field values for the fields of the prototype
interface may be given. If given, the field values are used for all
nodes in the prototype definition that have IS statements for those
fields. Similarly, when a prototype instance is sent an event, the event
is delivered to all nodes that have IS statements for that event. When
a node in a prototype instance generates an event that has an IS statement,
the event is sent to any eventIns connected (via ROUTE) to the prototype
instance's eventOut.
IS statements may appear inside the prototype
definition wherever fields may appear. IS statements shall refer to
fields or events defined in the prototype declaration. It is an error
for an IS statement to refer to a non-existent declaration. It is an
error if the type of the field or event being associated does not match
the type declared in the prototype's interface declaration. For example,
it is illegal to associate an SFColor with an SFVec3f. It is also illegal
to associate an SFColor with an MFColor or vice versa.
It is illegal for an eventIn to be associated
with a field or an eventOut, an eventOut to be associated with a field
or eventIn, or a field to be associated with an eventIn or eventOut.
An exposedField in the prototype interface may be associated only with
an exposedField in the prototype definition, but an exposedField in
the prototype definition may be associated with either a field, eventIn,
eventOut or exposedField in the prototype interface. When associating
an exposedField in a prototype definition with an eventIn or eventOut
in the prototype declaration, it is valid to use either the shorthand
exposedField name (e.g., translation) or the explicit event
name (e.g., set_translation or translation_changed).
Table 2-4 defines the rules for mapping between the prototype declarations
and the primary scene graph's nodes (yes denotes a legal mapping,
no denotes an error).
Table 2-4: Rules for
mapping PROTOTYPE declarations to node instances
|
Prototype
declaration |
Prototype
scene
graph |
|
exposedField |
field |
eventIn |
eventOut |
exposedField |
yes |
yes |
yes |
yes |
field |
no |
yes |
no |
no |
eventIn |
no |
no |
yes |
no |
eventOut |
no |
no |
no |
yes |
|
Results are undefined if a field, eventIn, or
eventOut of a node in the prototype definition is associated with more
than one field, eventIn, or eventOut in the prototype's interface (i.e., multiple
IS statements for a field/eventIn/eventOut in a node in the prototype
definition), but multiple IS statements for the fields/eventIns/eventOuts
in the prototype interface declaration is valid. Results are undefined
if a field of a node in a prototype definition is both defined with
initial values (i.e., field statement) and associated by an IS
statement with a field in the prototype's interface. If a prototype
instance has an eventOut E associated with multiple eventOuts
in the prototype definition ED i , the value of E is the value of the eventOut that generated
the event with the greatest timestamp. If two or more of the eventOuts
generated events with identical timestamps, results are undefined.
TECHNICAL
NOTE: ExposedFields are really just a shorthand notation for
the combination of an eventIn, an eventOut, and a field, along with
the semantics that eventOuts are generated whenever eventIns are
received. Allowing the eventIn portion of an exposedField to be
referred to without its set_ prefix and the eventOut portion without
its _changed suffix makes it easier to create VRML files in a text
editor, but makes both the specification and implementations a little
more complicated. |
TECHNICAL
NOTE: Allowing
multiple eventIns to be mapped to the same prototype parameter
is a convenient way to do ROUTE fan-out transparently. For example,
you might want a prototype that starts several TimeSensors when
it receives a set_startTime eventIn:
PROTO Animations [ eventIn SFTime set_startTime ] {
DEF ANIM1 TimeSensor {
set_startTime IS set_startTime
cycleInterval 4.5
}
DEF ANIM2 TimeSensor {
set_startTime IS set_startTime
cycleInterval 11.3
}
}
Instantiating
and ROUTE-ing to an Animations object, like this:
DEF ANIMS Animations { }
DEF SENSOR TouchSensor { }
ROUTE SENSOR.touchTime TO ANIMS.set_startTime
is equivalent
to doing this:
DEF ANIM1 TimeSensor { cycleInterval 4.5 }
DEF ANIM2 TimeSensor { cycleInterval 11.3}
DEF SENSOR TouchSensor { }
ROUTE SENSOR.touchTime TO ANIM1.set_startTime
ROUTE SENSOR.touchTime TO ANIM2.set_startTime
Similarly,
allowing multiple eventOuts to be mapped to the same prototype
parameter allows implicit fan-in and, like regular ROUTE fan-in,
care must be taken to ensure that indeterministic situations
are not created. For example, events from this PROTO's out eventOut
are undefined:
PROTO BAD [
eventIn SFTime set_startTime
eventOut SFFloat out ]
{
DEF ANIM1 TimeSensor {
set_startTime IS set_startTime
cycleInterval 4.5
fraction_changed IS out
}
DEF ANIM2 TimeSensor {
set_startTime IS set_startTime
cycleInterval 11.3
fraction_changed IS out
}
}
Although
legal syntactically, such a construction makes no sense semantically.
In general, it is best to avoid associating multiple eventOuts
with a single prototype parameter.
|
Prototype definitions appearing inside a prototype
definition (i.e., nested) are local to the enclosing prototype.
IS statements inside a nested prototype's implementation may refer to
the prototype declarations of the innermost prototype.
A PROTO statement establishes a DEF/USE name
scope separate from the rest of the scene and separate from any nested
PROTO statements. Nodes given a name by a DEF construct inside
the prototype may not be referenced in a USE construct outside of the
prototype's scope. Nodes given a name by a DEF construct outside
the prototype scope may not be referenced in a USE construct inside
the prototype scope.
A prototype may be instantiated in a file anywhere
after the completion of the prototype definition. A prototype may not
be instantiated inside its own implementation (i.e., recursive
prototypes are illegal).
TECHNICAL
NOTE: A PROTO definition is almost like a completely separate
VRML file inside the VRML file. The only communication between the
main file and the nodes in the PROTO definition must occur through
the parameters defined in the prototype declaration, which is why
it is not possible to DEF a node in the main file and USE it inside
the prototype's definition or vice versa. However, prototypes can
be defined in terms of other prototypes. PROTOs defined before the
PROTO definition may be used inside the PROTO's definition, although
the converse is not true (PROTOs defined inside a prototype definition
are not available outside of that definition). |
TECHNICAL
NOTE: Like ROUTE statements, the position of a PROTO definition
in a file is irrelevant; the only constraint is that the PROTO appear
in the file before any instance of the prototype. Tools that read
and write VRML files will typically put all PROTO definitions at
the top of the file. |
TECHNICAL
NOTE: Each prototype instance is, conceptually, a completely
new copy of the prototype's definition inserted into the scene.
Each instance of a prototype must act independently of any other
instance. The USE keyword, on the other hand, inserts the same
object into the scene again. If it weren't for this key difference,
PROTO could replace the USE statement. The following DEF/USE statements:
DEF Something Transform { ... }
USE Something
are almost
equivalent to the following:
PROTO Something [ ] { Transform { ... } }
Something { }
Something { }
The first
two statements define and create a Something node, very much like
the previous DEF statement. And, instantiating another Something
node is very much like the USE statement. The key difference is
that in the first example there is only one Transform node, while
in the second example there are two different nodes.
Smart implementations
can determine which parts of a prototype instance can't possibly
change and can automatically share those parts of the prototype
definition between instances. For example, the Transform node
of the Something prototype can never change because none of its
eventIns are exposed in the prototype's interface, and Transform
is not given a name so there cannot be any ROUTE statements inside
the prototype that refer to it. If none of Transform's children
can change either, then implementations can create just one Transform
node to save memory. In VRML, there is no way to tell the difference
between two copies of a node if the copies are identical and cannot
change, which allows implementations to optimize and create just
one copy.
|
|