Rotation fix and refactor

This commit is contained in:
luiscuenca 2019-04-22 11:38:27 -07:00
parent 1ad197df26
commit 20cac4cd4d
No known key found for this signature in database
GPG key ID: 2387ECD129A6961D
11 changed files with 131 additions and 29 deletions

View file

@ -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>();
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);

View file

@ -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);

View file

@ -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";

View file

@ -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

View file

@ -213,6 +213,15 @@ public slots:
*/
void updateAvatarRenderStatus(bool shouldRenderAvatars);
/**jsdoc
* Displays other avatars skeletons debug graphics.
* @function AvatarManager.setEnableDebugDrawOtherSkeletons
* @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
*/
void setEnableDebugDrawOtherSkeletons(bool isEnabled) {
_drawOtherAvatarSkeletons = isEnabled;
}
protected:
AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override;
@ -250,6 +259,7 @@ private:
workload::SpacePointer _space;
AvatarTransit::TransitConfig _transitConfig;
bool _drawOtherAvatarSkeletons { false };
};
#endif // hifi_AvatarManager_h

View file

@ -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<AnimPose> jointPoses;
glm::quat rotationOffset = Quaternions::IDENTITY;
std::vector<QString> 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<AnimPose> 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");

View file

@ -66,7 +66,7 @@ public:
void setCollisionWithOtherAvatarsFlags() override;
void simulate(float deltaTime, bool inView) override;
void OtherAvatar::debugJointData() const;
friend AvatarManager;
protected:

View file

@ -1452,15 +1452,25 @@ QStringList Avatar::getJointNames() const {
std::vector<AvatarSkeletonTrait::UnpackedJointData> Avatar::getSkeletonDefaultData() {
std::vector<AvatarSkeletonTrait::UnpackedJointData> 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;

View file

@ -1635,6 +1635,13 @@ void AvatarData::setJointData(int index, const glm::quat& rotation, const glm::v
data.translationIsDefaultPose = false;
}
QVector<JointData> AvatarData::getJointData() const {
QVector<JointData> 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<const unsigned char*>(&jointData->defaultRotation), uJointData.defaultRotation);
unpackFloatVec3FromSignedTwoByteFixed(reinterpret_cast<const unsigned char*>(&jointData->defaultTranslation), uJointData.defaultTranslation, TRANSLATION_COMPRESSION_RADIX);
unpackFloatScalarFromSignedTwoByteFixed((const int16_t*)(&jointData->defaultScale), &uJointData.defaultScale, TRANSLATION_COMPRESSION_RADIX);
unpackFloatRatioFromTwoByte(reinterpret_cast<const unsigned char*>(&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<const char*>(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<AvatarSkeletonTrait::Unpacked
});
}
std::vector<AvatarSkeletonTrait::UnpackedJointData> AvatarData::getSkeletonData() const {
std::vector<AvatarSkeletonTrait::UnpackedJointData> skeletonData;
_avatarSkeletonDataLock.withReadLock([&] {
skeletonData = _avatarSkeletonData;
});
return skeletonData;
}
void AvatarData::sendSkeletonData() const{
if (_clientTraitsHandler) {
_clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonData);

View file

@ -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<AvatarSkeletonTrait::UnpackedJointData>& skeletonData);
std::vector<AvatarSkeletonTrait::UnpackedJointData> getSkeletonData() const;
void sendSkeletonData() const;
QVector<JointData> getJointData() const;
signals:

View file

@ -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;