initial movement of mesh/skeleton URLs out of data-server through avatar-mixer

This commit is contained in:
Stephen Birarda 2014-02-04 13:02:33 -08:00
parent f1b612d8d8
commit 8bf3b7586b
11 changed files with 98 additions and 117 deletions

View file

@ -242,6 +242,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
silentNodeTimer->moveToThread(_nodeThread);
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
// send the identity packet for our avatar each second to our avatar mixer
QTimer* identityPacketTimer = new QTimer();
connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket);
silentNodeTimer->start(1000);
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
@ -1855,12 +1860,6 @@ void Application::init() {
}
qDebug("Loaded settings");
if (!_profile.getUsername().isEmpty()) {
// we have a username for this avatar, ask the data-server for the mesh URL for this avatar
DataServerClient::getValueForKeyAndUserString(DataServerKey::FaceMeshURL, _profile.getUserString(), &_profile);
DataServerClient::getValueForKeyAndUserString(DataServerKey::SkeletonURL, _profile.getUserString(), &_profile);
}
// Set up VoxelSystem after loading preferences so we can get the desired max voxel count
_voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels());
_voxels.setUseVoxelShader(Menu::getInstance()->isOptionChecked(MenuOption::UseVoxelShader));

View file

@ -92,7 +92,8 @@ void DatagramProcessor::processDatagrams() {
application->_metavoxels.processData(incomingPacket, senderSockAddr);
break;
case PacketTypeBulkAvatarData:
case PacketTypeKillAvatar: {
case PacketTypeKillAvatar:
case PacketTypeAvatarIdentity: {
// update having heard from the avatar-mixer and record the bytes received
SharedNodePointer avatarMixer = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
@ -100,15 +101,9 @@ void DatagramProcessor::processDatagrams() {
avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
avatarMixer->recordBytesReceived(incomingPacket.size());
if (packetTypeForPacket(incomingPacket) == PacketTypeBulkAvatarData) {
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
Q_ARG(const QByteArray&, incomingPacket),
Q_ARG(const QWeakPointer<Node>&, avatarMixer));
} else {
// this is an avatar kill, pass it to the application AvatarManager
QMetaObject::invokeMethod(&application->getAvatarManager(), "processKillAvatar",
Q_ARG(const QByteArray&, incomingPacket));
}
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
Q_ARG(const QByteArray&, incomingPacket),
Q_ARG(const QWeakPointer<Node>&, avatarMixer));
}
application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size());

View file

@ -761,12 +761,12 @@ void Menu::editPreferences() {
QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1);
QString faceURLString = applicationInstance->getProfile()->getFaceModelURL().toString();
QString faceURLString = applicationInstance->getAvatar()->getHead().getFaceModel().getURL().toString();
QLineEdit* faceURLEdit = new QLineEdit(faceURLString);
faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Face URL:", faceURLEdit);
QString skeletonURLString = applicationInstance->getProfile()->getSkeletonModelURL().toString();
QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString();
QLineEdit* skeletonURLEdit = new QLineEdit(skeletonURLString);
skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Skeleton URL:", skeletonURLEdit);
@ -827,27 +827,25 @@ void Menu::editPreferences() {
int ret = dialog.exec();
if (ret == QDialog::Accepted) {
QUrl faceModelURL(faceURLEdit->text());
bool shouldDispatchIdentityPacket = false;
if (faceModelURL.toString() != faceURLString) {
// change the faceModelURL in the profile, it will also update this user's BlendFace
applicationInstance->getProfile()->setFaceModelURL(faceModelURL);
// send the new face mesh URL to the data-server (if we have a client UUID)
DataServerClient::putValueForKeyAndUserString(DataServerKey::FaceMeshURL,
faceModelURL.toString().toLocal8Bit().constData(),
applicationInstance->getProfile()->getUserString());
applicationInstance->getAvatar()->getHead().getFaceModel().setURL(faceModelURL);
shouldDispatchIdentityPacket = true;
}
QUrl skeletonModelURL(skeletonURLEdit->text());
if (skeletonModelURL.toString() != skeletonURLString) {
// change the skeletonModelURL in the profile, it will also update this user's Body
applicationInstance->getProfile()->setSkeletonModelURL(skeletonModelURL);
// send the new skeleton model URL to the data-server (if we have a client UUID)
DataServerClient::putValueForKeyAndUserString(DataServerKey::SkeletonURL,
skeletonModelURL.toString().toLocal8Bit().constData(),
applicationInstance->getProfile()->getUserString());
applicationInstance->getAvatar()->getSkeletonModel().setURL(skeletonModelURL);
shouldDispatchIdentityPacket = true;
}
if (shouldDispatchIdentityPacket) {
applicationInstance->getAvatar()->sendIdentityPacket();
}
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());

View file

@ -124,47 +124,32 @@ void AvatarManager::renderAvatarFades() {
}
}
void AvatarManager::processDataServerResponse(const QString& userString, const QStringList& keyList,
const QStringList &valueList) {
QUuid avatarKey = QUuid(userString);
if (avatarKey == MY_AVATAR_KEY) {
// ignore updates to our own mesh
return;
}
for (int i = 0; i < keyList.size(); i++) {
if (valueList[i] != " ") {
if (keyList[i] == DataServerKey::FaceMeshURL || keyList[i] == DataServerKey::SkeletonURL) {
// mesh URL for a UUID, find avatar in our list
AvatarSharedPointer matchingAvatar = _avatarHash.value(avatarKey);
if (matchingAvatar) {
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
if (keyList[i] == DataServerKey::FaceMeshURL) {
qDebug() << "Changing mesh to" << valueList[i] << "for avatar with UUID"
<< uuidStringWithoutCurlyBraces(avatarKey);
QMetaObject::invokeMethod(&(avatar->getHead().getFaceModel()),
"setURL", Q_ARG(QUrl, QUrl(valueList[i])));
} else if (keyList[i] == DataServerKey::SkeletonURL) {
qDebug() << "Changing skeleton to" << valueList[i] << "for avatar with UUID"
<< uuidStringWithoutCurlyBraces(avatarKey.toString());
QMetaObject::invokeMethod(&(avatar->getSkeletonModel()),
"setURL", Q_ARG(QUrl, QUrl(valueList[i])));
}
}
}
}
}
}
void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
switch (packetTypeForPacket(datagram)) {
case PacketTypeAvatarData:
processAvatarDataPacket(datagram, mixerWeakPointer);
break;
case PacketTypeAvatarIdentity:
processAvatarIdentityPacket(datagram);
break;
case PacketTypeKillAvatar:
processKillAvatar(datagram);
break;
default:
break;
}
}
void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
int bytesRead = numBytesForPacketHeader(datagram);
QByteArray dummyAvatarByteArray = byteArrayWithPopluatedHeader(PacketTypeAvatarData);
int numDummyHeaderBytes = dummyAvatarByteArray.size();
int numDummyHeaderBytesWithoutUUID = numDummyHeaderBytes - NUM_BYTES_RFC4122_UUID;
// enumerate over all of the avatars in this packet
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
@ -181,10 +166,6 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
matchingAvatar = AvatarSharedPointer(avatar);
_avatarHash.insert(nodeUUID, matchingAvatar);
// new UUID requires mesh and skeleton request to data-server
DataServerClient::getValuesForKeysAndUUID(QStringList() << DataServerKey::FaceMeshURL << DataServerKey::SkeletonURL,
nodeUUID, this);
qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash.";
}
@ -197,6 +178,42 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
// have the matching (or new) avatar parse the data from the packet
bytesRead += matchingAvatar->parseData(dummyAvatarByteArray) - numDummyHeaderBytesWithoutUUID;
}
}
void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) {
// setup a data stream to parse the packet
QDataStream identityStream(packet);
identityStream.skipRawData(numBytesForPacketHeader(packet));
QUuid nodeUUID;
while (!identityStream.atEnd()) {
identityStream >> nodeUUID;
// mesh URL for a UUID, find avatar in our list
AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID);
if (matchingAvatar) {
QUrl faceMeshURL, skeletonURL;
identityStream >> faceMeshURL >> skeletonURL;
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
if (avatar->getHead().getFaceModel().getURL() != faceMeshURL) {
qDebug() << "Changing mesh to" << faceMeshURL.toString() << "for avatar with UUID"
<< uuidStringWithoutCurlyBraces(nodeUUID);
avatar->getHead().getFaceModel().setURL(faceMeshURL);
}
if (avatar->getSkeletonModel().getURL() != skeletonURL) {
qDebug() << "Changing skeleton to" << skeletonURL << "for avatar with UUID"
<< uuidStringWithoutCurlyBraces(nodeUUID);
avatar->getSkeletonModel().setURL(skeletonURL);
}
}
}
}
void AvatarManager::processKillAvatar(const QByteArray& datagram) {

View file

@ -20,7 +20,7 @@
class MyAvatar;
class AvatarManager : public QObject, public DataServerCallbackObject, public AvatarHashMap {
class AvatarManager : public QObject, public AvatarHashMap {
Q_OBJECT
public:
AvatarManager(QObject* parent = 0);
@ -35,13 +35,14 @@ public:
void clearOtherAvatars();
public slots:
void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList);
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
void processKillAvatar(const QByteArray& datagram);
private:
AvatarManager(const AvatarManager& other);
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
void processAvatarIdentityPacket(const QByteArray& packet);
void processKillAvatar(const QByteArray& datagram);
void simulateAvatarFades(float deltaTime);
void renderAvatarFades();

View file

@ -641,6 +641,16 @@ void MyAvatar::sendKillAvatar() {
NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer);
}
void MyAvatar::sendIdentityPacket() {
QByteArray identityPacket = byteArrayWithPopluatedHeader(PacketTypeAvatarIdentity);
QDataStream identityStream(&identityPacket, QIODevice::Append);
identityStream << _head.getFaceModel().getURL();
identityStream << _skeletonModel.getURL();
NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer);
}
void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) {
// first orbit horizontally
glm::quat orientation = getOrientation();

View file

@ -94,6 +94,8 @@ public slots:
void increaseSize();
void decreaseSize();
void resetSize();
void sendIdentityPacket();
private:
bool _mousePressed;

View file

@ -20,17 +20,13 @@ Profile::Profile(const QString &username) :
_uuid(),
_lastDomain(),
_lastPosition(0.0, 0.0, 0.0),
_lastOrientationSend(0),
_faceModelURL(),
_skeletonModelURL()
_lastOrientationSend(0)
{
if (!username.isEmpty()) {
setUsername(username);
// we've been given a new username, ask the data-server for profile
DataServerClient::getValueForKeyAndUserString(DataServerKey::UUID, getUserString(), this);
DataServerClient::getValueForKeyAndUserString(DataServerKey::FaceMeshURL, getUserString(), this);
DataServerClient::getValueForKeyAndUserString(DataServerKey::SkeletonURL, getUserString(), this);
// send our current domain server to the data-server
updateDomain(NodeList::getInstance()->getDomainHostname());
@ -59,20 +55,6 @@ void Profile::setUUID(const QUuid& 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;
@ -137,8 +119,6 @@ void Profile::saveData(QSettings* settings) {
settings->setValue("username", _username);
settings->setValue("UUID", _uuid);
settings->setValue("faceModelURL", _faceModelURL);
settings->setValue("skeletonModelURL", _skeletonModelURL);
settings->endGroup();
}
@ -148,8 +128,6 @@ void Profile::loadData(QSettings* settings) {
setUsername(settings->value("username").toString());
this->setUUID(settings->value("UUID").toUuid());
_faceModelURL = settings->value("faceModelURL").toUrl();
_skeletonModelURL = settings->value("skeletonModelURL").toUrl();
settings->endGroup();
}
@ -157,17 +135,7 @@ void Profile::loadData(QSettings* settings) {
void Profile::processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList) {
for (int i = 0; i < keyList.size(); i++) {
if (valueList[i] != " ") {
if (keyList[i] == DataServerKey::FaceMeshURL) {
if (userString == _username || userString == uuidStringWithoutCurlyBraces(_uuid)) {
qDebug("Changing user's face model URL to %s", valueList[i].toLocal8Bit().constData());
Application::getInstance()->getProfile()->setFaceModelURL(QUrl(valueList[i]));
}
} else if (keyList[i] == DataServerKey::SkeletonURL) {
if (userString == _username || userString == uuidStringWithoutCurlyBraces(_uuid)) {
qDebug("Changing user's skeleton URL to %s", valueList[i].toLocal8Bit().constData());
Application::getInstance()->getProfile()->setSkeletonModelURL(QUrl(valueList[i]));
}
} else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position &&
if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position &&
keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " &&
valueList[i + 1] != " " && valueList[i + 2] != " ") {

View file

@ -31,12 +31,6 @@ public:
void setUUID(const QUuid& uuid);
const QUuid& getUUID() { return _uuid; }
void setFaceModelURL(const QUrl& faceModelURL);
const QUrl& getFaceModelURL() const { return _faceModelURL; }
void setSkeletonModelURL(const QUrl& skeletonModelURL);
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
void updateDomain(const QString& domain);
void updatePosition(const glm::vec3 position);
void updateOrientation(const glm::quat& orientation);
@ -58,8 +52,6 @@ private:
glm::vec3 _lastPosition;
glm::vec3 _lastOrientation;
quint64 _lastOrientationSend;
QUrl _faceModelURL;
QUrl _skeletonModelURL;
};
#endif /* defined(__hifi__Profile__) */

View file

@ -52,8 +52,6 @@ private:
namespace DataServerKey {
const QString Domain = "domain";
const QString FaceMeshURL = "mesh";
const QString SkeletonURL = "skeleton";
const QString Position = "position";
const QString Orientation = "orientation";
const QString UUID = "uuid";

View file

@ -51,7 +51,8 @@ enum PacketType {
PacketTypeParticleAddOrEdit,
PacketTypeParticleErase,
PacketTypeParticleAddResponse,
PacketTypeMetavoxelData
PacketTypeMetavoxelData,
PacketTypeAvatarIdentity
};
typedef char PacketVersion;