Working on sending the billboards over the network.

This commit is contained in:
Andrzej Kapolka 2014-02-21 11:49:29 -08:00
parent 495447fc0d
commit 10ce2cb3f0
8 changed files with 100 additions and 6 deletions

View file

@ -123,6 +123,23 @@ void broadcastIdentityPacket() {
}
}
void broadcastBillboardPacket(const SharedNodePointer& node) {
}
void broadcastBillboardPackets() {
NodeList* nodeList = NodeList::getInstance();
foreach (const SharedNodePointer& node, nodeList->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()) {
@ -170,6 +187,23 @@ void AvatarMixer::readPendingDatagrams() {
nodeList->broadcastToNodes(identityPacket, NodeSet() << NodeType::Agent);
}
}
break;
}
case PacketTypeAvatarBillboard: {
// check if we have a matching node in our list
SharedNodePointer avatarNode = nodeList->sendingNodeForPacket(receivedPacket);
if (avatarNode && avatarNode->getLinkedData()) {
AvatarMixerClientData* nodeData = static_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
if (nodeData->hasBillboardChangedAfterParsing(receivedPacket)
&& !nodeData->hasSentBillboardBetweenKeyFrames()) {
// this avatar changed their billboard and we haven't sent a packet in this keyframe
broadcastBillboardPacket(avatarNode);
nodeData->setHasSentBillboardBetweenKeyFrames(true);
}
}
break;
}
case PacketTypeKillAvatar: {
nodeList->processKillNode(receivedPacket);
@ -185,6 +219,7 @@ void AvatarMixer::readPendingDatagrams() {
}
const qint64 AVATAR_IDENTITY_KEYFRAME_MSECS = 5000;
const qint64 AVATAR_BILLBOARD_KEYFRAME_MSECS = 5000;
void AvatarMixer::run() {
commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer);
@ -202,6 +237,9 @@ void AvatarMixer::run() {
QElapsedTimer identityTimer;
identityTimer.start();
QElapsedTimer billboardTimer;
billboardTimer.start();
while (!_isFinished) {
QCoreApplication::processEvents();
@ -219,6 +257,11 @@ void AvatarMixer::run() {
// 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();
}
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * AVATAR_DATA_SEND_INTERVAL_USECS) - usecTimestampNow();

View file

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

View file

@ -21,9 +21,15 @@ public:
bool hasSentIdentityBetweenKeyFrames() const { return _hasSentIdentityBetweenKeyFrames; }
void setHasSentIdentityBetweenKeyFrames(bool hasSentIdentityBetweenKeyFrames)
{ _hasSentIdentityBetweenKeyFrames = hasSentIdentityBetweenKeyFrames; }
bool hasSentBillboardBetweenKeyFrames() const { return _hasSentBillboardBetweenKeyFrames; }
void setHasSentBillboardBetweenKeyFrames(bool hasSentBillboardBetweenKeyFrames)
{ _hasSentBillboardBetweenKeyFrames = hasSentBillboardBetweenKeyFrames; }
private:
bool _hasSentIdentityBetweenKeyFrames;
bool _hasSentBillboardBetweenKeyFrames;
};
#endif /* defined(__hifi__AvatarMixerClientData__) */

View file

@ -255,6 +255,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket);
identityPacketTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
// send the billboard packet for our avatar every few seconds
QTimer* billboardPacketTimer = new QTimer();
connect(billboardPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendBillboardPacket);
billboardPacketTimer->start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS);
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
_networkAccessManager = new QNetworkAccessManager(this);

View file

@ -9,6 +9,8 @@
#include <algorithm>
#include <vector>
#include <QBuffer>
#include <glm/gtx/vector_angle.hpp>
#include <NodeList.h>
@ -335,11 +337,7 @@ void MyAvatar::simulate(float deltaTime) {
_thrust = glm::vec3(0, 0, 0);
// consider updating our billboard
if (!_billboardValid && _skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures()) {
QImage image = Application::getInstance()->renderAvatarBillboard();
image.save("test.png");
_billboardValid = true;
}
maybeUpdateBillboard();
}
const float MAX_PITCH = 90.0f;
@ -1141,6 +1139,20 @@ void MyAvatar::updateChatCircle(float deltaTime) {
_position = glm::mix(_position, targetPosition, APPROACH_RATE);
}
void MyAvatar::maybeUpdateBillboard() {
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
return;
}
QImage image = Application::getInstance()->renderAvatarBillboard();
_billboard.clear();
QBuffer buffer(&_billboard);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "JPG");
_billboardValid = true;
sendBillboardPacket();
}
void MyAvatar::setGravity(glm::vec3 gravity) {
_gravity = gravity;
getHead()->setGravity(_gravity);

View file

@ -133,6 +133,7 @@ private:
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
void updateChatCircle(float deltaTime);
void maybeUpdateBillboard();
};
#endif

View file

@ -305,6 +305,15 @@ QByteArray AvatarData::identityByteArray() {
return identityData;
}
bool AvatarData::hasBillboardChangedAfterParsing(const QByteArray& packet) {
QByteArray newBillboard = packet.mid(numBytesForPacketHeader(packet));
if (newBillboard == _billboard) {
return false;
}
_billboard = newBillboard;
return true;
}
void AvatarData::setFaceModelURL(const QUrl& faceModelURL) {
_faceModelURL = faceModelURL.isEmpty() ? DEFAULT_HEAD_MODEL_URL : faceModelURL;
@ -344,3 +353,10 @@ void AvatarData::sendIdentityPacket() {
NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer);
}
void AvatarData::sendBillboardPacket() {
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
billboardPacket.append(_billboard);
NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer);
}

View file

@ -29,6 +29,7 @@ typedef unsigned long long quint64;
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QByteArray>
#include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtCore/QUuid>
@ -54,6 +55,7 @@ static const float MIN_AVATAR_SCALE = .005f;
const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000;
const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_head.fst");
const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_body.fst");
@ -151,6 +153,8 @@ public:
bool hasIdentityChangedAfterParsing(const QByteArray& packet);
QByteArray identityByteArray();
bool hasBillboardChangedAfterParsing(const QByteArray& packet);
const QUrl& getFaceModelURL() const { return _faceModelURL; }
QString getFaceModelURLString() const { return _faceModelURL.toString(); }
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
@ -159,6 +163,9 @@ public:
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
virtual void setDisplayName(const QString& displayName);
void setBillboard(const QByteArray& billboard) { _billboard = billboard; }
const QByteArray& getBillboard() const { return _billboard; }
QString getFaceModelURLFromScript() const { return _faceModelURL.toString(); }
void setFaceModelURLFromScript(const QString& faceModelString) { setFaceModelURL(faceModelString); }
@ -169,6 +176,7 @@ public:
public slots:
void sendIdentityPacket();
void sendBillboardPacket();
protected:
glm::vec3 _position;
@ -204,6 +212,8 @@ protected:
float _displayNameTargetAlpha;
float _displayNameAlpha;
QByteArray _billboard;
private:
// privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&);