Our engine handles both VRML 1.0 and VRML 2.0. As we have seen in Chapter 1, Overview of VRML, there are important differences between these VRML versions. The way how I decided to handle both VRML versions is the more difficult, but also more complete approach. Effectively, you have the sum of VRML 1.0 and 2.0 features available.
I decided to avoid trying to create some internal conversions from VRML 1.0 to VRML 2.0, or VRML 2.0 to 1.0, or to some newly invented internal format. I wanted to have a full, flexible, 100% conforming to VRML 1.0 and VRML 2.0 specifications engine. And the fact is that any conversion along the way will likely cause problems — ideologically speaking, that's because there is always something lost, or at least difficult to recover, when a complicated conversion is done.
Practically here are some reasons why a simple conversion between VRML 1.0 and VRML 2.0 is not possible, in any direction:
VRML 2.0 specification authors intentionally wanted to simplify some things that people (both VRML world authors and VRML browser implementors) thought were unnecessarily complicated in VRML 1.0. This causes problems for a potential converter from VRML 1.0 to 2.0, since it will have trouble to express some VRML 1.0 constructs. For example:
In VRML 1.0 you can specify multiple materials for a single geometry node. In VRML 2.0 each geometry node uses at most one material. So a potential converter from VRML 1.0 to 2.0 may need to split geometry nodes.
In VRML 1.0 you can accumulate texture transformations (
Texture2Transformnodes). In VRML 2.0 you can't (you can only place one
TextureTransformnode in the
Appearance.textureTransformfield). So a potential converter must accumulate texture transformations on it's own. And this is not trivial in a general case, because you can't directly specify texture transformation matrix in VRML 2.0. Instead you have to express texture transformation in terms of one translation, one rotation and one scaling.
In VRML 1.0 you can specify any 4x4 matrix transformation using
MatrixTransformationnode. This is not possible at all in VRML 2.0. In VRML 2.0 geometry transformation must be specified in terms of translations, rotations and scaling.
In VRML 1.0 you can limit which geometry nodes are affected by
SpotLightby placing light nodes at particular points in the node hierarchy. That's because in VRML 1.0 light nodes work just like other “state changing” nodes: they affect all subsequent nodes, until blocked by the end of the
In VRML 2.0 this doesn't work. You cannot control what parts of the scene are affected by light nodes by placing light nodes at some particular place in the node hierarchy. Instead, you have to use
radiusfield of light nodes. This means that some VRML 1.0 tricks are simply not possible.
OrthographicCamerais not possible to express using VRML 2.0 standard nodes.
Summary: in certain cases translating VRML 1.0 to 2.0 can be very hard or even impossible. If we want to handle VRML 1.0 perfectly, we can't just write a converter from VRML 1.0 to 2.0 and then define every operation only in terms of VRML 2.0.
On the other hand, VRML 2.0 also includes various things not present in VRML 1.0. This includes many new nodes, that often cannot be expressed at all in VRML 1.0: all sensors, scripts, interpolators, special things like
Moreover, VRML 2.0 uses
MFNode, and generally reduces the state that needs to be remembered when processing VRML graph. This means that many existing features have to be expressed differently.
For example consider specifying normals for
IndexedFaceSet. In VRML 2.0 everything that decides about how generated normals are supplied are the
normalIndexfields of given
IndexedFaceSetnode. We take advantage of the
SFNodefield type, and say that whole
Normalnode may be just placed within
IndexedFaceSet. So we just keep whole knowledge inside
On the other hand, in VRML 1.0 we have to use the value of last
NormalBindingnode. This says whether we should use the last
Normalnode, and how.
Potential VRML 2.0 to 1.0 converter would have to make a lot of effort to “deconstruct” VRML 2.0 shape properties back to VRML 1.0 state nodes. This makes conversion difficult to revert (e.g. when we want to write VRML 2.0 content back to file).
That's why I decided to support in my engine the sum of all VRML features.
For example, VRML 1.0 nodes can have direct children nodes, so I support it
Children property of
VRML 2.0 nodes can have children nodes through
MFNode fields, so I support it too.
I'm not trying hard to “combine”
these two ideas (direct children nodes and children inside
MFNode) into one
— I just implement and handle them both
In some cases this approach forces me to do more work. For example, for many routines that calculate bounding boxes of geometry nodes, I had to prepare three routines:
Common implementation, as a static procedure inside the
X3DNodesunit. This handles actual calculation and as parameters expects already calculated properties of given shape. As a simple example, when calculating bounding box of a cube, we expect to get three parameters describing cube's sizes in X, Y and Z dimension.
VRML 1.0 implementation in VRML 1.0-specific node version that calls the common implementation, after preparing parameters for common implementation. As a simple example,
TNodeCube_1(VRML 1.0 cube) just uses it's
FdDepthas appropriate sizes.
And VRML 2.0 implementation in VRML 2.0-specific node version, that also calls the common implementation after preparing it's parameters. As a simple example,
TNodeBox(VRML 2.0 cube) accesses three items of it's
FdSizefield to get the appropriate sizes.
In our simple example above we talked about a cube,
and the whole issue with calculating three size values differently
for VRML 1.0 and 2.0 was actually trivial.
But the point is that for some nodes,
IndexedFaceSet, this is much harder.
For VRML authors this “sum” approach means that when reading VRML 1.0, many VRML 2.0 constructs (that not conflict with anything in VRML 1.0) are allowed, and the other way around too. That's why you can actually mix VRML 1.0 and 2.0 code in my engine.
Update in 2022: As VRML 1.0 format is now ancient and maintaining it has been some work, this "sum" feature has been a little "downgraded". It is still possible to use many VRML 2.0 / X3D nodes in VRML 1.0, but not the other way around. That is, you can no longer use VRML 1.0 nodes in files declared as VRML 2.0 / X3D.
This also means that you have many VRML 2.0 features available
in VRML 1.0. VRML 2.0 nodes like
Fog and many others, that express features not available
at all in standard VRML 1.0, may be freely placed inside VRML 1.0 models
when using our engine.
Also including (using
Inline nodes) VRML 1.0 files within VRML 2.0
files (and the other way around) is possible. Each VRML file will
be parsed taking into account it's own header line, and then included
content is actually placed as a children node of including
So you get VRML graph hierarchy with nodes mixed from both VRML versions.
mentioned in the previous section somewhat combine
VRML 1.0 and 2.0 ideas of children nodes, but they are generally not used
except in some small pieces of code where they just make the code