add an AvatarManager that will keep Avatars in Application thread

This commit is contained in:
Stephen Birarda 2014-01-23 11:59:24 -08:00
parent 9a8e978733
commit a9f1984676
8 changed files with 102 additions and 53 deletions

View file

@ -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),

View file

@ -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

View file

@ -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<char*>(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:

View file

@ -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);

View file

@ -0,0 +1,54 @@
//
// AvatarManager.cpp
// hifi
//
// Created by Stephen Birarda on 1/23/2014.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include <UUID.h>
#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);
}
}

View file

@ -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 <QtCore/QHash>
#include <QtCore/QObject>
#include "Avatar.h"
class AvatarManager : public QObject {
Q_OBJECT
public:
AvatarManager(QObject* parent = 0);
public slots:
void processAvatarMixerDatagram(const QByteArray& datagram);
private:
QHash<QUuid, Avatar*> _hash;
};
#endif /* defined(__hifi__AvatarManager__) */

View file

@ -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());

View file

@ -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);