spread out billboard and identity fallbacks

This commit is contained in:
Stephen Birarda 2014-03-25 09:39:43 -07:00
parent 24b80fca81
commit e8b9594758
3 changed files with 22 additions and 116 deletions

View file

@ -46,6 +46,8 @@ void attachAvatarDataToNode(Node* newNode) {
}
}
const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f;
// NOTE: some additional optimizations to consider.
// 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present
// if the avatar is not in view or in the keyhole.
@ -99,6 +101,23 @@ void AvatarMixer::broadcastAvatarData() {
// copy the avatar into the mixedAvatarByteArray packet
mixedAvatarByteArray.append(avatarByteArray);
if (randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY) {
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
billboardPacket.append(otherNode->getUUID().toRfc4122());
billboardPacket.append(otherNodeData->getAvatar().getBillboard());
nodeList->writeDatagram(billboardPacket, node);
}
if (randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY) {
QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity);
QByteArray individualData = otherNodeData->getAvatar().identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122());
identityPacket.append(individualData);
nodeList->writeDatagram(identityPacket, node);
}
}
}
}
@ -108,66 +127,6 @@ void AvatarMixer::broadcastAvatarData() {
}
}
void broadcastIdentityPacket() {
NodeList* nodeList = NodeList::getInstance();
QByteArray avatarIdentityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity);
int numPacketHeaderBytes = avatarIdentityPacket.size();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
if (node->getLinkedData() && node->getType() == NodeType::Agent) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
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) {
// we've hit MTU, send out the current packet before appending
nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent);
avatarIdentityPacket.resize(numPacketHeaderBytes);
}
// append the individual data to the current the avatarIdentityPacket
avatarIdentityPacket.append(individualData);
// re-set the bool in AvatarMixerClientData so a change between key frames gets sent out
nodeData->setHasSentIdentityBetweenKeyFrames(false);
}
}
// send out the final packet
if (avatarIdentityPacket.size() > numPacketHeaderBytes) {
nodeList->broadcastToNodes(avatarIdentityPacket, NodeSet() << NodeType::Agent);
}
}
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(avatar.getBillboard());
NodeList* nodeList = NodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
if (node->getType() == NodeType::Agent && node != sendingNode) {
nodeList->writeDatagram(packet, node);
}
}
}
void broadcastBillboardPackets() {
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
if (node->getLinkedData() && node->getType() == NodeType::Agent) {
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(node->getLinkedData());
broadcastBillboardPacket(node);
nodeData->setHasSentBillboardBetweenKeyFrames(false);
}
}
}
void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
if (killedNode->getType() == NodeType::Agent
&& killedNode->getLinkedData()) {
@ -202,19 +161,7 @@ void AvatarMixer::readPendingDatagrams() {
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
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 = avatar.identityByteArray();
individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122());
identityPacket.append(individualByteArray);
nodeData->setHasSentIdentityBetweenKeyFrames(true);
nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent);
}
avatar.hasIdentityChangedAfterParsing(receivedPacket);
}
break;
}
@ -226,12 +173,7 @@ void AvatarMixer::readPendingDatagrams() {
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
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);
nodeData->setHasSentBillboardBetweenKeyFrames(true);
}
avatar.hasBillboardChangedAfterParsing(receivedPacket);
}
break;
}
@ -261,9 +203,6 @@ void AvatarMixer::sendStatsPacket() {
_numStatFrames = 0;
}
const qint64 AVATAR_IDENTITY_KEYFRAME_MSECS = 5000;
const qint64 AVATAR_BILLBOARD_KEYFRAME_MSECS = 5000;
void AvatarMixer::run() {
ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer);
@ -277,12 +216,6 @@ void AvatarMixer::run() {
gettimeofday(&startTime, NULL);
QElapsedTimer identityTimer;
identityTimer.start();
QElapsedTimer billboardTimer;
billboardTimer.start();
int usecToSleep = AVATAR_DATA_SEND_INTERVAL_USECS;
const int TRAILING_AVERAGE_FRAMES = 100;
@ -338,19 +271,6 @@ void AvatarMixer::run() {
broadcastAvatarData();
if (identityTimer.elapsed() >= AVATAR_IDENTITY_KEYFRAME_MSECS) {
// it's time to broadcast the keyframe identity packets
broadcastIdentityPacket();
// restart the timer so we do it again in AVATAR_IDENTITY_KEYFRAME_MSECS
identityTimer.restart();
}
if (billboardTimer.elapsed() >= AVATAR_BILLBOARD_KEYFRAME_MSECS) {
broadcastBillboardPackets();
billboardTimer.restart();
}
QCoreApplication::processEvents();
if (_isFinished) {

View file

@ -9,9 +9,7 @@
#include "AvatarMixerClientData.h"
AvatarMixerClientData::AvatarMixerClientData() :
NodeData(),
_hasSentIdentityBetweenKeyFrames(false),
_hasSentBillboardBetweenKeyFrames(false)
NodeData()
{
}

View file

@ -20,21 +20,9 @@ public:
AvatarMixerClientData();
int parseData(const QByteArray& packet);
bool hasSentIdentityBetweenKeyFrames() const { return _hasSentIdentityBetweenKeyFrames; }
void setHasSentIdentityBetweenKeyFrames(bool hasSentIdentityBetweenKeyFrames)
{ _hasSentIdentityBetweenKeyFrames = hasSentIdentityBetweenKeyFrames; }
bool hasSentBillboardBetweenKeyFrames() const { return _hasSentBillboardBetweenKeyFrames; }
void setHasSentBillboardBetweenKeyFrames(bool hasSentBillboardBetweenKeyFrames)
{ _hasSentBillboardBetweenKeyFrames = hasSentBillboardBetweenKeyFrames; }
AvatarData& getAvatar() { return _avatar; }
private:
bool _hasSentIdentityBetweenKeyFrames;
bool _hasSentBillboardBetweenKeyFrames;
AvatarData _avatar;
};