overte/interface/src/avatar/Profile.cpp
Andrzej Kapolka 2d5df38907 Persist the user orientation as well as the position, show up a couple meters
in front of (and facing) target.  Closes #1367.
2014-01-13 13:51:51 -08:00

141 lines
5 KiB
C++

//
// Profile.cpp
// hifi
//
// Created by Stephen Birarda on 10/8/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/QSettings>
#include <UUID.h>
#include "Profile.h"
#include "DataServerClient.h"
Profile::Profile(const QString &username) :
_username(username),
_uuid(),
_lastDomain(),
_lastPosition(0.0, 0.0, 0.0),
_lastOrientationSend(0),
_faceModelURL()
{
if (!_username.isEmpty()) {
// we've been given a new username, ask the data-server for profile
DataServerClient::getClientValueForKey(DataServerKey::UUID);
DataServerClient::getClientValueForKey(DataServerKey::FaceMeshURL);
DataServerClient::getClientValueForKey(DataServerKey::SkeletonURL);
// send our current domain server to the data-server
updateDomain(NodeList::getInstance()->getDomainHostname());
}
}
QString Profile::getUserString() const {
if (_uuid.isNull()) {
return _username;
} else {
return uuidStringWithoutCurlyBraces(_uuid);
}
}
void Profile::setUUID(const QUuid& uuid) {
_uuid = uuid;
// when the UUID is changed we need set it appropriately on our avatar instance
Application::getInstance()->getAvatar()->setUUID(_uuid);
}
void Profile::setFaceModelURL(const QUrl& faceModelURL) {
_faceModelURL = faceModelURL;
QMetaObject::invokeMethod(&Application::getInstance()->getAvatar()->getHead().getFaceModel(),
"setURL", Q_ARG(QUrl, _faceModelURL));
}
void Profile::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_skeletonModelURL = skeletonModelURL;
QMetaObject::invokeMethod(&Application::getInstance()->getAvatar()->getSkeletonModel(),
"setURL", Q_ARG(QUrl, _skeletonModelURL));
}
void Profile::updateDomain(const QString& domain) {
if (_lastDomain != domain) {
_lastDomain = domain;
// send the changed domain to the data-server
DataServerClient::putValueForKey(DataServerKey::Domain, domain.toLocal8Bit().constData());
}
}
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) {
static timeval lastPositionSend = {};
const uint64_t DATA_SERVER_POSITION_UPDATE_INTERVAL_USECS = 5 * 1000 * 1000;
const float DATA_SERVER_POSITION_CHANGE_THRESHOLD_METERS = 1;
if (usecTimestampNow() - usecTimestamp(&lastPositionSend) >= DATA_SERVER_POSITION_UPDATE_INTERVAL_USECS &&
(fabsf(_lastPosition.x - position.x) >= DATA_SERVER_POSITION_CHANGE_THRESHOLD_METERS ||
fabsf(_lastPosition.y - position.y) >= DATA_SERVER_POSITION_CHANGE_THRESHOLD_METERS ||
fabsf(_lastPosition.z - position.z) >= DATA_SERVER_POSITION_CHANGE_THRESHOLD_METERS)) {
// if it has been 5 seconds since the last position change and the user has moved >= the threshold
// in at least one of the axis then send the position update to the data-server
_lastPosition = position;
// update the lastPositionSend to now
gettimeofday(&lastPositionSend, NULL);
// send the changed position to the data-server
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");
settings->setValue("username", _username);
settings->setValue("UUID", _uuid);
settings->setValue("faceModelURL", _faceModelURL);
settings->setValue("skeletonModelURL", _skeletonModelURL);
settings->endGroup();
}
void Profile::loadData(QSettings* settings) {
settings->beginGroup("Profile");
_username = settings->value("username").toString();
this->setUUID(settings->value("UUID").toUuid());
_faceModelURL = settings->value("faceModelURL").toUrl();
_skeletonModelURL = settings->value("skeletonModelURL").toUrl();
settings->endGroup();
}