VR-Engage  2.2
Loading...
Searching...
No Matches
VR-Forces Integration

The VR-Engage backend process (vrEngageSim.exe) builds upon VR-Forces, MAK's simulation engine. This architecture provides access to entity modeling, physics simulation, terrain interaction, and network interoperability. This section covers how VR-Engage extends VR-Forces when developing backend components that model vehicle dynamics, weapon systems, sensor behavior, and other simulation logic.

The backend process hosts the authoritative simulation logic that determines entity behavior, physics response, and system state. While the frontend handles user input and visualization, the backend calculates vehicle dynamics, weapon effects, sensor performance, and damage assessment. This separation produces consistent simulation results across distributed exercises and allows the same physics to drive both player-controlled and AI-controlled entities.

Architecture overview

This section describes the backend architecture and extension patterns that VR-Engage uses to build on VR-Forces.

Prerequisites

This documentation assumes familiarity with VR-Forces toolkit development. Developers should understand VR-Forces entity modeling, the simulation component system, and plugin architecture before extending VR-Engage's backend. The VR-Forces Developer's Guide provides comprehensive coverage of these topics.

VR-Engage backend development requires these VR-Forces concepts:

Entity and Component Model: VR-Forces entities consist of simulation objects with attached components that implement behavior. Components derive from DtSimComponent and participate in the simulation tick cycle. VR-Engage extends this model with player-control-aware components.

System Definitions: VR-Forces uses .sysdef files to configure entity systems including weapons, sensors, and actuators. These Lisp-format files define component types, parameters, and interconnections. VR-Engage adds system definition templates for player-controlled variants.

Joystick Function System: VR-Forces provides a joystick function mechanism for mapping control inputs to entity behaviors. VR-Engage uses this system to route frontend input to backend actuators.

Plugin Architecture: VR-Forces simulation plugins register component factories and extend entity behavior through documented entry points (DtInitializeVrfPlugin, DtPostInitializeVrfPlugin). VR-Engage backend plugins follow the same pattern.

Object State Repository: VR-Forces maintains entity state through the object state repository, which VR-Engage components read and write to synchronize with frontend displays.

VR-Engage extension patterns

VR-Engage extends VR-Forces in several ways to support player-controlled entities. These extension patterns indicate where to find appropriate base classes and integration points.

Player Control Detection: VR-Engage components distinguish between CGF-controlled and player-controlled operation. The DtVreSimComponent template class provides isPlayerControlled() to check control state, allowing components to adjust behavior based on control authority.

Frontend Message Integration: While VR-Forces entities respond to tasks and plans, VR-Engage entities also respond to real-time input from frontend processes. The message routing infrastructure delivers frontend commands to appropriate backend components.

Actuator Coexistence: VR-Engage entities can transition between player and CGF control during runtime. This requires coordinating VR-Engage actuators with VR-Forces CGF actuators to prevent conflicting commands.

Multi-Session Support: VR-Engage supports multiple players controlling different roles on the same entity. The backend routes inputs from multiple frontend sessions to appropriate subsystems based on role authority.

State Synchronization: VR-Engage components publish state changes to connected frontends in addition to the standard DIS/HLA network publication. This dual publication keeps frontend displays synchronized with backend simulation state.

Backend process role

The backend process hosts the authoritative simulation state for player-controlled entities. While the frontend handles visualization and user input, the backend calculates physics, processes damage, evaluates sensor detection, and publishes entity state to the distributed simulation network. This separation maintains simulation fidelity regardless of frontend frame rate fluctuations.

flowchart TB
    subgraph Frontend["Frontend Process (vrEngage.exe)"]
        Input["Input Manager"]
        Visual["Visualization"]
        UI["User Interface"]
    end

    subgraph Backend["Backend Process (vrEngageSim.exe)"]
        subgraph VRF["VR-Forces Engine"]
            EntityMgr["Entity Manager"]
            Physics["Physics Engine"]
            Terrain["Terrain System"]
            Network["Network Publisher"]
        end

        subgraph VRE["VR-Engage Extensions"]
            VreManager["VrfModelManager"]
            Components["VRE Components"]
            Actuators["Actuator Components"]
            Sensors["Sensor Components"]
        end
    end

    Input -->|Commands| VreManager
    VreManager --> Components
    Components --> Actuators
    Components --> Sensors
    Actuators --> Physics
    Sensors --> EntityMgr
    Physics --> Network
    Network -->|State Updates| Visual

The VR-Engage extension layer wraps VR-Forces functionality, providing a simplified interface for common operations while preserving access to the full VR-Forces API when needed. This layered approach addresses typical use cases while supporting customization.

Backend simulation logic operates within the VR-Forces framework, extending entity models with VR-Engage-specific behavior. The simulation architecture layers VR-Engage components on top of VR-Forces entity management, with each layer providing specific capabilities.

flowchart TB
    subgraph VREComponents["VR-Engage Components"]
        Actuators2["Actuator Components"]
        Sensors2["Sensor Components"]
        Weapons["Weapon Components"]
        Systems["System Components"]
    end

    subgraph VRFEntity["VR-Forces Entity"]
        VrfModel2["DtSimObject"]
        StateRepo["State Repository"]
        PhysicsModel["Physics Model"]
    end

    subgraph PhysicsEngines["Physics Engine"]
        Vortex["Vortex Dynamics"]
        RTDynamics["RTDynamics"]
        Custom["Custom Physics"]
    end

    subgraph TerrainSys["Terrain System"]
        TerrainDB["Terrain Database"]
        Collision["Collision Detection"]
    end

    Actuators2 --> VrfModel2
    Sensors2 --> VrfModel2
    Weapons --> VrfModel2
    Systems --> VrfModel2

    VrfModel2 --> StateRepo
    VrfModel2 --> PhysicsModel

    PhysicsModel --> Vortex
    PhysicsModel --> RTDynamics
    PhysicsModel --> Custom

    PhysicsModel --> Collision
    Collision --> TerrainDB

Each VR-Engage entity uses standard VR-Forces entity management with VR-Engage simulation components attached via system definition files. Components execute during the simulation tick cycle, processing input commands from the frontend and updating entity state that gets published to the network.

Core backend classes

VR-Engage backend functionality is implemented through VR-Forces plugins that register simulation components with the CGF engine. VR-Engage extends VR-Forces through composition rather than a traditional class hierarchy, adding player-control-aware components to standard VR-Forces entities.

Plugin initialization

The VR-Engage simulation plugin registers components through the standard VR-Forces plugin mechanism. The DtInitializeVrfPlugin entry point registers VR-Engage component factories with the CGF engine:

// filepath: libsrc/vrfExtensions/vreVrfSimPlugin/vreVrfPlugin.cxx
namespace makVre
{
namespace DtVreVrfSimPlugin
{
DT_VRF_DLL_PLUGIN bool DtInitializeVrfPlugin(DtCgf* cgf)
{
DtSimComponentFactory* factory = cgf->simComponentFactory();
// Register VR-Engage component types with the factory
return true;
}
} // namespace DtVreVrfSimPlugin
} // namespace makVre
Include export definitions for this library.
Definition glsVreMessageUtil.h:49

This plugin architecture allows VR-Engage to add player control capabilities to any VR-Forces entity without modifying VR-Forces core code.

Entity component model

VR-Engage entities use the standard VR-Forces entity model. Player control is added through VR-Engage components attached via system definition files. The DtVreSimComponent template class provides the foundation for all VR-Engage backend components, adding player control detection to standard VR-Forces components.

Player control state is stored in the entity's extended data within the VR-Forces object state repository. Components check for player control by looking for role entries in the extended data map:

// From DtVreSimComponent::isPlayerControlled()
const makVrf::DtVrfStateComponent* component =
this->entity()->getNextFrameStateComponent<makVrf::DtVrfStateComponent>();
const DtVrfObjectStateRepository::ExtendedData& extendedDataMap = component->extendedData();
// Check for role assignment
std::string key = "role-" + role;
DtVrfObjectStateRepository::ExtendedData::const_iterator valueIter = extendedDataMap.find(key.c_str());
if (valueIter != extendedDataMap.end())
{
return true; // Entity is player-controlled for this role
}

This approach integrates with VR-Forces entity management, allowing the same entity to transition between player and CGF control without requiring different entity classes.

Component development

Backend components fall into two primary categories: actuators that modify entity state, and sensors that observe the simulation environment. Both types derive from base classes that integrate with the VR-Forces component system.

Actuator components

Actuators in VR-Engage extend VR-Forces actuator components using the DtVreSimComponent template. This template adds player control detection and VR-Engage message handling to standard VR-Forces components.

// filepath: include/vrfExtensions/vreVrfmodel/vreSimComponent.h
namespace makVre
{
//! Base template class for VR-Engage simulation components.
//! \tparam ComponentBase The VR-Forces component class to extend
template <typename ComponentBase>
class VREVRFMODEL_DLL DtVreSimComponent : public ComponentBase
{
public:
DtVreSimComponent(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc = 0,
DtReaderWriterRegistry* parentRegistry = 0);
//! Check if the owning entity is currently player-controlled
//! Optional role parameter selects a specific role to query.
bool isPlayerControlled(const std::string& role = "") const;
//! Get the system name for this component's entity
DtString entitySystemName() const;
};
} // namespace makVre
#define VREVRFMODEL_DLL
Definition export.h:22

VR-Engage provides several actuator components that extend VR-Forces base classes:

VR-Engage Component Base Class Purpose
DtVreTurretActuator DtTurretActuatorComponent Turret control with player input
DtVreRotaryWingActuatorComponent DtRotaryWingActuatorComponent Helicopter flight control
DtControlSurfacesActuator DtActuatorComponent Fixed-wing control surfaces
DtVreHumanMovementActuator DtHumanMovementActuator Human entity movement

Implementing a custom actuator

The following example demonstrates extending a VR-Forces actuator with VR-Engage functionality. This pattern applies to any component that responds to player control.

// filepath: src/myActuator.h
#pragma once
#include <vrfmodel/actuatorComponent.h>
namespace makVre
{
const char DtMyActuatorType[] = "my-custom-actuator";
//! Custom actuator that extends VR-Forces with player control support.
class DtMyActuator : public DtVreSimComponent<DtActuatorComponent>
{
public:
DtMyActuator(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc = 0,
DtReaderWriterRegistry* parentRegistry = 0);
virtual ~DtMyActuator() override;
//! Component type identifier
virtual const char* type() const override { return DtMyActuatorType; }
//! Called each simulation frame
virtual void tick() override;
//! Factory method for component creation
static DtSimComponent* creator(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc = 0,
DtReaderWriterRegistry* parentRegistry = 0);
protected:
//! Called before the first simulation tick
virtual void preFirstTickInit() override;
private:
double myThrottlePosition;
};
} // namespace makVre
Base template class for VR-Engage simulation components.
// filepath: src/myActuator.cxx
#include "myActuator.h"
#include <vrfobjcore/simComponent.h>
#include <vrfobjcore/localObject.h>
namespace makVre
{
DtMyActuator::DtMyActuator(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc,
DtReaderWriterRegistry* parentRegistry)
: DtVreSimComponent<DtActuatorComponent>(name, owner, simManager, desc, parentRegistry)
, myThrottlePosition(0.0)
{
}
DtMyActuator::~DtMyActuator()
{
}
void DtMyActuator::preFirstTickInit()
{
DtVreSimComponent<DtActuatorComponent>::preFirstTickInit();
// Initialize component state
}
void DtMyActuator::tick()
{
DtVreSimComponent<DtActuatorComponent>::tick();
// Process only when player-controlled
{
return;
}
// Component-specific logic
}
DtSimComponent* DtMyActuator::creator(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc,
DtReaderWriterRegistry* parentRegistry)
{
return new DtMyActuator(name, owner, simManager, desc, parentRegistry);
}
} // namespace makVre
VREVRFOBJCORE_DLL bool isPlayerControlled(const DtSimObject &stateRep)
Checks if an entity is under player control.

Sensor components

VR-Engage sensor components also use the DtVreSimComponent template to extend VR-Forces sensor classes. Sensors like DtVreGimbalController extend VR-Forces sensor controllers with player-controlled aiming:

// filepath: include/vrfExtensions/vreVrfmodel/vreGimbalController.h
namespace makVre
{
const char DtVreGimbalControllerType[] = "vre-gimbal-controller";
//! Sensor gimbal controller that extends VR-Forces gimbal control with player aiming.
//! Handles both player-controlled and autonomous gimbal operation modes.
class VREVRFMODEL_DLL DtVreGimbalController : public DtVreSimComponent<DtSensorGimbalController>
{
public:
DtVreGimbalController(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc = 0,
DtReaderWriterRegistry* parentRegistry = 0);
//! Component type identifier
virtual const char* type() const override { return DtVreGimbalControllerType; }
//! Factory method for component creation
static DtSimComponent* creator(const DtString& name, DtLocalObject* owner,
DtSimulationServices* simManager,
DtComponentDescriptor* desc = 0,
DtReaderWriterRegistry* parentRegistry = 0);
protected:
//! Process aim gimbal commands from player input
virtual void processSetAimGimbal(const DtVreMessage* msg);
};
} // namespace makVre
const char DtVreGimbalControllerType[]
Type identifier for the VRE sensor gimbal controller component.
Definition vreGimbalController.h:33

Physics engine integration

VR-Engage supports multiple physics backends through an abstraction layer.

Supported physics engines

Vortex Dynamics: CM Labs' Vortex provides detailed ground vehicle dynamics with realistic suspension, tire models, and terrain interaction. Vortex works well where accurate physics response matters for training fidelity.

RTDynamics (RTD): MAK's RTDynamics provides flight dynamics for fixed-wing and rotary-wing aircraft using performance data tables derived from real aircraft specifications. The performance-based approach produces realistic flight behavior without requiring full aerodynamic modeling, making RTD suitable for training simulations where consistent, repeatable behavior is more important than aerodynamic fidelity.

VR-Forces Internal Kinematics Model: The default model provides basic entity movement and collision detection, suitable for entities that do not require detailed dynamics simulation such as dismounted infantry.

Vortex mechanism configuration

Vortex mechanisms are configured through .vxmechanism files created in the Vortex Editor. These binary files define vehicle geometry, mass properties, rigid bodies, constraints, and collision geometry.

VR-Engage actuators interact with Vortex mechanisms through the VR-Forces integration layer. The mechanism file path is specified in the entity's system definition:

;; filepath: data/simulationModelSets/VR-Engage/vrfSim/systems/example.sysdef
(system-definition
(components
(vortex-vehicle
(component-type "vortex-vehicle-plugin")
(mechanism-file "Vortex/mechanisms/HMMWV/Dynamic/Design/HMMWV.vxmechanism")
)
)
)

RTDynamics integration

RTDynamics integrates with VR-Forces through flight model plugins that read RTD performance data files. These files define aircraft performance envelopes including maximum speeds at various altitudes, climb and descent rates, turn performance, and fuel consumption. VR-Engage actuators send control inputs (throttle, control surfaces, collective pitch) to the RTD model, which calculates the resulting aircraft state.

Because RTD uses performance tables rather than aerodynamic coefficients, new aircraft models can be created from publicly available performance specifications.

Player control coordination

VR-Engage entities support transitions between player and CGF control, and can be controlled by multiple players simultaneously. This section covers control authority management, input routing, and joystick controller architecture.

CGF and VR-Engage actuator coexistence

VR-Engage entities can operate under both CGF (Computer Generated Forces) control and player control. This coexistence requires managing actuator authority to prevent conflicting commands.

Control mode

An entity's control mode determines which system—player or CGF—issues commands affecting entity state. Only the system designated by the current control mode can modify entity position, orientation, weapon state, and other simulation properties. Without this distinction, simultaneous commands from both player input and CGF behavior scripts would conflict, causing erratic entity behavior.

Control mode operates at the entity level between players and CGF, not between individual players. Multiple players can simultaneously control the same entity, each operating different subsystems (driver controlling propulsion while gunner controls turret). The role-based input routing described in Multi-player entity support handles coordination between players on the same entity. Control mode determines whether any player has control versus CGF having control.

When a player engages an entity, the system transitions from CGF mode to player mode. During this transition, the system suspends CGF behavior execution, disables CGF actuators, and activates VR-Engage actuators. The reverse occurs when the last player disengages from the entity.

stateDiagram-v2
    [*] --> CGFControl: Entity Created
    CGFControl --> TransferringToPlayer: Player Engages
    TransferringToPlayer --> PlayerControl: Transfer Complete
    PlayerControl --> TransferringToCGF: Last Player Disengages
    TransferringToCGF --> CGFControl: Transfer Complete
    PlayerControl --> PlayerControl: Player Input
    CGFControl --> CGFControl: CGF Tasks/Plans

Returning entities to CGF plans

When a player disengages from an entity, control transfers back to CGF and the entity attempts to resume its previous behavior. The transition preserves entity state, and CGF continues from the entity's current position and orientation.

Multi-player entity support

VR-Engage supports multiple concurrent players operating the same entity, enabling crew simulation where different players control different roles (driver, gunner, commander). The backend coordinates inputs from multiple frontends and resolves conflicts when necessary.

Role-based input routing

When multiple players control the same entity, the backend must determine which player's inputs affect which subsystems. Role-based input routing solves this by associating each role with specific actuators. The driver role routes inputs to propulsion and steering actuators, while the gunner role routes inputs to turret and weapon actuators. This association is configured in system definition files through joystick function groups.

Each joystick function belongs to a function group (such as "driver" or "gunner"). When the backend receives a joystick message, it checks the function group to determine which actuator should receive the input. If a player sends an input for a function group their role does not control, the input has no effect.

flowchart TB
    subgraph Frontend1["Frontend 1 (Driver)"]
        Driver["Driver Role"]
    end

    subgraph Frontend2["Frontend 2 (Gunner)"]
        Gunner["Gunner Role"]
    end

    subgraph Frontend3["Frontend 3 (Commander)"]
        Commander["Commander Role"]
    end

    subgraph Backend["Backend Process"]
        InputRouter["Input Router"]

        subgraph Actuators["Actuator Components"]
            PropAct["Propulsion Actuator"]
            SteerAct["Steering Actuator"]
            TurretAct["Turret Actuator"]
            WeaponAct["Weapon Actuator"]
        end
    end

    Driver -->|Throttle, Steering, Brake| InputRouter
    Gunner -->|Turret, Fire| InputRouter
    Commander -->|Override, Designate| InputRouter

    InputRouter -->|driver group| PropAct
    InputRouter -->|driver group| SteerAct
    InputRouter -->|gunner group| TurretAct
    InputRouter -->|gunner group| WeaponAct

Typical function group assignments:

  • driver: Throttle, steering, brakes, transmission, lights
  • gunner: Turret azimuth, gun elevation, fire, weapon selection
  • commander: Target designation, sensor control, communications

Function groups are defined in system definition files. The following excerpt shows how a throttle function is assigned to the "driver" group:

(joystick-controls
(throttle
(function-name "throttle")
(function-group "driver")
(description "Controls vehicle throttle")
)
)

Each role's frontend configuration defines which joystick functions that role can send. The driver role maps input devices to throttle and steering functions, while the gunner role maps input devices to turret and fire functions. The function group in the system definition connects these frontend actions to the correct backend actuator.

Shared state synchronization

When multiple players operate the same entity, the backend maintains authoritative state and synchronizes changes to all connected frontends. State updates include timestamps to maintain consistency across sessions.

Joystick controller architecture

Joystick controllers route player input to backend actuators through the VR-Forces port system. This section covers the backend components that receive joystick input and deliver it to actuators—the controller classes, port wiring, and system definition configuration. For the JoystickMessage structure and frontend message creation, see Inter-Process Communication.

Input routing flow

When the frontend sends a JoystickMessage, the backend receives it through DtVrfRemoteControlConnector. The connector routes the message into the VR-Forces joystick infrastructure, which dispatches it to the appropriate controller component. The controller updates output ports that actuators read during their simulation tick.

sequenceDiagram
    participant Remote as DtVrfRemoteControlConnector
    participant JoySrc as DtJoystickSource
    participant Controller as DtVreJoystickController
    participant Ports as Output Ports
    participant Actuator as Actuator Component

    Remote->>JoySrc: joystickFunction()
    JoySrc->>Controller: calcAndSetPortValues()
    Controller->>Ports: Set Output Values
    Actuator->>Ports: Read Input Values
    Actuator->>Actuator: Apply Control

Joystick controller interface

Joystick controllers implement DtJoystickControllerInterface and receive routed input through the calcAndSetPortValues() method. The DtVreJoystickController base class provides infrastructure for VR-Engage-specific controllers:

// filepath: include/vrfExtensions/vreVrfmodel/vreJoystickController.h
namespace makVre
{
const char DtVreJoystickControllerType[] = "vre-joystick-controller";
//! Base controller for routing joystick input to entity actuators.
//! Receives joystick function calls from the frontend via the VR-Forces
//! joystick infrastructure and translates them into output port values
//! that actuator components consume.
class VREVRFMODEL_DLL DtVreJoystickController : public DtVreSimComponent<DtControllerComponent>,
public DtJoystickControllerInterface
{
public:
DtVreJoystickController(const DtString& name, DtLocalObject* owner, DtSimulationServices* simManager,
DtComponentDescriptor* desc, DtReaderWriterRegistry* parentRegistry = 0);
virtual ~DtVreJoystickController() override;
//! Component type identifier
virtual const char* type() const override;
//! Initialize controller and create port groups/ports
virtual bool init() override;
virtual bool createPortGroups() override;
virtual bool createPorts() override;
//! Process a joystick function call from the frontend.
//! Looks up the output port matching the function name and sets its value.
//! \param functionGroup The controller group (used for filtering)
//! \param function The control function name (maps to output port name)
//! \param value The control value to set
//! \param repeat Whether this is a repeated action
virtual void calcAndSetPortValues(
const DtString& functionGroup,
const DtString& function,
double value,
bool repeat) override;
//! Called when a joystick connects to this controller.
virtual void joystickConnected() override;
//! Called when a joystick disconnects from this controller.
virtual void joystickDisconnected() override;
//! Per-frame update of controller state
virtual void tick() override;
};
} // namespace makVre
const char DtVreJoystickControllerType[]
Type identifier for the VRE joystick controller component.
Definition vreJoystickController.h:35

The controller's calcAndSetPortValues() implementation looks up output ports by function name and sets their values. Actuator components wire their input ports to these outputs through system definition connections.

Specialized controllers

VR-Engage provides specialized joystick controllers for different entity types and roles:

Controller Entity Type Key Functions
DtVreJoystickController Generic vehicles throttle, steering, brake
DtVreTurretJoystickController Weapon turrets azimuth, elevation, aimMode
DtFixedWingJoyFlightController Fixed-wing aircraft pitch, roll, yaw, throttle
DtRotaryWingJoyFlightController Rotary-wing aircraft cyclic, collective, pedals
DtHumanJoystickMovementController Dismounted infantry walk, run, strafe, turn
DtHumanJoystickCombatController Dismounted infantry aim, fire, weaponSelect

Specialized controllers add role-specific logic. For example, DtVreTurretJoystickController handles turret rate limits and stabilization modes, while flight controllers apply control surface mixing and trim.

Port wiring architecture

Joystick controllers communicate with actuators through the VR-Forces port system. Controllers create output ports for each joystick function; actuators create input ports for control values they consume. System definitions wire these ports together by matching port names.

Output ports (controller side):

  • Created based on joystick-controls configuration in system definition
  • Named to match the function names used in joystick messages
  • Support analog (double) and boolean port types

Input ports (actuator side):

  • Created by actuator components during initialization
  • Named to match expected output port names
  • Read during actuator tick() to get current control values

System definition configuration

Joystick controllers and their port connections are configured in system definition (.sysdef) files. The configuration specifies which joystick functions the controller handles:

;; filepath: data/simulationModelSets/VR-Engage/vrfSim/systems/driver.sysdef
(system-definition
(components
(driver-joystick
(component-type "vre-joystick-controller")
(function-groups ("driver"))
(joystick-controls
(throttle
(function-name "throttle")
(port-type "analog")
(default-value 0.0)
)
(steering
(function-name "steering")
(port-type "analog")
(default-value 0.0)
)
(brake
(function-name "brake")
(port-type "analog")
(default-value 0.0)
)
)
)
)
)

The joystick-controls block defines output ports that the controller creates. Each control specifies:

Field Purpose
function-name Name matching the function field in JoystickMessage
port-type "analog" for double values, "boolean" for on/off
default-value Initial value before any input received

Actuator input port consumption

Actuators read joystick input through their input ports during each simulation tick:

// filepath: examples/vehicleBlinker/vehicleBlinkerBackend/vehicleBlinkerActuator.cxx
void DtVehicleBlinkerActuator::createPorts()
{
// Create input ports that will be wired to joystick controller outputs
myLeftBlinkerPort = addInputPort<DtBooleanInputPort>("LeftBlinker");
myRightBlinkerPort = addInputPort<DtBooleanInputPort>("RightBlinker");
}
void DtVehicleBlinkerActuator::tick(double dt)
{
// Check for new input on each port
if (myLeftBlinkerPort->activeConnection() && myLeftBlinkerPort->newData())
{
bool pressed = myLeftBlinkerPort->value();
if (pressed)
{
toggleLeftBlinker();
}
}
if (myRightBlinkerPort->activeConnection() && myRightBlinkerPort->newData())
{
bool pressed = myRightBlinkerPort->value();
if (pressed)
{
toggleRightBlinker();
}
}
updateBlinkerState(dt);
}

The newData() method returns true when the port has received a new value since the last check, allowing actuators to respond only to actual input changes rather than polling the same value repeatedly.

Weapon systems integration

VR-Engage weapon systems are managed through the backend using VR-Forces weapon components. The weapon architecture coordinates frontend controls with backend ballistics, ammunition tracking, and fire interactions published to the distributed simulation network.

Weapon system architecture

Weapon systems in VR-Engage consist of frontend control logic that handles player input and backend components that manage weapon state, ammunition, and fire interactions.

flowchart TB
    subgraph Frontend["Frontend Process"]
        GunnerLogic["DtGunnerControlLogic"]
        WeaponResource["DtWeaponResourceLogic"]
        WeaponPose["DtWeaponPoseUpdater"]
    end

    subgraph Backend["Backend Process"]
        WeaponStatus["DtWeaponsStatusController"]
        WeaponController["Weapon Controller Component"]
        FireTask["Fire Task"]
    end

    subgraph Messages["VRE Messages"]
        ConfigRequest["WeaponConfigRequest"]
        ConfigResponse["WeaponConfigResponse"]
        SelectWeapon["WeaponConfigSelectWeapon"]
        AmmoUpdate["WeaponAmmoUpdate"]
        WeaponGeom["WeaponGeometry"]
    end

    GunnerLogic -->|Fire Command| WeaponController
    GunnerLogic -->|Select Weapon| SelectWeapon
    SelectWeapon --> WeaponStatus

    WeaponResource -->|Request Config| ConfigRequest
    ConfigRequest --> WeaponStatus
    WeaponStatus -->|Respond| ConfigResponse
    ConfigResponse --> WeaponResource

    WeaponStatus -->|Ammo Changes| AmmoUpdate
    AmmoUpdate --> WeaponResource

    WeaponPose -->|Aim Position| WeaponGeom
    WeaponGeom --> WeaponController

    WeaponController --> FireTask

Weapons status controller

The DtWeaponsStatusController component manages weapon configuration and state on the backend.

// filepath: include/vrfExtensions/vreVrfmodel/weaponsStatusController.h
namespace makVre
{
const char DtWeaponsStatusControllerType[] = "vre-weapons-status-controller";
//! Backend component that manages weapon system status and configuration.
class VREVRFMODEL_DLL DtWeaponsStatusController : public DtVreSimComponent<DtSimComponent>,
public DtJoystickControllerInterface
{
public:
//! Initialize the controller
virtual bool init() override;
//! Called before the first tick
virtual void preFirstTickInit() override;
//! Update each simulation frame
virtual void tick() override;
//! Select the next weapon
virtual bool selectNextWeapon();
//! Select a specific weapon by category
virtual bool selectWeapon(const DtString& selection);
//! Get ammunition count for a munition type
virtual int munitionResourceCount(const DtEntityType& munitionType) const;
protected:
//! Handle weapon configuration request messages
virtual DtVreMessageResult handleWeaponConfigRequestMessage(DtVreMessage* msg);
//! Handle weapon selection messages
virtual DtVreMessageResult handleWeaponConfigSelectWeapon(DtVreMessage* msg);
};
} // namespace makVre

Weapon configuration messages

The frontend queries weapon configuration through the VR-Engage message system. The DtWeaponsStatusController responds to WeaponConfigRequest messages with information about available weapons, ammunition types, and display ordering via WeaponConfigResponse messages.

The weapon configuration workflow:

  1. Frontend sends WeaponConfigRequest with entity ID
  2. Backend DtWeaponsStatusController receives request and builds configuration response
  3. Backend sends WeaponConfigResponse with weapon categories, ranges, and ammunition data
  4. Frontend DtWeaponResourceLogic receives response and updates UI

Message definitions are generated from Lua specifications in libsrc/framework/vreMessages/. The WeaponConfigResponse includes fields for weapon name, category, range limits, and munition type.

Weapon system definitions

Weapon systems are defined in .sysdef files that specify components, connections, and joystick control mappings. The system definition determines how player input flows through weapon components.

;; filepath: data/simulationModelSets/VR-Engage/vrfSim/systems/weapons/templates/engage-mm-gun.template_sysdef
;; Template for a rotating, elevating mounted ballistic weapon
(system-definition
(components
;; Weapon joystick controller handles fire input
(weapon-joystick
(component-descriptor-type "vre-joystick-controller-descriptor")
(component-type "vre-joystick-controller")
(joystick-controls
(weapon-fire
(function-name "fire")
(function-group $weapon-group)
(description "Fires the selected weapon")
(min-value 1.0)
(max-value 1.0)
)
(next-weapon
(function-name "next weapon")
(function-group $weapon-group)
(description "Selects the next weapon")
)
(previous-weapon
(function-name "previous weapon")
(function-group $weapon-group)
(description "Selects the previous weapon")
)
)
)
)
(meta-data
(system-name "VR-Engage Ballistic Gun (Elevating/Rotating)")
(system-categories "weapon")
)
)

Gunner control logic

The DtGunnerControlLogic component on the frontend handles player input for weapon systems. It processes turret slew commands, fire actions, and weapon selection through configurable input mappings.

// filepath: include/commonRoleLibraries/vreCommonComponents/gunnerControlLogic.h
namespace makVre
{
namespace GunnerControlLogicConfig
{
//! \vreRoleParam{azimuthStateAttribute,string,"mainGunAzimuth",gunnerControlLogic,
//! State attribute name for storing the main gun azimuth angle.}
constexpr const char* azimuthStateAttribute = "azimuthStateAttribute";
//! \vreRoleParam{elevationStateAttribute,string,"mainGunElevation",gunnerControlLogic,
//! State attribute name for storing the main gun elevation angle.}
constexpr const char* elevationStateAttribute = "elevationStateAttribute";
//! \vreRoleParam{fireRequiresIntersection,bool,false,gunnerControlLogic,
//! Determines whether firing requires a valid target intersection.}
constexpr const char* fireRequiresIntersection = "fireRequiresIntersection";
}
//! Control logic component for gunner roles in ground vehicles.
//! Handles weapon control, turret movement, firing, and aiming modes.
class DtGunnerControlLogic : public DtEntityControlLogic
{
public:
//! Process azimuth input for turret rotation
virtual void azimuth(double val);
//! Process elevation input for gun elevation
virtual void elevation(double val);
//! Fire the currently selected weapon
virtual void fire(double val);
//! Select the next available weapon
virtual void nextWeapon(double val);
//! Select the previous available weapon
virtual void previousWeapon(double val);
//! Toggle weapon stabilization
virtual void stabilize(double val);
};
} // namespace makVre
virtual void stabilize(double val)
Controls weapon stabilization system.
virtual void previousWeapon(double val)
Selects the previous available weapon.
virtual void azimuth(double val)
Controls turret azimuth (horizontal rotation)
virtual void fire(double val)
Input functions mapped to particular action strings in configuration.
virtual void nextWeapon(double val)
Selects the next available weapon.
virtual void elevation(double val)
Controls turret elevation (vertical angle)
constexpr const char * fireRequiresIntersection
Definition gunnerControlLogic.h:49
constexpr const char * azimuthStateAttribute
Definition gunnerControlLogic.h:43

Configuration and libraries

This section covers entity configuration files that bridge frontend and backend, and the VR-Engage extension libraries available for backend development.

Entity and role configuration

VR-Engage configuration spans both frontend and backend, with .entity files serving as the connection point. Entity files are primarily a backend concept—they define the VR-Forces entity type, physics model, and system definitions that determine which simulation components are attached. However, entity files also reference frontend role configurations, creating the link between backend simulation and frontend player interface.

Within an entity file, role references point to frontend role Lua files that define component groups, input mappings, and display layouts. Parameter overrides in the entity file can customize role behavior for specific entity types without modifying the base role definition. This separation allows the same role (such as "driver") to work across different vehicle types while permitting entity-specific adjustments.

For comprehensive coverage of role configuration including inheritance, parameter overrides, and component groups, see Role Configuration.

System definition structure

System definitions (.sysdef files) configure backend components using Lisp format. These files specify joystick controllers, actuators, and sensors that execute in the backend simulation:

;; filepath: data/simulationModelSets/VR-Engage/vrfSim/systems/tank/tankDriver.sysdef
(system-definition
(components
(driver-controller
(component-type "vre-joystick-controller")
(joystick-controls
(throttle
(function-name "throttle")
(function-group "driver")
)
(steering
(function-name "steering")
(function-group "driver")
)
)
)
)
(meta-data
(system-name "Tank Driver Controls")
(system-categories "vehicle" "ground")
)
)

System definitions attach to entities through .entity files and determine which backend components participate in the simulation. The joystick controls defined here correspond to input actions mapped in frontend role configuration.

VR-Engage extension libraries

VR-Engage backend development involves several libraries that extend VR-Forces functionality.

vreVrfmodel

The vreVrfmodel library (libsrc/vrfExtensions/vreVrfmodel/) contains the core VR-Engage entity model extensions. This library provides the primary classes for player-controlled entity behavior.

Key headers:

vreManager

The vreManager library (libsrc/vrfExtensions/vreManager/) coordinates VR-Engage entities within the VR-Forces simulation. It manages entity registration, message routing, and lifecycle events.

Key headers:

  • vrfModelManager.h - Central entity coordinator
  • vreTableView.h - Entity state table access

vreMessageManager

The vreMessageManager library (libsrc/framework/vreMessageManager/) provides the messaging infrastructure for frontend-backend communication. Backend components use this library to receive commands and publish state.

Key headers:

  • vreMessage.h - Base message class
  • vreMessageManager.h - Message routing and subscription

Linking against VR-Engage libraries

Backend plugins link against VR-Engage and VR-Forces libraries. Consult the example plugin projects in the examples/ directory for current CMake configuration patterns.

Key libraries for backend development:

  • vreVrfmodel - Core VR-Engage simulation components
  • vreManager - Entity management and coordination
  • vreMessageManager - Frontend-backend messaging

Headers are organized under include/vrfExtensions/ with subdirectories matching library names.

Header organization

VR-Engage backend headers are organized under include/vrfExtensions/:

Directory Purpose
vreVrfmodel/ Entity model components, actuators, controllers
vreManager/ Entity management and coordination
vreVrfobjcore/ Object core extensions (projectiles, munitions)

When developing backend components, include headers using the library directory prefix:

Controller for handling joystick input.
Controller for managing weapon systems status and selection.

See also