Merge pull request #12909 from hyperlogic/bug-fix/case-12628-rc66

RC66: Fix for avatar glitches, head and legs folding into chest.
This commit is contained in:
John Conklin II 2018-04-17 08:28:35 -07:00 committed by GitHub
commit ab4d328d4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 8 deletions

View file

@ -5940,6 +5940,9 @@ void Application::nodeActivated(SharedNodePointer node) {
} }
getMyAvatar()->markIdentityDataChanged(); getMyAvatar()->markIdentityDataChanged();
getMyAvatar()->resetLastSent(); getMyAvatar()->resetLastSent();
// transmit a "sendAll" packet to the AvatarMixer we just connected to.
getMyAvatar()->sendAvatarDataPacket(true);
} }
} }

View file

@ -58,6 +58,13 @@ void SkeletonModel::initJointStates() {
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset); glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
_rig.initJointStates(geometry, modelOffset); _rig.initJointStates(geometry, modelOffset);
{
// initialize _jointData with proper values for default joints
QVector<JointData> defaultJointData;
_rig.copyJointsIntoJointData(defaultJointData);
_owningAvatar->setRawJointData(defaultJointData);
}
// Determine the default eye position for avatar scale = 1.0 // Determine the default eye position for avatar scale = 1.0
int headJointIndex = geometry.headJointIndex; int headJointIndex = geometry.headJointIndex;
if (0 > headJointIndex || headJointIndex >= _rig.getJointStateCount()) { if (0 > headJointIndex || headJointIndex >= _rig.getJointStateCount()) {

View file

@ -559,7 +559,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
const JointData& last = lastSentJointData[i]; const JointData& last = lastSentJointData[i];
if (!data.rotationIsDefaultPose) { if (!data.rotationIsDefaultPose) {
if (sendAll || last.rotationIsDefaultPose || last.rotation != data.rotation) { bool mustSend = sendAll || last.rotationIsDefaultPose;
if (mustSend || last.rotation != data.rotation) {
bool largeEnoughRotation = true; bool largeEnoughRotation = true;
if (cullSmallChanges) { if (cullSmallChanges) {
@ -568,7 +569,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
largeEnoughRotation = fabsf(glm::dot(last.rotation, data.rotation)) < minRotationDOT; largeEnoughRotation = fabsf(glm::dot(last.rotation, data.rotation)) < minRotationDOT;
} }
if (sendAll || !cullSmallChanges || largeEnoughRotation) { if (mustSend || !cullSmallChanges || largeEnoughRotation) {
validity |= (1 << validityBit); validity |= (1 << validityBit);
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
rotationSentCount++; rotationSentCount++;
@ -608,10 +609,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
float maxTranslationDimension = 0.0; float maxTranslationDimension = 0.0;
for (int i = 0; i < _jointData.size(); i++) { for (int i = 0; i < _jointData.size(); i++) {
const JointData& data = _jointData[i]; const JointData& data = _jointData[i];
const JointData& last = lastSentJointData[i];
if (!data.translationIsDefaultPose) { if (!data.translationIsDefaultPose) {
if (sendAll || lastSentJointData[i].translation != data.translation) { bool mustSend = sendAll || last.translationIsDefaultPose;
if (sendAll || !cullSmallChanges || glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation) { if (mustSend || last.translation != data.translation) {
if (mustSend || !cullSmallChanges || glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation) {
validity |= (1 << validityBit); validity |= (1 << validityBit);
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
translationSentCount++; translationSentCount++;
@ -669,6 +672,19 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
} }
if (sentJointDataOut) { if (sentJointDataOut) {
// Mark default poses in lastSentJointData, so when they become non-default we send them.
for (int i = 0; i < _jointData.size(); i++) {
const JointData& data = _jointData[i];
JointData& local = localSentJointDataOut[i];
if (data.rotationIsDefaultPose) {
local.rotationIsDefaultPose = true;
}
if (data.translationIsDefaultPose) {
local.translationIsDefaultPose = true;
}
}
// Push new sent joint data to sentJointDataOut // Push new sent joint data to sentJointDataOut
sentJointDataOut->swap(localSentJointDataOut); sentJointDataOut->swap(localSentJointDataOut);
} }
@ -1816,13 +1832,13 @@ void AvatarData::setJointMappingsFromNetworkReply() {
networkReply->deleteLater(); networkReply->deleteLater();
} }
void AvatarData::sendAvatarDataPacket() { void AvatarData::sendAvatarDataPacket(bool sendAll) {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
// about 2% of the time, we send a full update (meaning, we transmit all the joint data), even if nothing has changed. // about 2% of the time, we send a full update (meaning, we transmit all the joint data), even if nothing has changed.
// this is to guard against a joint moving once, the packet getting lost, and the joint never moving again. // this is to guard against a joint moving once, the packet getting lost, and the joint never moving again.
bool cullSmallData = (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO); bool cullSmallData = !sendAll && (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
auto dataDetail = cullSmallData ? SendAllData : CullSmallData; auto dataDetail = cullSmallData ? SendAllData : CullSmallData;
QByteArray avatarByteArray = toByteArrayStateful(dataDetail); QByteArray avatarByteArray = toByteArrayStateful(dataDetail);

View file

@ -256,6 +256,11 @@ namespace AvatarDataPacket {
SixByteQuat rotation[numValidRotations]; // encodeded and compressed by packOrientationQuatToSixBytes() SixByteQuat rotation[numValidRotations]; // encodeded and compressed by packOrientationQuatToSixBytes()
uint8_t translationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed translation follows. uint8_t translationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed translation follows.
SixByteTrans translation[numValidTranslations]; // encodeded and compressed by packFloatVec3ToSignedTwoByteFixed() SixByteTrans translation[numValidTranslations]; // encodeded and compressed by packFloatVec3ToSignedTwoByteFixed()
SixByteQuat leftHandControllerRotation;
SixByteTrans leftHandControllerTranslation;
SixByteQuat rightHandControllerRotation;
SixByteTrans rightHandControllerTranslation;
}; };
*/ */
size_t maxJointDataSize(size_t numJoints); size_t maxJointDataSize(size_t numJoints);
@ -707,11 +712,11 @@ signals:
void sessionUUIDChanged(); void sessionUUIDChanged();
public slots: public slots:
void sendAvatarDataPacket(); void sendAvatarDataPacket(bool sendAll = false);
void sendIdentityPacket(); void sendIdentityPacket();
void setJointMappingsFromNetworkReply(); void setJointMappingsFromNetworkReply();
void setSessionUUID(const QUuid& sessionUUID) { virtual void setSessionUUID(const QUuid& sessionUUID) {
if (sessionUUID != getID()) { if (sessionUUID != getID()) {
if (sessionUUID == QUuid()) { if (sessionUUID == QUuid()) {
setID(AVATAR_SELF_ID); setID(AVATAR_SELF_ID);