mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into animationGroupSettings
This commit is contained in:
commit
e93326e43f
26 changed files with 322 additions and 217 deletions
|
@ -2351,6 +2351,7 @@ void Application::saveSettings() {
|
|||
|
||||
Menu::getInstance()->saveSettings();
|
||||
getMyAvatar()->saveData();
|
||||
PluginManager::getInstance()->saveSettings();
|
||||
}
|
||||
|
||||
bool Application::importEntities(const QString& urlOrFilename) {
|
||||
|
@ -2758,7 +2759,7 @@ void Application::update(float deltaTime) {
|
|||
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK));
|
||||
setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK));
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
||||
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
||||
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK),
|
||||
|
|
|
@ -464,7 +464,7 @@ Menu::Menu() {
|
|||
|
||||
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
|
||||
qApp, SLOT(setLowVelocityFilter(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
||||
|
|
|
@ -204,7 +204,7 @@ namespace MenuOption {
|
|||
const QString FrameTimer = "Show Timer";
|
||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString HandMouseInput = "Enable Hand Mouse Input";
|
||||
const QString EnableHandMouseInput = "Enable Hand Controller Mouse Input";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString IndependentMode = "Independent Mode";
|
||||
const QString InputMenu = "Avatar>Input Devices";
|
||||
|
|
|
@ -549,7 +549,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
|
||||
auto cameraMode = qApp->getCamera()->getMode();
|
||||
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
|
||||
renderDisplayName(batch, *renderArgs->_viewFrustum, renderArgs->_viewport);
|
||||
auto& frustum = *renderArgs->_viewFrustum;
|
||||
auto textPosition = getDisplayNamePosition();
|
||||
|
||||
if (frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE) {
|
||||
renderDisplayName(batch, frustum, textPosition);
|
||||
}
|
||||
}
|
||||
endRender();
|
||||
}
|
||||
|
@ -685,120 +690,85 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
|
|||
}
|
||||
|
||||
float Avatar::getBillboardSize() const {
|
||||
return _scale * BILLBOARD_DISTANCE * tanf(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||
return _scale * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void debugValue(const QString& str, const glm::vec3& value) {
|
||||
if (glm::any(glm::isnan(value)) || glm::any(glm::isinf(value))) {
|
||||
qCWarning(interfaceapp) << "debugValue() " << str << value;
|
||||
}
|
||||
};
|
||||
void debugValue(const QString& str, const float& value) {
|
||||
if (glm::isnan(value) || glm::isinf(value)) {
|
||||
qCWarning(interfaceapp) << "debugValue() " << str << value;
|
||||
}
|
||||
};
|
||||
#define DEBUG_VALUE(str, value) debugValue(str, value)
|
||||
#else
|
||||
#define DEBUG_VALUE(str, value)
|
||||
#endif
|
||||
|
||||
glm::vec3 Avatar::getDisplayNamePosition() const {
|
||||
glm::vec3 namePosition(0.0f);
|
||||
glm::vec3 bodyUpDirection = getBodyUpDirection();
|
||||
DEBUG_VALUE("bodyUpDirection =", bodyUpDirection);
|
||||
|
||||
if (getSkeletonModel().getNeckPosition(namePosition)) {
|
||||
namePosition += getBodyUpDirection() * getHeadHeight() * 1.1f;
|
||||
float headHeight = getHeadHeight();
|
||||
DEBUG_VALUE("namePosition =", namePosition);
|
||||
DEBUG_VALUE("headHeight =", headHeight);
|
||||
|
||||
static const float SLIGHTLY_ABOVE = 1.1f;
|
||||
namePosition += bodyUpDirection * headHeight * SLIGHTLY_ABOVE;
|
||||
} else {
|
||||
const float HEAD_PROPORTION = 0.75f;
|
||||
namePosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION);
|
||||
float billboardSize = getBillboardSize();
|
||||
|
||||
DEBUG_VALUE("_position =", _position);
|
||||
DEBUG_VALUE("billboardSize =", billboardSize);
|
||||
namePosition = _position + bodyUpDirection * (billboardSize * HEAD_PROPORTION);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
// TODO: Temporary logging to track cause of invalid scale value; remove once cause has been fixed.
|
||||
// See other TODO below.
|
||||
if (glm::isnan(namePosition.x) || glm::isnan(namePosition.y) || glm::isnan(namePosition.z)
|
||||
|| glm::isinf(namePosition.x) || glm::isinf(namePosition.y) || glm::isinf(namePosition.z)) {
|
||||
qDebug() << "namePosition =" << namePosition;
|
||||
glm::vec3 tempPosition(0.0f);
|
||||
if (getSkeletonModel().getNeckPosition(tempPosition)) {
|
||||
qDebug() << "getBodyUpDirection() =" << getBodyUpDirection();
|
||||
qDebug() << "getHeadHeight() =" << getHeadHeight();
|
||||
} else {
|
||||
qDebug() << "_position =" << _position;
|
||||
qDebug() << "getBodyUpDirection() =" << getBodyUpDirection();
|
||||
qDebug() << "getBillboardSize() =" << getBillboardSize();
|
||||
}
|
||||
|
||||
if (glm::any(glm::isnan(namePosition)) || glm::any(glm::isinf(namePosition))) {
|
||||
qCWarning(interfaceapp) << "Invalid display name position" << namePosition
|
||||
<< ", setting is to (0.0f, 0.5f, 0.0f)";
|
||||
namePosition = glm::vec3(0.0f, 0.5f, 0.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
return namePosition;
|
||||
}
|
||||
|
||||
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, const glm::ivec4& viewport) const {
|
||||
Transform result;
|
||||
// We assume textPosition is whithin the frustum
|
||||
glm::vec3 textPosition = getDisplayNamePosition();
|
||||
|
||||
// Compute viewProjection matrix
|
||||
glm::mat4 projMat, viewMat;
|
||||
Transform view;
|
||||
frustum.evalProjectionMatrix(projMat);
|
||||
frustum.evalViewTransform(view);
|
||||
glm::mat4 viewProj = projMat * view.getInverseMatrix(viewMat);
|
||||
|
||||
// Used to determine correct scale
|
||||
glm::vec3 testPoint0 = textPosition;
|
||||
glm::vec3 testPoint1 = testPoint0 + glm::normalize(frustum.getUp());
|
||||
// testPoints projections
|
||||
glm::vec4 p0 = viewProj * glm::vec4(testPoint0, 1.0);
|
||||
glm::vec4 p1 = viewProj * glm::vec4(testPoint1, 1.0);
|
||||
|
||||
float windowSizeY = viewport.w;
|
||||
|
||||
const float DESIRED_HIGHT_ON_SCREEN = 20; // In pixels (this is double on retinas)
|
||||
|
||||
// Projected point are between -1.0f and 1.0f, hence 0.5f * windowSizeY
|
||||
float pixelHeight = 0.5f * windowSizeY * glm::abs((p1.y / p1.w) - (p0.y / p0.w)); //
|
||||
// Handles pixel density (especially for macs retina displays)
|
||||
float devicePixelRatio = (float)qApp->getDevicePixelRatio() * qApp->getRenderResolutionScale(); // pixels / unit
|
||||
|
||||
// Compute correct scale to apply
|
||||
float scale = DESIRED_HIGHT_ON_SCREEN / (fontSize * pixelHeight) * devicePixelRatio;
|
||||
#ifdef DEBUG
|
||||
// TODO: Temporary logging to track cause of invalid scale value; remove once cause has been fixed.
|
||||
// Problem is probably due to an invalid getDisplayNamePosition(). See extra logging above.
|
||||
if (scale == 0.0f || glm::isnan(scale) || glm::isinf(scale)) {
|
||||
if (scale == 0.0f) {
|
||||
qDebug() << "ASSERT because scale == 0.0f";
|
||||
}
|
||||
if (glm::isnan(scale)) {
|
||||
qDebug() << "ASSERT because isnan(scale)";
|
||||
}
|
||||
if (glm::isinf(scale)) {
|
||||
qDebug() << "ASSERT because isinf(scale)";
|
||||
}
|
||||
qDebug() << "textPosition =" << textPosition;
|
||||
qDebug() << "projMat =" << projMat;
|
||||
qDebug() << "viewMat =" << viewMat;
|
||||
qDebug() << "viewProj =" << viewProj;
|
||||
qDebug() << "windowSizeY =" << windowSizeY;
|
||||
qDebug() << "p1 =" << p1;
|
||||
qDebug() << "p0 =" << p0;
|
||||
qDebug() << "qApp->getDevicePixelRatio() =" << qApp->getDevicePixelRatio();
|
||||
qDebug() << "fontSize =" << fontSize;
|
||||
qDebug() << "pixelHeight =" << pixelHeight;
|
||||
qDebug() << "devicePixelRatio =" << devicePixelRatio;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compute pixel alignment offset
|
||||
float clipToPix = 0.5f * windowSizeY / p1.w; // Got from clip to pixel coordinates
|
||||
glm::vec4 screenPos = clipToPix * p1; // in pixels coords
|
||||
glm::vec4 screenOffset = (glm::round(screenPos) - screenPos) / clipToPix; // in clip coords
|
||||
glm::vec3 worldOffset = glm::vec3(screenOffset.x, screenOffset.y, 0.0f) / (float)pixelHeight;
|
||||
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const {
|
||||
Q_ASSERT_X(frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE,
|
||||
"Avatar::calculateDisplayNameTransform", "Text not in viewfrustum.");
|
||||
glm::vec3 toFrustum = frustum.getPosition() - textPosition;
|
||||
|
||||
// Compute orientation
|
||||
glm::vec3 dPosition = frustum.getPosition() - getPosition();
|
||||
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
|
||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
||||
// If x and z are 0, atan(x, z) adais undefined, so default to 0 degrees
|
||||
const float yawRotation = (toFrustum.x == 0.0f && toFrustum.z == 0.0f) ? 0.0f : glm::atan(toFrustum.x, toFrustum.z);
|
||||
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
||||
|
||||
// Set transform (The order IS important)
|
||||
// Compute correct scale to apply
|
||||
static const float DESIRED_HEIGHT_RAD = glm::radians(1.5f);
|
||||
float scale = glm::length(toFrustum) * glm::tan(DESIRED_HEIGHT_RAD);
|
||||
|
||||
// Set transform
|
||||
Transform result;
|
||||
result.setTranslation(textPosition);
|
||||
result.setRotation(orientation); // Always face the screen
|
||||
result.postTranslate(worldOffset); // Pixel alignment
|
||||
result.setScale(scale);
|
||||
// raise by half the scale up so that textPosition be the bottom
|
||||
result.postTranslate(Vectors::UP / 2.0f);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::ivec4& viewport) const {
|
||||
void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const {
|
||||
bool shouldShowReceiveStats = DependencyManager::get<AvatarManager>()->shouldShowReceiveStats() && !isMyAvatar();
|
||||
|
||||
// If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return
|
||||
const float CLIP_DISTANCE = 0.2f;
|
||||
static const float CLIP_DISTANCE = 0.2f;
|
||||
if ((_displayName.isEmpty() && !shouldShowReceiveStats) || _displayNameAlpha == 0.0f
|
||||
|| (glm::dot(frustum.getDirection(), getDisplayNamePosition() - frustum.getPosition()) <= CLIP_DISTANCE)) {
|
||||
return;
|
||||
|
@ -818,39 +788,45 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
|
|||
}
|
||||
|
||||
// Compute display name extent/position offset
|
||||
glm::vec2 extent = renderer->computeExtent(renderedDisplayName);
|
||||
QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y);
|
||||
const int text_x = -nameDynamicRect.width() / 2;
|
||||
const int text_y = -nameDynamicRect.height() / 2;
|
||||
|
||||
// Compute background position/size
|
||||
static const float SLIGHTLY_IN_FRONT = 0.1f;
|
||||
const int border = 0.1f * nameDynamicRect.height();
|
||||
const int left = text_x - border;
|
||||
const int bottom = text_y - border;
|
||||
const int width = nameDynamicRect.width() + 2.0f * border;
|
||||
const int height = nameDynamicRect.height() + 2.0f * border;
|
||||
const int bevelDistance = 0.1f * height;
|
||||
|
||||
// Display name and background colors
|
||||
glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha);
|
||||
glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f,
|
||||
(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
|
||||
|
||||
// Compute display name transform
|
||||
auto textTransform = calculateDisplayNameTransform(frustum, renderer->getFontSize(), viewport);
|
||||
batch.setModelTransform(textTransform);
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, true, true, true);
|
||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||
bevelDistance, backgroundColor);
|
||||
// Render actual name
|
||||
QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit();
|
||||
|
||||
// Render text slightly in front to avoid z-fighting
|
||||
textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize()));
|
||||
batch.setModelTransform(textTransform);
|
||||
renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor);
|
||||
const glm::vec2 extent = renderer->computeExtent(renderedDisplayName);
|
||||
if (!glm::any(glm::isCompNull(extent, EPSILON))) {
|
||||
const QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y);
|
||||
const int text_x = -nameDynamicRect.width() / 2;
|
||||
const int text_y = -nameDynamicRect.height() / 2;
|
||||
|
||||
// Compute background position/size
|
||||
static const float SLIGHTLY_IN_FRONT = 0.1f;
|
||||
static const float BORDER_RELATIVE_SIZE = 0.1f;
|
||||
static const float BEVEL_FACTOR = 0.1f;
|
||||
const int border = BORDER_RELATIVE_SIZE * nameDynamicRect.height();
|
||||
const int left = text_x - border;
|
||||
const int bottom = text_y - border;
|
||||
const int width = nameDynamicRect.width() + 2.0f * border;
|
||||
const int height = nameDynamicRect.height() + 2.0f * border;
|
||||
const int bevelDistance = BEVEL_FACTOR * height;
|
||||
|
||||
// Display name and background colors
|
||||
glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha);
|
||||
glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f,
|
||||
(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
|
||||
|
||||
// Compute display name transform
|
||||
auto textTransform = calculateDisplayNameTransform(frustum, textPosition);
|
||||
// Test on extent above insures abs(height) > 0.0f
|
||||
textTransform.postScale(1.0f / height);
|
||||
batch.setModelTransform(textTransform);
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, true, true, true);
|
||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||
bevelDistance, backgroundColor);
|
||||
// Render actual name
|
||||
QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit();
|
||||
|
||||
// Render text slightly in front to avoid z-fighting
|
||||
textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize()));
|
||||
batch.setModelTransform(textTransform);
|
||||
renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor);
|
||||
}
|
||||
}
|
||||
|
||||
void Avatar::setSkeletonOffset(const glm::vec3& offset) {
|
||||
|
|
|
@ -217,8 +217,8 @@ protected:
|
|||
float getPelvisFloatingHeight() const;
|
||||
glm::vec3 getDisplayNamePosition() const;
|
||||
|
||||
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, const glm::ivec4& viewport) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::ivec4& viewport) const;
|
||||
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const;
|
||||
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const;
|
||||
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
|
||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||
virtual void fixupModelsInScene();
|
||||
|
|
|
@ -1345,11 +1345,11 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl
|
|||
glm::mat4 headPose = qApp->getActiveDisplayPlugin()->getHeadPose();
|
||||
glm::mat4 leftEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left);
|
||||
leftEyePose = leftEyePose * headPose;
|
||||
glm::vec3 leftEyePosition = glm::vec3(leftEyePose[3]);
|
||||
glm::vec3 leftEyePosition = extractTranslation(leftEyePose);
|
||||
glm::mat4 rightEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Right);
|
||||
rightEyePose = rightEyePose * headPose;
|
||||
glm::vec3 rightEyePosition = glm::vec3(rightEyePose[3]);
|
||||
glm::vec3 headPosition = glm::vec3(headPose[3]);
|
||||
glm::vec3 rightEyePosition = extractTranslation(rightEyePose);
|
||||
glm::vec3 headPosition = extractTranslation(headPose);
|
||||
|
||||
getHead()->renderLookAts(renderArgs,
|
||||
cameraPosition + getOrientation() * (leftEyePosition - headPosition),
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
|
||||
#include "MotionTracker.h"
|
||||
#include "GLMHelpers.h"
|
||||
|
||||
|
||||
// glm::mult(mat43, mat43) just the composition of the 2 matrices assuming they are in fact mat44 with the last raw = { 0, 0, 0, 1 }
|
||||
|
@ -177,7 +178,7 @@ void MotionTracker::Frame::setRotation(const glm::quat& rotation) {
|
|||
}
|
||||
|
||||
void MotionTracker::Frame::getRotation(glm::quat& rotation) const {
|
||||
rotation = glm::quat_cast( _transform);
|
||||
rotation = glm::quat_cast(_transform);
|
||||
}
|
||||
|
||||
void MotionTracker::Frame::setTranslation(const glm::vec3& translation) {
|
||||
|
@ -185,6 +186,6 @@ void MotionTracker::Frame::setTranslation(const glm::vec3& translation) {
|
|||
}
|
||||
|
||||
void MotionTracker::Frame::getTranslation(glm::vec3& translation) const {
|
||||
translation = glm::vec3(_transform[3]);
|
||||
translation = extractTranslation(_transform);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,3 +63,22 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const {
|
|||
|
||||
return compositor.calculateRayUICollisionPoint(position, direction, result);
|
||||
}
|
||||
|
||||
glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
}
|
||||
|
||||
glm::vec3 HMDScriptingInterface::getPosition() const {
|
||||
if (qApp->getActiveDisplayPlugin()->isHmd()) {
|
||||
return extractTranslation(getWorldHMDMatrix());
|
||||
}
|
||||
return glm::vec3();
|
||||
}
|
||||
|
||||
glm::quat HMDScriptingInterface::getOrientation() const {
|
||||
if (qApp->getActiveDisplayPlugin()->isHmd()) {
|
||||
return glm::normalize(glm::quat_cast(getWorldHMDMatrix()));
|
||||
}
|
||||
return glm::quat();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ class QScriptEngine;
|
|||
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool magnifier READ getMagnifier)
|
||||
Q_PROPERTY(glm::vec3 position READ getPosition)
|
||||
Q_PROPERTY(glm::quat orientation READ getOrientation)
|
||||
public:
|
||||
HMDScriptingInterface();
|
||||
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
|
||||
|
@ -34,7 +36,14 @@ public slots:
|
|||
|
||||
private:
|
||||
bool getMagnifier() const;
|
||||
// Get the position of the HMD
|
||||
glm::vec3 getPosition() const;
|
||||
|
||||
// Get the orientation of the HMD
|
||||
glm::quat getOrientation() const;
|
||||
|
||||
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
||||
glm::mat4 getWorldHMDMatrix() const;
|
||||
};
|
||||
|
||||
#endif // hifi_HMDScriptingInterface_h
|
||||
|
|
|
@ -317,8 +317,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
|||
glm::mat4 overlayXfm;
|
||||
_modelTransform.getMatrix(overlayXfm);
|
||||
|
||||
// Only render the hand pointers if the HandMouseInput is enabled
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
||||
// Only render the hand pointers if the EnableHandMouseInput is enabled
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
|
||||
PalmData& palm = myAvatar->getHand()->getPalms()[i];
|
||||
|
@ -436,7 +436,8 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
|
|||
_magActive[MOUSE] = _magnifier;
|
||||
_reticleActive[LEFT_CONTROLLER] = false;
|
||||
_reticleActive[RIGHT_CONTROLLER] = false;
|
||||
} else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
||||
} else if (qApp->getLastMouseMoveWasSimulated()
|
||||
&& Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||
//only render controller pointer if we aren't already rendering a mouse pointer
|
||||
_reticleActive[MOUSE] = false;
|
||||
_magActive[MOUSE] = false;
|
||||
|
|
|
@ -200,9 +200,6 @@ void PreferencesDialog::loadPreferences() {
|
|||
|
||||
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
|
||||
|
||||
SixenseManager& sixense = SixenseManager::getInstance();
|
||||
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
|
||||
|
||||
// LOD items
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS());
|
||||
|
@ -276,9 +273,7 @@ void PreferencesDialog::savePreferences() {
|
|||
|
||||
qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value());
|
||||
|
||||
SixenseManager& sixense = SixenseManager::getInstance();
|
||||
InputDevice::setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
|
||||
sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked());
|
||||
|
||||
auto audio = DependencyManager::get<AudioClient>();
|
||||
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
|
||||
|
|
|
@ -2768,40 +2768,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_26">
|
||||
<property name="topMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="invertSixenseButtonsCheckBox">
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Invert Mouse Buttons</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<property name="spacing">
|
||||
|
|
|
@ -132,7 +132,6 @@ public:
|
|||
bool getJointStateTranslation(int index, glm::vec3& translation) const;
|
||||
void applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority);
|
||||
JointState getJointState(int jointIndex) const; // XXX
|
||||
bool getVisibleJointState(int index, glm::quat& rotation) const;
|
||||
void clearJointState(int index);
|
||||
void clearJointStates();
|
||||
void clearJointAnimationPriority(int index);
|
||||
|
@ -154,9 +153,6 @@ public:
|
|||
bool getJointRotation(int jointIndex, glm::quat& rotation) const;
|
||||
bool getJointTranslation(int jointIndex, glm::vec3& translation) const;
|
||||
bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const;
|
||||
bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position,
|
||||
glm::vec3 translation, glm::quat rotation) const;
|
||||
bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result, glm::quat rotation) const;
|
||||
glm::mat4 getJointTransform(int jointIndex) const;
|
||||
glm::mat4 getJointVisibleTransform(int jointIndex) const;
|
||||
void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform);
|
||||
|
@ -179,7 +175,6 @@ public:
|
|||
float priority, float mix = 1.0f);
|
||||
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
||||
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
||||
void updateVisibleJointStates();
|
||||
void clearJointStatePriorities();
|
||||
|
||||
virtual void updateJointState(int index, glm::mat4 rootTransform) = 0;
|
||||
|
|
|
@ -37,3 +37,9 @@ InputPluginList getInputPlugins() {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void saveInputPluginSettings(const InputPluginList& plugins) {
|
||||
foreach (auto inputPlugin, plugins) {
|
||||
inputPlugin->saveSettings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <GLMHelpers.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <PerfStat.h>
|
||||
#include <SettingHandle.h>
|
||||
#include <plugins/PluginContainer.h>
|
||||
|
||||
#include "NumericalConstants.h"
|
||||
|
@ -38,7 +39,7 @@ const unsigned int RIGHT_MASK = 1U << 1;
|
|||
#ifdef HAVE_SIXENSE
|
||||
|
||||
const int CALIBRATION_STATE_IDLE = 0;
|
||||
const int CALIBRATION_STATE_X = 1;
|
||||
const int CALIBRATION_STATE_IN_PROGRESS = 1;
|
||||
const int CALIBRATION_STATE_COMPLETE = 2;
|
||||
|
||||
const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame
|
||||
|
@ -56,25 +57,23 @@ typedef int (*SixenseTakeIntAndSixenseControllerData)(int, sixenseControllerData
|
|||
#endif
|
||||
|
||||
const QString SixenseManager::NAME = "Sixense";
|
||||
const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra";
|
||||
|
||||
const QString MENU_PARENT = "Avatar";
|
||||
const QString MENU_NAME = "Sixense";
|
||||
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
||||
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
|
||||
const float DEFAULT_REACH_LENGTH = 1.5f;
|
||||
|
||||
SixenseManager& SixenseManager::getInstance() {
|
||||
static SixenseManager sharedInstance;
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
SixenseManager::SixenseManager() :
|
||||
InputDevice("Hydra"),
|
||||
#ifdef __APPLE__
|
||||
_sixenseLibrary(NULL),
|
||||
#endif
|
||||
_reachLength(DEFAULT_REACH_LENGTH),
|
||||
_hydrasConnected(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool SixenseManager::isSupported() const {
|
||||
|
@ -92,7 +91,7 @@ void SixenseManager::activate() {
|
|||
|
||||
CONTAINER->addMenu(MENU_PATH);
|
||||
CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH,
|
||||
[this] (bool clicked) { this->setFilter(clicked); },
|
||||
[this] (bool clicked) { this->setSixenseFilter(clicked); },
|
||||
true, true);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -120,6 +119,7 @@ void SixenseManager::activate() {
|
|||
|
||||
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
||||
#endif
|
||||
loadSettings();
|
||||
sixenseInit();
|
||||
#endif
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ void SixenseManager::deactivate() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void SixenseManager::setFilter(bool filter) {
|
||||
void SixenseManager::setSixenseFilter(bool filter) {
|
||||
#ifdef HAVE_SIXENSE
|
||||
#ifdef __APPLE__
|
||||
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
||||
|
@ -282,6 +282,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
|||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
|
||||
xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis));
|
||||
_reachLength = glm::dot(xAxis, _reachRight - _reachLeft);
|
||||
_avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis)));
|
||||
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
|
||||
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
|
||||
|
@ -317,7 +318,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
|||
_lastDistance = reach;
|
||||
_lockExpiry = usecTimestampNow() + LOCK_DURATION;
|
||||
// move to next state
|
||||
_calibrationState = CALIBRATION_STATE_X;
|
||||
_calibrationState = CALIBRATION_STATE_IN_PROGRESS;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -327,7 +328,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
|||
_averageLeft = 0.9f * _averageLeft + 0.1f * positionLeft;
|
||||
_averageRight = 0.9f * _averageRight + 0.1f * positionRight;
|
||||
|
||||
if (_calibrationState == CALIBRATION_STATE_X) {
|
||||
if (_calibrationState == CALIBRATION_STATE_IN_PROGRESS) {
|
||||
// compute new sliding average
|
||||
float distance = glm::distance(_averageLeft, _averageRight);
|
||||
if (fabsf(distance - _lastDistance) > MAXIMUM_NOISE_LEVEL) {
|
||||
|
@ -340,7 +341,6 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
|||
// lock has expired so clamp the data and move on
|
||||
_lockExpiry = now + LOCK_DURATION;
|
||||
_lastDistance = 0.0f;
|
||||
_reachUp = 0.5f * (_reachLeft + _reachRight);
|
||||
_calibrationState = CALIBRATION_STATE_COMPLETE;
|
||||
qCDebug(inputplugins, "success: sixense calibration: left");
|
||||
}
|
||||
|
@ -543,6 +543,31 @@ void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) {
|
|||
|
||||
}
|
||||
|
||||
// virtual
|
||||
void SixenseManager::saveSettings() const {
|
||||
Settings settings;
|
||||
QString idString = getID();
|
||||
settings.beginGroup(idString);
|
||||
{
|
||||
settings.setVec3Value(QString("avatarPosition"), _avatarPosition);
|
||||
settings.setQuatValue(QString("avatarRotation"), _avatarRotation);
|
||||
settings.setValue(QString("reachLength"), QVariant(_reachLength));
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void SixenseManager::loadSettings() {
|
||||
Settings settings;
|
||||
QString idString = getID();
|
||||
settings.beginGroup(idString);
|
||||
{
|
||||
settings.getVec3ValueIfValid(QString("avatarPosition"), _avatarPosition);
|
||||
settings.getQuatValueIfValid(QString("avatarRotation"), _avatarRotation);
|
||||
settings.getFloatValueIfValid(QString("reachLength"), _reachLength);
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
UserInputMapper::Input SixenseManager::makeInput(unsigned int button, int index) {
|
||||
return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON);
|
||||
}
|
||||
|
|
|
@ -58,12 +58,11 @@ public:
|
|||
|
||||
SixenseManager();
|
||||
|
||||
static SixenseManager& getInstance();
|
||||
|
||||
// Plugin functions
|
||||
virtual bool isSupported() const override;
|
||||
virtual bool isJointController() const override { return true; }
|
||||
const QString& getName() const override { return NAME; }
|
||||
const QString& getID() const override { return HYDRA_ID_STRING; }
|
||||
|
||||
virtual void activate() override;
|
||||
virtual void deactivate() override;
|
||||
|
@ -77,15 +76,15 @@ public:
|
|||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
|
||||
bool getInvertButtons() const { return _invertButtons; }
|
||||
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
|
||||
|
||||
UserInputMapper::Input makeInput(unsigned int button, int index);
|
||||
UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index);
|
||||
UserInputMapper::Input makeInput(JointChannel joint);
|
||||
|
||||
virtual void saveSettings() const override;
|
||||
virtual void loadSettings() override;
|
||||
|
||||
public slots:
|
||||
void setFilter(bool filter);
|
||||
void setSixenseFilter(bool filter);
|
||||
|
||||
private:
|
||||
void handleButtonEvent(unsigned int buttons, int index);
|
||||
|
@ -99,7 +98,7 @@ private:
|
|||
// these are calibration results
|
||||
glm::vec3 _avatarPosition; // in hydra-frame
|
||||
glm::quat _avatarRotation; // in hydra-frame
|
||||
float _armLength;
|
||||
float _reachLength;
|
||||
|
||||
// these are measured values used to compute the calibration results
|
||||
quint64 _lockExpiry;
|
||||
|
@ -107,9 +106,8 @@ private:
|
|||
glm::vec3 _averageRight;
|
||||
glm::vec3 _reachLeft;
|
||||
glm::vec3 _reachRight;
|
||||
glm::vec3 _reachUp;
|
||||
glm::vec3 _reachForward;
|
||||
float _lastDistance;
|
||||
bool _useSixenseFilter = true;
|
||||
|
||||
#ifdef __APPLE__
|
||||
QLibrary* _sixenseLibrary;
|
||||
|
@ -117,9 +115,8 @@ private:
|
|||
|
||||
bool _hydrasConnected;
|
||||
|
||||
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
||||
|
||||
static const QString NAME;
|
||||
static const QString HYDRA_ID_STRING;
|
||||
};
|
||||
|
||||
#endif // hifi_SixenseManager_h
|
||||
|
|
|
@ -241,20 +241,21 @@ ViewFrustum::location ViewFrustum::boxInKeyhole(const AABox& box) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
|
||||
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point, bool ignoreKeyhole) const {
|
||||
ViewFrustum::location regularResult = INSIDE;
|
||||
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||
|
||||
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||
if (_keyholeRadius >= 0.0f) {
|
||||
if (!ignoreKeyhole && _keyholeRadius >= 0.0f) {
|
||||
keyholeResult = pointInKeyhole(point);
|
||||
}
|
||||
if (keyholeResult == INSIDE) {
|
||||
return keyholeResult;
|
||||
|
||||
if (keyholeResult == INSIDE) {
|
||||
return keyholeResult;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're not known to be INSIDE the keyhole, then check the regular frustum
|
||||
for(int i=0; i < 6; i++) {
|
||||
for(int i = 0; i < 6; ++i) {
|
||||
float distance = _planes[i].distance(point);
|
||||
if (distance < 0) {
|
||||
return keyholeResult; // escape early will be the value from checking the keyhole
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
|
||||
|
||||
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
|
||||
ViewFrustum::location pointInFrustum(const glm::vec3& point, bool ignoreKeyhole = false) const;
|
||||
ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const;
|
||||
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
|
||||
ViewFrustum::location boxInFrustum(const AABox& box) const;
|
||||
|
|
|
@ -35,9 +35,8 @@ public:
|
|||
if (rayResult.m_collisionObject == _me) {
|
||||
return 1.0f;
|
||||
}
|
||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace
|
||||
);
|
||||
}
|
||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||
}
|
||||
protected:
|
||||
btRigidBody* _me;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
PluginContainer* Plugin::CONTAINER{ nullptr };
|
||||
|
||||
QString Plugin::UNKNOWN_PLUGIN_ID("unknown");
|
||||
|
||||
void Plugin::setContainer(PluginContainer* container) {
|
||||
CONTAINER = container;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
|
@ -14,7 +16,12 @@
|
|||
|
||||
class Plugin : public QObject {
|
||||
public:
|
||||
/// \return human-readable name
|
||||
virtual const QString& getName() const = 0;
|
||||
|
||||
/// \return string ID (not necessarily human-readable)
|
||||
virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; }
|
||||
|
||||
virtual bool isSupported() const;
|
||||
|
||||
static void setContainer(PluginContainer* container);
|
||||
|
@ -37,6 +44,11 @@ public:
|
|||
*/
|
||||
virtual void idle();
|
||||
|
||||
virtual void saveSettings() const {}
|
||||
virtual void loadSettings() {}
|
||||
|
||||
protected:
|
||||
static PluginContainer* CONTAINER;
|
||||
static QString UNKNOWN_PLUGIN_ID;
|
||||
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "PluginManager.h"
|
||||
#include <mutex>
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
PluginManager* PluginManager::getInstance() {
|
||||
static PluginManager _manager;
|
||||
return &_manager;
|
||||
|
@ -16,6 +18,7 @@ PluginManager* PluginManager::getInstance() {
|
|||
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
|
||||
extern DisplayPluginList getDisplayPlugins();
|
||||
extern InputPluginList getInputPlugins();
|
||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||
|
||||
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||
static DisplayPluginList displayPlugins;
|
||||
|
@ -35,3 +38,6 @@ const InputPluginList& PluginManager::getInputPlugins() {
|
|||
return inputPlugins;
|
||||
}
|
||||
|
||||
void PluginManager::saveSettings() {
|
||||
saveInputPluginSettings(getInputPlugins());
|
||||
}
|
||||
|
|
|
@ -15,4 +15,5 @@ public:
|
|||
|
||||
const DisplayPluginList& getDisplayPlugins();
|
||||
const InputPluginList& getInputPlugins();
|
||||
void saveSettings();
|
||||
};
|
||||
|
|
83
libraries/shared/src/SettingHandle.cpp
Normal file
83
libraries/shared/src/SettingHandle.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// SettingHandle.h
|
||||
//
|
||||
//
|
||||
// Created by AndrewMeadows 2015.10.05
|
||||
// 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 "SettingHandle.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
void Settings::getFloatValueIfValid(const QString& name, float& floatValue) {
|
||||
const QVariant badDefaultValue = NAN;
|
||||
bool ok = true;
|
||||
float tempFloat = value(name, badDefaultValue).toFloat(&ok);
|
||||
if (ok && !isnan(tempFloat)) {
|
||||
floatValue = tempFloat;
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::getBoolValue(const QString& name, bool& boolValue) {
|
||||
const QVariant defaultValue = false;
|
||||
boolValue = value(name, defaultValue).toBool();
|
||||
}
|
||||
|
||||
|
||||
void Settings::setVec3Value(const QString& name, const glm::vec3& vecValue) {
|
||||
beginGroup(name);
|
||||
{
|
||||
setValue(QString("x"), vecValue.x);
|
||||
setValue(QString("y"), vecValue.y);
|
||||
setValue(QString("z"), vecValue.z);
|
||||
}
|
||||
endGroup();
|
||||
}
|
||||
|
||||
void Settings::getVec3ValueIfValid(const QString& name, glm::vec3& vecValue) {
|
||||
beginGroup(name);
|
||||
{
|
||||
bool ok = true;
|
||||
const QVariant badDefaultValue = NAN;
|
||||
float x = value(QString("x"), badDefaultValue).toFloat(&ok);
|
||||
float y = value(QString("y"), badDefaultValue).toFloat(&ok);
|
||||
float z = value(QString("z"), badDefaultValue).toFloat(&ok);
|
||||
if (ok && (!isnan(x) && !isnan(y) && !isnan(z))) {
|
||||
vecValue = glm::vec3(x, y, z);
|
||||
}
|
||||
}
|
||||
endGroup();
|
||||
}
|
||||
|
||||
void Settings::setQuatValue(const QString& name, const glm::quat& quatValue) {
|
||||
beginGroup(name);
|
||||
{
|
||||
setValue(QString("x"), quatValue.x);
|
||||
setValue(QString("y"), quatValue.y);
|
||||
setValue(QString("z"), quatValue.z);
|
||||
setValue(QString("w"), quatValue.w);
|
||||
}
|
||||
endGroup();
|
||||
}
|
||||
|
||||
void Settings::getQuatValueIfValid(const QString& name, glm::quat& quatValue) {
|
||||
beginGroup(name);
|
||||
{
|
||||
bool ok = true;
|
||||
const QVariant badDefaultValue = NAN;
|
||||
float x = value(QString("x"), badDefaultValue).toFloat(&ok);
|
||||
float y = value(QString("y"), badDefaultValue).toFloat(&ok);
|
||||
float z = value(QString("z"), badDefaultValue).toFloat(&ok);
|
||||
float w = value(QString("w"), badDefaultValue).toFloat(&ok);
|
||||
if (ok && (!isnan(x) && !isnan(y) && !isnan(z) && !isnan(w))) {
|
||||
quatValue = glm::quat(w, x, y, z);
|
||||
}
|
||||
}
|
||||
endGroup();
|
||||
}
|
||||
|
|
@ -18,11 +18,22 @@
|
|||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include "SettingInterface.h"
|
||||
|
||||
// TODO: remove
|
||||
class Settings : public QSettings {
|
||||
|
||||
public:
|
||||
void getFloatValueIfValid(const QString& name, float& floatValue);
|
||||
void getBoolValue(const QString& name, bool& boolValue);
|
||||
|
||||
void setVec3Value(const QString& name, const glm::vec3& vecValue);
|
||||
void getVec3ValueIfValid(const QString& name, glm::vec3& vecValue);
|
||||
|
||||
void setQuatValue(const QString& name, const glm::quat& quatValue);
|
||||
void getQuatValueIfValid(const QString& name, glm::quat& quatValue);
|
||||
};
|
||||
|
||||
namespace Setting {
|
||||
|
@ -65,4 +76,4 @@ namespace Setting {
|
|||
}
|
||||
}
|
||||
|
||||
#endif // hifi_SettingHandle_h
|
||||
#endif // hifi_SettingHandle_h
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include "GLMHelpers.h"
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
|
@ -419,7 +418,7 @@ inline Transform::Mat4& Transform::getRotationScaleMatrixInverse(Mat4& result) c
|
|||
inline Transform& Transform::evalFromRawMatrix(const Mat4& matrix) {
|
||||
// for now works only in the case of TRS transformation
|
||||
if ((matrix[0][3] == 0.0f) && (matrix[1][3] == 0.0f) && (matrix[2][3] == 0.0f) && (matrix[3][3] == 1.0f)) {
|
||||
setTranslation(Vec3(matrix[3]));
|
||||
setTranslation(extractTranslation(matrix));
|
||||
evalFromRawMatrix(Mat3(matrix));
|
||||
}
|
||||
return *this;
|
||||
|
|
Loading…
Reference in a new issue