cleanup: AvatarData doesn't derive from NodeData

Cleaner Interface since the AvatarData is already not the NodeList.
Reduces overhead/confusing code when parsing packets from AvatarMixer.
This commit is contained in:
Andrew Meadows 2014-03-17 14:10:42 -07:00
parent c329cebf92
commit ed3cf36045
8 changed files with 44 additions and 34 deletions

View file

@ -62,7 +62,8 @@ void broadcastAvatarData() {
mixedAvatarByteArray.resize(numPacketHeaderBytes);
AvatarMixerClientData* myData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
glm::vec3 myPosition = myData->getPosition();
AvatarData& avatar = myData->getAvatar();
glm::vec3 myPosition = avatar.getPosition();
// this is an AGENT we have received head data from
// send back a packet with other active node data to this node
@ -70,7 +71,8 @@ void broadcastAvatarData() {
if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID()) {
AvatarMixerClientData* otherNodeData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
glm::vec3 otherPosition = otherNodeData->getPosition();
AvatarData& otherAvatar = otherNodeData->getAvatar();
glm::vec3 otherPosition = otherAvatar.getPosition();
float distanceToAvatar = glm::length(myPosition - otherPosition);
// The full rate distance is the distance at which EVERY update will be sent for this avatar
// at a distance of twice the full rate distance, there will be a 50% chance of sending this avatar's update
@ -79,7 +81,7 @@ void broadcastAvatarData() {
if ((distanceToAvatar == 0.f) || (randFloat() < FULL_RATE_DISTANCE / distanceToAvatar)) {
QByteArray avatarByteArray;
avatarByteArray.append(otherNode->getUUID().toRfc4122());
avatarByteArray.append(otherNodeData->toByteArray());
avatarByteArray.append(otherAvatar.toByteArray());
if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) {
nodeList->writeDatagram(mixedAvatarByteArray, node);
@ -110,7 +112,8 @@ void broadcastIdentityPacket() {
if (node->getLinkedData() && node->getType() == NodeType::Agent) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
QByteArray individualData = nodeData->identityByteArray();
AvatarData& avatar = nodeData->getAvatar();
QByteArray individualData = avatar.identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, node->getUUID().toRfc4122());
if (avatarIdentityPacket.size() + individualData.size() > MAX_PACKET_SIZE) {
@ -135,9 +138,10 @@ void broadcastIdentityPacket() {
void broadcastBillboardPacket(const SharedNodePointer& sendingNode) {
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(sendingNode->getLinkedData());
AvatarData& avatar = nodeData->getAvatar();
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
packet.append(sendingNode->getUUID().toRfc4122());
packet.append(nodeData->getBillboard());
packet.append(avatar.getBillboard());
NodeList* nodeList = NodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
@ -190,12 +194,13 @@ void AvatarMixer::readPendingDatagrams() {
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
if (nodeData->hasIdentityChangedAfterParsing(receivedPacket)
AvatarData& avatar = nodeData->getAvatar();
if (avatar.hasIdentityChangedAfterParsing(receivedPacket)
&& !nodeData->hasSentIdentityBetweenKeyFrames()) {
// this avatar changed their identity in some way and we haven't sent a packet in this keyframe
QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity);
QByteArray individualByteArray = nodeData->identityByteArray();
QByteArray individualByteArray = avatar.identityByteArray();
individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122());
identityPacket.append(individualByteArray);
@ -213,7 +218,8 @@ void AvatarMixer::readPendingDatagrams() {
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
if (nodeData->hasBillboardChangedAfterParsing(receivedPacket)
AvatarData& avatar = nodeData->getAvatar();
if (avatar.hasBillboardChangedAfterParsing(receivedPacket)
&& !nodeData->hasSentBillboardBetweenKeyFrames()) {
// this avatar changed their billboard and we haven't sent a packet in this keyframe
broadcastBillboardPacket(avatarNode);

View file

@ -9,8 +9,15 @@
#include "AvatarMixerClientData.h"
AvatarMixerClientData::AvatarMixerClientData() :
NodeData(),
_hasSentIdentityBetweenKeyFrames(false),
_hasSentBillboardBetweenKeyFrames(false)
{
}
int AvatarMixerClientData::parseData(const QByteArray& packet) {
// increment to push past the packet header
int offset = numBytesForPacketHeader(packet);
return _avatar.parseDataAtOffset(packet, offset);
}

View file

@ -12,11 +12,14 @@
#include <QtCore/QUrl>
#include <AvatarData.h>
#include <NodeData.h>
class AvatarMixerClientData : public AvatarData {
class AvatarMixerClientData : public NodeData {
Q_OBJECT
public:
AvatarMixerClientData();
int parseData(const QByteArray& packet);
bool hasSentIdentityBetweenKeyFrames() const { return _hasSentIdentityBetweenKeyFrames; }
void setHasSentIdentityBetweenKeyFrames(bool hasSentIdentityBetweenKeyFrames)
@ -25,11 +28,14 @@ public:
bool hasSentBillboardBetweenKeyFrames() const { return _hasSentBillboardBetweenKeyFrames; }
void setHasSentBillboardBetweenKeyFrames(bool hasSentBillboardBetweenKeyFrames)
{ _hasSentBillboardBetweenKeyFrames = hasSentBillboardBetweenKeyFrames; }
AvatarData& getAvatar() { return _avatar; }
private:
bool _hasSentIdentityBetweenKeyFrames;
bool _hasSentBillboardBetweenKeyFrames;
AvatarData _avatar;
};
#endif /* defined(__hifi__AvatarMixerClientData__) */

View file

@ -633,11 +633,11 @@ void Avatar::setBillboard(const QByteArray& billboard) {
_billboardTexture.reset();
}
int Avatar::parseData(const QByteArray& packet) {
int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) {
// change in position implies movement
glm::vec3 oldPosition = _position;
int bytesRead = AvatarData::parseData(packet);
int bytesRead = AvatarData::parseDataAtOffset(packet, offset);
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
_moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD;

View file

@ -133,7 +133,7 @@ public:
void setShowDisplayName(bool showDisplayName);
int parseData(const QByteArray& packet);
int parseDataAtOffset(const QByteArray& packet, int offset);
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);

View file

@ -148,10 +148,6 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const
void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
int bytesRead = numBytesForPacketHeader(datagram);
QByteArray dummyAvatarByteArray = byteArrayWithPopulatedHeader(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()) {
@ -171,16 +167,10 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW
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
dummyAvatarByteArray.resize(numDummyHeaderBytesWithoutUUID);
// make this Avatar's UUID the UUID in the packet and tack the remaining data onto the end
dummyAvatarByteArray.append(datagram.mid(bytesRead));
// have the matching (or new) avatar parse the data from the packet
bytesRead += matchingAvatar->parseData(dummyAvatarByteArray) - numDummyHeaderBytesWithoutUUID;
bytesRead += matchingAvatar->parseDataAtOffset(datagram, bytesRead);
}
}
void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) {

View file

@ -29,7 +29,6 @@ using namespace std;
QNetworkAccessManager* AvatarData::networkAccessManager = NULL;
AvatarData::AvatarData() :
NodeData(),
_handPosition(0,0,0),
_bodyYaw(-90.f),
_bodyPitch(0.0f),
@ -184,8 +183,8 @@ QByteArray AvatarData::toByteArray() {
return avatarDataByteArray.left(destinationBuffer - startPosition);
}
// called on the other nodes - assigns it to my views of the others
int AvatarData::parseData(const QByteArray& packet) {
// read data in packet starting at byte offset and return number of bytes parsed
int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
// lazily allocate memory for HeadData in case we're not an Avatar instance
if (!_headData) {
@ -197,9 +196,8 @@ int AvatarData::parseData(const QByteArray& packet) {
_handData = new HandData(this);
}
// increment to push past the packet header
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(packet.data());
const unsigned char* sourceBuffer = startPosition + numBytesForPacketHeader(packet);
const unsigned char* sourceBuffer = startPosition + offset;
// Body world position
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
@ -288,13 +286,13 @@ int AvatarData::parseData(const QByteArray& packet) {
// joint data
int jointCount = *sourceBuffer++;
_jointData.resize(jointCount);
unsigned char validity = 0; // although always set below, this fixes a warning of potential uninitialized use
unsigned char validity = 0;
int validityBit = 0;
for (int i = 0; i < jointCount; i++) {
if (validityBit == 0) {
validity = *sourceBuffer++;
}
_jointData[i].valid = validity & (1 << validityBit);
_jointData[i].valid = (bool)(validity & (1 << validityBit));
validityBit = (validityBit + 1) % BITS_IN_BYTE;
}
for (int i = 0; i < jointCount; i++) {

View file

@ -40,7 +40,6 @@ typedef unsigned long long quint64;
#include <CollisionInfo.h>
#include <RegisteredMetaTypes.h>
#include <NodeData.h>
#include "HeadData.h"
#include "HandData.h"
@ -74,7 +73,7 @@ class QNetworkAccessManager;
class JointData;
class AvatarData : public NodeData {
class AvatarData : public QObject {
Q_OBJECT
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
@ -97,7 +96,7 @@ class AvatarData : public NodeData {
Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL)
public:
AvatarData();
~AvatarData();
virtual ~AvatarData();
const glm::vec3& getPosition() const { return _position; }
void setPosition(const glm::vec3 position) { _position = position; }
@ -106,7 +105,11 @@ public:
void setHandPosition(const glm::vec3& handPosition);
QByteArray toByteArray();
int parseData(const QByteArray& packet);
/// \param packet byte array of data
/// \param offset number of bytes into packet where data starts
/// \return number of bytes parsed
virtual int parseDataAtOffset(const QByteArray& packet, int offset);
// Body Rotation (degrees)
float getBodyYaw() const { return _bodyYaw; }