mirror of
https://github.com/overte-org/overte.git
synced 2025-08-16 11:12:25 +02:00
initial movement of mesh/skeleton URLs out of data-server through avatar-mixer
This commit is contained in:
parent
f1b612d8d8
commit
8bf3b7586b
11 changed files with 98 additions and 117 deletions
|
@ -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));
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -94,6 +94,8 @@ public slots:
|
|||
void increaseSize();
|
||||
void decreaseSize();
|
||||
void resetSize();
|
||||
|
||||
void sendIdentityPacket();
|
||||
|
||||
private:
|
||||
bool _mousePressed;
|
||||
|
|
|
@ -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] != " ") {
|
||||
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -51,7 +51,8 @@ enum PacketType {
|
|||
PacketTypeParticleAddOrEdit,
|
||||
PacketTypeParticleErase,
|
||||
PacketTypeParticleAddResponse,
|
||||
PacketTypeMetavoxelData
|
||||
PacketTypeMetavoxelData,
|
||||
PacketTypeAvatarIdentity
|
||||
};
|
||||
|
||||
typedef char PacketVersion;
|
||||
|
|
Loading…
Reference in a new issue