mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 16:10:40 +02:00
add compression and minimal data flags to AvatarData
This commit is contained in:
parent
7189f766a2
commit
2290179281
4 changed files with 250 additions and 188 deletions
|
@ -227,7 +227,7 @@ void MyAvatar::simulateAttachments(float deltaTime) {
|
|||
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation()
|
||||
}
|
||||
|
||||
QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||
QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll, bool sendMinimum, bool compressed) {
|
||||
CameraMode mode = qApp->getCamera()->getMode();
|
||||
_globalPosition = getPosition();
|
||||
_globalBoundingBoxCorner.x = _characterController.getCapsuleRadius();
|
||||
|
@ -238,12 +238,12 @@ QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
// fake the avatar position that is sent up to the AvatarMixer
|
||||
glm::vec3 oldPosition = getPosition();
|
||||
setPosition(getSkeletonPosition());
|
||||
QByteArray array = AvatarData::toByteArray(cullSmallChanges, sendAll);
|
||||
QByteArray array = AvatarData::toByteArray(cullSmallChanges, sendAll, sendMinimum, compressed);
|
||||
// copy the correct position back
|
||||
setPosition(oldPosition);
|
||||
return array;
|
||||
}
|
||||
return AvatarData::toByteArray(cullSmallChanges, sendAll);
|
||||
return AvatarData::toByteArray(cullSmallChanges, sendAll, sendMinimum, compressed);
|
||||
}
|
||||
|
||||
void MyAvatar::centerBody() {
|
||||
|
|
|
@ -333,7 +333,7 @@ private:
|
|||
|
||||
glm::vec3 getWorldBodyPosition() const;
|
||||
glm::quat getWorldBodyOrientation() const;
|
||||
QByteArray toByteArray(bool cullSmallChanges, bool sendAll) override;
|
||||
QByteArray toByteArray(bool cullSmallChanges, bool sendAll, bool sendMinimum, bool compressed) override;
|
||||
void simulate(float deltaTime);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
|
||||
|
|
|
@ -181,7 +181,7 @@ void AvatarData::setHandPosition(const glm::vec3& handPosition) {
|
|||
_handPosition = glm::inverse(getOrientation()) * (handPosition - getPosition());
|
||||
}
|
||||
|
||||
QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||
QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll, bool sendMinimum, bool compressed) {
|
||||
// TODO: DRY this up to a shared method
|
||||
// that can pack any type given the number of bytes
|
||||
// and return the number of bytes to push the pointer
|
||||
|
@ -199,6 +199,20 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(avatarDataByteArray.data());
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
|
||||
// Leading flags, to indicate how much data is actually included in the packet...
|
||||
UINT8 packetStateFlags = 0;
|
||||
if (sendMinimum) {
|
||||
setAtBit(packetStateFlags, AVATARDATA_FLAGS_MINIMUM);
|
||||
}
|
||||
|
||||
// do we need this, or do we just always compress it?
|
||||
if (compressed) {
|
||||
setAtBit(packetStateFlags, AVATARDATA_FLAGS_COMPRESSED);
|
||||
}
|
||||
memcpy(destinationBuffer, &packetStateFlags, sizeof(packetStateFlags));
|
||||
destinationBuffer += sizeof(packetStateFlags);
|
||||
|
||||
if (!sendMinimum) {
|
||||
auto header = reinterpret_cast<AvatarDataPacket::Header*>(destinationBuffer);
|
||||
header->position[0] = getLocalPosition().x;
|
||||
header->position[1] = getLocalPosition().y;
|
||||
|
@ -400,7 +414,27 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
<< (destinationBuffer - startPosition);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: first byte of array should always be uncompressed
|
||||
|
||||
if (compressed) {
|
||||
static const int SKIP_PACKET_FLAGS = 1;
|
||||
static const int COMPRESSION_LEVEL = 9;
|
||||
QByteArray uncompressedPortion = avatarDataByteArray.mid(SKIP_PACKET_FLAGS,
|
||||
(destinationBuffer - startPosition) - SKIP_PACKET_FLAGS);
|
||||
|
||||
QByteArray compressedPortion = qCompress(uncompressedPortion, COMPRESSION_LEVEL);
|
||||
QByteArray flagsAndCompressed;
|
||||
flagsAndCompressed.append(packetStateFlags);
|
||||
flagsAndCompressed.append(compressedPortion);
|
||||
|
||||
//qDebug() << __FUNCTION__ << "compressing data was:" << (uncompressedPortion.size() + SKIP_PACKET_FLAGS) << "now:" << flagsAndCompressed.size();
|
||||
|
||||
return flagsAndCompressed;
|
||||
}
|
||||
|
||||
// entire buffer is uncompressed
|
||||
return avatarDataByteArray.left(destinationBuffer - startPosition);
|
||||
}
|
||||
|
||||
|
@ -474,9 +508,30 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
_headData = new HeadData(this);
|
||||
}
|
||||
|
||||
UINT8 packetStateFlags = buffer.at(0);
|
||||
bool minimumSent = oneAtBit(packetStateFlags, AVATARDATA_FLAGS_MINIMUM);
|
||||
bool packetIsCompressed = oneAtBit(packetStateFlags, AVATARDATA_FLAGS_COMPRESSED);
|
||||
|
||||
// if this is the minimum, then it only includes the flags
|
||||
if (minimumSent) {
|
||||
int numBytesRead = sizeof(packetStateFlags);
|
||||
_averageBytesReceived.updateAverage(numBytesRead);
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
QByteArray uncompressBuffer;
|
||||
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(buffer.data());
|
||||
const unsigned char* endPosition = startPosition + buffer.size();
|
||||
const unsigned char* sourceBuffer = startPosition;
|
||||
|
||||
if (packetIsCompressed) {
|
||||
uncompressBuffer = qUncompress(buffer.right(buffer.size() - sizeof(packetStateFlags)));
|
||||
startPosition = reinterpret_cast<const unsigned char*>(uncompressBuffer.data());
|
||||
endPosition = startPosition + uncompressBuffer.size();
|
||||
sourceBuffer = startPosition;
|
||||
//qDebug() << __FUNCTION__ << "uncompressing compressed data was:" << buffer.size() << "now:" << uncompressBuffer.size();
|
||||
}
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
PACKET_READ_CHECK(Header, sizeof(AvatarDataPacket::Header));
|
||||
|
|
|
@ -106,6 +106,13 @@ const char LEFT_HAND_POINTING_FLAG = 1;
|
|||
const char RIGHT_HAND_POINTING_FLAG = 2;
|
||||
const char IS_FINGER_POINTING_FLAG = 4;
|
||||
|
||||
// AvatarData state flags - we store the details about the packet encoding in the first byte,
|
||||
// before the "header" structure
|
||||
const char AVATARDATA_FLAGS_MINIMUM = 0;
|
||||
const char AVATARDATA_FLAGS_COMPRESSED = 1;
|
||||
|
||||
|
||||
|
||||
static const float MAX_AVATAR_SCALE = 1000.0f;
|
||||
static const float MIN_AVATAR_SCALE = .005f;
|
||||
|
||||
|
@ -201,7 +208,7 @@ public:
|
|||
glm::vec3 getHandPosition() const;
|
||||
void setHandPosition(const glm::vec3& handPosition);
|
||||
|
||||
virtual QByteArray toByteArray(bool cullSmallChanges, bool sendAll);
|
||||
virtual QByteArray toByteArray(bool cullSmallChanges, bool sendAll, bool sendMinimum = false, bool compressed = true);
|
||||
virtual void doneEncoding(bool cullSmallChanges);
|
||||
|
||||
/// \return true if an error should be logged
|
||||
|
|
Loading…
Reference in a new issue