Within this section, we provide a brief overview of the
member functions from the base VR Juggler application interface.
This interface is defined by
vrj::App, and the member functions are shown in Figure 2.3, “Application object interface”. Refer to Figure 2.2, “Kernel loop sequence” for a visual presentation
of the order in which the methods are invoked.
The base interface of the application object defines the following functions:
init()
apiInit()
preFrame()
intraFrame()
postFrame()
As previously described, the VR Juggler kernel calls these functions from its control loop to allocate processing time to them. These functions handle initialization and computation. Other member functions that can be used for reconfiguration, focus control, resetting, and exiting will be covered later in this book.
The following is a description of the application objects related to the initialization of a VR Juggler application. The order of presentation is the same as the order of execution when the application is executed by the kernel.
The init() method is called
by the kernel to initialize any application data. When the
kernel prepares to start a new application, it first calls
init() to signal the application
that it is about to be executed.
This member function is called immediately after the kernel is told to start running the application and before any graphics API handling has been started by VR Juggler.
This member function is for any graphics API-specific initialization required by the application. Data members that cannot be initialized until after the graphics API is started should be initialized here.
In OpenGL, there is no concept of initializing the API, so this method is normally empty in such applications.
This member function is called after the graphics API has been started but before the kernel frame is started.
Once the application object has been initialized by the VR Juggler kernel, the kernel frame loop begins. Each frame, there are specific application object methods that are invoked, and understanding the timing and potential uses of these methods can improve the functionality of the immersive application. In some cases, it is possible to use these member functions to optimize the application to improve the frame rate and the level of interactivity.
As of VR Juggler 2.0 Alpha 1, applications can specify
the units of measure that are the basis for the graphics
they render. The default unit of measure is feet (identified
by the constant scale factor
gadget::PositionUnitConversion::ConvertToFeet)
to maintain backwards compatibility with the previous VR
Juggler semantics. By overriding this method, applications
can identify the unit of measure they expect. The default
implementation is the following:
float vrj::App::getDrawScaleFactor()
{
return gadget::PositionUnitConversion::ConvertToFeet;
}Overriding this method means changing the rendering
scale factor used by the VR Juggler Draw Managers. The
current list of constants (defined in
gadget/Position/PositionUnitConversion.h)
is as follows:
gadget::PositionUnitConversion::ConvertToFeet
gadget::PositionUnitConversion::ConvertToInches
gadget::PositionUnitConversion::ConvertToMeters
gadget::PositionUnitConversion::ConvertToCentimeters
Because the value returned is simply a scaling factor, user applications can define whatever units they want. Note that internally, VR Juggler is treating all units as meters, so the scaling factor converts from meters to the desired units.
The preFrame() method is
called when the system is about to trigger drawing. This is
the time that the application object should do any
last-minute updates of data based on input device status. It
is best to avoid doing any time-consuming computation in
this method. The time used in this method contributes to the
overall device latency in the system. The devices will not
be re-sampled before rendering begins.
The latePreFrame() method is
called after preFrame() and after
shared application-specific data is synchronized among the
cluster nodes (see the section called “Cluster Application Programming”
for more details) but before the scene is rendered. Scene
graph-based application objects making use of
application-specific data in a cluster configuration should
perform scene graph updates based on the most recently
received copy of the shared application data. Application
objects not using a scene graph can make state updates in
this method or in the rendering method
(draw() in the case of
vrj::GlApp). The writer node must
have written to the shared application data in
preFrame() to minimize the latency
of the data.
This method is called after application-specific data is sychronized among the cluster nodes but before triggering rendering of the current frame.
When using shared application-specific data with a
scene-graph based application object in a cluster
configuration, the nodes that read from the shared data
(those where
cluster::UserData<T>::isLocal()
returns false) should perform state updates based on the
freshly received update to the shared data.
The code in this method executes in parallel with the rendering method. That is, it executes while the current frame is being drawn. This is the place to put any processing that can be done in advance for the next frame. By doing parallel processing in this method, the application can increase its frame rate because drawing and computation can be parallelized. Special care must be taken to ensure that any data being used for rendering does not change while rendering is happening. One method for doing this is buffering. Use of synchronization primitives is not recommended because that technique could lower the frame rate.
This method is invoked after rendering has been triggered but before the rendering has finished.
Finally, the postFrame()
method is available for final processing at the end of the
kernel frame loop. This is a good place to do any data
updates that are not dependent upon input data and cannot be
overlapped with the rendering process (see the discussion on
vrj::App::intraFrame()
above).
This method is invoked after rendering has completed but before VR Juggler updates devices and other internal data.