In short, for single-player games, the current
idea of time origin ("January 1, 1970") in VRML / X3D is uncomfortable.
Castle Game Engine complies with VRML/X3D standard in this regard anyway,
although you can change it
by using our extension NavigationInfo.timeOriginAtLoad
.
What's the problem?
VRML/X3D have an idea that time stored in SFTime
corresponds to a real-world time. More precisely, it's the number
of seconds since 00:00:00 GMT January 1, 1970.
This affects time-dependent
nodes behavior, like TimeSensor
and MovieTexture
,
and timestamps generated by events.
As far as I'm concerned, this is a bad idea.
Any general-purpose VRML/X3D browser must
honor it in some way, not necessarily by using real-world
time, but at least by setting initial time to some very large value.
Reason: otherwise many animations in VRML/X3D files start playing
immediately after file is loaded, and VRML/X3D authors don't expect
this. Default field values are designed such that
a default time-dependent node (with default loop = FALSE
)
should play one cycle from time 0 to the end of it's cycle.
If a browser starts with real-world time value, this is
a very large time value,
larger than usual cycle interval, so node will not play at all.
So VRML/X3D authors learned to expect that actually "default values for time-dependent nodes mean that node doesn't play when file is loaded".
Why this state is bad in my opinion?
The main problem is that honoring this rule literally would prevent user from pausing the animation. If you continuously supply time values as real-world time, there's no way to just "pause" the animation. It may not be rendered for some time, but real-world time is always ticking. That's why it's called "real" world time after all.
That's why Castle Game Engine and view3dscene don't really supply real-world time. Although initial VRML/X3D time is taken from real-world time, it's not guaranteed to be synchronized with real-world time. As soon as you pause the animation, or open some modal window, time pass is paused, and VRML/X3D world time is no longer synchronized with real-world time. This way you can "pause" the animation, which is a very useful feature in our opinion.
Another trouble is that VRML/X3D authors cannot easily synchronize
starting of the animation with loading of the file.
startTime = 0
is useless, as "0" means "January 1, 1970".
For constantly looping animations (loop = TRUE
,
rest of the fields as default) this is also a problem,
as you have no idea in what stage of the animation you
are when loading the file.
And the default outputs of TimeSensor.elapsedTime
and TimeSensor.time
are incredibly large values.
Which means you have to be careful when operating on them.
Passing these large values to shaders is usually a bad idea, since they
will be rounded to something useless.
Making some "welcome" animation
requires you to use tricks to route some
sensor like ProximitySensor
(positioned to
include default viewpoint) to time-dependent node.
The trick looks a little ugly, like this:
DEF MyProximitySensor ProximitySensor { size 10000000 10000000 10000000 } # some size that is in practice infinite DEF MyTimeSensor TimeSensor { loop TRUE } ROUTE MyProximitySensor.enterTime TO MyTimeSensor.startTime ROUTE MyTimeSensor.elapsedTime TO ... # this starts from zero and grows
That's why view3dscene allows VRML/X3D author to
change VRML/X3D time origin by NavigationInfo.timeOriginAtLoad
.
This allows you to use startTime = 0
predictably.
Also, user has menu item "Animation -> Rewind to the
Beginning", for testing.
It allows to simply write:
NavigationInfo { timeOriginAtLoad TRUE } DEF MyTimeSensor TimeSensor { loop TRUE } ROUTE MyTimeSensor.time TO ... # this starts from zero and grows
When using my engine to develop your own games, you can
simply start VRML/X3D time from 0.0 (by TCastleSceneCore.ResetTime(0.0))
,
or to any other value you want. For example, setting it to some
large but determined value, like exactly a million, allows
you to work correctly with standard animations and at the same
time you're able to express startTime
relative to loading time.
Large time values are not nice to show to the user.
It's strange to average user to see time value like
1220626229.13
immediately after opening the file.
And manual input
of such time values is difficult. This is a pity,
as sometimes I really have to ask or show VRML/X3D time
for user: for example when recording the VRML/X3D animation
(view3dscene can record animation to the movie,
or as a precalculated animation), and for things
like Logger
node output timestamps.
To remedy this at least a little, view3dscene displays time
as World time: load time + %f = %f for standard VRML/X3D files
(that do not use timeOriginAtLoad = TRUE
).
This way user sees also the simpler time (since load).
A minor problem is also that user doesn't expect different behavior of VRML/X3D world depending on the real-world time at which it is loaded. True, it opens some interesting possibilities (VRML/X3D world may adjust to real-world day/night state for example), but also some nightmarish scenarios ("VRML/X3D world crashes with segfault but only when opened ~5 minutues after the midnight" — now imagine you have to debug this :) ).
More sane definition of "time origin" would seem to be
"for single-user games, time origin 0.0 is equivalent to the time when
browser finished initialization
and presented VRML/X3D world to the user, starting VRML/X3D sensors listening
and events processing". (For multi-player games over the network,
real-world time or some other server time may be more appropriate indeed.)
Actually this is exactly done
when our extension NavigationInfo.timeOriginAtLoad = TRUE
.
This also means that time-dependent node with all fields set as default
plays exactly once when the model is loaded — which is actually quite
sensible default behavior for me. (You can always set for example
startTime = -1
and stopTime = -0.5
to prevent node from playing.)