diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cf865ce299..33cee4299c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -116,6 +116,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _voxelImporter(_window), _wantToKillLocalVoxels(false), _audioScope(256, 200, true), + _avatarManager(), _profile(QString()), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _mouseX(0), diff --git a/interface/src/Application.h b/interface/src/Application.h index 514591e1df..373020c571 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -50,6 +50,7 @@ #include "VoxelSystem.h" #include "VoxelImporter.h" #include "avatar/Avatar.h" +#include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" #include "avatar/Profile.h" #include "devices/Faceshift.h" @@ -167,7 +168,7 @@ public: GlowEffect* getGlowEffect() { return &_glowEffect; } Avatar* getLookatTargetAvatar() const { return _lookatTargetAvatar; } - + AvatarManager& getAvatarManager() { return _avatarManager; } Profile* getProfile() { return &_profile; } void resetProfile(const QString& username); @@ -227,15 +228,13 @@ public slots: void initAvatarAndViewFrustum(); private slots: - void timer(); void idle(); void terminate(); void setFullscreen(bool fullscreen); void setEnable3DTVMode(bool enable3DTVMode); - - + void renderThrustAtVoxel(const glm::vec3& thrust); void renderCoverageMap(); @@ -372,6 +371,7 @@ private: VoxelQuery _voxelQuery; // NodeData derived class for querying voxels from voxel server + AvatarManager _avatarManager; MyAvatar _myAvatar; // The rendered avatar of oneself Profile _profile; // The data-server linked profile for this user diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 9a6c1bea05..13d43c2f81 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -89,12 +89,23 @@ void DatagramProcessor::processDatagrams() { application->_metavoxels.processData(QByteArray((const char*) incomingPacket, bytesReceived), senderSockAddr); break; - case PACKET_TYPE_BULK_AVATAR_DATA: - NodeList::getInstance()->processBulkNodeData(senderSockAddr, - incomingPacket, - bytesReceived); + case PACKET_TYPE_BULK_AVATAR_DATA: { + // update having heard from the avatar-mixer and record the bytes received + SharedNodePointer avatarMixer = NodeList::getInstance()->nodeWithAddress(senderSockAddr); + + if (avatarMixer) { + avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); + avatarMixer->recordBytesReceived(bytesReceived); + + + QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", + Q_ARG(const QByteArray&, + QByteArray(reinterpret_cast(incomingPacket), bytesReceived))); + } + application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(bytesReceived); break; + } case PACKET_TYPE_DATA_SERVER_GET: case PACKET_TYPE_DATA_SERVER_PUT: case PACKET_TYPE_DATA_SERVER_SEND: diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 725aa9d5cf..ec575be462 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -111,7 +111,7 @@ public: /// \return whether or not the sphere collided virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision); - virtual int parseData(unsigned char* sourceBuffer, int numBytes); + int parseData(unsigned char* sourceBuffer, int numBytes); static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp new file mode 100644 index 0000000000..f9a3422fb5 --- /dev/null +++ b/interface/src/avatar/AvatarManager.cpp @@ -0,0 +1,54 @@ +// +// AvatarManager.cpp +// hifi +// +// Created by Stephen Birarda on 1/23/2014. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include + +#include "Avatar.h" + +#include "AvatarManager.h" + +AvatarManager::AvatarManager(QObject* parent) : + _hash() +{ + +} + +void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram) { + unsigned char packetData[MAX_PACKET_SIZE]; + memcpy(packetData, datagram.data(), datagram.size()); + + int numBytesPacketHeader = numBytesForPacketHeader(packetData); + + QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(numBytesPacketHeader, NUM_BYTES_RFC4122_UUID)); + + int bytesRead = numBytesPacketHeader; + + unsigned char avatarData[MAX_PACKET_SIZE]; + populateTypeAndVersion(avatarData, PACKET_TYPE_HEAD_DATA); + + while (bytesRead < datagram.size()) { + Avatar* matchingAvatar = _hash.value(nodeUUID); + + if (!matchingAvatar) { + // construct a new Avatar for this node + matchingAvatar = new Avatar(); + + // insert the new avatar into our hash + _hash.insert(nodeUUID, matchingAvatar); + + qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash."; + } + + // copy the rest of the packet to the avatarData holder so we can read the next Avatar from there + memcpy(avatarData, packetData + bytesRead, datagram.size() - bytesRead); + + // have the matching (or new) avatar parse the data from the packet + bytesRead += matchingAvatar->parseData(avatarData, + datagram.size() - bytesRead); + } +} \ No newline at end of file diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h new file mode 100644 index 0000000000..5ea7607660 --- /dev/null +++ b/interface/src/avatar/AvatarManager.h @@ -0,0 +1,27 @@ +// +// AvatarManager.h +// hifi +// +// Created by Stephen Birarda on 1/23/2014. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AvatarManager__ +#define __hifi__AvatarManager__ + +#include +#include + +#include "Avatar.h" + +class AvatarManager : public QObject { + Q_OBJECT +public: + AvatarManager(QObject* parent = 0); +public slots: + void processAvatarMixerDatagram(const QByteArray& datagram); +private: + QHash _hash; +}; + +#endif /* defined(__hifi__AvatarManager__) */ diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 65993cb275..e821f105bd 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -187,49 +187,6 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, unsigned char } } -void NodeList::processBulkNodeData(const HifiSockAddr& senderAddress, unsigned char *packetData, int numTotalBytes) { - SharedNodePointer bulkSendNode = nodeWithAddress(senderAddress); - - // find the avatar mixer in our node list and update the lastRecvTime from it - if (bulkSendNode) { - - bulkSendNode->setLastHeardMicrostamp(usecTimestampNow()); - bulkSendNode->recordBytesReceived(numTotalBytes); - - int numBytesPacketHeader = numBytesForPacketHeader(packetData); - - unsigned char* startPosition = packetData; - unsigned char* currentPosition = startPosition + numBytesPacketHeader; - unsigned char* packetHolder = new unsigned char[numTotalBytes]; - - // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date - populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA); - - while ((currentPosition - startPosition) < numTotalBytes) { - - memcpy(packetHolder + numBytesPacketHeader, - currentPosition, - numTotalBytes - (currentPosition - startPosition)); - - QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)currentPosition, NUM_BYTES_RFC4122_UUID)); - SharedNodePointer matchingNode = nodeWithUUID(nodeUUID); - - if (!matchingNode) { - // we're missing this node, we need to add it to the list - matchingNode = addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, HifiSockAddr(), HifiSockAddr()); - } - - currentPosition += updateNodeWithData(matchingNode.data(), - HifiSockAddr(), - packetHolder, - numTotalBytes - (currentPosition - startPosition)); - - } - - delete[] packetHolder; - } -} - int NodeList::updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, unsigned char *packetData, int dataBytes) { QMutexLocker locker(&node->getMutex()); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 9ac6c5970c..96ee78a9b0 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -111,7 +111,6 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); void processNodeData(const HifiSockAddr& senderSockAddr, unsigned char *packetData, size_t dataBytes); - void processBulkNodeData(const HifiSockAddr& senderSockAddr, unsigned char *packetData, int numTotalBytes); int updateNodeWithData(Node *node, const HifiSockAddr& senderSockAddr, unsigned char *packetData, int dataBytes);