mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 20:06:48 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into permissions-grid
This commit is contained in:
commit
4cad94216c
19 changed files with 228 additions and 47 deletions
|
@ -994,7 +994,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
if (_keyboardFocusedItem != entityItemID) {
|
||||
_keyboardFocusedItem = UNKNOWN_ENTITY_ID;
|
||||
auto properties = entityScriptingInterface->getEntityProperties(entityItemID);
|
||||
if (EntityTypes::Web == properties.getType() && !properties.getLocked()) {
|
||||
if (EntityTypes::Web == properties.getType() && !properties.getLocked() && properties.getVisible()) {
|
||||
auto entity = entityScriptingInterface->getEntityTree()->findEntityByID(entityItemID);
|
||||
RenderableWebEntityItem* webEntity = dynamic_cast<RenderableWebEntityItem*>(entity.get());
|
||||
if (webEntity) {
|
||||
|
@ -1049,6 +1049,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
}
|
||||
});
|
||||
|
||||
connect(this, &Application::aboutToQuit, [=]() {
|
||||
_keyboardFocusedItem = UNKNOWN_ENTITY_ID;
|
||||
if (_keyboardFocusHighlight) {
|
||||
_keyboardFocusHighlight->setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
|
||||
|
@ -1503,7 +1510,13 @@ void Application::paintGL() {
|
|||
// FIXME not needed anymore?
|
||||
_offscreenContext->makeCurrent();
|
||||
|
||||
displayPlugin->beginFrameRender(_frameCount);
|
||||
// If a display plugin loses it's underlying support, it
|
||||
// needs to be able to signal us to not use it
|
||||
if (!displayPlugin->beginFrameRender(_frameCount)) {
|
||||
_inPaint = false;
|
||||
updateDisplayMode();
|
||||
return;
|
||||
}
|
||||
|
||||
// update the avatar with a fresh HMD pose
|
||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||
|
@ -5098,9 +5111,17 @@ void Application::updateDisplayMode() {
|
|||
|
||||
foreach(auto displayPlugin, standard) {
|
||||
addDisplayPluginToMenu(displayPlugin, first);
|
||||
auto displayPluginName = displayPlugin->getName();
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
||||
resizeGL();
|
||||
});
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::outputDeviceLost, [this, displayPluginName] {
|
||||
PluginManager::getInstance()->disableDisplayPlugin(displayPluginName);
|
||||
auto menu = Menu::getInstance();
|
||||
if (menu->menuItemExists(MenuOption::OutputMenu, displayPluginName)) {
|
||||
menu->removeMenuItem(MenuOption::OutputMenu, displayPluginName);
|
||||
}
|
||||
});
|
||||
first = false;
|
||||
}
|
||||
|
||||
|
@ -5116,6 +5137,10 @@ void Application::updateDisplayMode() {
|
|||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||
QString name = displayPlugin->getName();
|
||||
QAction* action = menu->getActionForOption(name);
|
||||
// Menu might have been removed if the display plugin lost
|
||||
if (!action) {
|
||||
continue;
|
||||
}
|
||||
if (action->isChecked()) {
|
||||
newDisplayPlugin = displayPlugin;
|
||||
break;
|
||||
|
|
|
@ -322,7 +322,7 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
|||
const auto characterController = myAvatar->getCharacterController();
|
||||
const float avatarVelocityChange = (characterController ? glm::length(characterController->getVelocityChange()) : 0.0f);
|
||||
const float velocityChange = glm::length(collision.velocityChange) + avatarVelocityChange;
|
||||
const float MIN_AVATAR_COLLISION_ACCELERATION = 0.01f;
|
||||
const float MIN_AVATAR_COLLISION_ACCELERATION = 2.4f; // walking speed
|
||||
const bool isSound = (collision.type == CONTACT_EVENT_TYPE_START) && (velocityChange > MIN_AVATAR_COLLISION_ACCELERATION);
|
||||
|
||||
if (!isSound) {
|
||||
|
@ -330,14 +330,24 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
|||
}
|
||||
// Your avatar sound is personal to you, so let's say the "mass" part of the kinetic energy is already accounted for.
|
||||
const float energy = velocityChange * velocityChange;
|
||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 0.5f;
|
||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 10.0f;
|
||||
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
||||
|
||||
// For general entity collisionSoundURL, playSound supports changing the pitch for the sound based on the size of the object,
|
||||
// but most avatars are roughly the same size, so let's not be so fancy yet.
|
||||
const float AVATAR_STRETCH_FACTOR = 1.0f;
|
||||
|
||||
AudioInjector::playSound(collisionSound, energyFactorOfFull, AVATAR_STRETCH_FACTOR, myAvatar->getPosition());
|
||||
|
||||
_collisionInjectors.remove_if([](QPointer<AudioInjector>& injector) {
|
||||
return !injector || injector->isFinished();
|
||||
});
|
||||
|
||||
static const int MAX_INJECTOR_COUNT = 3;
|
||||
if (_collisionInjectors.size() < MAX_INJECTOR_COUNT) {
|
||||
auto injector = AudioInjector::playSound(collisionSound, energyFactorOfFull, AVATAR_STRETCH_FACTOR,
|
||||
myAvatar->getPosition());
|
||||
_collisionInjectors.emplace_back(injector);
|
||||
}
|
||||
myAvatar->collisionWithEntity(collision);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "AvatarMotionState.h"
|
||||
|
||||
class MyAvatar;
|
||||
class AudioInjector;
|
||||
|
||||
class AvatarManager : public AvatarHashMap {
|
||||
Q_OBJECT
|
||||
|
@ -94,6 +95,8 @@ private:
|
|||
|
||||
bool _shouldShowReceiveStats = false;
|
||||
|
||||
std::list<QPointer<AudioInjector>> _collisionInjectors;
|
||||
|
||||
SetOfAvatarMotionStates _motionStatesThatMightUpdate;
|
||||
SetOfMotionStates _motionStatesToAddToPhysics;
|
||||
VectorOfMotionStates _motionStatesToRemoveFromPhysics;
|
||||
|
|
|
@ -226,10 +226,15 @@ void RenderableWebEntityItem::setSourceUrl(const QString& value) {
|
|||
}
|
||||
|
||||
void RenderableWebEntityItem::setProxyWindow(QWindow* proxyWindow) {
|
||||
_webSurface->setProxyWindow(proxyWindow);
|
||||
if (_webSurface) {
|
||||
_webSurface->setProxyWindow(proxyWindow);
|
||||
}
|
||||
}
|
||||
|
||||
QObject* RenderableWebEntityItem::getEventHandler() {
|
||||
if (!_webSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
return _webSurface->getEventHandler();
|
||||
}
|
||||
|
||||
|
|
|
@ -687,15 +687,80 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
}
|
||||
}
|
||||
{ // When we own the simulation we don't accept updates to the entity's transform/velocities
|
||||
// but since we're using macros below we have to temporarily modify overwriteLocalData.
|
||||
bool oldOverwrite = overwriteLocalData;
|
||||
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePositionFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotationFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
|
||||
overwriteLocalData = oldOverwrite;
|
||||
// we also want to ignore any duplicate packets that have the same "recently updated" values
|
||||
// as a packet we've already recieved. This is because we want multiple edits of the same
|
||||
// information to be idempotent, but if we applied new physics properties we'd resimulation
|
||||
// with small differences in results.
|
||||
|
||||
// Because the regular streaming property "setters" only have access to the new value, we've
|
||||
// made these lambdas that can access other details about the previous updates to suppress
|
||||
// any duplicates.
|
||||
|
||||
// Note: duplicate packets are expected and not wrong. They may be sent for any number of
|
||||
// reasons and the contract is that the client handles them in an idempotent manner.
|
||||
auto lastEdited = lastEditedFromBufferAdjusted;
|
||||
auto customUpdatePositionFromNetwork = [this, lastEdited, overwriteLocalData, weOwnSimulation](glm::vec3 value){
|
||||
bool simulationChanged = lastEdited > _lastUpdatedPositionTimestamp;
|
||||
bool valueChanged = value != _lastUpdatedPositionValue;
|
||||
bool shouldUpdate = overwriteLocalData && !weOwnSimulation && simulationChanged && valueChanged;
|
||||
if (shouldUpdate) {
|
||||
updatePositionFromNetwork(value);
|
||||
_lastUpdatedPositionTimestamp = lastEdited;
|
||||
_lastUpdatedPositionValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
auto customUpdateRotationFromNetwork = [this, lastEdited, overwriteLocalData, weOwnSimulation](glm::quat value){
|
||||
bool simulationChanged = lastEdited > _lastUpdatedRotationTimestamp;
|
||||
bool valueChanged = value != _lastUpdatedRotationValue;
|
||||
bool shouldUpdate = overwriteLocalData && !weOwnSimulation && simulationChanged && valueChanged;
|
||||
if (shouldUpdate) {
|
||||
updateRotationFromNetwork(value);
|
||||
_lastUpdatedRotationTimestamp = lastEdited;
|
||||
_lastUpdatedRotationValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
auto customUpdateVelocityFromNetwork = [this, lastEdited, overwriteLocalData, weOwnSimulation](glm::vec3 value){
|
||||
bool simulationChanged = lastEdited > _lastUpdatedVelocityTimestamp;
|
||||
bool valueChanged = value != _lastUpdatedVelocityValue;
|
||||
bool shouldUpdate = overwriteLocalData && !weOwnSimulation && simulationChanged && valueChanged;
|
||||
if (shouldUpdate) {
|
||||
updateVelocityFromNetwork(value);
|
||||
_lastUpdatedVelocityTimestamp = lastEdited;
|
||||
_lastUpdatedVelocityValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
auto customUpdateAngularVelocityFromNetwork = [this, lastEdited, overwriteLocalData, weOwnSimulation](glm::vec3 value){
|
||||
bool simulationChanged = lastEdited > _lastUpdatedAngularVelocityTimestamp;
|
||||
bool valueChanged = value != _lastUpdatedAngularVelocityValue;
|
||||
bool shouldUpdate = overwriteLocalData && !weOwnSimulation && simulationChanged && valueChanged;
|
||||
if (shouldUpdate) {
|
||||
updateAngularVelocityFromNetwork(value);
|
||||
_lastUpdatedAngularVelocityTimestamp = lastEdited;
|
||||
_lastUpdatedAngularVelocityValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
auto customSetAcceleration = [this, lastEdited, overwriteLocalData, weOwnSimulation](glm::vec3 value){
|
||||
bool simulationChanged = lastEdited > _lastUpdatedAccelerationTimestamp;
|
||||
bool valueChanged = value != _lastUpdatedAccelerationValue;
|
||||
bool shouldUpdate = overwriteLocalData && !weOwnSimulation && simulationChanged && valueChanged;
|
||||
if (shouldUpdate) {
|
||||
setAcceleration(value);
|
||||
_lastUpdatedAccelerationTimestamp = lastEdited;
|
||||
_lastUpdatedAccelerationValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, customUpdatePositionFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, customUpdateRotationFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, customUpdateVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, customUpdateAngularVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, customSetAcceleration);
|
||||
|
||||
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
|
||||
|
@ -922,13 +987,11 @@ void EntityItem::simulate(const quint64& now) {
|
|||
qCDebug(entities) << " ********** EntityItem::simulate() .... SETTING _lastSimulated=" << _lastSimulated;
|
||||
#endif
|
||||
|
||||
if (!hasActions()) {
|
||||
if (!stepKinematicMotion(timeElapsed)) {
|
||||
// this entity is no longer moving
|
||||
// flag it to transition from KINEMATIC to STATIC
|
||||
_dirtyFlags |= Simulation::DIRTY_MOTION_TYPE;
|
||||
setAcceleration(Vectors::ZERO);
|
||||
}
|
||||
if (!stepKinematicMotion(timeElapsed)) {
|
||||
// this entity is no longer moving
|
||||
// flag it to transition from KINEMATIC to STATIC
|
||||
_dirtyFlags |= Simulation::DIRTY_MOTION_TYPE;
|
||||
setAcceleration(Vectors::ZERO);
|
||||
}
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
|
|
@ -550,6 +550,22 @@ protected:
|
|||
|
||||
bool _clientOnly { false };
|
||||
QUuid _owningAvatarID;
|
||||
|
||||
// physics related changes from the network to suppress any duplicates and make
|
||||
// sure redundant applications are idempotent
|
||||
glm::vec3 _lastUpdatedPositionValue;
|
||||
glm::quat _lastUpdatedRotationValue;
|
||||
glm::vec3 _lastUpdatedVelocityValue;
|
||||
glm::vec3 _lastUpdatedAngularVelocityValue;
|
||||
glm::vec3 _lastUpdatedAccelerationValue;
|
||||
|
||||
quint64 _lastUpdatedPositionTimestamp { 0 };
|
||||
quint64 _lastUpdatedRotationTimestamp { 0 };
|
||||
quint64 _lastUpdatedVelocityTimestamp { 0 };
|
||||
quint64 _lastUpdatedAngularVelocityTimestamp { 0 };
|
||||
quint64 _lastUpdatedAccelerationTimestamp { 0 };
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_EntityItem_h
|
||||
|
|
|
@ -401,11 +401,10 @@ glm::vec3 CharacterController::getLinearVelocity() const {
|
|||
}
|
||||
|
||||
glm::vec3 CharacterController::getVelocityChange() const {
|
||||
glm::vec3 velocity(0.0f);
|
||||
if (_rigidBody) {
|
||||
velocity = bulletToGLM(_rigidBody->getLinearVelocity());
|
||||
return bulletToGLM(_velocityChange);
|
||||
}
|
||||
return velocity;
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
void CharacterController::clearMotors() {
|
||||
|
|
|
@ -137,7 +137,7 @@ public:
|
|||
}
|
||||
|
||||
// will query the underlying hmd api to compute the most recent head pose
|
||||
virtual void beginFrameRender(uint32_t frameIndex) {}
|
||||
virtual bool beginFrameRender(uint32_t frameIndex) { return true; }
|
||||
|
||||
// returns a copy of the most recent head pose, computed via updateHeadPose
|
||||
virtual glm::mat4 getHeadPose() const {
|
||||
|
@ -170,6 +170,10 @@ public:
|
|||
|
||||
signals:
|
||||
void recommendedFramebufferSizeChanged(const QSize & size);
|
||||
// Indicates that this display plugin is no longer valid for use.
|
||||
// For instance if a user exits Oculus Home or Steam VR while
|
||||
// using the corresponding plugin, that plugin should be disabled.
|
||||
void outputDeviceLost();
|
||||
|
||||
protected:
|
||||
void incrementPresentCount();
|
||||
|
|
|
@ -62,11 +62,10 @@ PluginManager::PluginManager() {
|
|||
extern DisplayPluginList getDisplayPlugins();
|
||||
extern InputPluginList getInputPlugins();
|
||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||
static DisplayPluginList displayPlugins;
|
||||
|
||||
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||
static DisplayPluginList displayPlugins;
|
||||
static std::once_flag once;
|
||||
|
||||
std::call_once(once, [&] {
|
||||
// Grab the built in plugins
|
||||
displayPlugins = ::getDisplayPlugins();
|
||||
|
@ -90,6 +89,16 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
|||
return displayPlugins;
|
||||
}
|
||||
|
||||
void PluginManager::disableDisplayPlugin(const QString& name) {
|
||||
for (size_t i = 0; i < displayPlugins.size(); ++i) {
|
||||
if (displayPlugins[i]->getName() == name) {
|
||||
displayPlugins.erase(displayPlugins.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const InputPluginList& PluginManager::getInputPlugins() {
|
||||
static InputPluginList inputPlugins;
|
||||
static std::once_flag once;
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
PluginManager();
|
||||
|
||||
const DisplayPluginList& getDisplayPlugins();
|
||||
void disableDisplayPlugin(const QString& name);
|
||||
const InputPluginList& getInputPlugins();
|
||||
void saveSettings();
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ void OculusBaseDisplayPlugin::resetSensors() {
|
|||
_currentRenderFrameInfo.renderPose = glm::mat4(); // identity
|
||||
}
|
||||
|
||||
void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
_currentRenderFrameInfo = FrameInfo();
|
||||
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();;
|
||||
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||
|
@ -26,6 +26,7 @@ void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||
Lock lock(_mutex);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
||||
using Parent = HmdDisplayPlugin;
|
||||
public:
|
||||
virtual bool isSupported() const override;
|
||||
bool isSupported() const override;
|
||||
|
||||
// Stereo specific methods
|
||||
virtual void resetSensors() override final;
|
||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||
void resetSensors() override final;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||
|
||||
|
||||
|
|
|
@ -40,13 +40,14 @@ void OculusLegacyDisplayPlugin::resetSensors() {
|
|||
ovrHmd_RecenterPose(_hmd);
|
||||
}
|
||||
|
||||
void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
bool OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
_currentRenderFrameInfo = FrameInfo();
|
||||
_currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||
_trackingState = ovrHmd_GetTrackingState(_hmd, _currentRenderFrameInfo.predictedDisplayTime);
|
||||
_currentRenderFrameInfo.rawRenderPose = _currentRenderFrameInfo.renderPose = toGlm(_trackingState.HeadPose.ThePose);
|
||||
Lock lock(_mutex);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OculusLegacyDisplayPlugin::isSupported() const {
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
|
||||
// Stereo specific methods
|
||||
void resetSensors() override;
|
||||
void beginFrameRender(uint32_t frameIndex) override;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
|
||||
float getTargetFrameRate() const override;
|
||||
|
||||
|
|
|
@ -121,7 +121,12 @@ void OpenVrDisplayPlugin::resetSensors() {
|
|||
}
|
||||
|
||||
|
||||
void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
handleOpenVrEvents();
|
||||
if (openVrQuitRequested()) {
|
||||
emit outputDeviceLost();
|
||||
return false;
|
||||
}
|
||||
double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
|
||||
double frameDuration = 1.f / displayFrequency;
|
||||
double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
|
||||
|
@ -148,6 +153,7 @@ void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
|
||||
Lock lock(_mutex);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::hmdPresent() {
|
||||
|
|
|
@ -18,16 +18,16 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device p
|
|||
class OpenVrDisplayPlugin : public HmdDisplayPlugin {
|
||||
using Parent = HmdDisplayPlugin;
|
||||
public:
|
||||
virtual bool isSupported() const override;
|
||||
virtual const QString& getName() const override { return NAME; }
|
||||
bool isSupported() const override;
|
||||
const QString& getName() const override { return NAME; }
|
||||
|
||||
virtual float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; }
|
||||
float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; }
|
||||
|
||||
virtual void customizeContext() override;
|
||||
void customizeContext() override;
|
||||
|
||||
// Stereo specific methods
|
||||
virtual void resetSensors() override;
|
||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||
void resetSensors() override;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
void cycleDebugOutput() override { _lockCurrentTexture = !_lockCurrentTexture; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -26,6 +26,11 @@ using Lock = std::unique_lock<Mutex>;
|
|||
static int refCount { 0 };
|
||||
static Mutex mutex;
|
||||
static vr::IVRSystem* activeHmd { nullptr };
|
||||
static bool _openVrQuitRequested { false };
|
||||
|
||||
bool openVrQuitRequested() {
|
||||
return _openVrQuitRequested;
|
||||
}
|
||||
|
||||
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
||||
|
||||
|
@ -56,17 +61,17 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
|||
if (hmdPresent) {
|
||||
Lock lock(mutex);
|
||||
if (!activeHmd) {
|
||||
qCDebug(displayplugins) << "openvr: No vr::IVRSystem instance active, building";
|
||||
qCDebug(displayplugins) << "OpenVR: No vr::IVRSystem instance active, building";
|
||||
vr::EVRInitError eError = vr::VRInitError_None;
|
||||
activeHmd = vr::VR_Init(&eError, vr::VRApplication_Scene);
|
||||
qCDebug(displayplugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
|
||||
qCDebug(displayplugins) << "OpenVR display: HMD is " << activeHmd << " error is " << eError;
|
||||
}
|
||||
if (activeHmd) {
|
||||
qCDebug(displayplugins) << "openvr: incrementing refcount";
|
||||
qCDebug(displayplugins) << "OpenVR: incrementing refcount";
|
||||
++refCount;
|
||||
}
|
||||
} else {
|
||||
qCDebug(displayplugins) << "openvr: no hmd present";
|
||||
qCDebug(displayplugins) << "OpenVR: no hmd present";
|
||||
}
|
||||
return activeHmd;
|
||||
}
|
||||
|
@ -74,12 +79,38 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
|||
void releaseOpenVrSystem() {
|
||||
if (activeHmd) {
|
||||
Lock lock(mutex);
|
||||
qCDebug(displayplugins) << "openvr: decrementing refcount";
|
||||
qCDebug(displayplugins) << "OpenVR: decrementing refcount";
|
||||
--refCount;
|
||||
if (0 == refCount) {
|
||||
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
|
||||
qCDebug(displayplugins) << "OpenVR: zero refcount, deallocate VR system";
|
||||
vr::VR_Shutdown();
|
||||
_openVrQuitRequested = false;
|
||||
activeHmd = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleOpenVrEvents() {
|
||||
if (!activeHmd) {
|
||||
return;
|
||||
}
|
||||
Lock lock(mutex);
|
||||
if (!activeHmd) {
|
||||
return;
|
||||
}
|
||||
|
||||
vr::VREvent_t event;
|
||||
while (activeHmd->PollNextEvent(&event, sizeof(event))) {
|
||||
switch (event.eventType) {
|
||||
case vr::VREvent_Quit:
|
||||
_openVrQuitRequested = true;
|
||||
activeHmd->AcknowledgeQuit_Exiting();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
qDebug() << "OpenVR: Event " << event.eventType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ bool openVrSupported();
|
|||
|
||||
vr::IVRSystem* acquireOpenVrSystem();
|
||||
void releaseOpenVrSystem();
|
||||
void handleOpenVrEvents();
|
||||
bool openVrQuitRequested();
|
||||
|
||||
template<typename F>
|
||||
void openvr_for_each_eye(F f) {
|
||||
|
|
|
@ -214,6 +214,11 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch&
|
|||
|
||||
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
handleOpenVrEvents();
|
||||
if (openVrQuitRequested()) {
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
// because update mutates the internal state we need to lock
|
||||
userInputMapper->withLock([&, this]() {
|
||||
|
|
Loading…
Reference in a new issue