Merge branch 'master' of https://github.com/highfidelity/hifi into keylightInheritance

This commit is contained in:
Nissim Hadar 2018-01-05 23:14:51 -08:00
commit f742ab7952
8 changed files with 170 additions and 30 deletions

View file

@ -56,29 +56,28 @@
{
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
},
{
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
},
{
"from": "Vive.Hips", "to" : "Standard.Hips",
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
},
{
"from": "Vive.Spine2", "to" : "Standard.Spine2",
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
},
{ "from": "Vive.Head", "to" : "Standard.Head"},
{ "from": "Vive.RightArm", "to" : "Standard.RightArm" },
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm" },
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
{ "from": "Vive.TrackedObject02", "to" : "Standard.TrackedObject02" },

View file

@ -151,7 +151,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
glm::vec3 normal;
boundingBox.findRayIntersection(cameraPosition, direction, distance, face, normal);
float offsetAngle = -CONTEXT_OVERLAY_OFFSET_ANGLE;
if (DependencyManager::get<PointerManager>()->isLeftHand(event.getID())) {
if (event.getID() == 1) { // "1" is left hand
offsetAngle *= -1.0f;
}
contextOverlayPosition = cameraPosition +

View file

@ -30,6 +30,7 @@
#include "filters/PostTransformFilter.h"
#include "filters/RotateFilter.h"
#include "filters/LowVelocityFilter.h"
#include "filters/ExponentialSmoothingFilter.h"
using namespace controller;
@ -49,6 +50,7 @@ REGISTER_FILTER_CLASS_INSTANCE(TransformFilter, "transform")
REGISTER_FILTER_CLASS_INSTANCE(PostTransformFilter, "postTransform")
REGISTER_FILTER_CLASS_INSTANCE(RotateFilter, "rotate")
REGISTER_FILTER_CLASS_INSTANCE(LowVelocityFilter, "lowVelocity")
REGISTER_FILTER_CLASS_INSTANCE(ExponentialSmoothingFilter, "exponentialSmoothing")
const QString JSON_FILTER_TYPE = QStringLiteral("type");
const QString JSON_FILTER_PARAMS = QStringLiteral("params");
@ -93,7 +95,7 @@ bool Filter::parseSingleFloatParameter(const QJsonValue& parameters, const QStri
output = objectParameters[name].toDouble();
return true;
}
}
}
return false;
}
@ -117,7 +119,7 @@ bool Filter::parseVec3Parameter(const QJsonValue& parameters, glm::vec3& output)
objectParameters["z"].toDouble());
return true;
}
}
}
return false;
}
@ -126,7 +128,7 @@ bool Filter::parseMat4Parameter(const QJsonValue& parameters, glm::mat4& output)
auto objectParameters = parameters.toObject();
if (objectParameters.contains("r0c0") &&
if (objectParameters.contains("r0c0") &&
objectParameters.contains("r1c0") &&
objectParameters.contains("r2c0") &&
objectParameters.contains("r3c0") &&
@ -169,9 +171,9 @@ bool Filter::parseMat4Parameter(const QJsonValue& parameters, glm::mat4& output)
bool Filter::parseQuatParameter(const QJsonValue& parameters, glm::quat& output) {
if (parameters.isObject()) {
auto objectParameters = parameters.toObject();
if (objectParameters.contains("w") &&
objectParameters.contains("x") &&
objectParameters.contains("y") &&
if (objectParameters.contains("w") &&
objectParameters.contains("x") &&
objectParameters.contains("y") &&
objectParameters.contains("z")) {
output = glm::quat(objectParameters["w"].toDouble(),

View file

@ -32,6 +32,7 @@
#include "filters/PostTransformFilter.h"
#include "filters/RotateFilter.h"
#include "filters/LowVelocityFilter.h"
#include "filters/ExponentialSmoothingFilter.h"
#include "conditionals/AndConditional.h"
using namespace controller;
@ -134,6 +135,11 @@ QObject* RouteBuilderProxy::lowVelocity(float rotationConstant, float translatio
return this;
}
QObject* RouteBuilderProxy::exponentialSmoothing(float rotationConstant, float translationConstant) {
addFilter(std::make_shared<ExponentialSmoothingFilter>(rotationConstant, translationConstant));
return this;
}
QObject* RouteBuilderProxy::constrainToInteger() {
addFilter(std::make_shared<ConstrainToIntegerFilter>());
return this;

View file

@ -53,6 +53,7 @@ class RouteBuilderProxy : public QObject {
Q_INVOKABLE QObject* postTransform(glm::mat4 transform);
Q_INVOKABLE QObject* rotate(glm::quat rotation);
Q_INVOKABLE QObject* lowVelocity(float rotationConstant, float translationConstant);
Q_INVOKABLE QObject* exponentialSmoothing(float rotationConstant, float translationConstant);
Q_INVOKABLE QObject* logicalNot();
private:

View file

@ -0,0 +1,71 @@
//
// Created by Anthony Thibault 2017/12/07
// Copyright 2017 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 "ExponentialSmoothingFilter.h"
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include "../../UserInputMapper.h"
#include "../../Input.h"
#include <DependencyManager.h>
static const QString JSON_ROTATION = QStringLiteral("rotation");
static const QString JSON_TRANSLATION = QStringLiteral("translation");
namespace controller {
Pose ExponentialSmoothingFilter::apply(Pose value) const {
if (value.isValid()) {
// to perform filtering in sensor space, we need to compute the transformations.
auto userInputMapper = DependencyManager::get<UserInputMapper>();
const InputCalibrationData calibrationData = userInputMapper->getInputCalibrationData();
glm::mat4 sensorToAvatarMat = glm::inverse(calibrationData.avatarMat) * calibrationData.sensorToWorldMat;
glm::mat4 avatarToSensorMat = glm::inverse(calibrationData.sensorToWorldMat) * calibrationData.avatarMat;
// transform pose into sensor space.
Pose sensorValue = value.transform(avatarToSensorMat);
if (_prevSensorValue.isValid()) {
// exponential smoothing filter
sensorValue.translation = _translationConstant * sensorValue.getTranslation() + (1.0f - _translationConstant) * _prevSensorValue.getTranslation();
sensorValue.rotation = safeMix(sensorValue.getRotation(), _prevSensorValue.getRotation(), _rotationConstant);
// remember previous sensor space value.
_prevSensorValue = sensorValue;
// transform back into avatar space
return sensorValue.transform(sensorToAvatarMat);
} else {
// remember previous sensor space value.
_prevSensorValue = sensorValue;
// no previous value to smooth with, so return value unchanged
return value;
}
} else {
// return invalid value unchanged
return value;
}
}
bool ExponentialSmoothingFilter::parseParameters(const QJsonValue& parameters) {
if (parameters.isObject()) {
auto obj = parameters.toObject();
if (obj.contains(JSON_ROTATION) && obj.contains(JSON_TRANSLATION)) {
_rotationConstant = glm::clamp((float)obj[JSON_ROTATION].toDouble(), 0.0f, 1.0f);
_translationConstant = glm::clamp((float)obj[JSON_TRANSLATION].toDouble(), 0.0f, 1.0f);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,42 @@
//
// Created by Anthony Thibault 2017/12/17
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Controllers_Filters_Exponential_Smoothing_h
#define hifi_Controllers_Filters_Exponential_Smoothing_h
#include "../Filter.h"
namespace controller {
class ExponentialSmoothingFilter : public Filter {
REGISTER_FILTER_CLASS(ExponentialSmoothingFilter);
public:
ExponentialSmoothingFilter() {}
ExponentialSmoothingFilter(float rotationConstant, float translationConstant) :
_translationConstant(translationConstant), _rotationConstant(rotationConstant) {}
float apply(float value) const override { return value; }
Pose apply(Pose value) const override;
bool parseParameters(const QJsonValue& parameters) override;
private:
// Constant between 0 and 1.
// 1 indicates no smoothing at all, poses are passed through unaltered.
// Values near 1 are less smooth with lower latency.
// Values near 0 are more smooth with higher latency.
float _translationConstant { 0.375f };
float _rotationConstant { 0.375f };
mutable Pose _prevSensorValue { Pose() }; // sensor space
};
}
#endif

View file

@ -98,6 +98,7 @@ Script.include("/~/system/libraries/Xform.js");
this.targetObject = null;
this.actionID = null; // action this script created...
this.entityToLockOnto = null;
this.potentialEntityWithContextOverlay = false;
this.entityWithContextOverlay = false;
this.contextOverlayTimer = false;
this.previousCollisionStatus = false;
@ -364,6 +365,7 @@ Script.include("/~/system/libraries/Xform.js");
if (this.entityWithContextOverlay) {
ContextOverlay.destroyContextOverlay(this.entityWithContextOverlay);
this.entityWithContextOverlay = false;
this.potentialEntityWithContextOverlay = false;
}
};
@ -444,9 +446,13 @@ Script.include("/~/system/libraries/Xform.js");
this.targetObject = new TargetObject(entityID, targetProps);
this.targetObject.parentProps = getEntityParents(targetProps);
Script.clearTimeout(this.contextOverlayTimer);
this.contextOverlayTimer = false;
if (entityID !== this.entityWithContextOverlay) {
this.destroyContextOverlay();
}
var targetEntity = this.targetObject.getTargetEntity();
entityID = targetEntity.id;
targetProps = targetEntity.props;
@ -470,26 +476,39 @@ Script.include("/~/system/libraries/Xform.js");
this.startFarGrabAction(controllerData, targetProps);
}
}
} else if (!this.entityWithContextOverlay && !this.contextOverlayTimer) {
} else if (!this.entityWithContextOverlay) {
var _this = this;
_this.contextOverlayTimer = Script.setTimeout(function () {
if (!_this.entityWithContextOverlay && _this.contextOverlayTimer) {
var props = Entities.getEntityProperties(rayPickInfo.objectID);
var pointerEvent = {
type: "Move",
id: this.hand + 1, // 0 is reserved for hardware mouse
pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, rayPickInfo.intersection, props),
pos3D: rayPickInfo.intersection,
normal: rayPickInfo.surfaceNormal,
direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal),
button: "Secondary"
};
if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) {
_this.entityWithContextOverlay = rayPickInfo.objectID;
}
if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) {
if (_this.contextOverlayTimer) {
Script.clearTimeout(_this.contextOverlayTimer);
}
_this.contextOverlayTimer = false;
}, 500);
_this.potentialEntityWithContextOverlay = rayPickInfo.objectID;
}
if (!_this.contextOverlayTimer) {
_this.contextOverlayTimer = Script.setTimeout(function () {
if (!_this.entityWithContextOverlay &&
_this.contextOverlayTimer &&
_this.potentialEntityWithContextOverlay === rayPickInfo.objectID) {
var props = Entities.getEntityProperties(rayPickInfo.objectID);
var pointerEvent = {
type: "Move",
id: _this.hand + 1, // 0 is reserved for hardware mouse
pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, rayPickInfo.intersection, props),
pos3D: rayPickInfo.intersection,
normal: rayPickInfo.surfaceNormal,
direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal),
button: "Secondary"
};
if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) {
_this.entityWithContextOverlay = rayPickInfo.objectID;
}
}
_this.contextOverlayTimer = false;
}, 500);
}
}
} else if (this.distanceRotating) {
this.distanceRotate(otherFarGrabModule);