![]() |
VR-Forces Developer's Guide
|
The VR-Forces Simulation Engine is responsible for updating all object state for each simulation frame, and publishing the updated state to the network. In order to accomplish this, the simulation engine provides data to the simulation models to take into account when computing updated state, including the state of other objects in the world (potentially received from the network), the terrain, weather, messages, and much more. All interaction with the simulation engine is done though network messages.
All persistent state in VRF Sim is maintained in VRF Objects, using the DtLocalObject class. These objects include:
The DtCgf class is the primary top level class in a VR-Forces Simulation Engine. It creates and owns all other classes that make up a VR-Forces simulation engine. This includes the Sim Manager, DtSimManager, which owns all of the other managers.
The simulation is run over a series of frames. Each call to DtCgf::tick() executes a single frame of the simulation. Most components of VR-Forces Simulation Engine have a tick() function which is called once per frame as a result of the top level DtCgf::tick().
The External State data of each object in the simulation is double buffered. This means that there are two copies of this data, referred to as Current Frame State and Next Frame State.
The VR-Forces Simulation Engine is a multithreaded application that can take advantage of many CPUs on the same physical hardware. Each simulation frame is broken into four major parts:
The double buffered state data for objects allows VR-Forces to simulate local objects using multiple threads, even when the objects need to access state of other objects in the simulation without requiring locking each time cross-object state is accessed.
This section runs at the start of each frame, and sets up any necessary data structures and subsystems for use during the frame execution. This section includes:
This section runs all the simulation logic for local objects simulated by the engine by calling the DtLocalObject::tick() for each local object simulated by the engine. This is typically the most processor intensive section of the simulation engine.
Multiple threads are used during Object Tick, and objects are distributed among the threads to execute simultaniously. Each DtLocalObject and all its subcomponents are always executed by the same thread, so data can be set and accessed freely within a single DtLocalObject, but other DtLocalObject instances cannot be accessed, as they are running in other threads at the same time.
This section synconizes the local engine data with the simulation network by calling tick() on the DtSimObjectNetInterface instances as well as other NetInterface classes.
Depending on the configuration, there may be multiple threads used for Network Tick, and the DtSimObjectNetInterface instances will be distributed among the available threads.
This section ends the execution of the frame by copying all needed data from the Next Frame State into Current Frame State.
Advance Frame runs once both Object Tick and Network tick have completed.
The Performance Monitor panel in the GUI allows you to monitor the performance of the sim engines and see how long they are taken in each of these parts of the simulation frame. For more details see Monitoring Performance of the Simulation Engine.
The Network Tick threads are responsible for sending data to the network and processing data from the network, using the chosen protocol, HLA or DIS. All simulation occurs in the other threads. As a result, and data passing between the simulation and the network must be passed in a threadsafe manner between these threads. Different types of data is transferred utilizing different mechanims. A brief overview of these mechanisms is outlined below.
Some classes are protocol specific and rely upon protocol specific VR-Link libraries. Protocol specific classes can only be used within the network threads, as only the VR-Forces network libraries are built with protocol specific versions. These means that many VR-Link classes, such as publishers, reflected lists, state repositories, and interactions, are only available to the network threads. This means that any data from these classes cannot be directly accessed by simulation threads, it must first be converted to an internal format.
One notable example is the DtGlobalObjectDesignator, a VR-Link concept for identifying an object that has different meanings in HLA and DIS. The DtGlobalObjectDesignator must be converted to a DtUUID before passing it to a simulation thread. From the network threads, this conversion can be made using functions available through the DtVrlinkNetworkInterface.
As mentioned in the section Doubled Buffered State, all external data for the simulation objects is stored in double buffered memory. This buffering scheme allows safe read access to current frame data from all threads, and safe write access to next frame data from entity state components in the Object Tick threads. All object state data is passed between the network and simulation threads using this mechanism.
Events that occur in the simulation are generally sent over the network as interactions. These interactions are fleeting events, and therefore do not have persistent data that should be stored for extended periods as object state data. Events are communicated via the DtEventManager. This manager handles the translation from VR-Link interactions to internal VR-Forces events.
VR-Forces messages to and from simulation objects are sent via the DtVrfObjectCommunicationInterface. This includes messages sent via simulated radio as well as internal messages.