mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 19:28:41 +02:00
added flags for procedural face movement AvatarData.cpp toByteArray and parseDataFromBuffer
This commit is contained in:
parent
01848fafe0
commit
2879eeb687
4 changed files with 61 additions and 23 deletions
|
@ -308,7 +308,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
|
||||
|
||||
const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE +
|
||||
(hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) +
|
||||
(hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getBlendshapeCoefficients().size()) : 0) +
|
||||
(hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0) +
|
||||
(hasJointDefaultPoseFlags ? AvatarDataPacket::maxJointDefaultPoseFlagsSize(_jointData.size()) : 0);
|
||||
|
||||
|
@ -443,7 +443,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
auto startSection = destinationBuffer;
|
||||
auto data = reinterpret_cast<AvatarDataPacket::AdditionalFlags*>(destinationBuffer);
|
||||
|
||||
uint8_t flags { 0 };
|
||||
uint16_t flags { 0 };
|
||||
|
||||
setSemiNibbleAt(flags, KEY_STATE_START_BIT, _keyState);
|
||||
|
||||
|
@ -451,20 +451,33 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
bool isFingerPointing = _handState & IS_FINGER_POINTING_FLAG;
|
||||
setSemiNibbleAt(flags, HAND_STATE_START_BIT, _handState & ~IS_FINGER_POINTING_FLAG);
|
||||
if (isFingerPointing) {
|
||||
setAtBit(flags, HAND_STATE_FINGER_POINTING_BIT);
|
||||
setAtBit16(flags, HAND_STATE_FINGER_POINTING_BIT);
|
||||
}
|
||||
// face tracker state
|
||||
if (_headData->_isFaceTrackerConnected) {
|
||||
setAtBit(flags, IS_FACE_TRACKER_CONNECTED);
|
||||
setAtBit16(flags, IS_FACE_TRACKER_CONNECTED);
|
||||
}
|
||||
// eye tracker state
|
||||
if (_headData->_isEyeTrackerConnected) {
|
||||
setAtBit(flags, IS_EYE_TRACKER_CONNECTED);
|
||||
setAtBit16(flags, IS_EYE_TRACKER_CONNECTED);
|
||||
}
|
||||
// referential state
|
||||
if (!parentID.isNull()) {
|
||||
setAtBit(flags, HAS_REFERENTIAL);
|
||||
setAtBit16(flags, HAS_REFERENTIAL);
|
||||
}
|
||||
// audio face movement
|
||||
if (_headData->getHasAudioEnabledFaceMovement()) {
|
||||
setAtBit16(flags, AUDIO_ENABLED_FACE_MOVEMENT);
|
||||
}
|
||||
// procedural eye face movement
|
||||
if (_headData->getHasProceduralEyeFaceMovement()) {
|
||||
setAtBit16(flags, PROCEDURAL_EYE_FACE_MOVEMENT);
|
||||
}
|
||||
// procedural blink face movement
|
||||
if (_headData->getHasProceduralBlinkFaceMovement()) {
|
||||
setAtBit16(flags, PROCEDURAL_BLINK_FACE_MOVEMENT);
|
||||
}
|
||||
|
||||
data->flags = flags;
|
||||
destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
|
||||
|
||||
|
@ -507,7 +520,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
if (hasFaceTrackerInfo) {
|
||||
auto startSection = destinationBuffer;
|
||||
auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer);
|
||||
const auto& blendshapeCoefficients = _headData->getSummedBlendshapeCoefficients();
|
||||
const auto& blendshapeCoefficients = _headData->getBlendshapeCoefficients();
|
||||
|
||||
faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink;
|
||||
faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink;
|
||||
|
@ -973,7 +986,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
|
||||
PACKET_READ_CHECK(AdditionalFlags, sizeof(AvatarDataPacket::AdditionalFlags));
|
||||
auto data = reinterpret_cast<const AvatarDataPacket::AdditionalFlags*>(sourceBuffer);
|
||||
uint8_t bitItems = data->flags;
|
||||
uint16_t bitItems = data->flags;
|
||||
|
||||
// key state, stored as a semi-nibble in the bitItems
|
||||
auto newKeyState = (KeyState)getSemiNibbleAt(bitItems, KEY_STATE_START_BIT);
|
||||
|
@ -981,26 +994,37 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
// hand state, stored as a semi-nibble plus a bit in the bitItems
|
||||
// we store the hand state as well as other items in a shared bitset. The hand state is an octal, but is split
|
||||
// into two sections to maintain backward compatibility. The bits are ordered as such (0-7 left to right).
|
||||
// +---+-----+-----+--+
|
||||
// |x,x|H0,H1|x,x,x|H2|
|
||||
// +---+-----+-----+--+
|
||||
// AA 6/1/18 added three more flags here for procedural audio, blink, and eye saccade enabled
|
||||
// +---+-----+-----+--+--+--+--+-----+
|
||||
// |x,x|H0,H1|x,x,x|H2|Au|Bl|Ey|xxxxx|
|
||||
// +---+-----+-----+--+--+--+--+-----+
|
||||
// Hand state - H0,H1,H2 is found in the 3rd, 4th, and 8th bits
|
||||
auto newHandState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT)
|
||||
+ (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0);
|
||||
+ (oneAtBit16(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0);
|
||||
|
||||
auto newFaceTrackerConnected = oneAtBit(bitItems, IS_FACE_TRACKER_CONNECTED);
|
||||
auto newEyeTrackerConnected = oneAtBit(bitItems, IS_EYE_TRACKER_CONNECTED);
|
||||
auto newFaceTrackerConnected = oneAtBit16(bitItems, IS_FACE_TRACKER_CONNECTED);
|
||||
auto newEyeTrackerConnected = oneAtBit16(bitItems, IS_EYE_TRACKER_CONNECTED);
|
||||
|
||||
auto newHasAudioEnabledFaceMovement = oneAtBit16(bitItems, AUDIO_ENABLED_FACE_MOVEMENT);
|
||||
auto newHasProceduralEyeFaceMovement = oneAtBit16(bitItems, PROCEDURAL_EYE_FACE_MOVEMENT);
|
||||
auto newHasProceduralBlinkFaceMovement = oneAtBit16(bitItems, PROCEDURAL_BLINK_FACE_MOVEMENT);
|
||||
|
||||
bool keyStateChanged = (_keyState != newKeyState);
|
||||
bool handStateChanged = (_handState != newHandState);
|
||||
bool faceStateChanged = (_headData->_isFaceTrackerConnected != newFaceTrackerConnected);
|
||||
bool eyeStateChanged = (_headData->_isEyeTrackerConnected != newEyeTrackerConnected);
|
||||
bool somethingChanged = keyStateChanged || handStateChanged || faceStateChanged || eyeStateChanged;
|
||||
bool audioEnableFaceMovementChanged = (_headData->getHasAudioEnabledFaceMovement() != newHasAudioEnabledFaceMovement);
|
||||
bool proceduralEyeFaceMovementChanged = (_headData->getHasProceduralEyeFaceMovement() != newHasProceduralEyeFaceMovement);
|
||||
bool proceduralBlinkFaceMovementChanged = (_headData->getHasProceduralBlinkFaceMovement() != newHasProceduralBlinkFaceMovement);
|
||||
bool somethingChanged = keyStateChanged || handStateChanged || faceStateChanged || eyeStateChanged || audioEnableFaceMovementChanged || proceduralEyeFaceMovementChanged || proceduralBlinkFaceMovementChanged;
|
||||
|
||||
_keyState = newKeyState;
|
||||
_handState = newHandState;
|
||||
_headData->_isFaceTrackerConnected = newFaceTrackerConnected;
|
||||
_headData->_isEyeTrackerConnected = newEyeTrackerConnected;
|
||||
_headData->setHasAudioEnabledFaceMovement(newHasAudioEnabledFaceMovement);
|
||||
_headData->setHasProceduralEyeFaceMovement(newHasProceduralEyeFaceMovement);
|
||||
_headData->setHasProceduralBlinkFaceMovement(newHasProceduralBlinkFaceMovement);
|
||||
|
||||
sourceBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
|
||||
|
||||
|
|
|
@ -93,6 +93,9 @@ const int IS_FACE_TRACKER_CONNECTED = 4; // 5th bit
|
|||
const int IS_EYE_TRACKER_CONNECTED = 5; // 6th bit (was CHAT_CIRCLING)
|
||||
const int HAS_REFERENTIAL = 6; // 7th bit
|
||||
const int HAND_STATE_FINGER_POINTING_BIT = 7; // 8th bit
|
||||
const int AUDIO_ENABLED_FACE_MOVEMENT = 8; // 9th bit
|
||||
const int PROCEDURAL_EYE_FACE_MOVEMENT = 9; // 10th bit
|
||||
const int PROCEDURAL_BLINK_FACE_MOVEMENT = 10; // 11th bit
|
||||
|
||||
|
||||
const char HAND_STATE_NULL = 0;
|
||||
|
@ -200,9 +203,9 @@ namespace AvatarDataPacket {
|
|||
static_assert(sizeof(SensorToWorldMatrix) == SENSOR_TO_WORLD_SIZE, "AvatarDataPacket::SensorToWorldMatrix size doesn't match.");
|
||||
|
||||
PACKED_BEGIN struct AdditionalFlags {
|
||||
uint8_t flags; // additional flags: hand state, key state, eye tracking
|
||||
uint16_t flags; // additional flags: hand state, key state, eye tracking
|
||||
} PACKED_END;
|
||||
const size_t ADDITIONAL_FLAGS_SIZE = 1;
|
||||
const size_t ADDITIONAL_FLAGS_SIZE = 2;
|
||||
static_assert(sizeof(AdditionalFlags) == ADDITIONAL_FLAGS_SIZE, "AvatarDataPacket::AdditionalFlags size doesn't match.");
|
||||
|
||||
// only present if HAS_REFERENTIAL flag is set in AvatarInfo.flags
|
||||
|
|
|
@ -297,14 +297,23 @@ void setAtBit(unsigned char& byte, int bitIndex) {
|
|||
byte |= (1 << (7 - bitIndex));
|
||||
}
|
||||
|
||||
bool oneAtBit16(unsigned short word, int bitIndex) {
|
||||
return (word >> (7 - bitIndex) & 1);
|
||||
}
|
||||
|
||||
void setAtBit16(unsigned short& word, int bitIndex) {
|
||||
word |= (1 << (7 - bitIndex));
|
||||
}
|
||||
|
||||
|
||||
void clearAtBit(unsigned char& byte, int bitIndex) {
|
||||
if (oneAtBit(byte, bitIndex)) {
|
||||
byte -= (1 << (7 - bitIndex));
|
||||
}
|
||||
}
|
||||
|
||||
int getSemiNibbleAt(unsigned char byte, int bitIndex) {
|
||||
return (byte >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11
|
||||
int getSemiNibbleAt(unsigned short word, int bitIndex) {
|
||||
return (word >> (6 - bitIndex) & 3); // semi-nibbles store 00, 01, 10, or 11
|
||||
}
|
||||
|
||||
int getNthBit(unsigned char byte, int ordinal) {
|
||||
|
@ -326,9 +335,9 @@ int getNthBit(unsigned char byte, int ordinal) {
|
|||
return ERROR_RESULT;
|
||||
}
|
||||
|
||||
void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value) {
|
||||
void setSemiNibbleAt(unsigned short& word, int bitIndex, int value) {
|
||||
//assert(value <= 3 && value >= 0);
|
||||
byte |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11
|
||||
word |= ((value & 3) << (6 - bitIndex)); // semi-nibbles store 00, 01, 10, or 11
|
||||
}
|
||||
|
||||
bool isInEnvironment(const char* environment) {
|
||||
|
|
|
@ -163,9 +163,11 @@ void printVoxelCode(unsigned char* voxelCode);
|
|||
int numberOfOnes(unsigned char byte);
|
||||
bool oneAtBit(unsigned char byte, int bitIndex);
|
||||
void setAtBit(unsigned char& byte, int bitIndex);
|
||||
bool oneAtBit16(unsigned short word, int bitIndex);
|
||||
void setAtBit16(unsigned short& word, int bitIndex);
|
||||
void clearAtBit(unsigned char& byte, int bitIndex);
|
||||
int getSemiNibbleAt(unsigned char byte, int bitIndex);
|
||||
void setSemiNibbleAt(unsigned char& byte, int bitIndex, int value);
|
||||
int getSemiNibbleAt(unsigned short word, int bitIndex);
|
||||
void setSemiNibbleAt(unsigned short& word, int bitIndex, int value);
|
||||
|
||||
int getNthBit(unsigned char byte, int ordinal); /// determines the bit placement 0-7 of the ordinal set bit
|
||||
|
||||
|
|
Loading…
Reference in a new issue