local position tweaks

This commit is contained in:
ZappoMan 2017-01-13 09:09:29 -08:00
parent ee4df20df3
commit 3a9a6e8283
2 changed files with 62 additions and 72 deletions

View file

@ -233,39 +233,40 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
//
// TODO -
// typical -- 1jd 0ft 0p 1af 1stw 0loud 1look 0s 0o 1d 1lp 1gp
//
// 2) determine if local position really only matters for parent - 12 bytes - 4.32 kbps (when moving and/or not parented)
// 3) SensorToWorld - should we only send this for avatars with attachments?? - 20 bytes - 7.20 kbps
// 5) GUIID for the session change to 2byte index (savings) - 14 bytes - 5.04 kbps
//
// ----- Subtotal -- non-joint savings --- ~21.2 kbps --- ~12.8% savings?
//
// 5) Joints... use more aggressive quantization and/or culling for more distance between avatars
// 1) Joints... use more aggressive quantization and/or culling for more distance between avatars
// 2) SensorToWorld - should we only send this for avatars with attachments?? - 20 bytes - 7.20 kbps
// 3) GUIID for the session change to 2byte index (savings) - 14 bytes - 5.04 kbps
//
// Joints --
// 63 rotations * 6 bytes = 136kbps
// 3 translations * 6 bytes = 6.48kbps
//
bool hasAvatarGlobalPosition = true; // always include global position
bool hasAvatarLocalPosition = sendAll || tranlationChangedSince(lastSentTime);
bool hasAvatarOrientation = sendAll || rotationChangedSince(lastSentTime);
auto localPosition = getLocalPosition();
auto parentID = getParentID();
bool hasAvatarGlobalPosition = true; // always include global position
bool hasAvatarOrientation = sendAll || rotationChangedSince(lastSentTime);
bool hasAvatarBoundingBox = sendAll || avatarBoundingBoxChangedSince(lastSentTime);
bool hasAvatarScale = sendAll || avatarScaleChangedSince(lastSentTime);
bool hasLookAtPosition = sendAll || lookAtPositionChangedSince(lastSentTime);
bool hasAudioLoudness = sendAll || audioLoudnessChangedSince(lastSentTime);
bool hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChangedSince(lastSentTime);
bool hasAdditionalFlags = sendAll || additionalFlagsChangedSince(lastSentTime);
// local position, and parent info only apply to avatars that are parented. The local position
// and the parent info can change independently though, so we track their "changed since"
// separately
bool hasParentInfo = hasParent() && (sendAll || parentInfoChangedSince(lastSentTime));
bool hasAvatarLocalPosition = hasParent() && (sendAll || tranlationChangedSince(lastSentTime));
bool hasFaceTrackerInfo = hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime));
bool hasJointData = sendAll || !sendMinimum;
// Leading flags, to indicate how much data is actually included in the packet...
AvatarDataPacket::HasFlags packetStateFlags =
(hasAvatarGlobalPosition ? AvatarDataPacket::PACKET_HAS_AVATAR_GLOBAL_POSITION : 0)
| (hasAvatarLocalPosition ? AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION : 0)
| (hasAvatarBoundingBox ? AvatarDataPacket::PACKET_HAS_AVATAR_BOUNDING_BOX : 0)
| (hasAvatarOrientation ? AvatarDataPacket::PACKET_HAS_AVATAR_ORIENTATION : 0)
| (hasAvatarScale ? AvatarDataPacket::PACKET_HAS_AVATAR_SCALE : 0)
@ -274,6 +275,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
| (hasSensorToWorldMatrix ? AvatarDataPacket::PACKET_HAS_SENSOR_TO_WORLD_MATRIX : 0)
| (hasAdditionalFlags ? AvatarDataPacket::PACKET_HAS_ADDITIONAL_FLAGS : 0)
| (hasParentInfo ? AvatarDataPacket::PACKET_HAS_PARENT_INFO : 0)
| (hasAvatarLocalPosition ? AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION : 0)
| (hasFaceTrackerInfo ? AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO : 0)
| (hasJointData ? AvatarDataPacket::PACKET_HAS_JOINT_DATA : 0);
@ -288,19 +290,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
destinationBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition);
}
// FIXME - I was told by tony this was "skeletal model position"-- but it seems to be
// SpatiallyNestable::getLocalPosition() ... which AFAICT is almost always the same as
// the global position (unless presumably you're on a parent)... we might be able to
// include this in the parent info record
if (hasAvatarLocalPosition) {
auto data = reinterpret_cast<AvatarDataPacket::AvatarLocalPosition*>(destinationBuffer);
auto localPosition = getLocalPosition();
data->localPosition[0] = localPosition.x;
data->localPosition[1] = localPosition.y;
data->localPosition[2] = localPosition.z;
destinationBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition);
}
if (hasAvatarBoundingBox) {
auto data = reinterpret_cast<AvatarDataPacket::AvatarBoundingBox*>(destinationBuffer);
@ -354,8 +343,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
destinationBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix);
}
QUuid parentID = getParentID();
if (hasAdditionalFlags) {
auto data = reinterpret_cast<AvatarDataPacket::AdditionalFlags*>(destinationBuffer);
@ -385,6 +372,15 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
}
if (hasAvatarLocalPosition) {
auto data = reinterpret_cast<AvatarDataPacket::AvatarLocalPosition*>(destinationBuffer);
auto localPosition = getLocalPosition();
data->localPosition[0] = localPosition.x;
data->localPosition[1] = localPosition.y;
data->localPosition[2] = localPosition.z;
destinationBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition);
}
if (hasParentInfo) {
auto parentInfo = reinterpret_cast<AvatarDataPacket::ParentInfo*>(destinationBuffer);
QByteArray referentialAsBytes = parentID.toRfc4122();
@ -633,7 +629,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
#define HAS_FLAG(B,F) ((B & F) == F)
bool hasAvatarGlobalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_GLOBAL_POSITION);
bool hasAvatarLocalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION);
bool hasAvatarBoundingBox = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_BOUNDING_BOX);
bool hasAvatarOrientation = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_ORIENTATION);
bool hasAvatarScale = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_SCALE);
@ -642,6 +637,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
bool hasSensorToWorldMatrix = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_SENSOR_TO_WORLD_MATRIX);
bool hasAdditionalFlags = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_ADDITIONAL_FLAGS);
bool hasParentInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_PARENT_INFO);
bool hasAvatarLocalPosition = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION);
bool hasFaceTrackerInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO);
bool hasJointData = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_JOINT_DATA);
@ -661,24 +657,11 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
sourceBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition);
int numBytesRead = sourceBuffer - startSection;
_globalPositionRate.increment(numBytesRead);
}
if (hasAvatarLocalPosition) {
auto startSection = sourceBuffer;
PACKET_READ_CHECK(AvatarLocalPosition, sizeof(AvatarDataPacket::AvatarLocalPosition));
auto data = reinterpret_cast<const AvatarDataPacket::AvatarLocalPosition*>(sourceBuffer);
glm::vec3 position = glm::vec3(data->localPosition[0], data->localPosition[1], data->localPosition[2]);
if (isNaN(position)) {
if (shouldLogError(now)) {
qCWarning(avatars) << "Discard AvatarData packet: position NaN, uuid " << getSessionUUID();
}
return buffer.size();
// if we don't have a parent, make sure to also set our local position
if (!hasParent()) {
setLocalPosition(newValue);
}
setLocalPosition(position);
sourceBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition);
int numBytesRead = sourceBuffer - startSection;
_localPositionRate.increment(numBytesRead);
}
if (hasAvatarBoundingBox) {
@ -863,6 +846,25 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
_parentID = QUuid();
}
if (hasAvatarLocalPosition) {
assert(hasParent()); // we shouldn't have local position unless we have a parent
auto startSection = sourceBuffer;
PACKET_READ_CHECK(AvatarLocalPosition, sizeof(AvatarDataPacket::AvatarLocalPosition));
auto data = reinterpret_cast<const AvatarDataPacket::AvatarLocalPosition*>(sourceBuffer);
glm::vec3 position = glm::vec3(data->localPosition[0], data->localPosition[1], data->localPosition[2]);
if (isNaN(position)) {
if (shouldLogError(now)) {
qCWarning(avatars) << "Discard AvatarData packet: position NaN, uuid " << getSessionUUID();
}
return buffer.size();
}
setLocalPosition(position);
sourceBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition);
int numBytesRead = sourceBuffer - startSection;
_localPositionRate.increment(numBytesRead);
}
if (hasFaceTrackerInfo) {
auto startSection = sourceBuffer;

View file

@ -126,15 +126,15 @@ namespace AvatarDataPacket {
// AvatarGlobalPosition, Avatar Faceshift, eye tracking, and existence of
using HasFlags = uint16_t;
const HasFlags PACKET_HAS_AVATAR_GLOBAL_POSITION = 1U << 0;
const HasFlags PACKET_HAS_AVATAR_LOCAL_POSITION = 1U << 1; // FIXME - can this be in the PARENT_INFO??
const HasFlags PACKET_HAS_AVATAR_BOUNDING_BOX = 1U << 2;
const HasFlags PACKET_HAS_AVATAR_ORIENTATION = 1U << 3;
const HasFlags PACKET_HAS_AVATAR_SCALE = 1U << 4;
const HasFlags PACKET_HAS_LOOK_AT_POSITION = 1U << 5;
const HasFlags PACKET_HAS_AUDIO_LOUDNESS = 1U << 6;
const HasFlags PACKET_HAS_SENSOR_TO_WORLD_MATRIX = 1U << 7;
const HasFlags PACKET_HAS_ADDITIONAL_FLAGS = 1U << 8;
const HasFlags PACKET_HAS_PARENT_INFO = 1U << 9;
const HasFlags PACKET_HAS_AVATAR_BOUNDING_BOX = 1U << 1;
const HasFlags PACKET_HAS_AVATAR_ORIENTATION = 1U << 2;
const HasFlags PACKET_HAS_AVATAR_SCALE = 1U << 3;
const HasFlags PACKET_HAS_LOOK_AT_POSITION = 1U << 4;
const HasFlags PACKET_HAS_AUDIO_LOUDNESS = 1U << 5;
const HasFlags PACKET_HAS_SENSOR_TO_WORLD_MATRIX = 1U << 6;
const HasFlags PACKET_HAS_ADDITIONAL_FLAGS = 1U << 7;
const HasFlags PACKET_HAS_PARENT_INFO = 1U << 8;
const HasFlags PACKET_HAS_AVATAR_LOCAL_POSITION = 1U << 9;
const HasFlags PACKET_HAS_FACE_TRACKER_INFO = 1U << 10;
const HasFlags PACKET_HAS_JOINT_DATA = 1U << 11;
@ -142,18 +142,6 @@ namespace AvatarDataPacket {
PACKED_BEGIN struct Header {
HasFlags packetHasFlags; // state flags, indicated which additional records are included in the packet
// bit 0 - has AvatarGlobalPosition
// bit 1 - has AvatarLocalPosition
// bit 2 - has AvatarBoundingBox
// bit 3 - has AvatarOrientation
// bit 4 - has AvatarScale
// bit 5 - has LookAtPosition
// bit 6 - has AudioLoudness
// bit 7 - has SensorToWorldMatrix
// bit 8 - has AdditionalFlags
// bit 9 - has ParentInfo
// bit 10 - has FaceTrackerInfo
// bit 11 - has JointData
} PACKED_END;
const size_t HEADER_SIZE = 2;
@ -162,13 +150,6 @@ namespace AvatarDataPacket {
} PACKED_END;
const size_t AVATAR_GLOBAL_POSITION_SIZE = 12;
PACKED_BEGIN struct AvatarLocalPosition {
float localPosition[3]; // this appears to be the avatar local position??
// this is a reduced precision radix
// FIXME - could this be changed into compressed floats?
} PACKED_END;
const size_t AVATAR_LOCAL_POSITION_SIZE = 12;
PACKED_BEGIN struct AvatarBoundingBox {
float avatarDimensions[3]; // avatar's bounding box in world space units, but relative to the position.
float boundOriginOffset[3]; // offset from the position of the avatar to the origin of the bounding box
@ -231,6 +212,13 @@ namespace AvatarDataPacket {
} PACKED_END;
const size_t PARENT_INFO_SIZE = 18;
// will only ever be included if the avatar has a parent but can change independent of changes to parent info
// and so we keep it a separate record
PACKED_BEGIN struct AvatarLocalPosition {
float localPosition[3]; // parent frame translation of the avatar
} PACKED_END;
const size_t AVATAR_LOCAL_POSITION_SIZE = 12;
// only present if IS_FACESHIFT_CONNECTED flag is set in AvatarInfo.flags
PACKED_BEGIN struct FaceTrackerInfo {
float leftEyeBlink;