mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-08 06:32:35 +02:00
Rotation fix and refactor
This commit is contained in:
parent
1ad197df26
commit
20cac4cd4d
11 changed files with 131 additions and 29 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
void setCollisionWithOtherAvatarsFlags() override;
|
||||
|
||||
void simulate(float deltaTime, bool inView) override;
|
||||
|
||||
void OtherAvatar::debugJointData() const;
|
||||
friend AvatarManager;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue