From 1ad197df268393a0d07cea7e1c0bce56543d1532 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 16 Apr 2019 17:40:43 -0700 Subject: [PATCH 1/6] Send avatar skeleton trait --- .../src/avatars/AvatarMixerClientData.cpp | 8 +- .../src/avatars-renderer/Avatar.cpp | 24 ++++ .../src/avatars-renderer/Avatar.h | 2 + libraries/avatars/src/AvatarData.cpp | 103 ++++++++++++++++++ libraries/avatars/src/AvatarData.h | 42 ++++++- libraries/avatars/src/AvatarTraits.h | 2 +- 6 files changed, 178 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 1b86e0dff2..29c0697249 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -179,7 +179,13 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, if (packetTraitVersion > _lastReceivedTraitVersions[traitType]) { _avatar->processTrait(traitType, message.read(traitSize)); _lastReceivedTraitVersions[traitType] = packetTraitVersion; - + if (traitType == AvatarTraits::SkeletonData) { + qDebug() << "Sending skeleton avatar trait"; + auto packet = NLPacket::create(PacketType::SetAvatarTraits, -1, true); + AvatarTraits::packVersionedTrait(AvatarTraits::SkeletonData, *packet, packetTraitVersion, *_avatar); + auto nodeList = DependencyManager::get(); + nodeList->sendPacket(std::move(packet), sendingNode); + } if (traitType == AvatarTraits::SkeletonModelURL) { // special handling for skeleton model URL, since we need to make sure it is in the whitelist checkSkeletonURLAgainstWhitelist(slaveSharedData, sendingNode, packetTraitVersion); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index b6c5c6d235..0d78bd810a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1449,6 +1449,28 @@ QStringList Avatar::getJointNames() const { return result; } +std::vector Avatar::getSkeletonDefaultData() { + std::vector defaultSkeletonData; + if (_skeletonModel->isLoaded()) { + auto jointNames = getJointNames(); + int sizeCount = 0; + for (int i = 0; i < min(43, jointNames.size()); i++) { + AvatarSkeletonTrait::UnpackedJointData jointData; + jointData.jointParent = _skeletonModel->getRig().getJointParentIndex(i); + jointData.jointIndex = i; + jointData.defaultRotation = getDefaultJointRotation(i); + jointData.defaultTranslation = getDefaultJointTranslation(i); + jointData.defaultScale = glm::length(getAbsoluteJointScaleInObjectFrame(i)); + jointData.jointName = jointNames[i]; + jointData.stringLength = jointNames[i].size(); + jointData.stringStart = sizeCount; + sizeCount += jointNames[i].size(); + defaultSkeletonData.push_back(jointData); + } + } + return defaultSkeletonData; +} + glm::vec3 Avatar::getJointPosition(int index) const { glm::vec3 position; _skeletonModel->getJointPositionInWorldFrame(index, position); @@ -1515,6 +1537,8 @@ void Avatar::rigReady() { buildSpine2SplineRatioCache(); computeMultiSphereShapes(); buildSpine2SplineRatioCache(); + setSkeletonData(getSkeletonDefaultData()); + sendSkeletonData(); } // rig has been reset. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index aef5ac09e9..afec768e33 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -199,6 +199,8 @@ public: virtual int getJointIndex(const QString& name) const override; virtual QStringList getJointNames() const override; + std::vector getSkeletonDefaultData(); + /**jsdoc * Gets the default rotation of a joint (in the current avatar) relative to its parent. *

For information on the joint hierarchy used, see diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a2b0b808ba..3491933ce5 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1990,11 +1990,98 @@ QUrl AvatarData::getWireSafeSkeletonModelURL() const { return QUrl(); } } +QByteArray AvatarData::packSkeletonData() const { + int avatarDataSize = 0; + QByteArray avatarDataByteArray; + //_avatarSkeletonDataLock.withReadLock([&] { + // Add header + AvatarSkeletonTrait::Header header; + header.maxScaleDimension = 0.0f; + header.maxTranslationDimension = 0.0f; + header.numJoints = (uint8_t)_avatarSkeletonData.size(); + header.padding = 0; + header.stringTableLength = 0; + qDebug() << "Dealing with: " << _avatarSkeletonData.size() << " joints"; + for (size_t i = 0; i < _avatarSkeletonData.size(); i++) { + header.stringTableLength += (uint16_t)_avatarSkeletonData[i].jointName.size(); + auto &translation = _avatarSkeletonData[i].defaultTranslation; + header.maxTranslationDimension = std::max(header.maxTranslationDimension, std::max(std::max(translation.x, translation.y), translation.z)); + header.maxScaleDimension = std::max(header.maxScaleDimension, _avatarSkeletonData[i].defaultScale); + } + + const int byteArraySize = (int)sizeof(AvatarSkeletonTrait::Header) + (int)(header.numJoints * sizeof(AvatarSkeletonTrait::JointData)) + header.stringTableLength; + avatarDataByteArray = QByteArray(byteArraySize, 0); + unsigned char* destinationBuffer = reinterpret_cast(avatarDataByteArray.data()); + const unsigned char* const startPosition = destinationBuffer; + + memcpy(destinationBuffer, &header, sizeof(header)); + destinationBuffer += sizeof(AvatarSkeletonTrait::Header); + + QString stringTable = ""; + for (size_t i = 0; i < _avatarSkeletonData.size(); i++) { + AvatarSkeletonTrait::JointData jdata; + jdata.boneType = _avatarSkeletonData[i].boneType; + jdata.jointParent = _avatarSkeletonData[i].jointParent; + packFloatRatioToTwoByte((uint8_t*)(&jdata.defaultScale), _avatarSkeletonData[i].defaultScale / header.maxScaleDimension); + packOrientationQuatToSixBytes(jdata.defaultRotation, _avatarSkeletonData[i].defaultRotation); + packFloatVec3ToSignedTwoByteFixed(jdata.defaultTranslation, _avatarSkeletonData[i].defaultTranslation / header.maxTranslationDimension, TRANSLATION_COMPRESSION_RADIX); + jdata.jointIndex = (uint16_t)i; + jdata.stringStart = (uint16_t)_avatarSkeletonData[i].stringStart; + jdata.stringLength = (uint8_t)_avatarSkeletonData[i].stringLength; + stringTable += _avatarSkeletonData[i].jointName; + memcpy(destinationBuffer, &jdata, sizeof(AvatarSkeletonTrait::JointData)); + destinationBuffer += sizeof(AvatarSkeletonTrait::JointData); + } + + memcpy(destinationBuffer, stringTable.toUtf8(), header.stringTableLength); + destinationBuffer += header.stringTableLength; + + avatarDataSize = destinationBuffer - startPosition; + qDebug() << "Data size: " << avatarDataSize; + //}); + return avatarDataByteArray.left(avatarDataSize); +} QByteArray AvatarData::packSkeletonModelURL() const { return getWireSafeSkeletonModelURL().toEncoded(); } +void AvatarData::unpackSkeletonData(const QByteArray& data) { + + const unsigned char* startPosition = reinterpret_cast(data.data()); + const unsigned char* endPosition = startPosition + data.size(); + const unsigned char* sourceBuffer = startPosition; + + auto header = reinterpret_cast(sourceBuffer); + sourceBuffer += sizeof(const AvatarSkeletonTrait::Header); + + std::vector joints; + for (uint8_t i = 0; i < header->numJoints; i++) { + auto jointData = reinterpret_cast(sourceBuffer); + sourceBuffer += sizeof(const AvatarSkeletonTrait::JointData); + AvatarSkeletonTrait::UnpackedJointData uJointData; + uJointData.boneType = (int)jointData->boneType; + uJointData.jointIndex = (int)i; + uJointData.stringLength = (int)jointData->stringLength; + uJointData.stringStart = (int)jointData->stringStart; + unpackOrientationQuatFromSixBytes(reinterpret_cast(&jointData->defaultRotation), uJointData.defaultRotation); + unpackFloatVec3FromSignedTwoByteFixed(reinterpret_cast(&jointData->defaultTranslation), uJointData.defaultTranslation, TRANSLATION_COMPRESSION_RADIX); + unpackFloatScalarFromSignedTwoByteFixed((const int16_t*)(&jointData->defaultScale), &uJointData.defaultScale, TRANSLATION_COMPRESSION_RADIX); + uJointData.defaultTranslation *= header->maxTranslationDimension; + uJointData.defaultScale *= header->maxScaleDimension; + joints.push_back(uJointData); + } + qDebug() << "_____length: " << header->stringTableLength; + QString table = QString::fromUtf8(reinterpret_cast(sourceBuffer), (int)header->stringTableLength); + for (size_t i = 0; i < joints.size(); i++) { + QStringRef subString(&table, joints[i].stringStart, joints[i].stringLength); + joints[i].jointName = subString.toString(); + qDebug() << "_____data: " << joints[i].boneType << " " << joints[i].jointIndex << " " << joints[i].stringLength << " " << joints[i].stringStart << " " << joints[i].defaultRotation << " " << joints[i].defaultScale << joints[i].defaultTranslation; + qDebug() << "_____JointNameReveived: " << joints[i].jointName; + } + setSkeletonData(joints); +} + void AvatarData::unpackSkeletonModelURL(const QByteArray& data) { auto skeletonModelURL = QUrl::fromEncoded(data); setSkeletonModelURL(skeletonModelURL); @@ -2030,6 +2117,8 @@ QByteArray AvatarData::packTrait(AvatarTraits::TraitType traitType) const { // Call packer function if (traitType == AvatarTraits::SkeletonModelURL) { traitBinaryData = packSkeletonModelURL(); + } else if (traitType == AvatarTraits::SkeletonData) { + traitBinaryData = packSkeletonData(); } return traitBinaryData; @@ -2051,6 +2140,8 @@ QByteArray AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, Avat void AvatarData::processTrait(AvatarTraits::TraitType traitType, QByteArray traitBinaryData) { if (traitType == AvatarTraits::SkeletonModelURL) { unpackSkeletonModelURL(traitBinaryData); + } else if (traitType == AvatarTraits::SkeletonData) { + unpackSkeletonData(traitBinaryData); } } @@ -2997,6 +3088,18 @@ AABox AvatarData::computeBubbleBox(float bubbleScale) const { return box; } +void AvatarData::setSkeletonData(const std::vector& skeletonData) { + _avatarSkeletonDataLock.withWriteLock([&] { + _avatarSkeletonData = skeletonData; + }); +} + +void AvatarData::sendSkeletonData() const{ + if (_clientTraitsHandler) { + _clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonData); + } +} + AABox AvatarData::getDefaultBubbleBox() const { AABox bubbleBox(_defaultBubbleBox); bubbleBox.translate(_globalPosition); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 1c4b0cfc53..a0ce5b2201 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -145,6 +145,39 @@ const char AVATARDATA_FLAGS_MINIMUM = 0; using SmallFloat = uint16_t; // a compressed float with less precision, user defined radix +namespace AvatarSkeletonTrait { + PACKED_BEGIN struct Header { + float maxTranslationDimension; + float maxScaleDimension; + uint8_t numJoints; + uint8_t padding; + uint16_t stringTableLength; + } PACKED_END; + + PACKED_BEGIN struct JointData { + uint16_t stringStart; + uint8_t stringLength; + uint8_t boneType; + uint8_t defaultTranslation[6]; + uint8_t defaultRotation[6]; + uint16_t defaultScale; + uint16_t jointIndex; + uint16_t jointParent; + } PACKED_END; + + struct UnpackedJointData { + int jointParent; + int stringStart; + int stringLength; + int boneType; + glm::vec3 defaultTranslation; + glm::quat defaultRotation; + float defaultScale; + int jointIndex; + QString jointName; + }; +} + namespace AvatarDataPacket { // NOTE: every time AvatarData is sent from mixer to client, it also includes the GUIID for the session @@ -258,6 +291,7 @@ namespace AvatarDataPacket { PACKED_BEGIN struct AvatarLocalPosition { float localPosition[3]; // parent frame translation of the avatar } PACKED_END; + const size_t AVATAR_LOCAL_POSITION_SIZE = 12; static_assert(sizeof(AvatarLocalPosition) == AVATAR_LOCAL_POSITION_SIZE, "AvatarDataPacket::AvatarLocalPosition size doesn't match."); @@ -1419,6 +1453,8 @@ public: void setIsNewAvatar(bool isNewAvatar) { _isNewAvatar = isNewAvatar; } bool getIsNewAvatar() { return _isNewAvatar; } void setIsClientAvatar(bool isClientAvatar) { _isClientAvatar = isClientAvatar; } + void setSkeletonData(const std::vector& skeletonData); + void sendSkeletonData() const; signals: @@ -1597,12 +1633,13 @@ protected: bool hasParent() const { return !getParentID().isNull(); } bool hasFaceTracker() const { return _headData ? _headData->_isFaceTrackerConnected : false; } + QByteArray packSkeletonData() const; QByteArray packSkeletonModelURL() const; QByteArray packAvatarEntityTraitInstance(AvatarTraits::TraitInstanceID traitInstanceID); QByteArray packGrabTraitInstance(AvatarTraits::TraitInstanceID traitInstanceID); void unpackSkeletonModelURL(const QByteArray& data); - + void unpackSkeletonData(const QByteArray& data); // isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "master" // Audio Mixer that the replicated avatar is connected to. @@ -1719,6 +1756,9 @@ protected: AvatarGrabDataMap _avatarGrabData; bool _avatarGrabDataChanged { false }; // by network + mutable ReadWriteLockable _avatarSkeletonDataLock; + std::vector _avatarSkeletonData; + // used to transform any sensor into world space, including the _hmdSensorMat, or hand controllers. ThreadSafeValueCache _sensorToWorldMatrixCache { glm::mat4() }; ThreadSafeValueCache _controllerLeftHandMatrixCache { glm::mat4() }; diff --git a/libraries/avatars/src/AvatarTraits.h b/libraries/avatars/src/AvatarTraits.h index 13d64ec225..007b0418a9 100644 --- a/libraries/avatars/src/AvatarTraits.h +++ b/libraries/avatars/src/AvatarTraits.h @@ -29,7 +29,7 @@ namespace AvatarTraits { // Simple traits SkeletonModelURL = 0, - + SkeletonData, // Instanced traits FirstInstancedTrait, AvatarEntity = FirstInstancedTrait, From 20cac4cd4d92ff5fd59f5826308a91db2f8deb78 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 22 Apr 2019 11:38:27 -0700 Subject: [PATCH 2/6] Rotation fix and refactor --- .../src/avatars/AvatarMixerClientData.cpp | 7 --- interface/src/Menu.cpp | 2 + interface/src/Menu.h | 1 + interface/src/avatar/AvatarManager.cpp | 7 +++ interface/src/avatar/AvatarManager.h | 10 ++++ interface/src/avatar/OtherAvatar.cpp | 57 +++++++++++++++++++ interface/src/avatar/OtherAvatar.h | 2 +- .../src/avatars-renderer/Avatar.cpp | 20 +++++-- libraries/avatars/src/AvatarData.cpp | 37 ++++++++---- libraries/avatars/src/AvatarData.h | 14 ++++- libraries/avatars/src/ClientTraitsHandler.cpp | 3 +- 11 files changed, 131 insertions(+), 29 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 29c0697249..3555669c65 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -179,13 +179,6 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, if (packetTraitVersion > _lastReceivedTraitVersions[traitType]) { _avatar->processTrait(traitType, message.read(traitSize)); _lastReceivedTraitVersions[traitType] = packetTraitVersion; - if (traitType == AvatarTraits::SkeletonData) { - qDebug() << "Sending skeleton avatar trait"; - auto packet = NLPacket::create(PacketType::SetAvatarTraits, -1, true); - AvatarTraits::packVersionedTrait(AvatarTraits::SkeletonData, *packet, packetTraitVersion, *_avatar); - auto nodeList = DependencyManager::get(); - nodeList->sendPacket(std::move(packet), sendingNode); - } if (traitType == AvatarTraits::SkeletonModelURL) { // special handling for skeleton model URL, since we need to make sure it is in the whitelist checkSkeletonURLAgainstWhitelist(slaveSharedData, sendingNode, packetTraitVersion); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e9aadea2b6..98c9fd92c9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -627,6 +627,8 @@ Menu::Menu() { avatar.get(), SLOT(setEnableDebugDrawAnimPose(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawPosition, 0, false, avatar.get(), SLOT(setEnableDebugDrawPosition(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawOtherSkeletons, 0, false, + avatarManager.data(), SLOT(setEnableDebugDrawOtherSkeletons(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true, avatar.get(), SLOT(setEnableMeshVisible(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3611faaf8f..076f54ca1d 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -33,6 +33,7 @@ namespace MenuOption { const QString AnimDebugDrawBaseOfSupport = "Debug Draw Base of Support"; const QString AnimDebugDrawDefaultPose = "Debug Draw Default Pose"; const QString AnimDebugDrawPosition= "Debug Draw Position"; + const QString AnimDebugDrawOtherSkeletons = "Debug Draw Other Skeletons"; const QString AskToResetSettings = "Ask To Reset Settings on Start"; const QString AssetMigration = "ATP Asset Migration"; const QString AssetServer = "Asset Browser"; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 575d87dfb7..38dc668ac2 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -120,6 +120,8 @@ void AvatarManager::init() { _myAvatar->addToScene(_myAvatar, scene, transaction); scene->enqueueTransaction(transaction); } + + setEnableDebugDrawOtherSkeletons(Menu::getInstance()->isOptionChecked(MenuOption::AnimDebugDrawOtherSkeletons)); } void AvatarManager::setSpace(workload::SpacePointer& space ) { @@ -334,9 +336,14 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { if (avatar->getSkeletonModel()->isLoaded() && avatar->getWorkloadRegion() == workload::Region::R1) { _myAvatar->addAvatarHandsToFlow(avatar); } + if (_drawOtherAvatarSkeletons) { + avatar->debugJointData(); + } + avatar->setEnableMeshVisible(!_drawOtherAvatarSkeletons); avatar->updateRenderItem(renderTransaction); avatar->updateSpaceProxy(workloadTransaction); avatar->setLastRenderUpdateTime(startTime); + } else { // we've spent our time budget for this priority bucket // let's deal with the reminding avatars if this pass and BREAK from the for loop diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index f9b82da0c1..bbc27b3d47 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -213,6 +213,15 @@ public slots: */ void updateAvatarRenderStatus(bool shouldRenderAvatars); + /**jsdoc + * Displays other avatars skeletons debug graphics. + * @function AvatarManager.setEnableDebugDrawOtherSkeletons + * @param {boolean} enabled - true to show the debug graphics, false to hide. + */ + void setEnableDebugDrawOtherSkeletons(bool isEnabled) { + _drawOtherAvatarSkeletons = isEnabled; + } + protected: AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) override; @@ -250,6 +259,7 @@ private: workload::SpacePointer _space; AvatarTransit::TransitConfig _transitConfig; + bool _drawOtherAvatarSkeletons { false }; }; #endif // hifi_AvatarManager_h diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 2e775a20c3..f179f4498e 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -16,6 +16,7 @@ #include "Application.h" #include "AvatarMotionState.h" #include "DetailedMotionState.h" +#include "DebugDraw.h" const float DISPLAYNAME_FADE_TIME = 0.5f; const float DISPLAYNAME_FADE_FACTOR = pow(0.01f, 1.0f / DISPLAYNAME_FADE_TIME); @@ -358,6 +359,62 @@ void OtherAvatar::simulate(float deltaTime, bool inView) { } } +void OtherAvatar::debugJointData() const { + // Get a copy of the joint data + auto jointData = getJointData(); + auto skeletonData = getSkeletonData(); + if ((int)skeletonData.size() == jointData.size() && jointData.size() != 0) { + const vec4 RED(1.0f, 0.0f, 0.0f, 1.0f); + const vec4 GREEN(0.0f, 1.0f, 0.0f, 1.0f); + const vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); + const vec4 LIGHT_RED(1.0f, 0.5f, 0.5f, 1.0f); + const vec4 LIGHT_GREEN(0.5f, 1.0f, 0.5f, 1.0f); + const vec4 LIGHT_BLUE(0.5f, 0.5f, 1.0f, 1.0f); + const vec4 GREY(0.3f, 0.3f, 0.3f, 1.0f); + const vec4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); + const float AXIS_LENGTH = 0.1f; + + std::vector jointPoses; + glm::quat rotationOffset = Quaternions::IDENTITY; + std::vector jointNames; + AnimPose rigToAvatar = AnimPose(Quaternions::Y_180 * getWorldOrientation(), getWorldPosition()); + for (int i = 0; i < jointData.size(); i++) { + float jointScale = skeletonData[i].defaultScale * getTargetScale(); + auto jointRotation = rigToAvatar.rot() * (jointData[i].rotationIsDefaultPose ? skeletonData[i].defaultRotation : jointData[i].rotation); + auto jointTranslation = jointScale * (jointData[i].translationIsDefaultPose ? skeletonData[i].defaultTranslation : jointData[i].translation); + if (skeletonData[i].jointName == "Hips") { + jointTranslation = glm::vec3(0.0f); + } + jointPoses.push_back(AnimPose(jointRotation, jointTranslation)); + jointNames.push_back(skeletonData[i].jointName); + } + QVector worldFramePoses; + for (size_t i = 0; i < jointPoses.size(); i++) { + auto &jointPose = jointPoses[i]; + int parentIndex = skeletonData[i].parentIndex; + if (parentIndex < worldFramePoses.size()) { + glm::vec3 xAxis = jointPose.rot() * Vectors::UNIT_X; + glm::vec3 yAxis = jointPose.rot() * Vectors::UNIT_Y; + glm::vec3 zAxis = jointPose.rot() * Vectors::UNIT_Z; + + auto parentRotation = parentIndex > -1 ? jointPoses[parentIndex].rot() : Quaternions::IDENTITY; + auto parentPosition = parentIndex > -1 ? worldFramePoses[parentIndex].trans() : rigToAvatar.trans(); + auto jointPosition = parentPosition + parentRotation * (jointPose.trans() * METERS_PER_CENTIMETER); + worldFramePoses.push_back(AnimPose(jointPose.rot(), jointPosition)); + + DebugDraw::getInstance().drawRay(jointPosition, jointPosition + AXIS_LENGTH * xAxis, jointData[i].rotationIsDefaultPose ? LIGHT_RED : RED); + DebugDraw::getInstance().drawRay(jointPosition, jointPosition + AXIS_LENGTH * yAxis, jointData[i].rotationIsDefaultPose ? LIGHT_GREEN : GREEN); + DebugDraw::getInstance().drawRay(jointPosition, jointPosition + AXIS_LENGTH * zAxis, jointData[i].rotationIsDefaultPose ? LIGHT_BLUE : BLUE); + // draw line to parent + if (parentIndex != -1) { + DebugDraw::getInstance().drawRay(jointPosition, parentPosition, jointData[i].translationIsDefaultPose ? WHITE : GREY); + } + } + } + + } +} + void OtherAvatar::handleChangedAvatarEntityData() { PerformanceTimer perfTimer("attachments"); diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index 7669f44806..743356f71d 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -66,7 +66,7 @@ public: void setCollisionWithOtherAvatarsFlags() override; void simulate(float deltaTime, bool inView) override; - + void OtherAvatar::debugJointData() const; friend AvatarManager; protected: diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 0d78bd810a..1129bee7e9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1452,15 +1452,25 @@ QStringList Avatar::getJointNames() const { std::vector Avatar::getSkeletonDefaultData() { std::vector defaultSkeletonData; if (_skeletonModel->isLoaded()) { - auto jointNames = getJointNames(); + auto &model = _skeletonModel->getHFMModel(); + auto &rig = _skeletonModel->getRig(); + float geometryToRigScale = glm::length(extractScale(rig.getGeometryToRigTransform())); + QStringList jointNames = getJointNames(); int sizeCount = 0; - for (int i = 0; i < min(43, jointNames.size()); i++) { + int jointCount = 0; + for (int i = 0; i < jointNames.size(); i++) { AvatarSkeletonTrait::UnpackedJointData jointData; - jointData.jointParent = _skeletonModel->getRig().getJointParentIndex(i); jointData.jointIndex = i; - jointData.defaultRotation = getDefaultJointRotation(i); + jointData.parentIndex = rig.getJointParentIndex(i); + if (jointData.parentIndex == -1) { + jointData.boneType = model.joints[i].isSkeletonJoint ? AvatarSkeletonTrait::BoneType::SkeletonRoot : AvatarSkeletonTrait::BoneType::NonSkeletonRoot; + } else { + jointData.boneType = model.joints[i].isSkeletonJoint ? AvatarSkeletonTrait::BoneType::SkeletonChild : AvatarSkeletonTrait::BoneType::NonSkeletonChild; + } + jointData.defaultRotation = rig.getAbsoluteDefaultPose(i).rot(); jointData.defaultTranslation = getDefaultJointTranslation(i); - jointData.defaultScale = glm::length(getAbsoluteJointScaleInObjectFrame(i)); + float jointLocalScale = glm::length(extractScale(model.joints[i].transform)); + jointData.defaultScale = jointLocalScale / geometryToRigScale; jointData.jointName = jointNames[i]; jointData.stringLength = jointNames[i].size(); jointData.stringStart = sizeCount; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 3491933ce5..5e68a26512 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1635,6 +1635,13 @@ void AvatarData::setJointData(int index, const glm::quat& rotation, const glm::v data.translationIsDefaultPose = false; } +QVector AvatarData::getJointData() const { + QVector jointData; + QReadLocker readLock(&_jointDataLock); + jointData = _jointData; + return jointData; +} + void AvatarData::clearJointData(int index) { if (index < 0 || index >= LOWEST_PSEUDO_JOINT_INDEX) { return; @@ -1991,17 +1998,17 @@ QUrl AvatarData::getWireSafeSkeletonModelURL() const { } } QByteArray AvatarData::packSkeletonData() const { + // Send an avatar trait packet with the skeleton data before the mesh is loaded int avatarDataSize = 0; QByteArray avatarDataByteArray; - //_avatarSkeletonDataLock.withReadLock([&] { + _avatarSkeletonDataLock.withReadLock([&] { // Add header AvatarSkeletonTrait::Header header; header.maxScaleDimension = 0.0f; header.maxTranslationDimension = 0.0f; header.numJoints = (uint8_t)_avatarSkeletonData.size(); - header.padding = 0; header.stringTableLength = 0; - qDebug() << "Dealing with: " << _avatarSkeletonData.size() << " joints"; + for (size_t i = 0; i < _avatarSkeletonData.size(); i++) { header.stringTableLength += (uint16_t)_avatarSkeletonData[i].jointName.size(); auto &translation = _avatarSkeletonData[i].defaultTranslation; @@ -2021,7 +2028,7 @@ QByteArray AvatarData::packSkeletonData() const { for (size_t i = 0; i < _avatarSkeletonData.size(); i++) { AvatarSkeletonTrait::JointData jdata; jdata.boneType = _avatarSkeletonData[i].boneType; - jdata.jointParent = _avatarSkeletonData[i].jointParent; + jdata.parentIndex = _avatarSkeletonData[i].parentIndex; packFloatRatioToTwoByte((uint8_t*)(&jdata.defaultScale), _avatarSkeletonData[i].defaultScale / header.maxScaleDimension); packOrientationQuatToSixBytes(jdata.defaultRotation, _avatarSkeletonData[i].defaultRotation); packFloatVec3ToSignedTwoByteFixed(jdata.defaultTranslation, _avatarSkeletonData[i].defaultTranslation / header.maxTranslationDimension, TRANSLATION_COMPRESSION_RADIX); @@ -2037,8 +2044,7 @@ QByteArray AvatarData::packSkeletonData() const { destinationBuffer += header.stringTableLength; avatarDataSize = destinationBuffer - startPosition; - qDebug() << "Data size: " << avatarDataSize; - //}); + }); return avatarDataByteArray.left(avatarDataSize); } @@ -2064,20 +2070,22 @@ void AvatarData::unpackSkeletonData(const QByteArray& data) { uJointData.jointIndex = (int)i; uJointData.stringLength = (int)jointData->stringLength; uJointData.stringStart = (int)jointData->stringStart; + uJointData.parentIndex = ((uJointData.boneType == AvatarSkeletonTrait::BoneType::SkeletonRoot) || + (uJointData.boneType == AvatarSkeletonTrait::BoneType::NonSkeletonRoot)) ? -1 : (int)jointData->parentIndex; unpackOrientationQuatFromSixBytes(reinterpret_cast(&jointData->defaultRotation), uJointData.defaultRotation); unpackFloatVec3FromSignedTwoByteFixed(reinterpret_cast(&jointData->defaultTranslation), uJointData.defaultTranslation, TRANSLATION_COMPRESSION_RADIX); - unpackFloatScalarFromSignedTwoByteFixed((const int16_t*)(&jointData->defaultScale), &uJointData.defaultScale, TRANSLATION_COMPRESSION_RADIX); + unpackFloatRatioFromTwoByte(reinterpret_cast(&jointData->defaultScale), uJointData.defaultScale); uJointData.defaultTranslation *= header->maxTranslationDimension; uJointData.defaultScale *= header->maxScaleDimension; joints.push_back(uJointData); } - qDebug() << "_____length: " << header->stringTableLength; QString table = QString::fromUtf8(reinterpret_cast(sourceBuffer), (int)header->stringTableLength); for (size_t i = 0; i < joints.size(); i++) { QStringRef subString(&table, joints[i].stringStart, joints[i].stringLength); joints[i].jointName = subString.toString(); - qDebug() << "_____data: " << joints[i].boneType << " " << joints[i].jointIndex << " " << joints[i].stringLength << " " << joints[i].stringStart << " " << joints[i].defaultRotation << " " << joints[i].defaultScale << joints[i].defaultTranslation; - qDebug() << "_____JointNameReveived: " << joints[i].jointName; + } + if (_clientTraitsHandler) { + _clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonData); } setSkeletonData(joints); } @@ -2204,7 +2212,6 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { } _skeletonModelURL = expanded; - if (_clientTraitsHandler) { _clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonModelURL); } @@ -3094,6 +3101,14 @@ void AvatarData::setSkeletonData(const std::vector AvatarData::getSkeletonData() const { + std::vector skeletonData; + _avatarSkeletonDataLock.withReadLock([&] { + skeletonData = _avatarSkeletonData; + }); + return skeletonData; +} + void AvatarData::sendSkeletonData() const{ if (_clientTraitsHandler) { _clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonData); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a0ce5b2201..08e5db61e7 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -146,11 +146,17 @@ const char AVATARDATA_FLAGS_MINIMUM = 0; using SmallFloat = uint16_t; // a compressed float with less precision, user defined radix namespace AvatarSkeletonTrait { + enum BoneType { + SkeletonRoot = 0, + SkeletonChild, + NonSkeletonRoot, + NonSkeletonChild + }; + PACKED_BEGIN struct Header { float maxTranslationDimension; float maxScaleDimension; uint8_t numJoints; - uint8_t padding; uint16_t stringTableLength; } PACKED_END; @@ -162,11 +168,10 @@ namespace AvatarSkeletonTrait { uint8_t defaultRotation[6]; uint16_t defaultScale; uint16_t jointIndex; - uint16_t jointParent; + uint16_t parentIndex; } PACKED_END; struct UnpackedJointData { - int jointParent; int stringStart; int stringLength; int boneType; @@ -174,6 +179,7 @@ namespace AvatarSkeletonTrait { glm::quat defaultRotation; float defaultScale; int jointIndex; + int parentIndex; QString jointName; }; } @@ -1454,7 +1460,9 @@ public: bool getIsNewAvatar() { return _isNewAvatar; } void setIsClientAvatar(bool isClientAvatar) { _isClientAvatar = isClientAvatar; } void setSkeletonData(const std::vector& skeletonData); + std::vector getSkeletonData() const; void sendSkeletonData() const; + QVector getJointData() const; signals: diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index f6bd66e89a..8f6871f0e9 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -107,8 +107,7 @@ int ClientTraitsHandler::sendChangedTraitsToMixer() { if (initialSend || *simpleIt == Updated) { bytesWritten += AvatarTraits::packTrait(traitType, *traitsPacketList, *_owningAvatar); - - + if (traitType == AvatarTraits::SkeletonModelURL) { // keep track of our skeleton version in case we get an override back _currentSkeletonVersion = _currentTraitVersion; From 4a236c3a4b53cf3f0abb92446ca543ae3fe2071a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 22 Apr 2019 12:40:56 -0700 Subject: [PATCH 3/6] Fix warnings --- interface/src/avatar/OtherAvatar.cpp | 4 ++-- interface/src/avatar/OtherAvatar.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index f179f4498e..7c7e1b390e 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -374,7 +374,7 @@ void OtherAvatar::debugJointData() const { const vec4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); const float AXIS_LENGTH = 0.1f; - std::vector jointPoses; + AnimPoseVec jointPoses; glm::quat rotationOffset = Quaternions::IDENTITY; std::vector jointNames; AnimPose rigToAvatar = AnimPose(Quaternions::Y_180 * getWorldOrientation(), getWorldPosition()); @@ -389,7 +389,7 @@ void OtherAvatar::debugJointData() const { jointNames.push_back(skeletonData[i].jointName); } QVector worldFramePoses; - for (size_t i = 0; i < jointPoses.size(); i++) { + for (int i = 0; i < (int)jointPoses.size(); i++) { auto &jointPose = jointPoses[i]; int parentIndex = skeletonData[i].parentIndex; if (parentIndex < worldFramePoses.size()) { diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index 743356f71d..43bfd2a9ae 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -66,7 +66,7 @@ public: void setCollisionWithOtherAvatarsFlags() override; void simulate(float deltaTime, bool inView) override; - void OtherAvatar::debugJointData() const; + void debugJointData() const; friend AvatarManager; protected: From 9c90a2b68479357e9b95874972e839b0499692c0 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 22 Apr 2019 13:17:42 -0700 Subject: [PATCH 4/6] more fixes --- interface/src/avatar/OtherAvatar.cpp | 1 - libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 1 - libraries/avatars/src/AvatarData.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 7c7e1b390e..7f9c8f854e 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -375,7 +375,6 @@ void OtherAvatar::debugJointData() const { const float AXIS_LENGTH = 0.1f; AnimPoseVec jointPoses; - glm::quat rotationOffset = Quaternions::IDENTITY; std::vector jointNames; AnimPose rigToAvatar = AnimPose(Quaternions::Y_180 * getWorldOrientation(), getWorldPosition()); for (int i = 0; i < jointData.size(); i++) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 1129bee7e9..f4c00ce9ab 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1457,7 +1457,6 @@ std::vector Avatar::getSkeletonDefaultDa float geometryToRigScale = glm::length(extractScale(rig.getGeometryToRigTransform())); QStringList jointNames = getJointNames(); int sizeCount = 0; - int jointCount = 0; for (int i = 0; i < jointNames.size(); i++) { AvatarSkeletonTrait::UnpackedJointData jointData; jointData.jointIndex = i; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5e68a26512..e3b023acf8 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2055,7 +2055,6 @@ QByteArray AvatarData::packSkeletonModelURL() const { void AvatarData::unpackSkeletonData(const QByteArray& data) { const unsigned char* startPosition = reinterpret_cast(data.data()); - const unsigned char* endPosition = startPosition + data.size(); const unsigned char* sourceBuffer = startPosition; auto header = reinterpret_cast(sourceBuffer); From b10aca10d4474a170b8707ab26b0aeb39df7025a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 23 Apr 2019 09:45:39 -0700 Subject: [PATCH 5/6] Fix code standard issues --- interface/src/avatar/OtherAvatar.cpp | 2 +- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 4 ++-- libraries/avatars/src/AvatarData.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 7f9c8f854e..7bdc9cb0f9 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -389,7 +389,7 @@ void OtherAvatar::debugJointData() const { } QVector worldFramePoses; for (int i = 0; i < (int)jointPoses.size(); i++) { - auto &jointPose = jointPoses[i]; + auto& jointPose = jointPoses[i]; int parentIndex = skeletonData[i].parentIndex; if (parentIndex < worldFramePoses.size()) { glm::vec3 xAxis = jointPose.rot() * Vectors::UNIT_X; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f4c00ce9ab..6961ba880d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1452,8 +1452,8 @@ QStringList Avatar::getJointNames() const { std::vector Avatar::getSkeletonDefaultData() { std::vector defaultSkeletonData; if (_skeletonModel->isLoaded()) { - auto &model = _skeletonModel->getHFMModel(); - auto &rig = _skeletonModel->getRig(); + auto& model = _skeletonModel->getHFMModel(); + auto& rig = _skeletonModel->getRig(); float geometryToRigScale = glm::length(extractScale(rig.getGeometryToRigTransform())); QStringList jointNames = getJointNames(); int sizeCount = 0; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index e3b023acf8..d9db60c757 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2011,7 +2011,7 @@ QByteArray AvatarData::packSkeletonData() const { for (size_t i = 0; i < _avatarSkeletonData.size(); i++) { header.stringTableLength += (uint16_t)_avatarSkeletonData[i].jointName.size(); - auto &translation = _avatarSkeletonData[i].defaultTranslation; + auto& translation = _avatarSkeletonData[i].defaultTranslation; header.maxTranslationDimension = std::max(header.maxTranslationDimension, std::max(std::max(translation.x, translation.y), translation.z)); header.maxScaleDimension = std::max(header.maxScaleDimension, _avatarSkeletonData[i].defaultScale); } From 080f891c9fa49a9edd3e311c9072ff7bee5aa7a0 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 25 Apr 2019 14:54:40 -0700 Subject: [PATCH 6/6] Fix scale and refactor debug function --- interface/src/avatar/OtherAvatar.cpp | 49 +++++++++---------- .../src/avatars-renderer/Avatar.cpp | 4 +- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 7bdc9cb0f9..d8cfe8f107 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -374,43 +374,40 @@ void OtherAvatar::debugJointData() const { const vec4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); const float AXIS_LENGTH = 0.1f; - AnimPoseVec jointPoses; - std::vector jointNames; + AnimPoseVec absoluteJointPoses; AnimPose rigToAvatar = AnimPose(Quaternions::Y_180 * getWorldOrientation(), getWorldPosition()); + bool drawBones = false; for (int i = 0; i < jointData.size(); i++) { - float jointScale = skeletonData[i].defaultScale * getTargetScale(); - auto jointRotation = rigToAvatar.rot() * (jointData[i].rotationIsDefaultPose ? skeletonData[i].defaultRotation : jointData[i].rotation); - auto jointTranslation = jointScale * (jointData[i].translationIsDefaultPose ? skeletonData[i].defaultTranslation : jointData[i].translation); - if (skeletonData[i].jointName == "Hips") { - jointTranslation = glm::vec3(0.0f); + float jointScale = skeletonData[i].defaultScale * getTargetScale() * METERS_PER_CENTIMETER; + auto absoluteRotation = jointData[i].rotationIsDefaultPose ? skeletonData[i].defaultRotation : jointData[i].rotation; + auto localJointTranslation = jointScale * (jointData[i].translationIsDefaultPose ? skeletonData[i].defaultTranslation : jointData[i].translation); + bool isHips = skeletonData[i].jointName == "Hips"; + if (isHips) { + localJointTranslation = glm::vec3(0.0f); + drawBones = true; } - jointPoses.push_back(AnimPose(jointRotation, jointTranslation)); - jointNames.push_back(skeletonData[i].jointName); - } - QVector worldFramePoses; - for (int i = 0; i < (int)jointPoses.size(); i++) { - auto& jointPose = jointPoses[i]; + AnimPose absoluteParentPose; int parentIndex = skeletonData[i].parentIndex; - if (parentIndex < worldFramePoses.size()) { + if (parentIndex != -1 && parentIndex < (int)absoluteJointPoses.size()) { + absoluteParentPose = absoluteJointPoses[parentIndex]; + } + AnimPose absoluteJointPose = AnimPose(absoluteRotation, absoluteParentPose.trans() + absoluteParentPose.rot() * localJointTranslation); + auto jointPose = rigToAvatar * absoluteJointPose; + auto parentPose = rigToAvatar * absoluteParentPose; + if (drawBones) { glm::vec3 xAxis = jointPose.rot() * Vectors::UNIT_X; glm::vec3 yAxis = jointPose.rot() * Vectors::UNIT_Y; glm::vec3 zAxis = jointPose.rot() * Vectors::UNIT_Z; - auto parentRotation = parentIndex > -1 ? jointPoses[parentIndex].rot() : Quaternions::IDENTITY; - auto parentPosition = parentIndex > -1 ? worldFramePoses[parentIndex].trans() : rigToAvatar.trans(); - auto jointPosition = parentPosition + parentRotation * (jointPose.trans() * METERS_PER_CENTIMETER); - worldFramePoses.push_back(AnimPose(jointPose.rot(), jointPosition)); - - DebugDraw::getInstance().drawRay(jointPosition, jointPosition + AXIS_LENGTH * xAxis, jointData[i].rotationIsDefaultPose ? LIGHT_RED : RED); - DebugDraw::getInstance().drawRay(jointPosition, jointPosition + AXIS_LENGTH * yAxis, jointData[i].rotationIsDefaultPose ? LIGHT_GREEN : GREEN); - DebugDraw::getInstance().drawRay(jointPosition, jointPosition + AXIS_LENGTH * zAxis, jointData[i].rotationIsDefaultPose ? LIGHT_BLUE : BLUE); - // draw line to parent - if (parentIndex != -1) { - DebugDraw::getInstance().drawRay(jointPosition, parentPosition, jointData[i].translationIsDefaultPose ? WHITE : GREY); + DebugDraw::getInstance().drawRay(jointPose.trans(), jointPose.trans() + AXIS_LENGTH * xAxis, jointData[i].rotationIsDefaultPose ? LIGHT_RED : RED); + DebugDraw::getInstance().drawRay(jointPose.trans(), jointPose.trans() + AXIS_LENGTH * yAxis, jointData[i].rotationIsDefaultPose ? LIGHT_GREEN : GREEN); + DebugDraw::getInstance().drawRay(jointPose.trans(), jointPose.trans() + AXIS_LENGTH * zAxis, jointData[i].rotationIsDefaultPose ? LIGHT_BLUE : BLUE); + if (!isHips) { + DebugDraw::getInstance().drawRay(jointPose.trans(), parentPose.trans(), jointData[i].translationIsDefaultPose ? WHITE : GREY); } } + absoluteJointPoses.push_back(absoluteJointPose); } - } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 6961ba880d..49e527fd8e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1454,7 +1454,7 @@ std::vector Avatar::getSkeletonDefaultDa if (_skeletonModel->isLoaded()) { auto& model = _skeletonModel->getHFMModel(); auto& rig = _skeletonModel->getRig(); - float geometryToRigScale = glm::length(extractScale(rig.getGeometryToRigTransform())); + float geometryToRigScale = extractScale(rig.getGeometryToRigTransform())[0]; QStringList jointNames = getJointNames(); int sizeCount = 0; for (int i = 0; i < jointNames.size(); i++) { @@ -1468,7 +1468,7 @@ std::vector Avatar::getSkeletonDefaultDa } jointData.defaultRotation = rig.getAbsoluteDefaultPose(i).rot(); jointData.defaultTranslation = getDefaultJointTranslation(i); - float jointLocalScale = glm::length(extractScale(model.joints[i].transform)); + float jointLocalScale = extractScale(model.joints[i].transform)[0]; jointData.defaultScale = jointLocalScale / geometryToRigScale; jointData.jointName = jointNames[i]; jointData.stringLength = jointNames[i].size();