mirror of
https://github.com/overte-org/overte.git
synced 2025-07-16 22:17:03 +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();
|
Menu::getInstance()->saveSettings();
|
||||||
getMyAvatar()->saveData();
|
getMyAvatar()->saveData();
|
||||||
|
PluginManager::getInstance()->saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::importEntities(const QString& urlOrFilename) {
|
bool Application::importEntities(const QString& urlOrFilename) {
|
||||||
|
@ -2758,7 +2759,7 @@ void Application::update(float deltaTime) {
|
||||||
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||||
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK));
|
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));
|
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),
|
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
||||||
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
||||||
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK),
|
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK),
|
||||||
|
|
|
@ -464,7 +464,7 @@ Menu::Menu() {
|
||||||
|
|
||||||
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
|
||||||
qApp, SLOT(setLowVelocityFilter(bool)));
|
qApp, SLOT(setLowVelocityFilter(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false);
|
||||||
|
|
|
@ -204,7 +204,7 @@ namespace MenuOption {
|
||||||
const QString FrameTimer = "Show Timer";
|
const QString FrameTimer = "Show Timer";
|
||||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
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 IncreaseAvatarSize = "Increase Avatar Size";
|
||||||
const QString IndependentMode = "Independent Mode";
|
const QString IndependentMode = "Independent Mode";
|
||||||
const QString InputMenu = "Avatar>Input Devices";
|
const QString InputMenu = "Avatar>Input Devices";
|
||||||
|
|
|
@ -549,7 +549,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
|
|
||||||
auto cameraMode = qApp->getCamera()->getMode();
|
auto cameraMode = qApp->getCamera()->getMode();
|
||||||
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
|
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();
|
endRender();
|
||||||
}
|
}
|
||||||
|
@ -685,120 +690,85 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float Avatar::getBillboardSize() const {
|
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 Avatar::getDisplayNamePosition() const {
|
||||||
glm::vec3 namePosition(0.0f);
|
glm::vec3 namePosition(0.0f);
|
||||||
|
glm::vec3 bodyUpDirection = getBodyUpDirection();
|
||||||
|
DEBUG_VALUE("bodyUpDirection =", bodyUpDirection);
|
||||||
|
|
||||||
if (getSkeletonModel().getNeckPosition(namePosition)) {
|
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 {
|
} else {
|
||||||
const float HEAD_PROPORTION = 0.75f;
|
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.
|
if (glm::any(glm::isnan(namePosition)) || glm::any(glm::isinf(namePosition))) {
|
||||||
// See other TODO below.
|
qCWarning(interfaceapp) << "Invalid display name position" << namePosition
|
||||||
if (glm::isnan(namePosition.x) || glm::isnan(namePosition.y) || glm::isnan(namePosition.z)
|
<< ", setting is to (0.0f, 0.5f, 0.0f)";
|
||||||
|| glm::isinf(namePosition.x) || glm::isinf(namePosition.y) || glm::isinf(namePosition.z)) {
|
namePosition = glm::vec3(0.0f, 0.5f, 0.0f);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return namePosition;
|
return namePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, const glm::ivec4& viewport) const {
|
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const {
|
||||||
Transform result;
|
Q_ASSERT_X(frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE,
|
||||||
// We assume textPosition is whithin the frustum
|
"Avatar::calculateDisplayNameTransform", "Text not in viewfrustum.");
|
||||||
glm::vec3 textPosition = getDisplayNamePosition();
|
glm::vec3 toFrustum = frustum.getPosition() - textPosition;
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Compute orientation
|
// Compute orientation
|
||||||
glm::vec3 dPosition = frustum.getPosition() - getPosition();
|
// If x and z are 0, atan(x, z) adais undefined, so default to 0 degrees
|
||||||
// If x and z are 0, atan(x, z) is 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);
|
||||||
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
|
|
||||||
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));
|
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.setTranslation(textPosition);
|
||||||
result.setRotation(orientation); // Always face the screen
|
result.setRotation(orientation); // Always face the screen
|
||||||
result.postTranslate(worldOffset); // Pixel alignment
|
|
||||||
result.setScale(scale);
|
result.setScale(scale);
|
||||||
|
// raise by half the scale up so that textPosition be the bottom
|
||||||
|
result.postTranslate(Vectors::UP / 2.0f);
|
||||||
|
|
||||||
return result;
|
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();
|
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
|
// 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
|
if ((_displayName.isEmpty() && !shouldShowReceiveStats) || _displayNameAlpha == 0.0f
|
||||||
|| (glm::dot(frustum.getDirection(), getDisplayNamePosition() - frustum.getPosition()) <= CLIP_DISTANCE)) {
|
|| (glm::dot(frustum.getDirection(), getDisplayNamePosition() - frustum.getPosition()) <= CLIP_DISTANCE)) {
|
||||||
return;
|
return;
|
||||||
|
@ -818,39 +788,45 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute display name extent/position offset
|
// Compute display name extent/position offset
|
||||||
glm::vec2 extent = renderer->computeExtent(renderedDisplayName);
|
const glm::vec2 extent = renderer->computeExtent(renderedDisplayName);
|
||||||
QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y);
|
if (!glm::any(glm::isCompNull(extent, EPSILON))) {
|
||||||
const int text_x = -nameDynamicRect.width() / 2;
|
const QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y);
|
||||||
const int text_y = -nameDynamicRect.height() / 2;
|
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;
|
// Compute background position/size
|
||||||
const int border = 0.1f * nameDynamicRect.height();
|
static const float SLIGHTLY_IN_FRONT = 0.1f;
|
||||||
const int left = text_x - border;
|
static const float BORDER_RELATIVE_SIZE = 0.1f;
|
||||||
const int bottom = text_y - border;
|
static const float BEVEL_FACTOR = 0.1f;
|
||||||
const int width = nameDynamicRect.width() + 2.0f * border;
|
const int border = BORDER_RELATIVE_SIZE * nameDynamicRect.height();
|
||||||
const int height = nameDynamicRect.height() + 2.0f * border;
|
const int left = text_x - border;
|
||||||
const int bevelDistance = 0.1f * height;
|
const int bottom = text_y - border;
|
||||||
|
const int width = nameDynamicRect.width() + 2.0f * border;
|
||||||
// Display name and background colors
|
const int height = nameDynamicRect.height() + 2.0f * border;
|
||||||
glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha);
|
const int bevelDistance = BEVEL_FACTOR * height;
|
||||||
glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f,
|
|
||||||
(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
|
// Display name and background colors
|
||||||
|
glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha);
|
||||||
// Compute display name transform
|
glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f,
|
||||||
auto textTransform = calculateDisplayNameTransform(frustum, renderer->getFontSize(), viewport);
|
(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
|
||||||
batch.setModelTransform(textTransform);
|
|
||||||
|
// Compute display name transform
|
||||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, true, true, true);
|
auto textTransform = calculateDisplayNameTransform(frustum, textPosition);
|
||||||
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
// Test on extent above insures abs(height) > 0.0f
|
||||||
bevelDistance, backgroundColor);
|
textTransform.postScale(1.0f / height);
|
||||||
// Render actual name
|
batch.setModelTransform(textTransform);
|
||||||
QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit();
|
|
||||||
|
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, false, true, true, true);
|
||||||
// Render text slightly in front to avoid z-fighting
|
DependencyManager::get<GeometryCache>()->renderBevelCornersRect(batch, left, bottom, width, height,
|
||||||
textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize()));
|
bevelDistance, backgroundColor);
|
||||||
batch.setModelTransform(textTransform);
|
// Render actual name
|
||||||
renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor);
|
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) {
|
void Avatar::setSkeletonOffset(const glm::vec3& offset) {
|
||||||
|
|
|
@ -217,8 +217,8 @@ protected:
|
||||||
float getPelvisFloatingHeight() const;
|
float getPelvisFloatingHeight() const;
|
||||||
glm::vec3 getDisplayNamePosition() const;
|
glm::vec3 getDisplayNamePosition() const;
|
||||||
|
|
||||||
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, 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::ivec4& viewport) 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 void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
|
||||||
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
|
||||||
virtual void fixupModelsInScene();
|
virtual void fixupModelsInScene();
|
||||||
|
|
|
@ -1345,11 +1345,11 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl
|
||||||
glm::mat4 headPose = qApp->getActiveDisplayPlugin()->getHeadPose();
|
glm::mat4 headPose = qApp->getActiveDisplayPlugin()->getHeadPose();
|
||||||
glm::mat4 leftEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left);
|
glm::mat4 leftEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Left);
|
||||||
leftEyePose = leftEyePose * headPose;
|
leftEyePose = leftEyePose * headPose;
|
||||||
glm::vec3 leftEyePosition = glm::vec3(leftEyePose[3]);
|
glm::vec3 leftEyePosition = extractTranslation(leftEyePose);
|
||||||
glm::mat4 rightEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Right);
|
glm::mat4 rightEyePose = qApp->getActiveDisplayPlugin()->getEyeToHeadTransform(Eye::Right);
|
||||||
rightEyePose = rightEyePose * headPose;
|
rightEyePose = rightEyePose * headPose;
|
||||||
glm::vec3 rightEyePosition = glm::vec3(rightEyePose[3]);
|
glm::vec3 rightEyePosition = extractTranslation(rightEyePose);
|
||||||
glm::vec3 headPosition = glm::vec3(headPose[3]);
|
glm::vec3 headPosition = extractTranslation(headPose);
|
||||||
|
|
||||||
getHead()->renderLookAts(renderArgs,
|
getHead()->renderLookAts(renderArgs,
|
||||||
cameraPosition + getOrientation() * (leftEyePosition - headPosition),
|
cameraPosition + getOrientation() * (leftEyePosition - headPosition),
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "MotionTracker.h"
|
#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 }
|
// 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 {
|
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) {
|
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 {
|
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);
|
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 {
|
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool magnifier READ getMagnifier)
|
Q_PROPERTY(bool magnifier READ getMagnifier)
|
||||||
|
Q_PROPERTY(glm::vec3 position READ getPosition)
|
||||||
|
Q_PROPERTY(glm::quat orientation READ getOrientation)
|
||||||
public:
|
public:
|
||||||
HMDScriptingInterface();
|
HMDScriptingInterface();
|
||||||
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
|
static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine);
|
||||||
|
@ -34,7 +36,14 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getMagnifier() const;
|
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;
|
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
||||||
|
glm::mat4 getWorldHMDMatrix() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_HMDScriptingInterface_h
|
#endif // hifi_HMDScriptingInterface_h
|
||||||
|
|
|
@ -317,8 +317,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
||||||
glm::mat4 overlayXfm;
|
glm::mat4 overlayXfm;
|
||||||
_modelTransform.getMatrix(overlayXfm);
|
_modelTransform.getMatrix(overlayXfm);
|
||||||
|
|
||||||
// Only render the hand pointers if the HandMouseInput is enabled
|
// Only render the hand pointers if the EnableHandMouseInput is enabled
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) {
|
||||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
|
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
|
||||||
PalmData& palm = myAvatar->getHand()->getPalms()[i];
|
PalmData& palm = myAvatar->getHand()->getPalms()[i];
|
||||||
|
@ -436,7 +436,8 @@ void ApplicationCompositor::renderPointers(gpu::Batch& batch) {
|
||||||
_magActive[MOUSE] = _magnifier;
|
_magActive[MOUSE] = _magnifier;
|
||||||
_reticleActive[LEFT_CONTROLLER] = false;
|
_reticleActive[LEFT_CONTROLLER] = false;
|
||||||
_reticleActive[RIGHT_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
|
//only render controller pointer if we aren't already rendering a mouse pointer
|
||||||
_reticleActive[MOUSE] = false;
|
_reticleActive[MOUSE] = false;
|
||||||
_magActive[MOUSE] = false;
|
_magActive[MOUSE] = false;
|
||||||
|
|
|
@ -200,9 +200,6 @@ void PreferencesDialog::loadPreferences() {
|
||||||
|
|
||||||
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
|
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
|
||||||
|
|
||||||
SixenseManager& sixense = SixenseManager::getInstance();
|
|
||||||
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
|
|
||||||
|
|
||||||
// LOD items
|
// LOD items
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS());
|
ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS());
|
||||||
|
@ -276,9 +273,7 @@ void PreferencesDialog::savePreferences() {
|
||||||
|
|
||||||
qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value());
|
qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value());
|
||||||
|
|
||||||
SixenseManager& sixense = SixenseManager::getInstance();
|
|
||||||
InputDevice::setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
|
InputDevice::setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
|
||||||
sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked());
|
|
||||||
|
|
||||||
auto audio = DependencyManager::get<AudioClient>();
|
auto audio = DependencyManager::get<AudioClient>();
|
||||||
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
|
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
|
||||||
|
|
|
@ -2768,40 +2768,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
|
|
|
@ -132,7 +132,6 @@ public:
|
||||||
bool getJointStateTranslation(int index, glm::vec3& translation) const;
|
bool getJointStateTranslation(int index, glm::vec3& translation) const;
|
||||||
void applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority);
|
void applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority);
|
||||||
JointState getJointState(int jointIndex) const; // XXX
|
JointState getJointState(int jointIndex) const; // XXX
|
||||||
bool getVisibleJointState(int index, glm::quat& rotation) const;
|
|
||||||
void clearJointState(int index);
|
void clearJointState(int index);
|
||||||
void clearJointStates();
|
void clearJointStates();
|
||||||
void clearJointAnimationPriority(int index);
|
void clearJointAnimationPriority(int index);
|
||||||
|
@ -154,9 +153,6 @@ public:
|
||||||
bool getJointRotation(int jointIndex, glm::quat& rotation) const;
|
bool getJointRotation(int jointIndex, glm::quat& rotation) const;
|
||||||
bool getJointTranslation(int jointIndex, glm::vec3& translation) const;
|
bool getJointTranslation(int jointIndex, glm::vec3& translation) const;
|
||||||
bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) 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 getJointTransform(int jointIndex) const;
|
||||||
glm::mat4 getJointVisibleTransform(int jointIndex) const;
|
glm::mat4 getJointVisibleTransform(int jointIndex) const;
|
||||||
void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform);
|
void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform);
|
||||||
|
@ -179,7 +175,6 @@ public:
|
||||||
float priority, float mix = 1.0f);
|
float priority, float mix = 1.0f);
|
||||||
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
||||||
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
||||||
void updateVisibleJointStates();
|
|
||||||
void clearJointStatePriorities();
|
void clearJointStatePriorities();
|
||||||
|
|
||||||
virtual void updateJointState(int index, glm::mat4 rootTransform) = 0;
|
virtual void updateJointState(int index, glm::mat4 rootTransform) = 0;
|
||||||
|
|
|
@ -37,3 +37,9 @@ InputPluginList getInputPlugins() {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveInputPluginSettings(const InputPluginList& plugins) {
|
||||||
|
foreach (auto inputPlugin, plugins) {
|
||||||
|
inputPlugin->saveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
#include <SettingHandle.h>
|
||||||
#include <plugins/PluginContainer.h>
|
#include <plugins/PluginContainer.h>
|
||||||
|
|
||||||
#include "NumericalConstants.h"
|
#include "NumericalConstants.h"
|
||||||
|
@ -38,7 +39,7 @@ const unsigned int RIGHT_MASK = 1U << 1;
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
|
|
||||||
const int CALIBRATION_STATE_IDLE = 0;
|
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 int CALIBRATION_STATE_COMPLETE = 2;
|
||||||
|
|
||||||
const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame
|
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
|
#endif
|
||||||
|
|
||||||
const QString SixenseManager::NAME = "Sixense";
|
const QString SixenseManager::NAME = "Sixense";
|
||||||
|
const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra";
|
||||||
|
|
||||||
const QString MENU_PARENT = "Avatar";
|
const QString MENU_PARENT = "Avatar";
|
||||||
const QString MENU_NAME = "Sixense";
|
const QString MENU_NAME = "Sixense";
|
||||||
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
||||||
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
|
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
|
||||||
|
const float DEFAULT_REACH_LENGTH = 1.5f;
|
||||||
|
|
||||||
SixenseManager& SixenseManager::getInstance() {
|
|
||||||
static SixenseManager sharedInstance;
|
|
||||||
return sharedInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
SixenseManager::SixenseManager() :
|
SixenseManager::SixenseManager() :
|
||||||
InputDevice("Hydra"),
|
InputDevice("Hydra"),
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
_sixenseLibrary(NULL),
|
_sixenseLibrary(NULL),
|
||||||
#endif
|
#endif
|
||||||
|
_reachLength(DEFAULT_REACH_LENGTH),
|
||||||
_hydrasConnected(false)
|
_hydrasConnected(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SixenseManager::isSupported() const {
|
bool SixenseManager::isSupported() const {
|
||||||
|
@ -92,7 +91,7 @@ void SixenseManager::activate() {
|
||||||
|
|
||||||
CONTAINER->addMenu(MENU_PATH);
|
CONTAINER->addMenu(MENU_PATH);
|
||||||
CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH,
|
CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH,
|
||||||
[this] (bool clicked) { this->setFilter(clicked); },
|
[this] (bool clicked) { this->setSixenseFilter(clicked); },
|
||||||
true, true);
|
true, true);
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
@ -120,6 +119,7 @@ void SixenseManager::activate() {
|
||||||
|
|
||||||
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
|
||||||
#endif
|
#endif
|
||||||
|
loadSettings();
|
||||||
sixenseInit();
|
sixenseInit();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ void SixenseManager::deactivate() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SixenseManager::setFilter(bool filter) {
|
void SixenseManager::setSixenseFilter(bool filter) {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
|
||||||
|
@ -282,6 +282,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
||||||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
|
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
|
||||||
xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis));
|
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)));
|
_avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis)));
|
||||||
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
|
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
|
||||||
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
|
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
|
||||||
|
@ -317,7 +318,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
||||||
_lastDistance = reach;
|
_lastDistance = reach;
|
||||||
_lockExpiry = usecTimestampNow() + LOCK_DURATION;
|
_lockExpiry = usecTimestampNow() + LOCK_DURATION;
|
||||||
// move to next state
|
// move to next state
|
||||||
_calibrationState = CALIBRATION_STATE_X;
|
_calibrationState = CALIBRATION_STATE_IN_PROGRESS;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -327,7 +328,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
||||||
_averageLeft = 0.9f * _averageLeft + 0.1f * positionLeft;
|
_averageLeft = 0.9f * _averageLeft + 0.1f * positionLeft;
|
||||||
_averageRight = 0.9f * _averageRight + 0.1f * positionRight;
|
_averageRight = 0.9f * _averageRight + 0.1f * positionRight;
|
||||||
|
|
||||||
if (_calibrationState == CALIBRATION_STATE_X) {
|
if (_calibrationState == CALIBRATION_STATE_IN_PROGRESS) {
|
||||||
// compute new sliding average
|
// compute new sliding average
|
||||||
float distance = glm::distance(_averageLeft, _averageRight);
|
float distance = glm::distance(_averageLeft, _averageRight);
|
||||||
if (fabsf(distance - _lastDistance) > MAXIMUM_NOISE_LEVEL) {
|
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
|
// lock has expired so clamp the data and move on
|
||||||
_lockExpiry = now + LOCK_DURATION;
|
_lockExpiry = now + LOCK_DURATION;
|
||||||
_lastDistance = 0.0f;
|
_lastDistance = 0.0f;
|
||||||
_reachUp = 0.5f * (_reachLeft + _reachRight);
|
|
||||||
_calibrationState = CALIBRATION_STATE_COMPLETE;
|
_calibrationState = CALIBRATION_STATE_COMPLETE;
|
||||||
qCDebug(inputplugins, "success: sixense calibration: left");
|
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) {
|
UserInputMapper::Input SixenseManager::makeInput(unsigned int button, int index) {
|
||||||
return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON);
|
return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,12 +58,11 @@ public:
|
||||||
|
|
||||||
SixenseManager();
|
SixenseManager();
|
||||||
|
|
||||||
static SixenseManager& getInstance();
|
|
||||||
|
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual bool isJointController() const override { return true; }
|
virtual bool isJointController() const override { return true; }
|
||||||
const QString& getName() const override { return NAME; }
|
const QString& getName() const override { return NAME; }
|
||||||
|
const QString& getID() const override { return HYDRA_ID_STRING; }
|
||||||
|
|
||||||
virtual void activate() override;
|
virtual void activate() override;
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
|
@ -77,15 +76,15 @@ public:
|
||||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||||
virtual void focusOutEvent() 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(unsigned int button, int index);
|
||||||
UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index);
|
UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index);
|
||||||
UserInputMapper::Input makeInput(JointChannel joint);
|
UserInputMapper::Input makeInput(JointChannel joint);
|
||||||
|
|
||||||
|
virtual void saveSettings() const override;
|
||||||
|
virtual void loadSettings() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setFilter(bool filter);
|
void setSixenseFilter(bool filter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleButtonEvent(unsigned int buttons, int index);
|
void handleButtonEvent(unsigned int buttons, int index);
|
||||||
|
@ -99,7 +98,7 @@ private:
|
||||||
// these are calibration results
|
// these are calibration results
|
||||||
glm::vec3 _avatarPosition; // in hydra-frame
|
glm::vec3 _avatarPosition; // in hydra-frame
|
||||||
glm::quat _avatarRotation; // in hydra-frame
|
glm::quat _avatarRotation; // in hydra-frame
|
||||||
float _armLength;
|
float _reachLength;
|
||||||
|
|
||||||
// these are measured values used to compute the calibration results
|
// these are measured values used to compute the calibration results
|
||||||
quint64 _lockExpiry;
|
quint64 _lockExpiry;
|
||||||
|
@ -107,9 +106,8 @@ private:
|
||||||
glm::vec3 _averageRight;
|
glm::vec3 _averageRight;
|
||||||
glm::vec3 _reachLeft;
|
glm::vec3 _reachLeft;
|
||||||
glm::vec3 _reachRight;
|
glm::vec3 _reachRight;
|
||||||
glm::vec3 _reachUp;
|
|
||||||
glm::vec3 _reachForward;
|
|
||||||
float _lastDistance;
|
float _lastDistance;
|
||||||
|
bool _useSixenseFilter = true;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
QLibrary* _sixenseLibrary;
|
QLibrary* _sixenseLibrary;
|
||||||
|
@ -117,9 +115,8 @@ private:
|
||||||
|
|
||||||
bool _hydrasConnected;
|
bool _hydrasConnected;
|
||||||
|
|
||||||
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
|
||||||
|
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
|
static const QString HYDRA_ID_STRING;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_SixenseManager_h
|
#endif // hifi_SixenseManager_h
|
||||||
|
|
|
@ -241,20 +241,21 @@ ViewFrustum::location ViewFrustum::boxInKeyhole(const AABox& box) const {
|
||||||
return result;
|
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 regularResult = INSIDE;
|
||||||
ViewFrustum::location keyholeResult = OUTSIDE;
|
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||||
|
|
||||||
// If we have a keyholeRadius, check that first, since it's cheaper
|
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||||
if (_keyholeRadius >= 0.0f) {
|
if (!ignoreKeyhole && _keyholeRadius >= 0.0f) {
|
||||||
keyholeResult = pointInKeyhole(point);
|
keyholeResult = pointInKeyhole(point);
|
||||||
}
|
|
||||||
if (keyholeResult == INSIDE) {
|
if (keyholeResult == INSIDE) {
|
||||||
return keyholeResult;
|
return keyholeResult;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're not known to be INSIDE the keyhole, then check the regular frustum
|
// 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);
|
float distance = _planes[i].distance(point);
|
||||||
if (distance < 0) {
|
if (distance < 0) {
|
||||||
return keyholeResult; // escape early will be the value from checking the keyhole
|
return keyholeResult; // escape early will be the value from checking the keyhole
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
|
|
||||||
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
|
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 sphereInFrustum(const glm::vec3& center, float radius) const;
|
||||||
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
|
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
|
||||||
ViewFrustum::location boxInFrustum(const AABox& box) const;
|
ViewFrustum::location boxInFrustum(const AABox& box) const;
|
||||||
|
|
|
@ -35,9 +35,8 @@ public:
|
||||||
if (rayResult.m_collisionObject == _me) {
|
if (rayResult.m_collisionObject == _me) {
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace
|
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
protected:
|
protected:
|
||||||
btRigidBody* _me;
|
btRigidBody* _me;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
PluginContainer* Plugin::CONTAINER{ nullptr };
|
PluginContainer* Plugin::CONTAINER{ nullptr };
|
||||||
|
|
||||||
|
QString Plugin::UNKNOWN_PLUGIN_ID("unknown");
|
||||||
|
|
||||||
void Plugin::setContainer(PluginContainer* container) {
|
void Plugin::setContainer(PluginContainer* container) {
|
||||||
CONTAINER = container;
|
CONTAINER = container;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
@ -14,7 +16,12 @@
|
||||||
|
|
||||||
class Plugin : public QObject {
|
class Plugin : public QObject {
|
||||||
public:
|
public:
|
||||||
|
/// \return human-readable name
|
||||||
virtual const QString& getName() const = 0;
|
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;
|
virtual bool isSupported() const;
|
||||||
|
|
||||||
static void setContainer(PluginContainer* container);
|
static void setContainer(PluginContainer* container);
|
||||||
|
@ -37,6 +44,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void idle();
|
virtual void idle();
|
||||||
|
|
||||||
|
virtual void saveSettings() const {}
|
||||||
|
virtual void loadSettings() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static PluginContainer* CONTAINER;
|
static PluginContainer* CONTAINER;
|
||||||
|
static QString UNKNOWN_PLUGIN_ID;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "PluginManager.h"
|
#include "PluginManager.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "Forward.h"
|
||||||
|
|
||||||
PluginManager* PluginManager::getInstance() {
|
PluginManager* PluginManager::getInstance() {
|
||||||
static PluginManager _manager;
|
static PluginManager _manager;
|
||||||
return &_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
|
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
|
||||||
extern DisplayPluginList getDisplayPlugins();
|
extern DisplayPluginList getDisplayPlugins();
|
||||||
extern InputPluginList getInputPlugins();
|
extern InputPluginList getInputPlugins();
|
||||||
|
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||||
|
|
||||||
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||||
static DisplayPluginList displayPlugins;
|
static DisplayPluginList displayPlugins;
|
||||||
|
@ -35,3 +38,6 @@ const InputPluginList& PluginManager::getInputPlugins() {
|
||||||
return inputPlugins;
|
return inputPlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PluginManager::saveSettings() {
|
||||||
|
saveInputPluginSettings(getInputPlugins());
|
||||||
|
}
|
||||||
|
|
|
@ -15,4 +15,5 @@ public:
|
||||||
|
|
||||||
const DisplayPluginList& getDisplayPlugins();
|
const DisplayPluginList& getDisplayPlugins();
|
||||||
const InputPluginList& getInputPlugins();
|
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 <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
#include "SettingInterface.h"
|
#include "SettingInterface.h"
|
||||||
|
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
class Settings : public QSettings {
|
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 {
|
namespace Setting {
|
||||||
|
@ -65,4 +76,4 @@ namespace Setting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_SettingHandle_h
|
#endif // hifi_SettingHandle_h
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include "GLMHelpers.h"
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtx/quaternion.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) {
|
inline Transform& Transform::evalFromRawMatrix(const Mat4& matrix) {
|
||||||
// for now works only in the case of TRS transformation
|
// 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)) {
|
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));
|
evalFromRawMatrix(Mat3(matrix));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
Loading…
Reference in a new issue