mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 16:23:39 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into feat/make-zones-lights-not-grabbable
This commit is contained in:
commit
b166f98702
13 changed files with 188 additions and 26 deletions
|
@ -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" },
|
||||
|
|
|
@ -597,18 +597,11 @@ Item {
|
|||
// Function body by Howard Stearns 2017-01-08
|
||||
function goToUserInDomain(avatarUuid) {
|
||||
var avatar = AvatarList.getAvatar(avatarUuid);
|
||||
if (!avatar) {
|
||||
if (!avatar || !avatar.position || !avatar.orientation) {
|
||||
console.log("This avatar is no longer present. goToUserInDomain() failed.");
|
||||
return;
|
||||
}
|
||||
// FIXME: We would like the avatar to recompute the avatar's "maybe fly" test at the new position, so that if high enough up,
|
||||
// the avatar goes into fly mode rather than falling. However, that is not exposed to Javascript right now.
|
||||
// FIXME: it would be nice if this used the same teleport steps and smoothing as in the teleport.js script.
|
||||
// Note, however, that this script allows teleporting to a person in the air, while teleport.js is going to a grounded target.
|
||||
// Position avatar 2 metres from the target in the direction that target avatar was facing.
|
||||
MyAvatar.position = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, {x: 0, y: 0, z: -2}));
|
||||
|
||||
// Rotate avatar on Y axis to face target avatar and cancel out any inherited roll and pitch.
|
||||
MyAvatar.orientation = Quat.cancelOutRollAndPitch(Quat.multiply(avatar.orientation, {y: 1}));
|
||||
// This is the last step of what AddressManager.goToUser does, but we don't need to resolve the username.
|
||||
MyAvatar.goToLocation(avatar.position, true, Quat.cancelOutRollAndPitch(avatar.orientation), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -424,6 +424,7 @@ void MyAvatar::update(float deltaTime) {
|
|||
emit positionGoneTo();
|
||||
// Run safety tests as soon as we can after goToLocation, or clear if we're not colliding.
|
||||
_physicsSafetyPending = getCollisionsEnabled();
|
||||
_characterController.recomputeFlying(); // In case we've gone to into the sky.
|
||||
}
|
||||
if (_physicsSafetyPending && qApp->isPhysicsEnabled() && _characterController.isEnabledAndReady()) {
|
||||
// When needed and ready, arrange to check and fix.
|
||||
|
@ -2315,6 +2316,19 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition,
|
|||
bool hasOrientation, const glm::quat& newOrientation,
|
||||
bool shouldFaceLocation) {
|
||||
|
||||
// Most cases of going to a place or user go through this now. Some possible improvements to think about in the future:
|
||||
// - It would be nice if this used the same teleport steps and smoothing as in the teleport.js script, as long as it
|
||||
// still worked if the target is in the air.
|
||||
// - Sometimes (such as the response from /api/v1/users/:username/location), the location can be stale, but there is a
|
||||
// node_id supplied by which we could update the information after going to the stale location first and "looking around".
|
||||
// This could be passed through AddressManager::goToAddressFromObject => AddressManager::handleViewpoint => here.
|
||||
// The trick is that you have to yield enough time to resolve the node_id.
|
||||
// - Instead of always doing the same thing for shouldFaceLocation -- which places users uncomfortabley on top of each other --
|
||||
// it would be nice to see how many users are already "at" a person or place, and place ourself in semicircle or other shape
|
||||
// around the target. Avatars and entities (specified by the node_id) could define an adjustable "face me" method that would
|
||||
// compute the position (e.g., so that if I'm on stage, going to me would compute an available seat in the audience rather than
|
||||
// being in my face on-stage). Note that this could work for going to an entity as well as to a person.
|
||||
|
||||
qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - moving to " << newPosition.x << ", "
|
||||
<< newPosition.y << ", " << newPosition.z;
|
||||
|
||||
|
@ -3152,6 +3166,7 @@ glm::mat4 MyAvatar::getLeftHandCalibrationMat() const {
|
|||
}
|
||||
|
||||
bool MyAvatar::pinJoint(int index, const glm::vec3& position, const glm::quat& orientation) {
|
||||
std::lock_guard<std::mutex> guard(_pinnedJointsMutex);
|
||||
auto hipsIndex = getJointIndex("Hips");
|
||||
if (index != hipsIndex) {
|
||||
qWarning() << "Pinning is only supported for the hips joint at the moment.";
|
||||
|
@ -3171,7 +3186,14 @@ bool MyAvatar::pinJoint(int index, const glm::vec3& position, const glm::quat& o
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MyAvatar::isJointPinned(int index) {
|
||||
std::lock_guard<std::mutex> guard(_pinnedJointsMutex);
|
||||
auto it = std::find(_pinnedJoints.begin(), _pinnedJoints.end(), index);
|
||||
return it != _pinnedJoints.end();
|
||||
}
|
||||
|
||||
bool MyAvatar::clearPinOnJoint(int index) {
|
||||
std::lock_guard<std::mutex> guard(_pinnedJointsMutex);
|
||||
auto it = std::find(_pinnedJoints.begin(), _pinnedJoints.end(), index);
|
||||
if (it != _pinnedJoints.end()) {
|
||||
_pinnedJoints.erase(it);
|
||||
|
|
|
@ -448,9 +448,8 @@ public:
|
|||
virtual void clearJointData(const QString& name) override;
|
||||
virtual void clearJointsData() override;
|
||||
|
||||
|
||||
|
||||
Q_INVOKABLE bool pinJoint(int index, const glm::vec3& position, const glm::quat& orientation);
|
||||
bool isJointPinned(int index);
|
||||
Q_INVOKABLE bool clearPinOnJoint(int index);
|
||||
|
||||
Q_INVOKABLE float getIKErrorOnLastSolve() const;
|
||||
|
@ -837,6 +836,7 @@ private:
|
|||
bool getIsAway() const { return _isAway; }
|
||||
void setAway(bool value);
|
||||
|
||||
std::mutex _pinnedJointsMutex;
|
||||
std::vector<int> _pinnedJoints;
|
||||
|
||||
// height of user in sensor space, when standing erect.
|
||||
|
|
|
@ -34,12 +34,25 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle
|
|||
}
|
||||
|
||||
static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
||||
|
||||
glm::mat4 worldToSensorMat = glm::inverse(myAvatar->getSensorToWorldMatrix());
|
||||
|
||||
// check for pinned hips.
|
||||
auto hipsIndex = myAvatar->getJointIndex("Hips");
|
||||
if (myAvatar->isJointPinned(hipsIndex)) {
|
||||
Transform avatarTransform = myAvatar->getTransform();
|
||||
AnimPose result = AnimPose(worldToSensorMat * avatarTransform.getMatrix() * Matrices::Y_180);
|
||||
result.scale() = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
return result;
|
||||
} else {
|
||||
DebugDraw::getInstance().removeMarker("pinnedHips");
|
||||
}
|
||||
|
||||
glm::mat4 hipsMat = myAvatar->deriveBodyFromHMDSensor();
|
||||
glm::vec3 hipsPos = extractTranslation(hipsMat);
|
||||
glm::quat hipsRot = glmExtractRotation(hipsMat);
|
||||
|
||||
glm::mat4 avatarToWorldMat = myAvatar->getTransform().getMatrix();
|
||||
glm::mat4 worldToSensorMat = glm::inverse(myAvatar->getSensorToWorldMatrix());
|
||||
glm::mat4 avatarToSensorMat = worldToSensorMat * avatarToWorldMat;
|
||||
|
||||
// dampen hips rotation, by mixing it with the avatar orientation in sensor space
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -596,7 +596,7 @@ bool AddressManager::handleDomainID(const QString& host) {
|
|||
void AddressManager::handlePath(const QString& path, LookupTrigger trigger, bool wasPathOnly) {
|
||||
if (!handleViewpoint(path, false, trigger, wasPathOnly)) {
|
||||
qCDebug(networking) << "User entered path could not be handled as a viewpoint - " << path <<
|
||||
"- wll attempt to ask domain-server to resolve.";
|
||||
"- will attempt to ask domain-server to resolve.";
|
||||
|
||||
if (!wasPathOnly) {
|
||||
// if we received a path with a host then we need to remember what it was here so we can not
|
||||
|
|
|
@ -391,6 +391,10 @@ void CharacterController::setState(State desiredState) {
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterController::recomputeFlying() {
|
||||
_pendingFlags |= PENDING_FLAG_RECOMPUTE_FLYING;
|
||||
}
|
||||
|
||||
void CharacterController::setLocalBoundingBox(const glm::vec3& minCorner, const glm::vec3& scale) {
|
||||
float x = scale.x;
|
||||
float z = scale.z;
|
||||
|
@ -657,6 +661,13 @@ void CharacterController::updateState() {
|
|||
if (!_dynamicsWorld) {
|
||||
return;
|
||||
}
|
||||
if (_pendingFlags & PENDING_FLAG_RECOMPUTE_FLYING) {
|
||||
SET_STATE(CharacterController::State::Hover, "recomputeFlying");
|
||||
_hasSupport = false;
|
||||
_stepHeight = _minStepHeight; // clears memory of last step obstacle
|
||||
_pendingFlags &= ~PENDING_FLAG_RECOMPUTE_FLYING;
|
||||
}
|
||||
|
||||
const btScalar FLY_TO_GROUND_THRESHOLD = 0.1f * _radius;
|
||||
const btScalar GROUND_TO_FLY_THRESHOLD = 0.8f * _radius + _halfHeight;
|
||||
const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 250 * MSECS_PER_SECOND;
|
||||
|
|
|
@ -31,6 +31,7 @@ const uint32_t PENDING_FLAG_REMOVE_FROM_SIMULATION = 1U << 1;
|
|||
const uint32_t PENDING_FLAG_UPDATE_SHAPE = 1U << 2;
|
||||
const uint32_t PENDING_FLAG_JUMP = 1U << 3;
|
||||
const uint32_t PENDING_FLAG_UPDATE_COLLISION_GROUP = 1U << 4;
|
||||
const uint32_t PENDING_FLAG_RECOMPUTE_FLYING = 1U << 5;
|
||||
const float DEFAULT_MIN_FLOOR_NORMAL_DOT_UP = cosf(PI / 3.0f);
|
||||
|
||||
class btRigidBody;
|
||||
|
@ -54,6 +55,7 @@ public:
|
|||
|
||||
void setGravity(float gravity);
|
||||
float getGravity();
|
||||
void recomputeFlying();
|
||||
|
||||
virtual void updateShapeIfNecessary() = 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue