You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Legacy/CryCommon/HMDBus.h

296 lines
13 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <ISystem.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/Math/Transform.h>
#include <IStereoRenderer.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <VRCommon.h>
struct IRenderAuxGeom;
namespace AZ
{
namespace VR
{
/**
* Bus for reacting to events triggered by the VR systems
*/
class VREvents : public AZ::EBusTraits
{
public:
virtual ~VREvents() {}
/**
* Event triggered when an HMD initializes successfully
*/
virtual void OnHMDInitialized() {}
/**
* Event triggered when an HMD shuts down
*/
virtual void OnHMDShutdown() {}
};
using VREventBus = AZ::EBus<VREvents>;
///
/// Device initialization bus. Each HMD device SDK should connect to this bus during startup in order to be initialized by the LY engine.
/// Any devices that successfully initialize will be connected to the HMDDeviceBus for actual use in VR rendering.
///
class HMDInitBus : public AZ::EBusTraits
{
public:
virtual ~HMDInitBus() {}
///
/// Attempt to initialize this device. If initialization is initially successful (device exists and is able to startup) then this device should connect to the
/// HMDDeviceRequestBus in order to be used as an HMD from the main Open 3D Engine system.
///
/// @return If true, initialization fully succeeded.
///
virtual bool AttemptInit() = 0;
///
/// Shutdown this device and destroy any internal context/state information that it may contain. Once this function has returned, the device should be in a
/// totally clean state and able to re-initialized if necessary.
///
virtual void Shutdown() = 0;
///
/// Priority values for the HMD to set. A higher priority value means that the HMD will be be initialized before
/// other HMDs with lower priority values.
///
enum HMDInitPriority
{
kNullVR = -100,
kLowest = 0,
kMiddle = 50,
kHighest = 100
};
///
/// Specify the initialization priority for this HMD device. Typically SDKs that have only one device that they support (e.g. Oculus) should have the highest
/// priority so that other VR Gems don't take the device context. For example, OpenVR is capable of driving an Oculus Rift and if initialized first will control
/// the device as opposed to the Oculus runtime.
///
virtual HMDInitPriority GetInitPriority() const = 0;
};
using HMDInitRequestBus = AZ::EBus<HMDInitBus>;
///
/// HMD device bus used to communicate with the rest of the engine. Every device supported by the engine lives in its own GEM and supports this bus. A device
/// wraps the underlying SDK into a single object for easy use by the rest of the system. Every device created should register with the EBus in order to be picked up as
/// a usable device during initialization via the EBus function BusConnect().
///
class HMDDeviceBus
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBus Traits
static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Multiple;
static const EBusAddressPolicy AddressPolicy = EBusAddressPolicy::Single;
using MutexType = AZStd::recursive_mutex;
//////////////////////////////////////////////////////////////////////////
virtual ~HMDDeviceBus() {}
///
/// Simple texture descriptor to pass to the device during render target creation.
///
struct TextureDesc
{
uint32 width;
uint32 height;
};
///
/// Get per-eye camera info from the device. The specific info to get is defined in the EyeCameraInfo struct. This function can be used to setup
/// rendering cameras per-eye. Note that each eye may have different projection matrix information.
///
/// @param eye The specific eye to get camera data for.
/// @param nearPlane Near distance for the main render camera.
/// @param farPlane Far distance for the main render camera.
/// @param cameraInfo Returned camera information for this particular eye.
///
virtual void GetPerEyeCameraInfo([[maybe_unused]] const EStereoEye eye, [[maybe_unused]] const float nearPlane, [[maybe_unused]] const float farPlane, [[maybe_unused]] PerEyeCameraInfo& cameraInfo) {}
///
/// Update the HMD's internal state and handle events
/// This is NOT where tracking is updated. This is for game-time
/// events such as controllers connecting/disconnecting or
/// certain compositor events being triggered.
///
virtual void UpdateInternalState() {}
///
/// Create the render targets for a rendering device. Note that this will create all necessary render targets but the render targets will be destroyed one at a time in DestroyRenderTargets.
///
/// @param renderDevice The render device to use when creating the render target.
/// @param desc TextureDesc object denoting texture options to use during creation.
/// @param eyeCount The number of HMDRenderTargets to be created in this function.
/// @param renderTargets Array of pointers to HMDRenderTargets of size eyeCount created upon successful return of this function. See struct RenderTarget for more info.
///
/// @returns If true, the render targets were successfully created.
///
virtual bool CreateRenderTargets([[maybe_unused]] void* renderDevice, [[maybe_unused]] const TextureDesc& desc, [[maybe_unused]] size_t eyeCount, [[maybe_unused]] HMDRenderTarget* renderTargets[]) { return false; }
///
/// Destroy the passed-in render target. Any device-specific texture data will be cleaned up after this function has finished executing.
///
virtual void DestroyRenderTarget([[maybe_unused]] HMDRenderTarget& renderTarget) {}
///
/// Take care of any frame preparations that may be necessary BEFORE rendering begins on either eye. This could be things like synchronization,
/// clearing old state, etc.
///
virtual void PrepareFrame() {}
///
/// Retrieve the latest tracking state that was cached since the last call
/// to UpdateTrackingStates.
///
/// TODO: Differentiate between tracking states viable for rendering and
/// tracking states viable for game simulation.
///
virtual TrackingState* GetTrackingState() { return nullptr; }
///
/// Per-eye target to submit to the device for final composition and rendering.
///
struct EyeTarget
{
void* renderTarget; ///< The device render target.
Vec2i viewportPosition; ///< Position of the viewport pertaining to this render target.
Vec2i viewportSize; ///< Size of the viewport pertaining to this render target.
};
///
/// Submit a new frame to the HMD device. Each eye should be fully rendered by this point. The device will automatically correlate the proper
/// tracking information with this frame.
///
/// @param left A reference to the left EyeTarget to present
/// @param right A reference to the right EyeTarget to present
///
virtual void SubmitFrame([[maybe_unused]] const EyeTarget& left, [[maybe_unused]] const EyeTarget& right) {}
///
/// Recent the current pose for the HMD based on the current direction that the viewer is looking.
///
virtual void RecenterPose() {}
///
/// Set the current tracking level of the HMD. Supported tracking levels are defined in struct TrackingLevel.
///
/// @param level The tracking level we want to use with this HMD
///
virtual void SetTrackingLevel([[maybe_unused]] const AZ::VR::HMDTrackingLevel level) {}
///
/// Write any HMD info to the console/log file(s). At a minimum this function should print the info contained in the HMDDeviceInfo object.
///
virtual void OutputHMDInfo() {}
///
/// Enable/disable debugging for this device. The device can decide what the most appropriate debugging information is
/// displayed to the user (e.g. HMD position, performance info, latency timing, etc.).
///
/// @param enable Set to true to enable debugging
///
virtual void EnableDebugging([[maybe_unused]] bool enable) {}
///
/// Draw any custom debug info for this device. This function is invoked by the HMDDebugger.
///
/// @param transform Local to world-space transform.
/// @param auxGeom A pointer to the auxiliary geometry renderer
///
virtual void DrawDebugInfo([[maybe_unused]] const AZ::Transform& transform, [[maybe_unused]] IRenderAuxGeom* auxGeom) {}
///
/// Get the device info object for this particular HMD. See struct HMDDeviceInfo for more details.
///
/// @return A pointer to this HMD's HMDDeviceInfo struct
///
virtual HMDDeviceInfo* GetDeviceInfo() { return nullptr; }
///
/// Get whether or not the HMD has been initialized. The HMD has been initialized when it has fully established an interface
/// with its necessary SDK and is ready to be used.
///
/// @return True if the device has been initialized and is usable
///
virtual bool IsInitialized() { return false; }
///
/// Get the play space of the device, if exists
///
/// @return True if the device has been initialized and is usable
///
virtual const Playspace* GetPlayspace() { return nullptr; }
///
/// Ask the HMD to update its internal tracking state; must be called once per frame.
/// Must be called from the render thread (the same thread that the device submits on).
/// This will calculate the internal tracking states fit for rendering the upcoming frame.
///
virtual void UpdateTrackingStates() {}
///
/// Retrieves the current index into the VR system's swapchain that should be used.
/// This only really need to be overridden by VR implementations that keep track
/// of an internal swapchain like Oculus. OpenVR will handle swapchains
/// internally and can just return 0.
///
virtual AZ::u32 GetSwapchainIndex([[maybe_unused]] const EStereoEye& eye) { return 0; }
protected:
};
using HMDDeviceRequestBus = AZ::EBus<HMDDeviceBus>;
///
/// Bus to define HMD debugging. This includes visualization of any HMD-specific objects as well as any
/// VR performance metrics displayed in the HMD.
///
class HMDDebuggerBus
: public AZ::EBusTraits
{
public:
virtual ~HMDDebuggerBus() {}
///
/// Enable/disable the debugger.
///
/// @param enable Pass in true to enable info debugging
///
virtual void EnableInfo(bool enable) = 0;
///
/// Enable/disable the camera debugger.
///
/// @param enable Pass in true to enable camera debugging
///
virtual void EnableCamera(bool enable) = 0;
};
using HMDDebuggerRequestBus = AZ::EBus<HMDDebuggerBus>;
} // namespace VR
} // namespace AZ