From 2d5df389071c0af3f2714644ff92dfacd31b5765 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 13:51:51 -0800 Subject: [PATCH] Persist the user orientation as well as the position, show up a couple meters in front of (and facing) target. Closes #1367. --- interface/src/Application.cpp | 3 ++- interface/src/DataServerClient.cpp | 24 +++++++++++++++++------- interface/src/DataServerClient.h | 1 + interface/src/Menu.cpp | 5 +++-- interface/src/avatar/Profile.cpp | 26 ++++++++++++++++++++++++-- interface/src/avatar/Profile.h | 6 ++++++ 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..6e050df72c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1347,8 +1347,9 @@ void Application::timer() { // ask the node list to check in with the domain server NodeList::getInstance()->sendDomainServerCheckIn(); - // give the MyAvatar object position to the Profile so it can propagate to the data-server + // give the MyAvatar object position, orientation to the Profile so it can propagate to the data-server _profile.updatePosition(_myAvatar.getPosition()); + _profile.updateOrientation(_myAvatar.getOrientation()); } static glm::vec3 getFaceVector(BoxFace face) { diff --git a/interface/src/DataServerClient.cpp b/interface/src/DataServerClient.cpp index 33fa59e3e4..56ab92dba3 100644 --- a/interface/src/DataServerClient.cpp +++ b/interface/src/DataServerClient.cpp @@ -175,25 +175,35 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int } } } - } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position - && valueList[i] != " " && valueList[i + 1] != " ") { + } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position && + keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " && + valueList[i + 1] != " " && valueList[i + 2] != " ") { QStringList coordinateItems = valueList[i + 1].split(','); + QStringList orientationItems = valueList[i + 2].split(','); - if (coordinateItems.size() == 3) { + if (coordinateItems.size() == 3 && orientationItems.size() == 3) { // send a node kill request, indicating to other clients that they should play the "disappeared" effect NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); qDebug() << "Changing domain to" << valueList[i].toLocal8Bit().constData() << - "and position to" << valueList[i + 1].toLocal8Bit().constData() << + ", position to" << valueList[i + 1].toLocal8Bit().constData() << + ", and orientation to" << valueList[i + 2].toLocal8Bit().constData() << "to go to" << userString << "\n"; NodeList::getInstance()->setDomainHostname(valueList[i]); - glm::vec3 newPosition(coordinateItems[0].toFloat(), - coordinateItems[1].toFloat(), - coordinateItems[2].toFloat()); + // orient the user to face the target + glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), + orientationItems[1].toFloat(), orientationItems[2].toFloat()))) * + glm::angleAxis(180.0f, 0.0f, 1.0f, 0.0f); + Application::getInstance()->getAvatar()->setOrientation(newOrientation); + + // move the user a couple units away + const float DISTANCE_TO_USER = 2.0f; + glm::vec3 newPosition = glm::vec3(coordinateItems[0].toFloat(), coordinateItems[1].toFloat(), + coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; Application::getInstance()->getAvatar()->setPosition(newPosition); } diff --git a/interface/src/DataServerClient.h b/interface/src/DataServerClient.h index b0ccbe13ee..89ec944eb6 100644 --- a/interface/src/DataServerClient.h +++ b/interface/src/DataServerClient.h @@ -41,6 +41,7 @@ namespace DataServerKey { const QString FaceMeshURL = "mesh"; const QString SkeletonURL = "skeleton"; const QString Position = "position"; + const QString Orientation = "orientation"; const QString UUID = "uuid"; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 545a765dce..c77be1e0a9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -999,8 +999,9 @@ void Menu::goToUser() { int dialogReturn = userDialog.exec(); if (dialogReturn == QDialog::Accepted && !userDialog.textValue().isEmpty()) { // there's a username entered by the user, make a request to the data-server - DataServerClient::getValuesForKeysAndUserString((QStringList() << DataServerKey::Domain << DataServerKey::Position), - userDialog.textValue()); + DataServerClient::getValuesForKeysAndUserString( + QStringList() << DataServerKey::Domain << DataServerKey::Position << DataServerKey::Orientation, + userDialog.textValue()); } sendFakeEnterEvent(); diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 4a185f5788..316ca195c9 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -18,6 +18,7 @@ Profile::Profile(const QString &username) : _uuid(), _lastDomain(), _lastPosition(0.0, 0.0, 0.0), + _lastOrientationSend(0), _faceModelURL() { if (!_username.isEmpty()) { @@ -69,6 +70,10 @@ void Profile::updateDomain(const QString& domain) { } } +static QByteArray createByteArray(const glm::vec3& vector) { + return QByteArray::number(vector.x) + ',' + QByteArray::number(vector.y) + ',' + QByteArray::number(vector.z); +} + void Profile::updatePosition(const glm::vec3 position) { if (_lastPosition != position) { @@ -90,12 +95,29 @@ void Profile::updatePosition(const glm::vec3 position) { gettimeofday(&lastPositionSend, NULL); // send the changed position to the data-server - QString positionString = QString("%1,%2,%3").arg(position.x).arg(position.y).arg(position.z); - DataServerClient::putValueForKey(DataServerKey::Position, positionString.toLocal8Bit().constData()); + DataServerClient::putValueForKey(DataServerKey::Position, createByteArray(position).constData()); } } } +void Profile::updateOrientation(const glm::quat& orientation) { + glm::vec3 eulerAngles = safeEulerAngles(orientation); + if (_lastOrientation == eulerAngles) { + return; + } + const uint64_t DATA_SERVER_ORIENTATION_UPDATE_INTERVAL_USECS = 5 * 1000 * 1000; + const float DATA_SERVER_ORIENTATION_CHANGE_THRESHOLD_DEGREES = 5.0f; + + uint64_t now = usecTimestampNow(); + if (now - _lastOrientationSend >= DATA_SERVER_ORIENTATION_UPDATE_INTERVAL_USECS && + glm::distance(_lastOrientation, eulerAngles) >= DATA_SERVER_ORIENTATION_CHANGE_THRESHOLD_DEGREES) { + DataServerClient::putValueForKey(DataServerKey::Orientation, createByteArray(eulerAngles).constData()); + + _lastOrientation = eulerAngles; + _lastOrientationSend = now; + } +} + void Profile::saveData(QSettings* settings) { settings->beginGroup("Profile"); diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index eb3f531819..06f8de94a3 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -9,11 +9,14 @@ #ifndef __hifi__Profile__ #define __hifi__Profile__ +#include + #include #include #include #include +#include class Profile { public: @@ -34,6 +37,7 @@ public: void updateDomain(const QString& domain); void updatePosition(const glm::vec3 position); + void updateOrientation(const glm::quat& orientation); QString getLastDomain() const { return _lastDomain; } const glm::vec3& getLastPosition() const { return _lastPosition; } @@ -45,6 +49,8 @@ private: QUuid _uuid; QString _lastDomain; glm::vec3 _lastPosition; + glm::vec3 _lastOrientation; + uint64_t _lastOrientationSend; QUrl _faceModelURL; QUrl _skeletonModelURL; };