From 568af7a0721f3febdff5bd82561c28e2e650b073 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 12 Apr 2018 11:24:26 -0700 Subject: [PATCH 1/2] Fix for avatar recording playback on avatars with many joints Before this fix, playback of avatar recording frames could overflow the maximum UDP packet size (MTU). This is playback of a recording was causing all the rotations and translations to be transmitted, even if the translations were not any different then the avatar default pose. This explicitly records the rotationIsDefaultPose and translationIsDefaultPose in the recording stream. This does not break backwards compatibility. However, it does require new recordings for avatars with large numbers of bones. --- libraries/avatars/src/AvatarData.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 1bbc8cc1a5..cd8ca5c547 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2060,22 +2060,30 @@ static const QString JSON_AVATAR_VERSION = QStringLiteral("version"); static const int JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION = 0; static const int JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION = 1; +static const int JSON_AVATAR_JOINT_DEFAULT_POSE_BITS_VERSION = 2; QJsonValue toJsonValue(const JointData& joint) { QJsonArray result; result.push_back(toJsonValue(joint.rotation)); result.push_back(toJsonValue(joint.translation)); + result.push_back(QJsonValue(joint.rotationIsDefaultPose)); + result.push_back(QJsonValue(joint.translationIsDefaultPose)); return result; } -JointData jointDataFromJsonValue(const QJsonValue& json) { +JointData jointDataFromJsonValue(int version, const QJsonValue& json) { JointData result; if (json.isArray()) { QJsonArray array = json.toArray(); result.rotation = quatFromJsonValue(array[0]); - result.rotationIsDefaultPose = false; result.translation = vec3FromJsonValue(array[1]); - result.translationIsDefaultPose = false; + if (version >= JSON_AVATAR_JOINT_DEFAULT_POSE_BITS_VERSION) { + result.rotationIsDefaultPose = array[2].toBool(); + result.translationIsDefaultPose = array[3].toBool(); + } else { + result.rotationIsDefaultPose = false; + result.translationIsDefaultPose = false; + } } return result; } @@ -2083,7 +2091,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) { QJsonObject AvatarData::toJson() const { QJsonObject root; - root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION; + root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_DEFAULT_POSE_BITS_VERSION; if (!getSkeletonModelURL().isEmpty()) { root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString(); @@ -2247,7 +2255,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray(); jointArray.reserve(jointArrayJson.size()); for (const auto& jointJson : jointArrayJson) { - auto joint = jointDataFromJsonValue(jointJson); + auto joint = jointDataFromJsonValue(version, jointJson); jointArray.push_back(joint); } setRawJointData(jointArray); @@ -2558,4 +2566,4 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap& value[EntityID] = binaryEntityProperties; } -} \ No newline at end of file +} From da319b9af62f51a815ce8319491528366d30e688 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 12 Apr 2018 15:09:01 -0700 Subject: [PATCH 2/2] Changed version constants into a enum class, to fix macosx warnings. --- libraries/avatars/src/AvatarData.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index cd8ca5c547..08eee947ef 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2058,9 +2058,11 @@ static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities"); static const QString JSON_AVATAR_SCALE = QStringLiteral("scale"); static const QString JSON_AVATAR_VERSION = QStringLiteral("version"); -static const int JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION = 0; -static const int JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION = 1; -static const int JSON_AVATAR_JOINT_DEFAULT_POSE_BITS_VERSION = 2; +enum class JsonAvatarFrameVersion : int { + JointRotationsInRelativeFrame = 0, + JointRotationsInAbsoluteFrame, + JointDefaultPoseBits +}; QJsonValue toJsonValue(const JointData& joint) { QJsonArray result; @@ -2077,7 +2079,7 @@ JointData jointDataFromJsonValue(int version, const QJsonValue& json) { QJsonArray array = json.toArray(); result.rotation = quatFromJsonValue(array[0]); result.translation = vec3FromJsonValue(array[1]); - if (version >= JSON_AVATAR_JOINT_DEFAULT_POSE_BITS_VERSION) { + if (version >= (int)JsonAvatarFrameVersion::JointDefaultPoseBits) { result.rotationIsDefaultPose = array[2].toBool(); result.translationIsDefaultPose = array[3].toBool(); } else { @@ -2091,7 +2093,7 @@ JointData jointDataFromJsonValue(int version, const QJsonValue& json) { QJsonObject AvatarData::toJson() const { QJsonObject root; - root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_DEFAULT_POSE_BITS_VERSION; + root[JSON_AVATAR_VERSION] = (int)JsonAvatarFrameVersion::JointDefaultPoseBits; if (!getSkeletonModelURL().isEmpty()) { root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString(); @@ -2166,7 +2168,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { version = json[JSON_AVATAR_VERSION].toInt(); } else { // initial data did not have a version field. - version = JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION; + version = (int)JsonAvatarFrameVersion::JointRotationsInRelativeFrame; } if (json.contains(JSON_AVATAR_BODY_MODEL)) { @@ -2243,7 +2245,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { // } if (json.contains(JSON_AVATAR_JOINT_ARRAY)) { - if (version == JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION) { + if (version == (int)JsonAvatarFrameVersion::JointRotationsInRelativeFrame) { // because we don't have the full joint hierarchy skeleton of the model, // we can't properly convert from relative rotations into absolute rotations. quint64 now = usecTimestampNow();