mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 10:02:24 +02:00
comfort mode -- squeeze vision to avoid sickness
This commit is contained in:
parent
dd9b4a8143
commit
9baf4c7078
21 changed files with 846 additions and 8 deletions
|
@ -6755,6 +6755,12 @@ void Application::update(float deltaTime) {
|
|||
if (!getActiveDisplayPlugin()->isActive()) {
|
||||
getMain3DScene()->processTransactionQueue();
|
||||
}
|
||||
|
||||
// decide if the sensorToWorldMatrix is changing in a way that warrents squeezing the edges of the view down
|
||||
if (getActiveDisplayPlugin()->isHmd()) {
|
||||
PerformanceTimer perfTimer("squeezeVision");
|
||||
_visionSqueeze.updateVisionSqueeze(myAvatar->getSensorToWorldMatrix(), deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateRenderArgs(float deltaTime) {
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include <ModelScriptingInterface.h>
|
||||
|
||||
#include "Sound.h"
|
||||
#include "VisionSqueeze.h"
|
||||
|
||||
class GLCanvas;
|
||||
class FaceTracker;
|
||||
|
@ -364,6 +365,9 @@ public:
|
|||
void forceLoginWithTokens(const QString& tokens);
|
||||
void setConfigFileURL(const QString& fileUrl);
|
||||
|
||||
// used by preferences and HMDScriptingInterface...
|
||||
VisionSqueeze& getVisionSqueeze() { return _visionSqueeze; }
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
||||
|
@ -731,6 +735,7 @@ private:
|
|||
|
||||
bool _loginDialogPoppedUp{ false };
|
||||
bool _desktopRootItemCreated{ false };
|
||||
|
||||
bool _developerMenuVisible{ false };
|
||||
QString _previousAvatarSkeletonModel;
|
||||
float _previousAvatarTargetScale;
|
||||
|
@ -837,5 +842,7 @@ private:
|
|||
bool _resumeAfterLoginDialogActionTaken_SafeToRun { false };
|
||||
bool _startUpFinished { false };
|
||||
bool _overrideEntry { false };
|
||||
|
||||
VisionSqueeze _visionSqueeze;
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
213
interface/src/VisionSqueeze.cpp
Normal file
213
interface/src/VisionSqueeze.cpp
Normal file
|
@ -0,0 +1,213 @@
|
|||
//
|
||||
// VisionSqueeze.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Seth Alves on 2019-3-13.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "VisionSqueeze.h"
|
||||
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
#include <glm/gtc/epsilon.hpp>
|
||||
|
||||
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
VisionSqueeze::VisionSqueeze() :
|
||||
_visionSqueezeEnabled(_visionSqueezeEnabledSetting.get()),
|
||||
_visionSqueezeRatioX(_visionSqueezeRatioXSetting.get()),
|
||||
_visionSqueezeRatioY(_visionSqueezeRatioYSetting.get()),
|
||||
_visionSqueezeUnSqueezeDelay(_visionSqueezeUnSqueezeDelaySetting.get()),
|
||||
_visionSqueezeUnSqueezeSpeed(_visionSqueezeUnSqueezeSpeedSetting.get()),
|
||||
_visionSqueezeTransition(_visionSqueezeTransitionSetting.get()),
|
||||
_visionSqueezePerEye(_visionSqueezePerEyeSetting.get()),
|
||||
_visionSqueezeGroundPlaneY(_visionSqueezeGroundPlaneYSetting.get()),
|
||||
_visionSqueezeSpotlightSize(_visionSqueezeSpotlightSizeSetting.get()),
|
||||
_visionSqueezeTurningXFactor(_visionSqueezeTurningXFactorSetting.get()),
|
||||
_visionSqueezeTurningYFactor(_visionSqueezeTurningYFactorSetting.get()) {
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeEnabled(bool value) {
|
||||
if (value != _visionSqueezeEnabled) {
|
||||
_visionSqueezeEnabled = value;
|
||||
_visionSqueezeEnabledSetting.set(_visionSqueezeEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeRatioX(float value) {
|
||||
if (value != _visionSqueezeRatioX) {
|
||||
_visionSqueezeRatioX = value;
|
||||
_visionSqueezeRatioXSetting.set(_visionSqueezeRatioX);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeRatioY(float value) {
|
||||
if (value != _visionSqueezeRatioY) {
|
||||
_visionSqueezeRatioY = value;
|
||||
_visionSqueezeRatioYSetting.set(_visionSqueezeRatioY);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeUnSqueezeDelay(float value) {
|
||||
if (value != _visionSqueezeUnSqueezeDelay) {
|
||||
_visionSqueezeUnSqueezeDelay = value;
|
||||
_visionSqueezeUnSqueezeDelaySetting.set(_visionSqueezeUnSqueezeDelay);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeUnSqueezeSpeed(float value) {
|
||||
if (value != _visionSqueezeUnSqueezeSpeed) {
|
||||
_visionSqueezeUnSqueezeSpeed = value;
|
||||
_visionSqueezeUnSqueezeSpeedSetting.set(_visionSqueezeUnSqueezeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeTransition(float value) {
|
||||
if (value != _visionSqueezeTransition) {
|
||||
_visionSqueezeTransition = value;
|
||||
_visionSqueezeTransitionSetting.set(_visionSqueezeTransition);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezePerEye(int value) {
|
||||
if (value != _visionSqueezePerEye) {
|
||||
_visionSqueezePerEye = value;
|
||||
_visionSqueezePerEyeSetting.set(_visionSqueezePerEye);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeGroundPlaneY(float value) {
|
||||
if (value != _visionSqueezeGroundPlaneY) {
|
||||
_visionSqueezeGroundPlaneY = value;
|
||||
_visionSqueezeGroundPlaneYSetting.set(_visionSqueezeGroundPlaneY);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeSpotlightSize(float value) {
|
||||
if (value != _visionSqueezeSpotlightSize) {
|
||||
_visionSqueezeSpotlightSize = value;
|
||||
_visionSqueezeSpotlightSizeSetting.set(_visionSqueezeSpotlightSize);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeTurningXFactor(float value) {
|
||||
if (value != _visionSqueezeTurningXFactor) {
|
||||
_visionSqueezeTurningXFactor = value;
|
||||
_visionSqueezeTurningXFactorSetting.set(_visionSqueezeTurningXFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::setVisionSqueezeTurningYFactor(float value) {
|
||||
if (value != _visionSqueezeTurningYFactor) {
|
||||
_visionSqueezeTurningYFactor = value;
|
||||
_visionSqueezeTurningYFactorSetting.set(_visionSqueezeTurningYFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void VisionSqueeze::updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime) {
|
||||
|
||||
const float SENSOR_TO_WORLD_TRANS_EPSILON = 0.0001f;
|
||||
const float SENSOR_TO_WORLD_TRANS_Y_EPSILON = 0.01f;
|
||||
const float SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED = 2.0f;
|
||||
const float SENSOR_TO_WORLD_ROT_EPSILON = 0.000005f;
|
||||
const float SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN = 0.99f;
|
||||
const float VISION_SQUEEZE_TP_LOCKOUT = 0.1f; // seconds
|
||||
|
||||
glm::vec3 scale;
|
||||
glm::quat rotation;
|
||||
glm::vec3 translation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(sensorToWorldMatrix, scale, rotation, translation, skew, perspective);
|
||||
|
||||
if (!_visionSqueezeEnabled) {
|
||||
_squeezeVision = false;
|
||||
_squeezeVisionTurning = false;
|
||||
} else if (_visionSqueezeLockout > 0.0f) {
|
||||
_visionSqueezeLockout -= deltaTime;
|
||||
} else {
|
||||
_squeezeVision = false;
|
||||
_squeezeVisionTurning = false;
|
||||
glm::vec3 absTransDelta = glm::abs(translation - _prevTranslation);
|
||||
float rotDot = fabsf(glm::dot(rotation, _prevRotation));
|
||||
|
||||
// if the avatar has just teleported or snap-turned, briefly disable triggering of vision-squeeze
|
||||
if (glm::length2(translation - _prevTranslation) > SENSOR_TO_WORLD_TRANS_ITS_A_TELEPORT_SQUARED ||
|
||||
rotDot < SENSOR_TO_WORLD_ROT_ITS_A_SNAP_TURN) {
|
||||
_visionSqueezeLockout = VISION_SQUEEZE_TP_LOCKOUT;
|
||||
_squeezeVision = true;
|
||||
_squeezeVisionTurning = true;
|
||||
} else if (rotDot < 1.0f - SENSOR_TO_WORLD_ROT_EPSILON) {
|
||||
_squeezeVision = true;
|
||||
_squeezeVisionTurning = true;
|
||||
} else if (absTransDelta.x > SENSOR_TO_WORLD_TRANS_EPSILON ||
|
||||
absTransDelta.y > SENSOR_TO_WORLD_TRANS_Y_EPSILON ||
|
||||
absTransDelta.z > SENSOR_TO_WORLD_TRANS_EPSILON) {
|
||||
_squeezeVision = true;
|
||||
_squeezeVisionTurning = false;
|
||||
}
|
||||
}
|
||||
|
||||
_prevTranslation = translation;
|
||||
_prevRotation = rotation;
|
||||
|
||||
static quint64 lastSqueezeTime = 0;
|
||||
quint64 now = usecTimestampNow();
|
||||
static float visionSqueezeX = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked
|
||||
static float visionSqueezeY = 0.0f; // 0.0 -- unobstructed, 1.0 -- fully blocked
|
||||
|
||||
if (_squeezeVision) {
|
||||
float ratioX = getVisionSqueezeRatioX();
|
||||
float ratioY = getVisionSqueezeRatioY();
|
||||
|
||||
if (ratioX >= 0.0f) {
|
||||
if (_squeezeVisionTurning) {
|
||||
ratioX += (1.0f - ratioX) * getVisionSqueezeTurningXFactor();
|
||||
}
|
||||
float newVisionSqueezeX = ratioX;
|
||||
if (newVisionSqueezeX >= visionSqueezeX) {
|
||||
lastSqueezeTime = now;
|
||||
visionSqueezeX = newVisionSqueezeX;
|
||||
}
|
||||
} else {
|
||||
visionSqueezeX = -1.0f;
|
||||
}
|
||||
|
||||
if (ratioY >= 0.0f) {
|
||||
float newVisionSqueezeY = ratioY;
|
||||
if (newVisionSqueezeY >= visionSqueezeY) {
|
||||
lastSqueezeTime = now;
|
||||
visionSqueezeY = newVisionSqueezeY;
|
||||
}
|
||||
} else {
|
||||
visionSqueezeY = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float unsqueezeAmount = deltaTime * getVisionSqueezeUnSqueezeSpeed();
|
||||
if (now - lastSqueezeTime > getVisionSqueezeUnSqueezeDelay() * USECS_PER_SECOND) {
|
||||
visionSqueezeX -= unsqueezeAmount;
|
||||
if (visionSqueezeX < 0.0f) {
|
||||
visionSqueezeX = -1.0f;
|
||||
}
|
||||
visionSqueezeY -= unsqueezeAmount;
|
||||
if (visionSqueezeY < 0.0f) {
|
||||
visionSqueezeY = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<HmdDisplayPlugin> hmdDisplayPlugin =
|
||||
std::dynamic_pointer_cast<HmdDisplayPlugin>(qApp->getActiveDisplayPlugin());
|
||||
if (hmdDisplayPlugin) {
|
||||
hmdDisplayPlugin->updateVisionSqueezeParameters(visionSqueezeX, visionSqueezeY,
|
||||
getVisionSqueezeTransition(),
|
||||
getVisionSqueezePerEye(),
|
||||
getVisionSqueezeGroundPlaneY(),
|
||||
getVisionSqueezeSpotlightSize());
|
||||
}
|
||||
}
|
108
interface/src/VisionSqueeze.h
Normal file
108
interface/src/VisionSqueeze.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// VisionSqueeze.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Seth Alves on 2019-3-13.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_VisionSqueeze_h
|
||||
#define hifi_VisionSqueeze_h
|
||||
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <SettingHandle.h>
|
||||
|
||||
static const float DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR = 0.51f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR = 0.36f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY = 0.2f; // seconds
|
||||
static const float DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED = 3.0f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_TRANSITION = 0.25f;
|
||||
static const int DEFAULT_VISION_SQUEEZE_PER_EYE = 1;
|
||||
static const float DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y = 0.0f;
|
||||
static const float DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE = 6.0f;
|
||||
|
||||
|
||||
class VisionSqueeze {
|
||||
|
||||
public:
|
||||
|
||||
VisionSqueeze();
|
||||
|
||||
bool getVisionSqueezeEnabled() const { return _visionSqueezeEnabled; }
|
||||
void setVisionSqueezeEnabled(bool value);
|
||||
float getVisionSqueezeRatioX() const { return _visionSqueezeRatioX; }
|
||||
float getVisionSqueezeRatioY() const { return _visionSqueezeRatioY; }
|
||||
void setVisionSqueezeRatioX(float value);
|
||||
void setVisionSqueezeRatioY(float value);
|
||||
float getVisionSqueezeUnSqueezeDelay() const { return _visionSqueezeUnSqueezeDelay; }
|
||||
void setVisionSqueezeUnSqueezeDelay(float value);
|
||||
float getVisionSqueezeUnSqueezeSpeed() const { return _visionSqueezeUnSqueezeSpeed; }
|
||||
void setVisionSqueezeUnSqueezeSpeed(float value);
|
||||
float getVisionSqueezeTransition() const { return _visionSqueezeTransition; }
|
||||
void setVisionSqueezeTransition(float value);
|
||||
int getVisionSqueezePerEye() const { return _visionSqueezePerEye; }
|
||||
void setVisionSqueezePerEye(int value);
|
||||
float getVisionSqueezeGroundPlaneY() const { return _visionSqueezeGroundPlaneY; }
|
||||
void setVisionSqueezeGroundPlaneY(float value);
|
||||
float getVisionSqueezeSpotlightSize() const { return _visionSqueezeSpotlightSize; }
|
||||
void setVisionSqueezeSpotlightSize(float value);
|
||||
float getVisionSqueezeTurningXFactor() const { return _visionSqueezeTurningXFactor; }
|
||||
void setVisionSqueezeTurningXFactor(float value);
|
||||
float getVisionSqueezeTurningYFactor() const { return _visionSqueezeTurningYFactor; }
|
||||
void setVisionSqueezeTurningYFactor(float value);
|
||||
|
||||
void updateVisionSqueeze(const glm::mat4& sensorToWorldMatrix, float deltaTime);
|
||||
|
||||
// state variable accessors used by Application.cpp...
|
||||
bool getSqueezeVision() const { return _squeezeVision; }
|
||||
void setSqueezeVision(bool value) { _squeezeVision = value; }
|
||||
bool getSqueezeVisionTurning() const { return _squeezeVisionTurning; }
|
||||
void setSqueezeVisionTurning(bool value) { _squeezeVisionTurning = value; }
|
||||
|
||||
private:
|
||||
Setting::Handle<bool> _visionSqueezeEnabledSetting {"visionSqueezeEnabled", false};
|
||||
Setting::Handle<float> _visionSqueezeRatioXSetting {"visionSqueezeRatioX", 0.0f};
|
||||
Setting::Handle<float> _visionSqueezeRatioYSetting {"visionSqueezeRatioY", 0.0f};
|
||||
Setting::Handle<float> _visionSqueezeUnSqueezeDelaySetting {"visionSqueezeUnSqueezeDelay",
|
||||
DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY};
|
||||
Setting::Handle<float> _visionSqueezeUnSqueezeSpeedSetting {"visionSqueezeUnSqueezeSpeed",
|
||||
DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED};
|
||||
Setting::Handle<float> _visionSqueezeTransitionSetting {"visionSqueezeTransition", DEFAULT_VISION_SQUEEZE_TRANSITION};
|
||||
Setting::Handle<float> _visionSqueezePerEyeSetting {"visionSqueezePerEye", DEFAULT_VISION_SQUEEZE_PER_EYE};
|
||||
Setting::Handle<float> _visionSqueezeGroundPlaneYSetting {"visionSqueezeGroundPlaneY",
|
||||
DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y};
|
||||
Setting::Handle<float> _visionSqueezeSpotlightSizeSetting {"visionSqueezeSpotlightSize",
|
||||
DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE};
|
||||
Setting::Handle<float> _visionSqueezeTurningXFactorSetting {"visionSqueezeTurningXFactor",
|
||||
DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR};
|
||||
Setting::Handle<float> _visionSqueezeTurningYFactorSetting {"visionSqueezeTurningYFactor",
|
||||
DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR};
|
||||
|
||||
|
||||
// these are readable and writable from the scripting interface (on a different thread), so make them atomic
|
||||
std::atomic<bool> _visionSqueezeEnabled { false };
|
||||
std::atomic<float> _visionSqueezeRatioX { 0.0f };
|
||||
std::atomic<float> _visionSqueezeRatioY { 0.0f };
|
||||
std::atomic<float> _visionSqueezeUnSqueezeDelay { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_DELAY }; // seconds
|
||||
std::atomic<float> _visionSqueezeUnSqueezeSpeed { DEFAULT_VISION_SQUEEZE_UNSQUEEZE_SPEED };
|
||||
std::atomic<float> _visionSqueezeTransition { DEFAULT_VISION_SQUEEZE_TRANSITION };
|
||||
std::atomic<int> _visionSqueezePerEye { DEFAULT_VISION_SQUEEZE_PER_EYE };
|
||||
std::atomic<float> _visionSqueezeGroundPlaneY { DEFAULT_VISION_SQUEEZE_GROUND_PLANE_Y };
|
||||
std::atomic<float> _visionSqueezeSpotlightSize { DEFAULT_VISION_SQUEEZE_SPOTLIGHT_SIZE };
|
||||
std::atomic<float> _visionSqueezeTurningXFactor { DEFAULT_VISION_SQUEEZE_TURNING_X_FACTOR };
|
||||
std::atomic<float> _visionSqueezeTurningYFactor { DEFAULT_VISION_SQUEEZE_TURNING_Y_FACTOR };
|
||||
|
||||
bool _squeezeVision { false };
|
||||
bool _squeezeVisionTurning { false };
|
||||
|
||||
float _visionSqueezeLockout { 0.0 };
|
||||
glm::vec3 _prevTranslation;
|
||||
glm::quat _prevRotation;
|
||||
};
|
||||
|
||||
#endif // hifi_VisionSqueeze_h
|
|
@ -6144,4 +6144,3 @@ void MyAvatar::sendPacket(const QUuid& entityID) const {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -236,3 +236,83 @@ QVariant HMDScriptingInterface::getPlayAreaRect() {
|
|||
QVector<glm::vec3> HMDScriptingInterface::getSensorPositions() {
|
||||
return qApp->getActiveDisplayPlugin()->getSensorPositions();
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeRatioX() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeRatioX();
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeRatioY() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeRatioY();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeRatioX(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioX(value);
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeRatioY(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioY(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeUnSqueezeDelay() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeDelay();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeUnSqueezeDelay(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeDelay(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeUnSqueezeSpeed() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeUnSqueezeSpeed();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeUnSqueezeSpeed(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeUnSqueezeSpeed(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeTransition() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeTransition();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeTransition(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeTransition(value);
|
||||
}
|
||||
|
||||
int HMDScriptingInterface::getVisionSqueezePerEye() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezePerEye();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezePerEye(int value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezePerEye(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeGroundPlaneY() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeGroundPlaneY();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeGroundPlaneY(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeGroundPlaneY(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeSpotlightSize() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeSpotlightSize();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeSpotlightSize(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeSpotlightSize(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeTurningXFactor() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeTurningXFactor();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeTurningXFactor(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeTurningXFactor(value);
|
||||
}
|
||||
|
||||
float HMDScriptingInterface::getVisionSqueezeTurningYFactor() const {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeTurningYFactor();
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::setVisionSqueezeTurningYFactor(float value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeTurningYFactor(value);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,17 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
|
|||
Q_PROPERTY(QVariant playArea READ getPlayAreaRect);
|
||||
Q_PROPERTY(QVector<glm::vec3> sensorPositions READ getSensorPositions);
|
||||
|
||||
Q_PROPERTY(float visionSqueezeRatioX READ getVisionSqueezeRatioX WRITE setVisionSqueezeRatioX);
|
||||
Q_PROPERTY(float visionSqueezeRatioY READ getVisionSqueezeRatioY WRITE setVisionSqueezeRatioY);
|
||||
Q_PROPERTY(float visionSqueezeUnSqueezeDelay READ getVisionSqueezeUnSqueezeDelay WRITE setVisionSqueezeUnSqueezeDelay);
|
||||
Q_PROPERTY(float visionSqueezeUnSqueezeSpeed READ getVisionSqueezeUnSqueezeSpeed WRITE setVisionSqueezeUnSqueezeSpeed);
|
||||
Q_PROPERTY(float visionSqueezeTransition READ getVisionSqueezeTransition WRITE setVisionSqueezeTransition);
|
||||
Q_PROPERTY(int visionSqueezePerEye READ getVisionSqueezePerEye WRITE setVisionSqueezePerEye);
|
||||
Q_PROPERTY(float visionSqueezeGroundPlaneY READ getVisionSqueezeGroundPlaneY WRITE setVisionSqueezeGroundPlaneY);
|
||||
Q_PROPERTY(float visionSqueezeSpotlightSize READ getVisionSqueezeSpotlightSize WRITE setVisionSqueezeSpotlightSize);
|
||||
Q_PROPERTY(float visionSqueezeTurningXFactor READ getVisionSqueezeTurningXFactor WRITE setVisionSqueezeTurningXFactor);
|
||||
Q_PROPERTY(float visionSqueezeTurningYFactor READ getVisionSqueezeTurningYFactor WRITE setVisionSqueezeTurningYFactor);
|
||||
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -339,6 +350,27 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void openTablet(bool contextualMode = false);
|
||||
|
||||
float getVisionSqueezeRatioX() const;
|
||||
float getVisionSqueezeRatioY() const;
|
||||
void setVisionSqueezeRatioX(float value);
|
||||
void setVisionSqueezeRatioY(float value);
|
||||
float getVisionSqueezeUnSqueezeDelay() const;
|
||||
void setVisionSqueezeUnSqueezeDelay(float value);
|
||||
float getVisionSqueezeUnSqueezeSpeed() const;
|
||||
void setVisionSqueezeUnSqueezeSpeed(float value);
|
||||
float getVisionSqueezeTransition() const;
|
||||
void setVisionSqueezeTransition(float value);
|
||||
int getVisionSqueezePerEye() const;
|
||||
void setVisionSqueezePerEye(int value);
|
||||
float getVisionSqueezeGroundPlaneY() const;
|
||||
void setVisionSqueezeGroundPlaneY(float value);
|
||||
float getVisionSqueezeSpotlightSize() const;
|
||||
void setVisionSqueezeSpotlightSize(float value);
|
||||
float getVisionSqueezeTurningXFactor() const;
|
||||
void setVisionSqueezeTurningXFactor(float value);
|
||||
float getVisionSqueezeTurningYFactor() const;
|
||||
void setVisionSqueezeTurningYFactor(float value);
|
||||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Triggered when a request to show or hide models of the HMD hand controllers is made using
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <Preferences.h>
|
||||
#include <plugins/PluginUtils.h>
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
||||
#include "scripting/RenderScriptingInterface.h"
|
||||
#include "Application.h"
|
||||
#include "DialogsManager.h"
|
||||
|
@ -377,6 +378,33 @@ void setupPreferences() {
|
|||
preference->setDecimals(2);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->bool {
|
||||
return qApp->getVisionSqueeze().getVisionSqueezeEnabled();
|
||||
};
|
||||
auto setter = [](bool value) {
|
||||
qApp->getVisionSqueeze().setVisionSqueezeEnabled(value);
|
||||
};
|
||||
auto preference = new CheckPreference(VR_MOVEMENT, "Enable HMD Comfort Mode", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
const float sliderPositions = 5.0f;
|
||||
auto getter = [sliderPositions]()->float {
|
||||
return roundf(sliderPositions * qApp->getVisionSqueeze().getVisionSqueezeRatioX());
|
||||
};
|
||||
auto setter = [sliderPositions](float value) {
|
||||
float ratio = value / sliderPositions;
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioX(ratio);
|
||||
qApp->getVisionSqueeze().setVisionSqueezeRatioY(ratio);
|
||||
};
|
||||
auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "Comfort Mode", getter, setter);
|
||||
preference->setMin(0.0f);
|
||||
preference->setMax(sliderPositions);
|
||||
preference->setStep(1.0f);
|
||||
preference->setDecimals(0);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); };
|
||||
auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); };
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTextureWithVisionSqueeze.frag
|
||||
//
|
||||
// Draw texture 0 fetched at texcoord.xy
|
||||
//
|
||||
// Created by Seth Alves on 2019-2-15
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include display-plugins/VisionSqueeze.slh@>
|
||||
|
||||
struct DrawTextureWithVisionSqueezeParams {
|
||||
float _visionSqueezeX;
|
||||
float _visionSqueezeY;
|
||||
float _spareA;
|
||||
float _spareB;
|
||||
mat4 _leftProjection;
|
||||
mat4 _rightProjection;
|
||||
mat4 _hmdSensorMatrix;
|
||||
float _visionSqueezeTransition;
|
||||
int _visionSqueezePerEye;
|
||||
float _visionSqueezeGroundPlaneY;
|
||||
float _visionSqueezeSpotlightSize;
|
||||
};
|
||||
|
||||
|
||||
LAYOUT(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
// binding=1 must match drawTextureWithSqueezeParamsSlot in OpenGLDisplayPlugin.h
|
||||
LAYOUT(binding=1) uniform drawTextureWithSqueezeMappingParamsBuffer {
|
||||
DrawTextureWithVisionSqueezeParams params;
|
||||
};
|
||||
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
|
||||
float getVisionSqueezeX() {
|
||||
return params._visionSqueezeX;
|
||||
}
|
||||
float getVisionSqueezeY() {
|
||||
return params._visionSqueezeY;
|
||||
}
|
||||
float getVisionSqueezeTransitionRatio() {
|
||||
return params._visionSqueezeTransition;
|
||||
}
|
||||
int getVisionSqueezePerEye() {
|
||||
return params._visionSqueezePerEye;
|
||||
}
|
||||
float getVisionSqueezeGroundPlaneY() {
|
||||
return params._visionSqueezeGroundPlaneY;
|
||||
}
|
||||
float getVisionSqueezeSpotlightSize() {
|
||||
return params._visionSqueezeSpotlightSize;
|
||||
}
|
||||
mat4 getProjectionMatrix(float eye) {
|
||||
if (eye == 0.0) {
|
||||
return params._leftProjection;
|
||||
} else {
|
||||
return params._rightProjection;
|
||||
}
|
||||
}
|
||||
mat4 getHMDSensorMatrix() {
|
||||
return params._hmdSensorMatrix;
|
||||
}
|
||||
|
||||
|
||||
void main(void) {
|
||||
|
||||
float side = float(varTexCoord0.x > 0.5);
|
||||
mat4 leftProjectionMatrix = getProjectionMatrix(0.0);
|
||||
vec4 fovTan = extractFovTan(leftProjectionMatrix);
|
||||
vec2 focalPointNDC = extractFocalPoint(fovTan);
|
||||
focalPointNDC.x -= 2.0 * focalPointNDC.x * (1.0 - side);
|
||||
vec2 focalPointUV = 0.5 * (focalPointNDC + vec2(1.0));
|
||||
|
||||
// block edges of vision to avoid sickness
|
||||
vec2 visionSqueezeRatios = vec2(getVisionSqueezeX(), getVisionSqueezeY());
|
||||
bool perEye = getVisionSqueezePerEye() > 0;
|
||||
float frac = squeezeVision(perEye, varTexCoord0, visionSqueezeRatios, getVisionSqueezeTransitionRatio(), focalPointUV);
|
||||
|
||||
if (frac == 0.0) {
|
||||
// world only
|
||||
outFragColor = texture(colorMap, varTexCoord0);
|
||||
} else {
|
||||
// grid on the floor only or mixed
|
||||
mat4 hmdSensorMatrix = getHMDSensorMatrix();
|
||||
mat4 projectionMatrix = getProjectionMatrix(side);
|
||||
mat4 projectionInverse = inverse(projectionMatrix);
|
||||
float groundPlaneY = getVisionSqueezeGroundPlaneY();
|
||||
float spotLightSize = getVisionSqueezeSpotlightSize();
|
||||
vec4 gridColor = vec4(gridFloor(varTexCoord0, hmdSensorMatrix, projectionInverse, groundPlaneY, spotLightSize), 1.0);
|
||||
|
||||
vec4 preSqueezeColor = texture(colorMap, varTexCoord0);
|
||||
// mix between grid and world
|
||||
outFragColor = mix(preSqueezeColor, gridColor, frac);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
VERTEX gpu::vertex::DrawUnitQuadTexcoord
|
|
@ -392,6 +392,9 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
|
||||
_drawTexturePipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTexture), scissorState);
|
||||
|
||||
_drawTextureSqueezePipeline =
|
||||
gpu::Pipeline::create(gpu::Shader::createProgram(shader::display_plugins::program::DrawTextureWithVisionSqueeze), scissorState);
|
||||
|
||||
_linearToSRGBPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureLinearToSRGB), scissorState);
|
||||
|
||||
_SRGBToLinearPipeline = gpu::Pipeline::create(gpu::Shader::createProgram(DrawTextureSRGBToLinear), scissorState);
|
||||
|
@ -407,6 +410,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
void OpenGLDisplayPlugin::uncustomizeContext() {
|
||||
|
||||
_drawTexturePipeline.reset();
|
||||
_drawTextureSqueezePipeline.reset();
|
||||
_linearToSRGBPipeline.reset();
|
||||
_SRGBToLinearPipeline.reset();
|
||||
_cursorPipeline.reset();
|
||||
|
@ -629,6 +633,10 @@ void OpenGLDisplayPlugin::compositePointer() {
|
|||
});
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) {
|
||||
batch.setPipeline(_drawTexturePipeline);
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositeScene() {
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
@ -637,8 +645,8 @@ void OpenGLDisplayPlugin::compositeScene() {
|
|||
batch.setStateScissorRect(ivec4(uvec2(), _compositeFramebuffer->getSize()));
|
||||
batch.resetViewTransform();
|
||||
batch.setProjectionTransform(mat4());
|
||||
batch.setPipeline(_drawTexturePipeline);
|
||||
batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0));
|
||||
setupCompositeScenePipeline(batch);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
}
|
||||
|
@ -958,4 +966,3 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne
|
|||
gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() {
|
||||
return _drawTexturePipeline;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ protected:
|
|||
|
||||
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
|
||||
virtual void compositeLayers();
|
||||
virtual void setupCompositeScenePipeline(gpu::Batch& batch);
|
||||
virtual void compositeScene();
|
||||
virtual void compositePointer();
|
||||
virtual void compositeExtra(){};
|
||||
|
@ -155,6 +156,7 @@ protected:
|
|||
gpu::PipelinePointer _mirrorHUDPipeline;
|
||||
gpu::ShaderPointer _mirrorHUDPS;
|
||||
gpu::PipelinePointer _drawTexturePipeline;
|
||||
gpu::PipelinePointer _drawTextureSqueezePipeline;
|
||||
gpu::PipelinePointer _linearToSRGBPipeline;
|
||||
gpu::PipelinePointer _SRGBToLinearPipeline;
|
||||
gpu::PipelinePointer _cursorPipeline;
|
||||
|
|
106
libraries/display-plugins/src/display-plugins/VisionSqueeze.slh
Normal file
106
libraries/display-plugins/src/display-plugins/VisionSqueeze.slh
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Created by Seth Alves on 2019-2-13.
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@if not VISION_SQUEEZE_SLH@>
|
||||
<@def VISION_SQUEEZE_SLH@>
|
||||
|
||||
|
||||
float ellipse(vec2 coord, vec2 centerUV, vec2 semiAxis) {
|
||||
return pow(coord.x - centerUV.x, 2.0) / semiAxis.x + pow(coord.y - centerUV.y, 2.0) / semiAxis.y;
|
||||
}
|
||||
|
||||
vec4 extractFovTan(mat4 m) {
|
||||
mat4 mt = transpose(m);
|
||||
vec4 v;
|
||||
vec4 result;
|
||||
|
||||
// x -- Left
|
||||
v = mt * vec4(1.0, 0.0, 0.0, 1.0);
|
||||
result.x = -(v.z / v.x);
|
||||
// y -- Right
|
||||
v = mt * vec4(-1.0, 0.0, 0.0, 1.0);
|
||||
result.y = (v.z / v.x);
|
||||
// z -- Down
|
||||
v = mt * vec4(0.0, 1.0, 0.0, 1.0);
|
||||
result.z = -(v.z / v.y);
|
||||
// w -- Up
|
||||
v = mt * vec4(0.0, -1.0, 0.0, 1.0);
|
||||
result.w = v.z / v.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
// takes left-side projection matrix, returns NDC for right eye. to get left, invert sign on x coord of result.
|
||||
vec2 extractFocalPoint(vec4 fovTan) {
|
||||
float fovwidth = fovTan.x + fovTan.y;
|
||||
float fovheight = fovTan.z + fovTan.w;
|
||||
vec2 focalPoint = vec2(fovTan.y / fovwidth, (fovTan.z / fovheight) - 0.5f);
|
||||
return focalPoint;
|
||||
}
|
||||
|
||||
float squeezeVision(bool perEye, vec2 varTexCoord0, vec2 visionSqueezeRatios, float transitionRatio, vec2 focalPointUV) {
|
||||
if (visionSqueezeRatios.x == 0.0 && visionSqueezeRatios.y == 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
vec2 centerUV;
|
||||
vec2 semiAxis;
|
||||
if (perEye) {
|
||||
// tubes in front of each eye
|
||||
centerUV = focalPointUV;
|
||||
semiAxis = vec2(0.25) - visionSqueezeRatios * 0.25;
|
||||
} else {
|
||||
// one tube in front of face
|
||||
centerUV = vec2(0.5, focalPointUV.y);
|
||||
semiAxis = vec2(0.5) - visionSqueezeRatios * 0.5;
|
||||
}
|
||||
float ellipseValue = ellipse(varTexCoord0, centerUV, semiAxis);
|
||||
float frac = clamp((ellipseValue - 1.0) / clamp(transitionRatio, 0.01, 0.7), 0.0, 1.0);
|
||||
|
||||
return frac;
|
||||
}
|
||||
|
||||
vec3 gridFloor(vec2 varTexCoord0, mat4 hmdSensorMatrix, mat4 projectionInverse, float groundPlaneY, float spotLightSize) {
|
||||
vec4 ndc = vec4(varTexCoord0.x * 4.0 - 1.0 - 2.0 * float(varTexCoord0.x > 0.5), varTexCoord0.y * 2.0 - 1.0, -1.0, 1.0);
|
||||
|
||||
vec4 fragmentEyeCoords = hmdSensorMatrix * projectionInverse * ndc;
|
||||
vec4 near4 = hmdSensorMatrix * vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
vec3 near = (near4 / near4.w).xyz;
|
||||
vec3 far = fragmentEyeCoords.xyz / fragmentEyeCoords.w;
|
||||
|
||||
// intersect a line from near to far with the plane y = groundPlaneY
|
||||
float t = -(near.y - groundPlaneY) / (far.y - near.y);
|
||||
vec2 R = (near + t * (far - near)).xz;
|
||||
|
||||
float lineThickness = 1.5 / length(R);
|
||||
vec4 gridColor = vec4(0.35);
|
||||
vec4 baseColor = vec4(0.1);
|
||||
vec4 skyColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
vec2 wrapped = fract(R) - 0.5f;
|
||||
vec2 range = abs(wrapped);
|
||||
vec2 speeds = fwidth(R);
|
||||
vec2 pixelRange = range/speeds;
|
||||
float lineWeight = clamp(min(pixelRange.x, pixelRange.y) - lineThickness, 0.0, 1.0);
|
||||
|
||||
float horizonFuzz = 0.02;
|
||||
if (t < 0.0) {
|
||||
return mix(gridColor, skyColor, clamp(0.0, 1.0, -t)).xyz;
|
||||
} else if (t < horizonFuzz) {
|
||||
lineWeight = lineWeight * max(0.0, t);
|
||||
}
|
||||
|
||||
vec4 c = mix(gridColor, baseColor, lineWeight);
|
||||
|
||||
// fade out grid to avoid shimmer
|
||||
float fadeVal = 0.7;
|
||||
return mix(c, baseColor * fadeVal + gridColor * (1.0 - fadeVal),
|
||||
0.1 * clamp((length(R) - spotLightSize), 0.0, 1.0)).xyz;
|
||||
}
|
||||
|
||||
<@endif@>
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// Created by Bradley Austin Davis on 2016/02/15
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -113,6 +113,11 @@ void HmdDisplayPlugin::internalDeactivate() {
|
|||
}
|
||||
|
||||
void HmdDisplayPlugin::customizeContext() {
|
||||
|
||||
VisionSqueezeParameters parameters;
|
||||
_visionSqueezeParametersBuffer =
|
||||
gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(VisionSqueezeParameters), (const gpu::Byte*) ¶meters));
|
||||
|
||||
Parent::customizeContext();
|
||||
_hudRenderer.build();
|
||||
}
|
||||
|
@ -478,3 +483,57 @@ HmdDisplayPlugin::~HmdDisplayPlugin() {
|
|||
float HmdDisplayPlugin::stutterRate() const {
|
||||
return _stutterRate.rate();
|
||||
}
|
||||
|
||||
float adjustVisionSqueezeRatioForDevice(float visionSqueezeRatio, float visionSqueezeDeviceLow, float visionSqueezeDeviceHigh) {
|
||||
const float SETTINGS_STEP = 0.2f; // adjusting the slider in preferences changes the ratio by this much
|
||||
|
||||
if (visionSqueezeRatio == 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float deviceRange = visionSqueezeDeviceHigh - visionSqueezeDeviceLow;
|
||||
|
||||
if (visionSqueezeRatio <= SETTINGS_STEP) {
|
||||
// lowest "enabled" setting -- without this special case the user doesn't see anything on the lowest setting
|
||||
float scaleFactor = (visionSqueezeRatio == SETTINGS_STEP) ? 0.24f : 0.18f; // these magic values were picked through experimentation
|
||||
return deviceRange * scaleFactor + visionSqueezeDeviceLow;
|
||||
} else {
|
||||
const float SQUEEZE_ADJUSTMENT = 0.75f; // magic number picked through experimentation
|
||||
return deviceRange * (SQUEEZE_ADJUSTMENT * visionSqueezeRatio) + visionSqueezeDeviceLow;
|
||||
}
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY,
|
||||
float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize) {
|
||||
|
||||
visionSqueezeX = adjustVisionSqueezeRatioForDevice(visionSqueezeX, _visionSqueezeDeviceLowX, _visionSqueezeDeviceHighX);
|
||||
visionSqueezeY = adjustVisionSqueezeRatioForDevice(visionSqueezeY, _visionSqueezeDeviceLowY, _visionSqueezeDeviceHighY);
|
||||
|
||||
auto& params = _visionSqueezeParametersBuffer.get<VisionSqueezeParameters>();
|
||||
if (params._visionSqueezeX != visionSqueezeX) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeX = visionSqueezeX;
|
||||
}
|
||||
if (params._visionSqueezeY != visionSqueezeY) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeY = visionSqueezeY;
|
||||
}
|
||||
if (params._visionSqueezeTransition != visionSqueezeTransition) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeTransition = visionSqueezeTransition;
|
||||
}
|
||||
if (params._visionSqueezePerEye != visionSqueezePerEye) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezePerEye = visionSqueezePerEye;
|
||||
}
|
||||
if (params._visionSqueezeGroundPlaneY != visionSqueezeGroundPlaneY) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeGroundPlaneY = visionSqueezeGroundPlaneY;
|
||||
}
|
||||
if (params._visionSqueezeSpotlightSize != visionSqueezeSpotlightSize) {
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._visionSqueezeSpotlightSize = visionSqueezeSpotlightSize;
|
||||
}
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::setupCompositeScenePipeline(gpu::Batch& batch) {
|
||||
batch.setPipeline(_drawTextureSqueezePipeline);
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose;
|
||||
batch.setUniformBuffer(drawTextureWithVisionSqueezeParamsSlot, _visionSqueezeParametersBuffer);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
|
||||
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::PAINT; }
|
||||
void updateVisionSqueezeParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize);
|
||||
|
||||
signals:
|
||||
void hmdMountedChanged();
|
||||
|
@ -91,6 +94,33 @@ protected:
|
|||
RateCounter<> _stutterRate;
|
||||
|
||||
bool _disablePreview { true };
|
||||
|
||||
class VisionSqueezeParameters {
|
||||
public:
|
||||
float _visionSqueezeX { 0.0f };
|
||||
float _visionSqueezeY { 0.0f };
|
||||
float _spareA { 0.0f };
|
||||
float _spareB { 0.0f };
|
||||
glm::mat4 _leftProjection;
|
||||
glm::mat4 _rightProjection;
|
||||
glm::mat4 _hmdSensorMatrix;
|
||||
float _visionSqueezeTransition { 0.15f };
|
||||
int _visionSqueezePerEye { 0 };
|
||||
float _visionSqueezeGroundPlaneY { 0.0f };
|
||||
float _visionSqueezeSpotlightSize { 0.0f };
|
||||
|
||||
VisionSqueezeParameters() {}
|
||||
};
|
||||
typedef gpu::BufferView UniformBufferView;
|
||||
gpu::BufferView _visionSqueezeParametersBuffer;
|
||||
|
||||
virtual void setupCompositeScenePipeline(gpu::Batch& batch) override;
|
||||
|
||||
float _visionSqueezeDeviceLowX { 0.0f };
|
||||
float _visionSqueezeDeviceHighX { 1.0f };
|
||||
float _visionSqueezeDeviceLowY { 0.0f };
|
||||
float _visionSqueezeDeviceHighY { 1.0f };
|
||||
|
||||
private:
|
||||
ivec4 getViewportForSourceSize(const uvec2& size) const;
|
||||
float getLeftCenterPixel() const;
|
||||
|
@ -112,7 +142,7 @@ private:
|
|||
struct Uniforms {
|
||||
float alpha { 1.0f };
|
||||
} uniforms;
|
||||
|
||||
|
||||
struct Vertex {
|
||||
vec3 pos;
|
||||
vec2 uv;
|
||||
|
@ -126,3 +156,5 @@ private:
|
|||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> render();
|
||||
} _hudRenderer;
|
||||
};
|
||||
|
||||
const int drawTextureWithVisionSqueezeParamsSlot = 1; // must match binding in DrawTextureWithVisionSqueeze.slf
|
||||
|
|
|
@ -220,7 +220,7 @@ double Context::getFrameTimerBatchAverage() const {
|
|||
const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const {
|
||||
_projectionInverse = glm::inverse(_projection);
|
||||
|
||||
// Get the viewEyeToWorld matrix form the transformView as passed to the gpu::Batch
|
||||
// Get the viewEyeToWorld matrix from the transformView as passed to the gpu::Batch
|
||||
// this is the "_viewInverse" fed to the shader
|
||||
// Genetrate the "_view" matrix as well from the xform
|
||||
xformView.getMatrix(_viewInverse);
|
||||
|
|
|
@ -214,6 +214,9 @@ public:
|
|||
virtual StencilMaskMode getStencilMaskMode() const { return StencilMaskMode::NONE; }
|
||||
using StencilMaskMeshOperator = std::function<void(gpu::Batch&)>;
|
||||
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() { return nullptr; }
|
||||
virtual void updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize) {}
|
||||
|
||||
signals:
|
||||
void recommendedFramebufferSizeChanged(const QSize& size);
|
||||
|
|
|
@ -142,6 +142,13 @@ namespace render {
|
|||
bool _takingSnapshot { false };
|
||||
StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE };
|
||||
std::function<void(gpu::Batch&)> _stencilMaskOperator;
|
||||
|
||||
float _visionSqueezeX { 0.0f };
|
||||
float _visionSqueezeY { 0.0f };
|
||||
float _visionSqueezeTransition { 0.15f };
|
||||
int _visionSqueezePerEye { 0 };
|
||||
float _visionSqueezeGroundPlaneY { 0.0f };
|
||||
float _visionSqueezeSpotlightSize { 0.02f };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -53,6 +53,13 @@ bool OculusDisplayPlugin::internalActivate() {
|
|||
void OculusDisplayPlugin::init() {
|
||||
Plugin::init();
|
||||
|
||||
// Different HMDs end up showing the squeezed-vision egg as different sizes. These values
|
||||
// attempt to make them appear the same.
|
||||
_visionSqueezeDeviceLowX = 0.8f;
|
||||
_visionSqueezeDeviceHighX = 0.98f;
|
||||
_visionSqueezeDeviceLowY = 0.8f;
|
||||
_visionSqueezeDeviceHighY = 0.9f;
|
||||
|
||||
emit deviceConnected(getName());
|
||||
}
|
||||
|
||||
|
@ -151,8 +158,11 @@ void OculusDisplayPlugin::hmdPresent() {
|
|||
GLuint curTexId;
|
||||
ovr_GetTextureSwapChainBufferGL(_session, _textureSwapChain, curIndex, &curTexId);
|
||||
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._leftProjection = _eyeProjections[0];
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._rightProjection = _eyeProjections[1];
|
||||
|
||||
// Manually bind the texture to the FBO
|
||||
// FIXME we should have a way of wrapping raw GL ids in GPU objects without
|
||||
// FIXME we should have a way of wrapping raw GL ids in GPU objects without
|
||||
// taking ownership of the object
|
||||
auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer);
|
||||
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0);
|
||||
|
|
|
@ -396,6 +396,13 @@ void OpenVrDisplayPlugin::init() {
|
|||
_lastGoodHMDPose.m[2][2] = 1.0f;
|
||||
_lastGoodHMDPose.m[2][3] = 0.0f;
|
||||
|
||||
// Different HMDs end up showing the squeezed-vision egg as different sizes. These values
|
||||
// attempt to make them appear the same.
|
||||
_visionSqueezeDeviceLowX = 0.8f;
|
||||
_visionSqueezeDeviceHighX = 0.98f;
|
||||
_visionSqueezeDeviceLowY = 0.8f;
|
||||
_visionSqueezeDeviceHighY = 0.9f;
|
||||
|
||||
emit deviceConnected(getName());
|
||||
}
|
||||
|
||||
|
@ -651,6 +658,11 @@ void OpenVrDisplayPlugin::hmdPresent() {
|
|||
if (_threadedSubmit) {
|
||||
_submitThread->waitForPresent();
|
||||
} else {
|
||||
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._leftProjection = _eyeProjections[0];
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._rightProjection = _eyeProjections[1];
|
||||
_visionSqueezeParametersBuffer.edit<VisionSqueezeParameters>()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose;
|
||||
|
||||
GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0));
|
||||
vr::Texture_t vrTexture{ (void*)(uintptr_t)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
|
||||
vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT);
|
||||
|
@ -828,4 +840,15 @@ DisplayPlugin::StencilMaskMeshOperator OpenVrDisplayPlugin::getStencilMaskMeshOp
|
|||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize) {
|
||||
_visionSqueezeX = visionSqueezeX;
|
||||
_visionSqueezeY = visionSqueezeY;
|
||||
_visionSqueezeTransition = visionSqueezeTransition;
|
||||
_visionSqueezePerEye = visionSqueezePerEye;
|
||||
_visionSqueezeGroundPlaneY = visionSqueezeGroundPlaneY;
|
||||
_visionSqueezeSpotlightSize = visionSqueezeSpotlightSize;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,10 @@ public:
|
|||
virtual StencilMaskMode getStencilMaskMode() const override { return StencilMaskMode::MESH; }
|
||||
virtual StencilMaskMeshOperator getStencilMaskMeshOperator() override;
|
||||
|
||||
virtual void updateParameters(float visionSqueezeX, float visionSqueezeY, float visionSqueezeTransition,
|
||||
int visionSqueezePerEye, float visionSqueezeGroundPlaneY,
|
||||
float visionSqueezeSpotlightSize) override;
|
||||
|
||||
protected:
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
|
@ -102,4 +106,11 @@ private:
|
|||
|
||||
std::array<graphics::MeshPointer, 2> _stencilMeshes;
|
||||
bool _stencilMeshesInitialized { false };
|
||||
|
||||
float _visionSqueezeX;
|
||||
float _visionSqueezeY;
|
||||
float _visionSqueezeTransition;
|
||||
int _visionSqueezePerEye;
|
||||
float _visionSqueezeGroundPlaneY;
|
||||
float _visionSqueezeSpotlightSize;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue