First version of faux joint optimizations

There are still some AJT: TODO sections, mostly about stat tracking for the new Hand Controllers section.

Created a new hand controller section that is optional, when not present hand controllers are assumed to be disabled.
This commit is contained in:
Anthony Thibault 2019-04-22 11:02:13 -07:00
parent 5971ddbe24
commit 0c0b847666
6 changed files with 90 additions and 51 deletions

View file

@ -1041,11 +1041,15 @@ void MyAvatar::updateJointFromController(controller::Action poseKey, ThreadSafeV
assert(QThread::currentThread() == thread());
auto userInputMapper = DependencyManager::get<UserInputMapper>();
controller::Pose controllerPose = userInputMapper->getPoseState(poseKey);
Transform transform;
transform.setTranslation(controllerPose.getTranslation());
transform.setRotation(controllerPose.getRotation());
glm::mat4 controllerMatrix = transform.getMatrix();
matrixCache.set(controllerMatrix);
if (controllerPose.isValid()) {
Transform transform;
transform.setTranslation(controllerPose.getTranslation());
transform.setRotation(controllerPose.getRotation());
glm::mat4 controllerMatrix = transform.getMatrix();
matrixCache.set(controllerMatrix);
} else {
matrixCache.invalidate();
}
}
// best called at end of main loop, after physics.

View file

@ -55,7 +55,7 @@ using namespace std;
const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData";
static const int TRANSLATION_COMPRESSION_RADIX = 14;
static const int FAUX_JOINT_COMPRESSION_RADIX = 12;
static const int HAND_CONTROLLER_COMPRESSION_RADIX = 12;
static const int SENSOR_TO_WORLD_SCALE_RADIX = 10;
static const float AUDIO_LOUDNESS_SCALE = 1024.0f;
static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water
@ -66,7 +66,7 @@ size_t AvatarDataPacket::maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients
return FACE_TRACKER_INFO_SIZE + numBlendshapeCoefficients * sizeof(float);
}
size_t AvatarDataPacket::maxJointDataSize(size_t numJoints, bool hasGrabJoints) {
size_t AvatarDataPacket::maxJointDataSize(size_t numJoints) {
const size_t validityBitsSize = calcBitVectorSize((int)numJoints);
size_t totalSize = sizeof(uint8_t); // numJoints
@ -76,14 +76,6 @@ size_t AvatarDataPacket::maxJointDataSize(size_t numJoints, bool hasGrabJoints)
totalSize += validityBitsSize; // Translations mask
totalSize += sizeof(float); // maxTranslationDimension
totalSize += numJoints * sizeof(SixByteTrans); // Translations
size_t NUM_FAUX_JOINT = 2;
totalSize += NUM_FAUX_JOINT * (sizeof(SixByteQuat) + sizeof(SixByteTrans)); // faux joints
if (hasGrabJoints) {
totalSize += sizeof(AvatarDataPacket::FarGrabJoints);
}
return totalSize;
}
@ -98,9 +90,6 @@ size_t AvatarDataPacket::minJointDataSize(size_t numJoints) {
totalSize += sizeof(float); // maxTranslationDimension
// assume no valid translations
size_t NUM_FAUX_JOINT = 2;
totalSize += NUM_FAUX_JOINT * (sizeof(SixByteQuat) + sizeof(SixByteTrans)); // faux joints
return totalSize;
}
@ -329,6 +318,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
// separately
bool hasParentInfo = false;
bool hasAvatarLocalPosition = false;
bool hasHandControllers = false;
bool hasFaceTrackerInfo = false;
@ -346,7 +336,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
hasAvatarLocalPosition = hasParent() && (sendAll ||
tranlationChangedSince(lastSentTime) ||
parentInfoChangedSince(lastSentTime));
hasHandControllers = _controllerLeftHandMatrixCache.isValid() || _controllerRightHandMatrixCache.isValid();
hasFaceTrackerInfo = !dropFaceTracking && (hasFaceTracker() || getHasScriptedBlendshapes()) &&
(sendAll || faceTrackerInfoChangedSince(lastSentTime));
hasJointData = !sendMinimum;
@ -364,6 +354,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
| (hasAdditionalFlags ? AvatarDataPacket::PACKET_HAS_ADDITIONAL_FLAGS : 0)
| (hasParentInfo ? AvatarDataPacket::PACKET_HAS_PARENT_INFO : 0)
| (hasAvatarLocalPosition ? AvatarDataPacket::PACKET_HAS_AVATAR_LOCAL_POSITION : 0)
| (hasHandControllers ? AvatarDataPacket::PACKET_HAS_HAND_CONTROLLERS : 0)
| (hasFaceTrackerInfo ? AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO : 0)
| (hasJointData ? AvatarDataPacket::PACKET_HAS_JOINT_DATA : 0)
| (hasJointDefaultPoseFlags ? AvatarDataPacket::PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS : 0)
@ -406,7 +397,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE + NUM_BYTES_RFC4122_UUID +
AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getBlendshapeCoefficients().size()) +
AvatarDataPacket::maxJointDataSize(_jointData.size(), true) +
AvatarDataPacket::maxJointDataSize(_jointData.size()) +
AvatarDataPacket::maxJointDefaultPoseFlagsSize(_jointData.size());
if (maxDataSize == 0) {
@ -592,7 +583,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
}
}
IF_AVATAR_SPACE(PACKET_HAS_AVATAR_LOCAL_POSITION, sizeof(getLocalPosition()) ) {
IF_AVATAR_SPACE(PACKET_HAS_AVATAR_LOCAL_POSITION, AvatarDataPacket::AVATAR_LOCAL_POSITION_SIZE) {
auto startSection = destinationBuffer;
const auto localPosition = getLocalPosition();
AVATAR_MEMCPY(localPosition);
@ -603,6 +594,30 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
}
}
// AJT: hand controller section
IF_AVATAR_SPACE(PACKET_HAS_HAND_CONTROLLERS, AvatarDataPacket::HAND_CONTROLLERS_SIZE) {
qDebug() << "AJT: sending hand controllers!";
// AJT: TODO
//auto startSection = destinationBuffer;
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerLeftHandTransform.getRotation());
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerLeftHandTransform.getTranslation(), HAND_CONTROLLER_COMPRESSION_RADIX);
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerRightHandTransform.getRotation());
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerRightHandTransform.getTranslation(), HAND_CONTROLLER_COMPRESSION_RADIX);
/* AJT: TODO
int numBytes = destinationBuffer - startSection;
if (outboundDataRateOut) {
outboundDataRateOut->handControllersRate.increment(numBytes);
}
*/
}
const auto& blendshapeCoefficients = _headData->getBlendshapeCoefficients();
// If it is connected, pack up the data
IF_AVATAR_SPACE(PACKET_HAS_FACE_TRACKER_INFO, sizeof(AvatarDataPacket::FaceTrackerInfo) + (size_t)blendshapeCoefficients.size() * sizeof(float)) {
@ -638,9 +653,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
// include jointData if there is room for the most minimal section. i.e. no translations or rotations.
IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, AvatarDataPacket::minJointDataSize(numJoints)) {
// Minimum space required for another rotation joint -
// size of joint + following translation bit-vector + translation scale + faux joints:
const ptrdiff_t minSizeForJoint = sizeof(AvatarDataPacket::SixByteQuat) + jointBitVectorSize +
sizeof(float) + AvatarDataPacket::FAUX_JOINTS_SIZE;
// size of joint + following translation bit-vector + translation scale:
const ptrdiff_t minSizeForJoint = sizeof(AvatarDataPacket::SixByteQuat) + jointBitVectorSize + sizeof(float);
auto startSection = destinationBuffer;
@ -759,17 +773,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
}
sendStatus.translationsSent = i;
// faux joints
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerLeftHandTransform.getRotation());
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerLeftHandTransform.getTranslation(),
FAUX_JOINT_COMPRESSION_RADIX);
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerRightHandTransform.getRotation());
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerRightHandTransform.getTranslation(),
FAUX_JOINT_COMPRESSION_RADIX);
IF_AVATAR_SPACE(PACKET_HAS_GRAB_JOINTS, sizeof (AvatarDataPacket::FarGrabJoints)) {
// the far-grab joints may range further than 3 meters, so we can't use packFloatVec3ToSignedTwoByteFixed etc
auto startSection = destinationBuffer;
@ -902,12 +905,12 @@ bool AvatarData::shouldLogError(const quint64& now) {
}
const unsigned char* unpackFauxJoint(const unsigned char* sourceBuffer, ThreadSafeValueCache<glm::mat4>& matrixCache) {
const unsigned char* unpackHandController(const unsigned char* sourceBuffer, ThreadSafeValueCache<glm::mat4>& matrixCache) {
glm::quat orientation;
glm::vec3 position;
Transform transform;
sourceBuffer += unpackOrientationQuatFromSixBytes(sourceBuffer, orientation);
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, position, FAUX_JOINT_COMPRESSION_RADIX);
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, position, HAND_CONTROLLER_COMPRESSION_RADIX);
transform.setTranslation(position);
transform.setRotation(orientation);
matrixCache.set(transform.getMatrix());
@ -952,6 +955,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
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 hasHandControllers = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_HAND_CONTROLLERS);
bool hasFaceTrackerInfo = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO);
bool hasJointData = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_JOINT_DATA);
bool hasJointDefaultPoseFlags = HAS_FLAG(packetStateFlags, AvatarDataPacket::PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS);
@ -1240,6 +1244,26 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
_localPositionUpdateRate.increment();
}
// AJT: hand controller section
if (hasHandControllers) {
qDebug() << "AJT: received hand controllers!";
// AJT: TODO
// auto startSection = sourceBuffer;
sourceBuffer = unpackHandController(sourceBuffer, _controllerLeftHandMatrixCache);
sourceBuffer = unpackHandController(sourceBuffer, _controllerRightHandMatrixCache);
// AJT: TODO
// int numBytesRead = sourceBuffer - startSection;
// _handControllerUpdateRate.increment(numBytesRead);
// _handControllerUpdateRate.increment();
} else {
_controllerLeftHandMatrixCache.invalidate();
_controllerRightHandMatrixCache.invalidate();
}
if (hasFaceTrackerInfo) {
auto startSection = sourceBuffer;
@ -1351,10 +1375,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
<< "size:" << (int)(sourceBuffer - startPosition);
}
#endif
// faux joints
sourceBuffer = unpackFauxJoint(sourceBuffer, _controllerLeftHandMatrixCache);
sourceBuffer = unpackFauxJoint(sourceBuffer, _controllerRightHandMatrixCache);
int numBytesRead = sourceBuffer - startSection;
_jointDataRate.increment(numBytesRead);
_jointDataUpdateRate.increment();

View file

@ -164,10 +164,11 @@ namespace AvatarDataPacket {
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;
const HasFlags PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS = 1U << 12;
const HasFlags PACKET_HAS_GRAB_JOINTS = 1U << 13;
const HasFlags PACKET_HAS_HAND_CONTROLLERS = 1U << 10;
const HasFlags PACKET_HAS_FACE_TRACKER_INFO = 1U << 11;
const HasFlags PACKET_HAS_JOINT_DATA = 1U << 12;
const HasFlags PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS = 1U << 13;
const HasFlags PACKET_HAS_GRAB_JOINTS = 1U << 14;
const size_t AVATAR_HAS_FLAGS_SIZE = 2;
using SixByteQuat = uint8_t[6];
@ -230,7 +231,7 @@ namespace AvatarDataPacket {
//
// POTENTIAL SAVINGS - 20 bytes
SixByteQuat sensorToWorldQuat; // 6 byte compressed quaternion part of sensor to world matrix
SixByteQuat sensorToWorldQuat; // 6 byte compressed quaternion part of sensor to world matrix
uint16_t sensorToWorldScale; // uniform scale of sensor to world matrix
float sensorToWorldTrans[3]; // fourth column of sensor to world matrix
// FIXME - sensorToWorldTrans might be able to be better compressed if it was
@ -273,6 +274,15 @@ namespace AvatarDataPacket {
PARENT_INFO_SIZE +
AVATAR_LOCAL_POSITION_SIZE;
PACKED_BEGIN struct HandControllers {
SixByteQuat leftHandRotation;
SixByteTrans leftHandTranslation;
SixByteQuat rightHandRotation;
SixByteTrans rightHandTranslation;
} PACKED_END;
static const size_t HAND_CONTROLLERS_SIZE = 24;
static_assert(sizeof(HandControllers) == HAND_CONTROLLERS_SIZE, "AvatarDataPacket::HandControllers size doesn't match.");
// variable length structure follows
@ -303,7 +313,7 @@ namespace AvatarDataPacket {
SixByteTrans rightHandControllerTranslation;
};
*/
size_t maxJointDataSize(size_t numJoints, bool hasGrabJoints);
size_t maxJointDataSize(size_t numJoints);
size_t minJointDataSize(size_t numJoints);
/*
@ -327,7 +337,6 @@ namespace AvatarDataPacket {
static_assert(sizeof(FarGrabJoints) == FAR_GRAB_JOINTS_SIZE, "AvatarDataPacket::FarGrabJoints size doesn't match.");
static const size_t MIN_BULK_PACKET_SIZE = NUM_BYTES_RFC4122_UUID + HEADER_SIZE;
static const size_t FAUX_JOINTS_SIZE = 2 * (sizeof(SixByteQuat) + sizeof(SixByteTrans));
struct SendStatus {
HasFlags itemFlags { 0 };

View file

@ -38,10 +38,10 @@ PacketVersion versionForPacketType(PacketType packetType) {
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
case PacketType::AvatarIdentity:
case PacketType::AvatarData:
return static_cast<PacketVersion>(AvatarMixerPacketVersion::FBXJointOrderChange);
return static_cast<PacketVersion>(AvatarMixerPacketVersion::HandControllerSection);
case PacketType::BulkAvatarData:
case PacketType::KillAvatar:
return static_cast<PacketVersion>(AvatarMixerPacketVersion::FBXJointOrderChange);
return static_cast<PacketVersion>(AvatarMixerPacketVersion::HandControllerSection);
case PacketType::MessagesData:
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
// ICE packets

View file

@ -331,7 +331,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
AvatarTraitsAck,
FasterAvatarEntities,
SendMaxTranslationDimension,
FBXJointOrderChange
FBXJointOrderChange,
HandControllerSection,
};
enum class DomainConnectRequestVersion : PacketVersion {

View file

@ -52,6 +52,11 @@ public:
_valid = false;
}
bool isValid() const {
std::lock_guard<std::mutex> guard(_mutex);
return _valid;
}
private:
mutable std::mutex _mutex;
T _value;