Merge remote-tracking branch 'tony/ajt/overlay-fade' into plugins

This commit is contained in:
Bradley Austin Davis 2015-07-24 13:59:11 -04:00
commit 975c95eded
11 changed files with 296 additions and 14 deletions

View file

@ -970,13 +970,15 @@ void Application::paintGL() {
// or with changes from the face tracker
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
_myCamera.setPosition(_myAvatar->getDefaultEyePosition());
if (!getActiveDisplayPlugin()->isHmd()) {
_myCamera.setPosition(_myAvatar->getDefaultEyePosition());
_myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation());
} else {
// The plugin getModelview() call below will compose the base
// avatar transform with the HMD pose.
_myCamera.setRotation(_myAvatar->getOrientation());
// sensor to world transform with the HMD pose.
mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix();
_myCamera.setPosition(extractTranslation(sensorToWorldMat));
_myCamera.setRotation(glm::quat_cast(sensorToWorldMat));
}
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
if (isHMDMode()) {
@ -1143,6 +1145,7 @@ void Application::audioMuteToggled() {
}
void Application::faceTrackerMuteToggled() {
QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteFaceTracking);
Q_CHECK_PTR(muteAction);
bool isMuted = getSelectedFaceTracker()->isMuted();
@ -1703,6 +1706,9 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
} else if (event->button() == Qt::RightButton) {
// right click items here
} else if (event->button() == Qt::MiddleButton) {
// toggle the overlay
_overlayConductor.setEnabled(!_overlayConductor.getEnabled());
}
}
}
@ -1988,6 +1994,9 @@ void Application::idle() {
}
}
float secondsSinceLastUpdate = (float)timeSinceLastUpdate / 1000.0f;
_overlayConductor.update(secondsSinceLastUpdate);
// depending on whether we're throttling or not.
// Once rendering is off on another thread we should be able to have Application::idle run at start(0) in
// perpetuity and not expect events to get backed up.
@ -4892,6 +4901,15 @@ mat4 Application::getEyePose(int eye) const {
return mat4();
}
mat4 Application::getEyeOffset(int eye) const {
if (isHMDMode()) {
mat4 identity;
return getActiveDisplayPlugin()->getModelview((Eye)eye, identity);
}
return mat4();
}
mat4 Application::getHMDSensorPose() const {
if (isHMDMode()) {
return getActiveDisplayPlugin()->getHeadPose();

View file

@ -61,6 +61,7 @@
#include "ui/overlays/Overlays.h"
#include "ui/ApplicationOverlay.h"
#include "ui/ApplicationCompositor.h"
#include "ui/OverlayConductor.h"
#include "ui/RunningScriptsWidget.h"
#include "ui/ToolWindow.h"
#include "octree/OctreePacketProcessor.h"
@ -317,6 +318,7 @@ public:
bool isHMDMode() const;
glm::mat4 getHMDSensorPose() const;
glm::mat4 getEyePose(int eye) const;
glm::mat4 getEyeOffset(int eye) const;
glm::mat4 getEyeProjection(int eye) const;
QRect getDesirableApplicationGeometry();
@ -654,12 +656,15 @@ private:
Overlays _overlays;
ApplicationOverlay _applicationOverlay;
ApplicationCompositor _compositor;
OverlayConductor _overlayConductor;
int _oldHandMouseX[2];
int _oldHandMouseY[2];
bool _oldHandLeftClick[2];
bool _oldHandRightClick[2];
int _numFramesSinceLastResize = 0;
bool _overlayEnabled = true;
};
#endif // hifi_Application_h

View file

@ -278,7 +278,7 @@ void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) {
const QString& collisionSoundURL = myAvatar->getCollisionSoundURL();
if (!collisionSoundURL.isEmpty()) {
const float velocityChange = glm::length(collision.velocityChange);
const float MIN_AVATAR_COLLISION_ACCELERATION = 0.01;
const float MIN_AVATAR_COLLISION_ACCELERATION = 0.01f;
const bool isSound = (collision.type == CONTACT_EVENT_TYPE_START) && (velocityChange > MIN_AVATAR_COLLISION_ACCELERATION);
if (!isSound) {

View file

@ -1345,7 +1345,6 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
void MyAvatar::updateOrientation(float deltaTime) {
// Smoothly rotate body with arrow keys
float driveLeft = _driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT];
float targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED;
if (targetSpeed != 0.0f) {
const float ROTATION_RAMP_TIMESCALE = 0.1f;

View file

@ -186,7 +186,8 @@ void ApplicationCompositor::bindCursorTexture(gpu::Batch& batch, uint8_t cursorI
// Draws the FBO texture for the screen
void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
PROFILE_RANGE(__FUNCTION__);
if (_alpha == 0.0f) {
if (_alpha <= 0.0f) {
return;
}
@ -253,7 +254,8 @@ vec2 getPolarCoordinates(const PalmData& palm) {
// Draws the FBO texture for Oculus rift.
void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int eye) {
PROFILE_RANGE(__FUNCTION__);
if (_alpha == 0.0f) {
if (_alpha <= 0.0f) {
return;
}
@ -280,11 +282,12 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0));
batch.setViewTransform(Transform());
batch.setProjectionTransform(qApp->getEyeProjection(eye));
mat4 camMat;
_cameraBaseTransform.getMatrix(camMat);
camMat = camMat * qApp->getEyePose(eye);
batch.setViewTransform(camMat);
mat4 eyePose = qApp->getEyePose(eye);
glm::mat4 overlayXfm = glm::inverse(eyePose);
batch.setProjectionTransform(qApp->getEyeProjection(eye));
#ifdef DEBUG_OVERLAY
{
@ -293,7 +296,9 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
}
#else
{
batch.setModelTransform(overlayXfm);
//batch.setModelTransform(overlayXfm);
batch.setModelTransform(_modelTransform);
drawSphereSection(batch);
}
#endif
@ -304,8 +309,11 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
bindCursorTexture(batch);
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
//Controller Pointers
glm::mat4 overlayXfm;
_modelTransform.getMatrix(overlayXfm);
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
PalmData& palm = myAvatar->getHand()->getPalms()[i];
if (palm.isActive()) {
@ -619,6 +627,19 @@ void ApplicationCompositor::drawSphereSection(gpu::Batch& batch) {
batch.setInputFormat(streamFormat);
static const int VERTEX_STRIDE = sizeof(vec3) + sizeof(vec2) + sizeof(vec4);
if (_prevAlpha != _alpha) {
// adjust alpha by munging vertex color alpha.
// FIXME we should probably just use a uniform for this.
float* floatPtr = reinterpret_cast<float*>(_hemiVertices->editData());
const auto ALPHA_FLOAT_OFFSET = (sizeof(vec3) + sizeof(vec2) + sizeof(vec3)) / sizeof(float);
const auto VERTEX_FLOAT_STRIDE = (sizeof(vec3) + sizeof(vec2) + sizeof(vec4)) / sizeof(float);
const auto NUM_VERTS = _hemiVertices->getSize() / VERTEX_STRIDE;
for (size_t i = 0; i < NUM_VERTS; i++) {
floatPtr[i * VERTEX_FLOAT_STRIDE + ALPHA_FLOAT_OFFSET] = _alpha;
}
}
gpu::BufferView posView(_hemiVertices, 0, _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
gpu::BufferView uvView(_hemiVertices, sizeof(vec3), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element);
gpu::BufferView colView(_hemiVertices, sizeof(vec3) + sizeof(vec2), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
@ -708,3 +729,13 @@ void ApplicationCompositor::updateTooltips() {
}
}
}
void ApplicationCompositor::update(float dt) {
const int ALPHA_FADE_RATE = 2.0f;
_prevAlpha = _alpha;
if (_fadeInAlpha && _alpha < 1.0f) {
_alpha = std::min(_alpha + ALPHA_FADE_RATE * dt, 1.0f);
} else if (!_fadeInAlpha && _alpha > 0.0f) {
_alpha = std::max(_alpha - ALPHA_FADE_RATE * dt, 0.0f);
}
}

View file

@ -64,6 +64,17 @@ public:
void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const;
uint32_t getOverlayTexture() const;
void setCameraBaseTransform(const Transform& transform) { _cameraBaseTransform = transform; }
const Transform& getCameraBaseTransform() const { return _cameraBaseTransform; }
void setModelTransform(const Transform& transform) { _modelTransform = transform; }
const Transform& getModelTransform() const { return _modelTransform; }
void fadeIn() { _fadeInAlpha = true; }
void fadeOut() { _fadeInAlpha = false; }
void toggle() { _fadeInAlpha = !_fadeInAlpha; }
void update(float dt);
static glm::vec2 directionToSpherical(const glm::vec3 & direction);
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);
static glm::vec2 screenToSpherical(const glm::vec2 & screenPos);
@ -100,6 +111,8 @@ private:
bool _magnifier{ true };
float _alpha{ 1.0f };
float _prevAlpha{ 1.0f };
float _fadeInAlpha{ true };
float _oculusUIRadius{ 1.0f };
QMap<uint16_t, gpu::TexturePointer> _cursors;
@ -115,6 +128,9 @@ private:
glm::vec3 _previousMagnifierBottomRight;
glm::vec3 _previousMagnifierTopLeft;
glm::vec3 _previousMagnifierTopRight;
Transform _modelTransform;
Transform _cameraBaseTransform;
};
#endif // hifi_ApplicationCompositor_h

View file

@ -0,0 +1,161 @@
//
// OverlayConductor.cpp
// interface/src/ui
//
// Copyright 2015 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 "Application.h"
#include "InterfaceLogging.h"
#include "avatar/AvatarManager.h"
#include "OverlayConductor.h"
OverlayConductor::OverlayConductor() {
}
OverlayConductor::~OverlayConductor() {
}
void OverlayConductor::update(float dt) {
updateMode();
switch (_mode) {
case SITTING: {
// when sitting, the overlay is at the origin, facing down the -z axis.
// the camera is taken directly from the HMD.
Transform identity;
qApp->getApplicationCompositor().setModelTransform(identity);
qApp->getApplicationCompositor().setCameraBaseTransform(identity);
break;
}
case STANDING: {
// when standing, the overlay is at a reference position, which is set when the overlay is
// enabled. The camera is taken directly from the HMD, but in world space.
// So the sensorToWorldMatrix must be applied.
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
Transform t;
t.evalFromRawMatrix(myAvatar->getSensorToWorldMatrix());
qApp->getApplicationCompositor().setCameraBaseTransform(t);
// detect when head moves out side of sweet spot, or looks away.
mat4 headMat = myAvatar->getSensorToWorldMatrix() * qApp->getHMDSensorPose();
vec3 headWorldPos = extractTranslation(headMat);
vec3 headForward = glm::quat_cast(headMat) * glm::vec3(0.0f, 0.0f, -1.0f);
Transform modelXform = qApp->getApplicationCompositor().getModelTransform();
vec3 compositorWorldPos = modelXform.getTranslation();
vec3 compositorForward = modelXform.getRotation() * glm::vec3(0.0f, 0.0f, -1.0f);
const float MAX_COMPOSITOR_DISTANCE = 0.6f;
const float MAX_COMPOSITOR_ANGLE = 110.0f;
if (_enabled && (glm::distance(headWorldPos, compositorWorldPos) > MAX_COMPOSITOR_DISTANCE ||
glm::dot(headForward, compositorForward) < cosf(glm::radians(MAX_COMPOSITOR_ANGLE)))) {
// fade out the overlay
setEnabled(false);
}
break;
}
case FLAT:
// do nothing
break;
}
// process alpha fade animations
qApp->getApplicationCompositor().update(dt);
}
void OverlayConductor::updateMode() {
Mode newMode;
if (qApp->isHMDMode()) {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
if (myAvatar->getStandingHMDSensorMode()) {
newMode = STANDING;
} else {
newMode = SITTING;
}
} else {
newMode = FLAT;
}
if (newMode != _mode) {
switch (newMode) {
case SITTING: {
// enter the SITTING state
// place the overlay at origin
Transform identity;
qApp->getApplicationCompositor().setModelTransform(identity);
break;
}
case STANDING: {
// enter the STANDING state
// place the overlay at the current hmd position in world space
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto camMat = cancelOutRollAndPitch(myAvatar->getSensorToWorldMatrix() * qApp->getHMDSensorPose());
Transform t;
t.setTranslation(extractTranslation(camMat));
t.setRotation(glm::quat_cast(camMat));
qApp->getApplicationCompositor().setModelTransform(t);
break;
}
case FLAT:
// do nothing
break;
}
}
_mode = newMode;
}
void OverlayConductor::setEnabled(bool enabled) {
if (enabled == _enabled) {
return;
}
if (_enabled) {
// alpha fadeOut the overlay mesh.
qApp->getApplicationCompositor().fadeOut();
// disable mouse clicks from script
qApp->getOverlays().disable();
// disable QML events
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->getRootItem()->setEnabled(false);
_enabled = false;
} else {
// alpha fadeIn the overlay mesh.
qApp->getApplicationCompositor().fadeIn();
// enable mouse clicks from script
qApp->getOverlays().enable();
// enable QML events
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->getRootItem()->setEnabled(true);
if (_mode == STANDING) {
// place the overlay at the current hmd position in world space
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto camMat = cancelOutRollAndPitch(myAvatar->getSensorToWorldMatrix() * qApp->getHMDSensorPose());
Transform t;
t.setTranslation(extractTranslation(camMat));
t.setRotation(glm::quat_cast(camMat));
qApp->getApplicationCompositor().setModelTransform(t);
}
_enabled = true;
}
}
bool OverlayConductor::getEnabled() const {
return _enabled;
}

View file

@ -0,0 +1,36 @@
//
// OverlayConductor.h
// interface/src/ui
//
// Copyright 2015 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_OverlayConductor_h
#define hifi_OverlayConductor_h
class OverlayConductor {
public:
OverlayConductor();
~OverlayConductor();
void update(float dt);
void setEnabled(bool enable);
bool getEnabled() const;
private:
void updateMode();
enum Mode {
FLAT,
SITTING,
STANDING
};
Mode _mode = FLAT;
bool _enabled = true;
};
#endif

View file

@ -124,6 +124,16 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
}
}
void Overlays::disable() {
QWriteLocker lock(&_lock);
_enabled = false;
}
void Overlays::enable() {
QWriteLocker lock(&_lock);
_enabled = true;
}
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {
unsigned int thisID = 0;
Overlay* thisOverlay = NULL;
@ -269,6 +279,9 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) {
}
QReadLocker lock(&_lock);
if (!_enabled) {
return 0;
}
QMapIterator<unsigned int, Overlay::Pointer> i(_overlaysHUD);
i.toBack();

View file

@ -56,6 +56,8 @@ public:
void init();
void update(float deltatime);
void renderHUD(RenderArgs* renderArgs);
void disable();
void enable();
public slots:
/// adds an overlay with the specific properties
@ -99,6 +101,7 @@ private:
QReadWriteLock _lock;
QReadWriteLock _deleteLock;
QScriptEngine* _scriptEngine;
bool _enabled = true;
};

View file

@ -145,7 +145,7 @@ mat4 OpenVrDisplayPlugin::getProjection(Eye eye, const mat4& baseProjection) con
}
glm::mat4 OpenVrDisplayPlugin::getModelview(Eye eye, const mat4& baseModelview) const {
return baseModelview * _eyesData[eye]._eyeOffset;
return baseModelview * getEyePose(eye);
}
void OpenVrDisplayPlugin::resetSensors() {