mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 06:54:11 +02:00
Merge branch 'controllers' of https://github.com/samcake/hifi into controllers
This commit is contained in:
commit
01a3539a2a
20 changed files with 365 additions and 54 deletions
|
@ -261,6 +261,12 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SharedNodePointer& destinationNode = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID);
|
const SharedNodePointer& destinationNode = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID);
|
||||||
|
// If the node no longer exists, wait until the ReceivedPacketProcessor has cleaned up the node
|
||||||
|
// to remove it from our stats list.
|
||||||
|
// FIXME Is it safe to clean it up here before ReceivedPacketProcess has?
|
||||||
|
if (!destinationNode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// retrieve sequence number stats of node, prune its missing set
|
// retrieve sequence number stats of node, prune its missing set
|
||||||
SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats();
|
SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats();
|
||||||
|
|
|
@ -80,12 +80,10 @@ const float MyAvatar::ZOOM_DEFAULT = 1.5f;
|
||||||
|
|
||||||
MyAvatar::MyAvatar(RigPointer rig) :
|
MyAvatar::MyAvatar(RigPointer rig) :
|
||||||
Avatar(rig),
|
Avatar(rig),
|
||||||
_gravity(0.0f, 0.0f, 0.0f),
|
|
||||||
_wasPushing(false),
|
_wasPushing(false),
|
||||||
_isPushing(false),
|
_isPushing(false),
|
||||||
_isBraking(false),
|
_isBraking(false),
|
||||||
_boomLength(ZOOM_DEFAULT),
|
_boomLength(ZOOM_DEFAULT),
|
||||||
_trapDuration(0.0f),
|
|
||||||
_thrust(0.0f),
|
_thrust(0.0f),
|
||||||
_keyboardMotorVelocity(0.0f),
|
_keyboardMotorVelocity(0.0f),
|
||||||
_keyboardMotorTimescale(DEFAULT_KEYBOARD_MOTOR_TIMESCALE),
|
_keyboardMotorTimescale(DEFAULT_KEYBOARD_MOTOR_TIMESCALE),
|
||||||
|
@ -111,7 +109,8 @@ MyAvatar::MyAvatar(RigPointer rig) :
|
||||||
_goToOrientation(),
|
_goToOrientation(),
|
||||||
_rig(rig),
|
_rig(rig),
|
||||||
_prevShouldDrawHead(true),
|
_prevShouldDrawHead(true),
|
||||||
_audioListenerMode(FROM_HEAD)
|
_audioListenerMode(FROM_HEAD),
|
||||||
|
_hmdAtRestDetector(glm::vec3(0), glm::quat())
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
|
||||||
_driveKeys[i] = 0.0f;
|
_driveKeys[i] = 0.0f;
|
||||||
|
@ -142,24 +141,46 @@ QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::reset() {
|
void MyAvatar::reset() {
|
||||||
_skeletonModel.reset();
|
// Gather animation mode...
|
||||||
getHead()->reset();
|
|
||||||
|
|
||||||
_targetVelocity = glm::vec3(0.0f);
|
|
||||||
setThrust(glm::vec3(0.0f));
|
|
||||||
// Reset the pitch and roll components of the avatar's orientation, preserve yaw direction
|
|
||||||
glm::vec3 eulers = safeEulerAngles(getOrientation());
|
|
||||||
eulers.x = 0.0f;
|
|
||||||
eulers.z = 0.0f;
|
|
||||||
setOrientation(glm::quat(eulers));
|
|
||||||
|
|
||||||
// This should be simpler when we have only graph animations always on.
|
// This should be simpler when we have only graph animations always on.
|
||||||
bool isRig = _rig->getEnableRig();
|
bool isRig = _rig->getEnableRig();
|
||||||
// seting rig animation to true, below, will clear the graph animation menu item, so grab it now.
|
// seting rig animation to true, below, will clear the graph animation menu item, so grab it now.
|
||||||
bool isGraph = _rig->getEnableAnimGraph() || Menu::getInstance()->isOptionChecked(MenuOption::EnableAnimGraph);
|
bool isGraph = _rig->getEnableAnimGraph() || Menu::getInstance()->isOptionChecked(MenuOption::EnableAnimGraph);
|
||||||
|
// ... and get to sane configuration where other activity won't bother us.
|
||||||
qApp->setRawAvatarUpdateThreading(false);
|
qApp->setRawAvatarUpdateThreading(false);
|
||||||
_rig->disableHands = true;
|
_rig->disableHands = true;
|
||||||
setEnableRigAnimations(true);
|
setEnableRigAnimations(true);
|
||||||
|
|
||||||
|
// Reset dynamic state.
|
||||||
|
_wasPushing = _isPushing = _isBraking = _billboardValid = _goToPending = _straighteningLean = false;
|
||||||
|
_skeletonModel.reset();
|
||||||
|
getHead()->reset();
|
||||||
|
_targetVelocity = glm::vec3(0.0f);
|
||||||
|
setThrust(glm::vec3(0.0f));
|
||||||
|
|
||||||
|
// Get fresh data, in case we're really slow and out of wack.
|
||||||
|
_hmdSensorMatrix = qApp->getHMDSensorPose();
|
||||||
|
_hmdSensorPosition = extractTranslation(_hmdSensorMatrix);
|
||||||
|
_hmdSensorOrientation = glm::quat_cast(_hmdSensorMatrix);
|
||||||
|
|
||||||
|
// Reset body position/orientation under the head.
|
||||||
|
auto newBodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation..
|
||||||
|
auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix;
|
||||||
|
glm::vec3 worldBodyPos = extractTranslation(worldBodyMatrix);
|
||||||
|
glm::quat worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix));
|
||||||
|
|
||||||
|
// FIXME: Hack to retain the previous behavior wrt height.
|
||||||
|
// I'd like to make the body match head height, but that will have to wait for separate PR.
|
||||||
|
worldBodyPos.y = getPosition().y;
|
||||||
|
|
||||||
|
setPosition(worldBodyPos);
|
||||||
|
setOrientation(worldBodyRot);
|
||||||
|
// If there is any discrepency between positioning and the head (as there is in initial deriveBodyFromHMDSensor),
|
||||||
|
// we can make that right by setting _bodySensorMatrix = newBodySensorMatrix.
|
||||||
|
// However, doing so will make the head want to point to the previous body orientation, as cached above.
|
||||||
|
//_bodySensorMatrix = newBodySensorMatrix;
|
||||||
|
//updateSensorToWorldMatrix(); // Uses updated position/orientation and _bodySensorMatrix changes
|
||||||
|
|
||||||
_skeletonModel.simulate(0.1f); // non-zero
|
_skeletonModel.simulate(0.1f); // non-zero
|
||||||
setEnableRigAnimations(false);
|
setEnableRigAnimations(false);
|
||||||
_skeletonModel.simulate(0.1f);
|
_skeletonModel.simulate(0.1f);
|
||||||
|
@ -311,37 +332,39 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
|
||||||
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
|
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
|
||||||
|
|
||||||
const float STRAIGHTING_LEAN_DURATION = 0.5f; // seconds
|
bool hmdIsAtRest = _hmdAtRestDetector.update(deltaTime, _hmdSensorPosition, _hmdSensorOrientation);
|
||||||
|
|
||||||
|
const float STRAIGHTENING_LEAN_DURATION = 0.5f; // seconds
|
||||||
|
|
||||||
// define a vertical capsule
|
// define a vertical capsule
|
||||||
const float STRAIGHTING_LEAN_CAPSULE_RADIUS = 0.2f; // meters
|
const float STRAIGHTENING_LEAN_CAPSULE_RADIUS = 0.2f; // meters
|
||||||
const float STRAIGHTING_LEAN_CAPSULE_LENGTH = 0.05f; // length of the cylinder part of the capsule in meters.
|
const float STRAIGHTENING_LEAN_CAPSULE_LENGTH = 0.05f; // length of the cylinder part of the capsule in meters.
|
||||||
|
|
||||||
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
||||||
glm::vec3 diff = extractTranslation(newBodySensorMatrix) - extractTranslation(_bodySensorMatrix);
|
glm::vec3 diff = extractTranslation(newBodySensorMatrix) - extractTranslation(_bodySensorMatrix);
|
||||||
if (!_straightingLean && capsuleCheck(diff, STRAIGHTING_LEAN_CAPSULE_LENGTH, STRAIGHTING_LEAN_CAPSULE_RADIUS)) {
|
if (!_straighteningLean && (capsuleCheck(diff, STRAIGHTENING_LEAN_CAPSULE_LENGTH, STRAIGHTENING_LEAN_CAPSULE_RADIUS) || hmdIsAtRest)) {
|
||||||
|
|
||||||
// begin homing toward derived body position.
|
// begin homing toward derived body position.
|
||||||
_straightingLean = true;
|
_straighteningLean = true;
|
||||||
_straightingLeanAlpha = 0.0f;
|
_straighteningLeanAlpha = 0.0f;
|
||||||
|
|
||||||
} else if (_straightingLean) {
|
} else if (_straighteningLean) {
|
||||||
|
|
||||||
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
|
||||||
auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix;
|
auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix;
|
||||||
glm::vec3 worldBodyPos = extractTranslation(worldBodyMatrix);
|
glm::vec3 worldBodyPos = extractTranslation(worldBodyMatrix);
|
||||||
glm::quat worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix));
|
glm::quat worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix));
|
||||||
|
|
||||||
_straightingLeanAlpha += (1.0f / STRAIGHTING_LEAN_DURATION) * deltaTime;
|
_straighteningLeanAlpha += (1.0f / STRAIGHTENING_LEAN_DURATION) * deltaTime;
|
||||||
|
|
||||||
if (_straightingLeanAlpha >= 1.0f) {
|
if (_straighteningLeanAlpha >= 1.0f) {
|
||||||
_straightingLean = false;
|
_straighteningLean = false;
|
||||||
nextAttitude(worldBodyPos, worldBodyRot);
|
nextAttitude(worldBodyPos, worldBodyRot);
|
||||||
_bodySensorMatrix = newBodySensorMatrix;
|
_bodySensorMatrix = newBodySensorMatrix;
|
||||||
} else {
|
} else {
|
||||||
// interp position toward the desired pos
|
// interp position toward the desired pos
|
||||||
glm::vec3 pos = lerp(getPosition(), worldBodyPos, _straightingLeanAlpha);
|
glm::vec3 pos = lerp(getPosition(), worldBodyPos, _straighteningLeanAlpha);
|
||||||
glm::quat rot = glm::normalize(safeMix(getOrientation(), worldBodyRot, _straightingLeanAlpha));
|
glm::quat rot = glm::normalize(safeMix(getOrientation(), worldBodyRot, _straighteningLeanAlpha));
|
||||||
nextAttitude(pos, rot);
|
nextAttitude(pos, rot);
|
||||||
|
|
||||||
// interp sensor matrix toward desired
|
// interp sensor matrix toward desired
|
||||||
|
@ -349,13 +372,13 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
glm::quat nextBodyRot = glm::normalize(glm::quat_cast(newBodySensorMatrix));
|
glm::quat nextBodyRot = glm::normalize(glm::quat_cast(newBodySensorMatrix));
|
||||||
glm::vec3 prevBodyPos = extractTranslation(_bodySensorMatrix);
|
glm::vec3 prevBodyPos = extractTranslation(_bodySensorMatrix);
|
||||||
glm::quat prevBodyRot = glm::normalize(glm::quat_cast(_bodySensorMatrix));
|
glm::quat prevBodyRot = glm::normalize(glm::quat_cast(_bodySensorMatrix));
|
||||||
pos = lerp(prevBodyPos, nextBodyPos, _straightingLeanAlpha);
|
pos = lerp(prevBodyPos, nextBodyPos, _straighteningLeanAlpha);
|
||||||
rot = glm::normalize(safeMix(prevBodyRot, nextBodyRot, _straightingLeanAlpha));
|
rot = glm::normalize(safeMix(prevBodyRot, nextBodyRot, _straighteningLeanAlpha));
|
||||||
_bodySensorMatrix = createMatFromQuatAndPos(rot, pos);
|
_bodySensorMatrix = createMatFromQuatAndPos(rot, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// best called at end of main loop, just before rendering.
|
// best called at end of main loop, just before rendering.
|
||||||
// update sensor to world matrix from current body position and hmd sensor.
|
// update sensor to world matrix from current body position and hmd sensor.
|
||||||
// This is so the correct camera can be used for rendering.
|
// This is so the correct camera can be used for rendering.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <Rig.h>
|
#include <Rig.h>
|
||||||
|
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
|
#include "AtRestDetector.h"
|
||||||
|
|
||||||
class ModelItemID;
|
class ModelItemID;
|
||||||
|
|
||||||
|
@ -282,8 +283,6 @@ private:
|
||||||
// results are in sensor space
|
// results are in sensor space
|
||||||
glm::mat4 deriveBodyFromHMDSensor() const;
|
glm::mat4 deriveBodyFromHMDSensor() const;
|
||||||
|
|
||||||
glm::vec3 _gravity;
|
|
||||||
|
|
||||||
float _driveKeys[MAX_DRIVE_KEYS];
|
float _driveKeys[MAX_DRIVE_KEYS];
|
||||||
bool _wasPushing;
|
bool _wasPushing;
|
||||||
bool _isPushing;
|
bool _isPushing;
|
||||||
|
@ -291,7 +290,6 @@ private:
|
||||||
|
|
||||||
float _boomLength;
|
float _boomLength;
|
||||||
|
|
||||||
float _trapDuration; // seconds that avatar has been trapped by collisions
|
|
||||||
glm::vec3 _thrust; // impulse accumulator for outside sources
|
glm::vec3 _thrust; // impulse accumulator for outside sources
|
||||||
|
|
||||||
glm::vec3 _keyboardMotorVelocity; // target local-frame velocity of avatar (keyboard)
|
glm::vec3 _keyboardMotorVelocity; // target local-frame velocity of avatar (keyboard)
|
||||||
|
@ -363,10 +361,11 @@ private:
|
||||||
glm::vec3 _customListenPosition;
|
glm::vec3 _customListenPosition;
|
||||||
glm::quat _customListenOrientation;
|
glm::quat _customListenOrientation;
|
||||||
|
|
||||||
bool _straightingLean = false;
|
bool _straighteningLean = false;
|
||||||
float _straightingLeanAlpha = 0.0f;
|
float _straighteningLeanAlpha = 0.0f;
|
||||||
|
|
||||||
quint64 _lastUpdateFromHMDTime = usecTimestampNow();
|
quint64 _lastUpdateFromHMDTime = usecTimestampNow();
|
||||||
|
AtRestDetector _hmdAtRestDetector;
|
||||||
};
|
};
|
||||||
|
|
||||||
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
||||||
|
|
14
libraries/controllers/CMakeLists.txt
Normal file
14
libraries/controllers/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
set(TARGET_NAME controllers)
|
||||||
|
|
||||||
|
# set a default root dir for each of our optional externals if it was not passed
|
||||||
|
setup_hifi_library(Script)
|
||||||
|
|
||||||
|
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
|
||||||
|
link_hifi_libraries(shared plugins input-plugins)
|
||||||
|
|
||||||
|
GroupSources("src/controllers")
|
||||||
|
|
||||||
|
add_dependency_external_projects(glm)
|
||||||
|
find_package(GLM REQUIRED)
|
||||||
|
target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS})
|
||||||
|
|
190
libraries/controllers/src/controllers/ControllerMapping.cpp
Normal file
190
libraries/controllers/src/controllers/ControllerMapping.cpp
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
#include <QtScript/QScriptValue>
|
||||||
|
|
||||||
|
extern float currentTime();
|
||||||
|
|
||||||
|
namespace Controllers {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encapsulates a particular input / output,
|
||||||
|
* i.e. Hydra.Button0, Standard.X, Action.Yaw
|
||||||
|
*/
|
||||||
|
class Endpoint {
|
||||||
|
public:
|
||||||
|
virtual float value() = 0;
|
||||||
|
virtual void apply(float newValue, float oldValue, const Endpoint& source) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
using EndpointList = std::list<Endpoint*>;
|
||||||
|
|
||||||
|
const EndpointList& getHardwareEndpoints();
|
||||||
|
|
||||||
|
// Ex: xbox.RY, xbox.A ....
|
||||||
|
class HardwareEndpoint : public Endpoint {
|
||||||
|
public:
|
||||||
|
virtual float value() override {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(float newValue, float oldValue, const Endpoint& source) override {
|
||||||
|
// Default does nothing, but in theory this could be something like vibration
|
||||||
|
// mapping.from(xbox.X).to(xbox.Vibrate)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class VirtualEndpoint : public Endpoint {
|
||||||
|
public:
|
||||||
|
virtual void apply(float newValue) {
|
||||||
|
if (newValue != _lastValue) {
|
||||||
|
_lastValue = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float value() {
|
||||||
|
return _lastValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float _lastValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A function which provides input
|
||||||
|
*/
|
||||||
|
class FunctionEndpoint : public Endpoint {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual float value() override {
|
||||||
|
float now = currentTime();
|
||||||
|
float delta = now - _lastCalled;
|
||||||
|
float result = _inputFunction.call(_object, QScriptValue(delta)).toNumber();
|
||||||
|
_lastCalled = now;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(float newValue, float oldValue, const Endpoint& source) override {
|
||||||
|
if (newValue != oldValue) {
|
||||||
|
//_outputFunction.call(newValue, oldValue, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float _lastValue{ NAN };
|
||||||
|
float _lastCalled{ 0 };
|
||||||
|
QScriptValue _outputFunction;
|
||||||
|
QScriptValue _inputFunction;
|
||||||
|
QScriptValue _object;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Encapsulates part of a filter chain
|
||||||
|
class Filter {
|
||||||
|
public:
|
||||||
|
virtual float apply(float newValue, float oldValue) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScaleFilter : public Filter {
|
||||||
|
public:
|
||||||
|
virtual float apply(float newValue, float oldValue) {
|
||||||
|
return newValue * _scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
float _scale{ 1.0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
class PulseFilter : public Filter {
|
||||||
|
public:
|
||||||
|
virtual float apply(float newValue, float oldValue) {
|
||||||
|
// ???
|
||||||
|
}
|
||||||
|
|
||||||
|
float _lastEmitValue{ 0 };
|
||||||
|
float _lastEmitTime{ 0 };
|
||||||
|
float _interval{ -1.0f };
|
||||||
|
};
|
||||||
|
|
||||||
|
using FilterList = std::list<Filter*>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* encapsulates a source, destination and filters to apply
|
||||||
|
*/
|
||||||
|
class Route {
|
||||||
|
public:
|
||||||
|
Endpoint* _source;
|
||||||
|
Endpoint* _destination;
|
||||||
|
FilterList _filters;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ValueMap = std::map<Endpoint*, float>;
|
||||||
|
|
||||||
|
class Mapping {
|
||||||
|
public:
|
||||||
|
// List of routes
|
||||||
|
using List = std::list<Route>;
|
||||||
|
// Map of source channels to route lists
|
||||||
|
using Map = std::map<Endpoint*, List>;
|
||||||
|
|
||||||
|
Map _channelMappings;
|
||||||
|
ValueMap _lastValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MappingsStack {
|
||||||
|
std::list<Mapping> _stack;
|
||||||
|
ValueMap _lastValues;
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
EndpointList hardwareInputs = getHardwareEndpoints();
|
||||||
|
ValueMap currentValues;
|
||||||
|
|
||||||
|
for (auto input : hardwareInputs) {
|
||||||
|
currentValues[input] = input->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now process the current values for each level of the stack
|
||||||
|
for (auto& mapping : _stack) {
|
||||||
|
update(mapping, currentValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastValues = currentValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(Mapping& mapping, ValueMap& values) {
|
||||||
|
ValueMap updates;
|
||||||
|
EndpointList consumedEndpoints;
|
||||||
|
for (const auto& entry : values) {
|
||||||
|
Endpoint* endpoint = entry.first;
|
||||||
|
if (!mapping._channelMappings.count(endpoint)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Mapping::List& routes = mapping._channelMappings[endpoint];
|
||||||
|
consumedEndpoints.push_back(endpoint);
|
||||||
|
for (const auto& route : routes) {
|
||||||
|
float lastValue = 0;
|
||||||
|
if (mapping._lastValues.count(endpoint)) {
|
||||||
|
lastValue = mapping._lastValues[endpoint];
|
||||||
|
}
|
||||||
|
float value = entry.second;
|
||||||
|
for (const auto& filter : route._filters) {
|
||||||
|
value = filter->apply(value, lastValue);
|
||||||
|
}
|
||||||
|
updates[route._destination] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the last seen values
|
||||||
|
mapping._lastValues = values;
|
||||||
|
|
||||||
|
// Remove all the consumed inputs
|
||||||
|
for (auto endpoint : consumedEndpoints) {
|
||||||
|
values.erase(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all the updates (may restore some of the consumed data if a passthrough was created (i.e. source == dest)
|
||||||
|
for (const auto& entry : updates) {
|
||||||
|
values[entry.first] = entry.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -339,8 +339,6 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
||||||
|
|
||||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
||||||
|
|
||||||
auto semantic = texture.getTexelFormat().getSemantic();
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||||
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
||||||
texelFormat.format, texelFormat.type, bytes);
|
texelFormat.format, texelFormat.type, bytes);
|
||||||
|
|
|
@ -68,10 +68,10 @@ const float DEFAULT_REACH_LENGTH = 1.5f;
|
||||||
|
|
||||||
SixenseManager::SixenseManager() :
|
SixenseManager::SixenseManager() :
|
||||||
InputDevice("Hydra"),
|
InputDevice("Hydra"),
|
||||||
#ifdef __APPLE__
|
|
||||||
_sixenseLibrary(NULL),
|
|
||||||
#endif
|
|
||||||
_reachLength(DEFAULT_REACH_LENGTH),
|
_reachLength(DEFAULT_REACH_LENGTH),
|
||||||
|
#ifdef __APPLE__
|
||||||
|
_sixenseLibrary(nullptr),
|
||||||
|
#endif
|
||||||
_hydrasConnected(false)
|
_hydrasConnected(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ private slots:
|
||||||
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AssetRequest* _assetRequest;
|
AssetRequest* _assetRequest { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -91,6 +91,7 @@ SendQueue& Connection::getSendQueue() {
|
||||||
|
|
||||||
// set defaults on the send queue from our congestion control object and estimatedTimeout()
|
// set defaults on the send queue from our congestion control object and estimatedTimeout()
|
||||||
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
||||||
|
_sendQueue->setSyncInterval(_synInterval);
|
||||||
_sendQueue->setEstimatedTimeout(estimatedTimeout());
|
_sendQueue->setEstimatedTimeout(estimatedTimeout());
|
||||||
_sendQueue->setFlowWindowSize(std::min(_flowWindowSize, (int) _congestionControl->_congestionWindowSize));
|
_sendQueue->setFlowWindowSize(std::min(_flowWindowSize, (int) _congestionControl->_congestionWindowSize));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
using namespace udt;
|
using namespace udt;
|
||||||
|
|
||||||
|
static int packetMetaTypeId = qRegisterMetaType<Packet*>("Packet*");
|
||||||
|
|
||||||
int Packet::localHeaderSize(bool isPartOfMessage) {
|
int Packet::localHeaderSize(bool isPartOfMessage) {
|
||||||
return sizeof(Packet::SequenceNumberAndBitField) +
|
return sizeof(Packet::SequenceNumberAndBitField) +
|
||||||
(isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0);
|
(isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0);
|
||||||
|
|
|
@ -88,7 +88,9 @@ private:
|
||||||
mutable PacketPosition _packetPosition { PacketPosition::ONLY };
|
mutable PacketPosition _packetPosition { PacketPosition::ONLY };
|
||||||
mutable MessagePartNumber _messagePartNumber { 0 };
|
mutable MessagePartNumber _messagePartNumber { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace udt
|
} // namespace udt
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(udt::Packet*);
|
||||||
|
|
||||||
#endif // hifi_Packet_h
|
#endif // hifi_Packet_h
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
using namespace udt;
|
using namespace udt;
|
||||||
|
|
||||||
|
static int packetListMetaTypeId = qRegisterMetaType<PacketList*>("PacketList*");
|
||||||
|
|
||||||
std::unique_ptr<PacketList> PacketList::create(PacketType packetType, QByteArray extendedHeader,
|
std::unique_ptr<PacketList> PacketList::create(PacketType packetType, QByteArray extendedHeader,
|
||||||
bool isReliable, bool isOrdered) {
|
bool isReliable, bool isOrdered) {
|
||||||
auto packetList = std::unique_ptr<PacketList>(new PacketList(packetType, extendedHeader,
|
auto packetList = std::unique_ptr<PacketList>(new PacketList(packetType, extendedHeader,
|
||||||
|
|
|
@ -118,4 +118,6 @@ template<typename T> std::unique_ptr<T> PacketList::takeFront() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(udt::PacketList*);
|
||||||
|
|
||||||
#endif // hifi_PacketList_h
|
#endif // hifi_PacketList_h
|
||||||
|
|
|
@ -439,7 +439,8 @@ bool SendQueue::isInactive(bool sentAPacket) {
|
||||||
} else {
|
} else {
|
||||||
// We think the client is still waiting for data (based on the sequence number gap)
|
// We think the client is still waiting for data (based on the sequence number gap)
|
||||||
// Let's wait either for a response from the client or until the estimated timeout
|
// Let's wait either for a response from the client or until the estimated timeout
|
||||||
auto waitDuration = std::chrono::microseconds(_estimatedTimeout);
|
// (plus the sync interval to allow the client to respond) has elapsed
|
||||||
|
auto waitDuration = std::chrono::microseconds(_estimatedTimeout + _syncInterval);
|
||||||
|
|
||||||
// use our condition_variable_any to wait
|
// use our condition_variable_any to wait
|
||||||
auto cvStatus = _emptyCondition.wait_for(locker, waitDuration);
|
auto cvStatus = _emptyCondition.wait_for(locker, waitDuration);
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; }
|
void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; }
|
||||||
|
|
||||||
void setEstimatedTimeout(int estimatedTimeout) { _estimatedTimeout = estimatedTimeout; }
|
void setEstimatedTimeout(int estimatedTimeout) { _estimatedTimeout = estimatedTimeout; }
|
||||||
|
void setSyncInterval(int syncInterval) { _syncInterval = syncInterval; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void stop();
|
void stop();
|
||||||
|
@ -114,6 +115,7 @@ private:
|
||||||
std::atomic<State> _state { State::NotStarted };
|
std::atomic<State> _state { State::NotStarted };
|
||||||
|
|
||||||
std::atomic<int> _estimatedTimeout { 0 }; // Estimated timeout, set from CC
|
std::atomic<int> _estimatedTimeout { 0 }; // Estimated timeout, set from CC
|
||||||
|
std::atomic<int> _syncInterval { udt::DEFAULT_SYN_INTERVAL_USECS }; // Sync interval, set from CC
|
||||||
std::atomic<int> _timeoutExpiryCount { 0 }; // The number of times the timeout has expired without response from client
|
std::atomic<int> _timeoutExpiryCount { 0 }; // The number of times the timeout has expired without response from client
|
||||||
std::atomic<uint64_t> _lastReceiverResponse { 0 }; // Timestamp for the last time we got new data from the receiver (ACK/NAK)
|
std::atomic<uint64_t> _lastReceiverResponse { 0 }; // Timestamp for the last time we got new data from the receiver (ACK/NAK)
|
||||||
|
|
||||||
|
|
|
@ -24,16 +24,10 @@
|
||||||
|
|
||||||
using namespace udt;
|
using namespace udt;
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Packet*);
|
|
||||||
Q_DECLARE_METATYPE(PacketList*);
|
|
||||||
|
|
||||||
Socket::Socket(QObject* parent) :
|
Socket::Socket(QObject* parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
_synTimer(new QTimer(this))
|
_synTimer(new QTimer(this))
|
||||||
{
|
{
|
||||||
qRegisterMetaType<Packet*>("Packet*");
|
|
||||||
qRegisterMetaType<PacketList*>("PacketList*");
|
|
||||||
|
|
||||||
connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams);
|
connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams);
|
||||||
|
|
||||||
// make sure our synchronization method is called every SYN interval
|
// make sure our synchronization method is called every SYN interval
|
||||||
|
|
41
libraries/shared/src/AtRestDetector.cpp
Normal file
41
libraries/shared/src/AtRestDetector.cpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include "AtRestDetector.h"
|
||||||
|
#include "SharedLogging.h"
|
||||||
|
|
||||||
|
AtRestDetector::AtRestDetector(const glm::vec3& startPosition, const glm::quat& startRotation) {
|
||||||
|
reset(startPosition, startRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtRestDetector::reset(const glm::vec3& startPosition, const glm::quat& startRotation) {
|
||||||
|
_positionAverage = startPosition;
|
||||||
|
_positionVariance = 0.0f;
|
||||||
|
|
||||||
|
glm::quat ql = glm::log(startRotation);
|
||||||
|
_quatLogAverage = glm::vec3(ql.x, ql.y, ql.z);
|
||||||
|
_quatLogVariance = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtRestDetector::update(float dt, const glm::vec3& position, const glm::quat& rotation) {
|
||||||
|
const float TAU = 1.0f;
|
||||||
|
float delta = glm::min(dt / TAU, 1.0f);
|
||||||
|
|
||||||
|
// keep a running average of position.
|
||||||
|
_positionAverage = position * delta + _positionAverage * (1 - delta);
|
||||||
|
|
||||||
|
// keep a running average of position variances.
|
||||||
|
glm::vec3 dx = position - _positionAverage;
|
||||||
|
_positionVariance = glm::dot(dx, dx) * delta + _positionVariance * (1 - delta);
|
||||||
|
|
||||||
|
// keep a running average of quaternion logarithms.
|
||||||
|
glm::quat quatLogAsQuat = glm::log(rotation);
|
||||||
|
glm::vec3 quatLog(quatLogAsQuat.x, quatLogAsQuat.y, quatLogAsQuat.z);
|
||||||
|
_quatLogAverage = quatLog * delta + _quatLogAverage * (1 - delta);
|
||||||
|
|
||||||
|
// keep a running average of quatLog variances.
|
||||||
|
glm::vec3 dql = quatLog - _quatLogAverage;
|
||||||
|
_quatLogVariance = glm::dot(dql, dql) * delta + _quatLogVariance * (1 - delta);
|
||||||
|
|
||||||
|
const float POSITION_VARIANCE_THRESHOLD = 0.001f;
|
||||||
|
const float QUAT_LOG_VARIANCE_THRESHOLD = 0.00002f;
|
||||||
|
|
||||||
|
return _positionVariance < POSITION_VARIANCE_THRESHOLD && _quatLogVariance < QUAT_LOG_VARIANCE_THRESHOLD;
|
||||||
|
}
|
34
libraries/shared/src/AtRestDetector.h
Normal file
34
libraries/shared/src/AtRestDetector.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//
|
||||||
|
// AtRestDetector.h
|
||||||
|
// libraries/shared/src
|
||||||
|
//
|
||||||
|
// Created by Anthony Thibault on 10/6/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_AtRestDetector_h
|
||||||
|
#define hifi_AtRestDetector_h
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
|
class AtRestDetector {
|
||||||
|
public:
|
||||||
|
AtRestDetector(const glm::vec3& startPosition, const glm::quat& startRotation);
|
||||||
|
void reset(const glm::vec3& startPosition, const glm::quat& startRotation);
|
||||||
|
|
||||||
|
// returns true if object is at rest, dt in assumed to be seconds.
|
||||||
|
bool update(float dt, const glm::vec3& position, const glm::quat& startRotation);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::vec3 _positionAverage;
|
||||||
|
float _positionVariance;
|
||||||
|
|
||||||
|
glm::vec3 _quatLogAverage;
|
||||||
|
float _quatLogVariance;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -979,7 +979,7 @@
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
},
|
},
|
||||||
grabbaleKey: {
|
grabbableKey: {
|
||||||
grabbable: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1165,7 +1165,7 @@
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
},
|
},
|
||||||
grabbableKey: {
|
grabbableKey: {
|
||||||
grabbale: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -1207,7 +1207,7 @@
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
},
|
},
|
||||||
grabbaleKey: {
|
grabbableKey: {
|
||||||
grabbable: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -946,7 +946,7 @@ MasterReset = function() {
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
},
|
},
|
||||||
grabbaleKey: {
|
grabbableKey: {
|
||||||
grabbable: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1132,7 +1132,7 @@ MasterReset = function() {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
},
|
},
|
||||||
grabbableKey: {
|
grabbableKey: {
|
||||||
grabbale: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -1174,7 +1174,7 @@ MasterReset = function() {
|
||||||
resetMe: {
|
resetMe: {
|
||||||
resetMe: true,
|
resetMe: true,
|
||||||
},
|
},
|
||||||
grabbaleKey: {
|
grabbableKey: {
|
||||||
grabbable: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue