From a4aa8e7bde88ceb046c624a6af30f03d00e85148 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 5 Jun 2013 14:55:49 -0700 Subject: [PATCH] Basic sharing of the avatar voxel URLs. --- avatar-mixer/src/main.cpp | 11 ++++++ interface/src/Application.cpp | 54 ++++++++++++++++++++++++++-- interface/src/AvatarVoxelSystem.cpp | 9 +++-- interface/src/AvatarVoxelSystem.h | 7 ++-- libraries/shared/src/PacketHeaders.h | 1 + 5 files changed, 76 insertions(+), 6 deletions(-) diff --git a/avatar-mixer/src/main.cpp b/avatar-mixer/src/main.cpp index caa9f609ce..0398a597fc 100644 --- a/avatar-mixer/src/main.cpp +++ b/avatar-mixer/src/main.cpp @@ -105,6 +105,17 @@ int main(int argc, const char* argv[]) { agentList->getAgentSocket()->send(agentAddress, broadcastPacket, currentBufferPosition - broadcastPacket); + break; + case PACKET_HEADER_AVATAR_VOXEL_URL: + // grab the agent ID from the packet + unpackAgentId(packetData + 1, &agentID); + + // let everyone else know about the update + for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { + if (agent->getActiveSocket() && agent->getAgentID() != agentID) { + agentList->getAgentSocket()->send(agent->getActiveSocket(), packetData, receivedBytes); + } + } break; case PACKET_HEADER_DOMAIN: // ignore the DS packet, for now agents are added only when they communicate directly with us diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f5f2085995..d70a1840ba 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -983,6 +983,44 @@ void Application::terminate() { } } +static void sendAvatarVoxelURLMessage(const QUrl& url) { + uint16_t ownerID = AgentList::getInstance()->getOwnerID(); + if (ownerID == UNKNOWN_AGENT_ID) { + return; // we don't yet know who we are + } + QByteArray message; + message.append(PACKET_HEADER_AVATAR_VOXEL_URL); + message.append((const char*)&ownerID, sizeof(ownerID)); + message.append(url.toEncoded()); + + AgentList::getInstance()->broadcastToAgents((unsigned char*)message.data(), message.size(), &AGENT_TYPE_AVATAR_MIXER, 1); +} + +static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes) { + // skip the header + packetData++; + dataBytes--; + + // read the agent id + uint16_t agentID = *(uint16_t*)packetData; + packetData += sizeof(agentID); + dataBytes -= sizeof(agentID); + + // make sure the agent exists + Agent* agent = AgentList::getInstance()->agentWithID(agentID); + if (!agent || !agent->getLinkedData()) { + return; + } + Avatar* avatar = static_cast(agent->getLinkedData()); + if (!avatar->isInitialized()) { + return; // wait until initialized + } + QUrl url = QUrl::fromEncoded(QByteArray::fromRawData((char*)packetData, dataBytes)); + + // invoke the set URL function on the simulate/render thread + QMetaObject::invokeMethod(avatar->getVoxels(), "setVoxelURL", Q_ARG(QUrl, url)); +} + void Application::editPreferences() { QDialog dialog(_glWidget); dialog.setWindowTitle("Interface Preferences"); @@ -1006,7 +1044,8 @@ void Application::editPreferences() { } QUrl url(avatarURL->text()); _settings->setValue("avatarURL", url); - _myAvatar.getVoxels()->loadVoxelsFromURL(url); + _myAvatar.getVoxels()->setVoxelURL(url); + sendAvatarVoxelURLMessage(url); } void Application::pair() { @@ -1507,7 +1546,9 @@ void Application::init() { _myCamera.setModeShiftRate(1.0f); _myAvatar.setDisplayingLookatVectors(false); - _myAvatar.getVoxels()->loadVoxelsFromURL(_settings->value("avatarURL").toUrl()); + QUrl avatarURL = _settings->value("avatarURL").toUrl(); + _myAvatar.getVoxels()->setVoxelURL(avatarURL); + sendAvatarVoxelURLMessage(avatarURL); QCursor::setPos(_headMouseX, _headMouseY); @@ -1599,6 +1640,12 @@ void Application::updateAvatar(float deltaTime) { const char broadcastReceivers[2] = {AGENT_TYPE_VOXEL, AGENT_TYPE_AVATAR_MIXER}; AgentList::getInstance()->broadcastToAgents(broadcastString, endOfBroadcastStringWrite - broadcastString, broadcastReceivers, sizeof(broadcastReceivers)); + + // once in a while, send my voxel url + const float AVATAR_VOXEL_URL_SEND_INTERVAL = 1.0f; // seconds + if (shouldDo(AVATAR_VOXEL_URL_SEND_INTERVAL, deltaTime)) { + sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL()); + } } // If I'm in paint mode, send a voxel out to VOXEL server agents. @@ -2435,6 +2482,9 @@ void* Application::networkReceive(void* args) { app->_incomingPacket, bytesReceived); break; + case PACKET_HEADER_AVATAR_VOXEL_URL: + processAvatarVoxelURLMessage(app->_incomingPacket, bytesReceived); + break; default: AgentList::getInstance()->processAgentData(&senderAddress, app->_incomingPacket, bytesReceived); break; diff --git a/interface/src/AvatarVoxelSystem.cpp b/interface/src/AvatarVoxelSystem.cpp index c50cb5b8a7..ef2066d69e 100644 --- a/interface/src/AvatarVoxelSystem.cpp +++ b/interface/src/AvatarVoxelSystem.cpp @@ -8,7 +8,6 @@ #include #include -#include #include @@ -24,6 +23,9 @@ const int BONE_ELEMENTS_PER_VOXEL = BONE_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXE AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) : VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR), _avatar(avatar), _voxelReply(0) { + + // we may have been created in the network thread, but we live in the main thread + moveToThread(Application::getInstance()->thread()); } AvatarVoxelSystem::~AvatarVoxelSystem() { @@ -75,7 +77,7 @@ void AvatarVoxelSystem::removeOutOfView() { // no-op for now } -void AvatarVoxelSystem::loadVoxelsFromURL(const QUrl& url) { +void AvatarVoxelSystem::setVoxelURL(const QUrl& url) { // cancel any current download if (_voxelReply != 0) { delete _voxelReply; @@ -84,6 +86,9 @@ void AvatarVoxelSystem::loadVoxelsFromURL(const QUrl& url) { killLocalVoxels(); + // remember the URL + _voxelURL = url; + // handle "file://" urls... if (url.isLocalFile()) { QString pathString = url.path(); diff --git a/interface/src/AvatarVoxelSystem.h b/interface/src/AvatarVoxelSystem.h index 3894fd75b9..cf297c25f4 100644 --- a/interface/src/AvatarVoxelSystem.h +++ b/interface/src/AvatarVoxelSystem.h @@ -10,6 +10,7 @@ #define __interface__AvatarVoxelSystem__ #include +#include #include "VoxelSystem.h" @@ -17,7 +18,6 @@ const int BONE_ELEMENTS_PER_VERTEX = 4; typedef GLubyte BoneIndices[BONE_ELEMENTS_PER_VERTEX]; class QNetworkReply; -class QUrl; class Avatar; @@ -33,7 +33,8 @@ public: virtual void removeOutOfView(); - void loadVoxelsFromURL(const QUrl& url); + Q_INVOKABLE void setVoxelURL(const QUrl& url); + const QUrl& getVoxelURL() const { return _voxelURL; } protected: @@ -55,6 +56,8 @@ private: Avatar* _avatar; + QUrl _voxelURL; + GLubyte* _readBoneIndicesArray; GLfloat* _readBoneWeightsArray; GLubyte* _writeBoneIndicesArray; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index ea9f5f9fcf..3e6f2ba152 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -27,6 +27,7 @@ const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E'; const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V'; const PACKET_HEADER PACKET_HEADER_VOXEL_DATA_MONOCHROME = 'v'; const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X'; +const PACKET_HEADER PACKET_HEADER_AVATAR_VOXEL_URL = 'U'; const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA_V2 = 'T'; const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e'; const PACKET_HEADER PACKET_HEADER_DOMAIN_LIST_REQUEST = 'L';