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.