Merge remote-tracking branch 'upstream/master' into tablet-ui

This commit is contained in:
Anthony J. Thibault 2017-01-09 10:37:46 -08:00
commit 6794ed7cc4
39 changed files with 408 additions and 230 deletions

View file

@ -68,6 +68,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket"); packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket");
packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket"); packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket");
packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket");
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled); connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
} }
@ -221,6 +222,20 @@ void AudioMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet,
} }
} }
void AudioMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
auto nodeList = DependencyManager::get<NodeList>();
nodeList->getOrCreateLinkedData(senderNode);
if (senderNode->getLinkedData()) {
AudioMixerClientData* nodeData = dynamic_cast<AudioMixerClientData*>(senderNode->getLinkedData());
if (nodeData != nullptr) {
bool isRequesting;
message->readPrimitive(&isRequesting);
nodeData->setRequestsDomainListData(isRequesting);
}
}
}
void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) { void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
sendingNode->parseIgnoreRequestMessage(packet); sendingNode->parseIgnoreRequestMessage(packet);
} }

View file

@ -61,6 +61,7 @@ private slots:
void handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode); void handleMuteEnvironmentPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void handleNegotiateAudioFormat(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); void handleNegotiateAudioFormat(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void handleNodeKilled(SharedNodePointer killedNode); void handleNodeKilled(SharedNodePointer killedNode);
void handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode); void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void handleRadiusIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode); void handleRadiusIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode); void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);

View file

@ -92,6 +92,8 @@ public:
glm::vec3 getPosition() { return getAvatarAudioStream() ? getAvatarAudioStream()->getPosition() : glm::vec3(0); } glm::vec3 getPosition() { return getAvatarAudioStream() ? getAvatarAudioStream()->getPosition() : glm::vec3(0); }
glm::vec3 getAvatarBoundingBoxCorner() { return getAvatarAudioStream() ? getAvatarAudioStream()->getAvatarBoundingBoxCorner() : glm::vec3(0); } glm::vec3 getAvatarBoundingBoxCorner() { return getAvatarAudioStream() ? getAvatarAudioStream()->getAvatarBoundingBoxCorner() : glm::vec3(0); }
glm::vec3 getAvatarBoundingBoxScale() { return getAvatarAudioStream() ? getAvatarAudioStream()->getAvatarBoundingBoxScale() : glm::vec3(0); } glm::vec3 getAvatarBoundingBoxScale() { return getAvatarAudioStream() ? getAvatarAudioStream()->getAvatarBoundingBoxScale() : glm::vec3(0); }
bool getRequestsDomainListData() { return _requestsDomainListData; }
void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; }
signals: signals:
void injectorStreamFinished(const QUuid& streamIdentifier); void injectorStreamFinished(const QUuid& streamIdentifier);
@ -122,6 +124,7 @@ private:
bool _shouldFlushEncoder { false }; bool _shouldFlushEncoder { false };
bool _shouldMuteClient { false }; bool _shouldMuteClient { false };
bool _requestsDomainListData { false };
}; };
#endif // hifi_AudioMixerClientData_h #endif // hifi_AudioMixerClientData_h

View file

@ -209,8 +209,13 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& node) {
// and that it isn't being ignored by our listening node // and that it isn't being ignored by our listening node
// and that it isn't ignoring our listening node // and that it isn't ignoring our listening node
AudioMixerClientData* otherData = static_cast<AudioMixerClientData*>(otherNode->getLinkedData()); AudioMixerClientData* otherData = static_cast<AudioMixerClientData*>(otherNode->getLinkedData());
// When this is true, the AudioMixer will send Audio data to a client about avatars that have ignored them
bool getsAnyIgnored = nodeData->getRequestsDomainListData() && node->getCanKick();
if (otherData if (otherData
&& !node->isIgnoringNodeWithID(otherNode->getUUID()) && !otherNode->isIgnoringNodeWithID(node->getUUID())) { && (!node->isIgnoringNodeWithID(otherNode->getUUID()) || (otherData->getRequestsDomainListData() && otherNode->getCanKick()))
&& (!otherNode->isIgnoringNodeWithID(node->getUUID()) || getsAnyIgnored)) {
// check to see if we're ignoring in radius // check to see if we're ignoring in radius
bool insideIgnoreRadius = false; bool insideIgnoreRadius = false;
@ -219,7 +224,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& node) {
// We'll always be inside the radius in that case. // We'll always be inside the radius in that case.
insideIgnoreRadius = true; insideIgnoreRadius = true;
// Check to see if the space bubble is enabled // Check to see if the space bubble is enabled
} else if ((node->isIgnoreRadiusEnabled() || otherNode->isIgnoreRadiusEnabled()) && (*otherNode != *node)) { } else if ((node->isIgnoreRadiusEnabled() || otherNode->isIgnoreRadiusEnabled())) {
// Define the minimum bubble size // Define the minimum bubble size
static const glm::vec3 minBubbleSize = glm::vec3(0.3f, 1.3f, 0.3f); static const glm::vec3 minBubbleSize = glm::vec3(0.3f, 1.3f, 0.3f);
AudioMixerClientData* nodeData = reinterpret_cast<AudioMixerClientData*>(node->getLinkedData()); AudioMixerClientData* nodeData = reinterpret_cast<AudioMixerClientData*>(node->getLinkedData());

View file

@ -299,7 +299,7 @@ void AvatarMixer::broadcastAvatarData() {
AvatarMixerClientData* otherData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData()); AvatarMixerClientData* otherData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData()); AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
// Check to see if the space bubble is enabled // Check to see if the space bubble is enabled
if ((node->isIgnoreRadiusEnabled() && !getsIgnoredByMe) || (otherNode->isIgnoreRadiusEnabled() && !getsAnyIgnored)) { if (node->isIgnoreRadiusEnabled() || otherNode->isIgnoreRadiusEnabled()) {
// Define the minimum bubble size // Define the minimum bubble size
static const glm::vec3 minBubbleSize = glm::vec3(0.3f, 1.3f, 0.3f); static const glm::vec3 minBubbleSize = glm::vec3(0.3f, 1.3f, 0.3f);
// Define the scale of the box for the current node // Define the scale of the box for the current node
@ -326,11 +326,11 @@ void AvatarMixer::broadcastAvatarData() {
// Perform the collision check between the two bounding boxes // Perform the collision check between the two bounding boxes
if (nodeBox.touches(otherNodeBox)) { if (nodeBox.touches(otherNodeBox)) {
nodeData->ignoreOther(node, otherNode); nodeData->ignoreOther(node, otherNode);
return false; return getsAnyIgnored;
} }
} }
// Not close enough to ignore // Not close enough to ignore
nodeData->removeFromRadiusIgnoringSet(otherNode->getUUID()); nodeData->removeFromRadiusIgnoringSet(node, otherNode->getUUID());
return true; return true;
} }
}, },

View file

@ -57,6 +57,15 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe
} }
} }
void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other) {
if (isRadiusIgnoring(other)) {
_radiusIgnoredOthers.erase(other);
auto exitingSpaceBubblePacket = NLPacket::create(PacketType::ExitingSpaceBubble, NUM_BYTES_RFC4122_UUID);
exitingSpaceBubblePacket->write(other.toRfc4122());
DependencyManager::get<NodeList>()->sendUnreliablePacket(*exitingSpaceBubblePacket, *self);
}
}
void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) { void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) {
_currentViewFrustum.fromByteArray(message); _currentViewFrustum.fromByteArray(message);
} }

View file

@ -89,7 +89,7 @@ public:
glm::vec3 getGlobalBoundingBoxCorner() { return _avatar ? _avatar->getGlobalBoundingBoxCorner() : glm::vec3(0); } glm::vec3 getGlobalBoundingBoxCorner() { return _avatar ? _avatar->getGlobalBoundingBoxCorner() : glm::vec3(0); }
bool isRadiusIgnoring(const QUuid& other) { return _radiusIgnoredOthers.find(other) != _radiusIgnoredOthers.end(); } bool isRadiusIgnoring(const QUuid& other) { return _radiusIgnoredOthers.find(other) != _radiusIgnoredOthers.end(); }
void addToRadiusIgnoringSet(const QUuid& other) { _radiusIgnoredOthers.insert(other); } void addToRadiusIgnoringSet(const QUuid& other) { _radiusIgnoredOthers.insert(other); }
void removeFromRadiusIgnoringSet(const QUuid& other) { _radiusIgnoredOthers.erase(other); } void removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other);
void ignoreOther(SharedNodePointer self, SharedNodePointer other); void ignoreOther(SharedNodePointer self, SharedNodePointer other);
void readViewFrustumPacket(const QByteArray& message); void readViewFrustumPacket(const QByteArray& message);

View file

@ -89,7 +89,7 @@ void ScriptableAvatar::update(float deltatime) {
int mapping = _bind->getGeometry().getJointIndex(name); int mapping = _bind->getGeometry().getJointIndex(name);
if (mapping != -1 && !_maskedJoints.contains(name)) { if (mapping != -1 && !_maskedJoints.contains(name)) {
// Eventually, this should probably deal with post rotations and translations, too. // Eventually, this should probably deal with post rotations and translations, too.
poses[mapping].rot = modelJoints[mapping].preRotation * poses[mapping].rot() = modelJoints[mapping].preRotation *
safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);; safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);;
} }
} }
@ -97,8 +97,8 @@ void ScriptableAvatar::update(float deltatime) {
for (int i = 0; i < nJoints; i++) { for (int i = 0; i < nJoints; i++) {
JointData& data = _jointData[i]; JointData& data = _jointData[i];
AnimPose& pose = poses[i]; AnimPose& pose = poses[i];
if (data.rotation != pose.rot) { if (data.rotation != pose.rot()) {
data.rotation = pose.rot; data.rotation = pose.rot();
data.rotationSet = true; data.rotationSet = true;
} }
} }

View file

@ -83,6 +83,18 @@ Item {
text: "Missed Frame Count: " + root.appdropped; text: "Missed Frame Count: " + root.appdropped;
visible: root.appdropped > 0; visible: root.appdropped > 0;
} }
StatText {
text: "Long Render Count: " + root.longrenders;
visible: root.longrenders > 0;
}
StatText {
text: "Long Submit Count: " + root.longsubmits;
visible: root.longsubmits > 0;
}
StatText {
text: "Long Frame Count: " + root.longframes;
visible: root.longframes > 0;
}
StatText { StatText {
text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount
} }

View file

@ -1339,7 +1339,10 @@ void Avatar::addToScene(AvatarSharedPointer myHandle) {
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
if (scene) { if (scene) {
render::PendingChanges pendingChanges; render::PendingChanges pendingChanges;
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars() && !DependencyManager::get<NodeList>()->isIgnoringNode(getSessionUUID())) { auto nodelist = DependencyManager::get<NodeList>();
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()
&& !nodelist->isIgnoringNode(getSessionUUID())
&& !nodelist->isRadiusIgnoringNode(getSessionUUID())) {
addToScene(myHandle, scene, pendingChanges); addToScene(myHandle, scene, pendingChanges);
} }
scene->enqueuePendingChanges(pendingChanges); scene->enqueuePendingChanges(pendingChanges);

View file

@ -503,8 +503,8 @@ void AvatarActionHold::lateAvatarUpdate(const AnimPose& prePhysicsRoomPose, cons
// then transform it back into world uisng the postAvatarUpdate sensor-to-world matrix. // then transform it back into world uisng the postAvatarUpdate sensor-to-world matrix.
AnimPose newWorldBodyPose = postAvatarUpdateRoomPose * prePhysicsRoomPose.inverse() * worldBodyPose; AnimPose newWorldBodyPose = postAvatarUpdateRoomPose * prePhysicsRoomPose.inverse() * worldBodyPose;
worldTrans.setOrigin(glmToBullet(newWorldBodyPose.trans)); worldTrans.setOrigin(glmToBullet(newWorldBodyPose.trans()));
worldTrans.setRotation(glmToBullet(newWorldBodyPose.rot)); worldTrans.setRotation(glmToBullet(newWorldBodyPose.rot()));
rigidBody->setWorldTransform(worldTrans); rigidBody->setWorldTransform(worldTrans);
bool positionSuccess; bool positionSuccess;

View file

@ -79,6 +79,7 @@ AvatarManager::AvatarManager(QObject* parent) :
packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket");
packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar"); packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar");
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket");
packetReceiver.registerListener(PacketType::ExitingSpaceBubble, this, "processExitingSpaceBubble");
// when we hear that the user has ignored an avatar by session UUID // when we hear that the user has ignored an avatar by session UUID
// immediately remove that avatar instead of waiting for the absence of packets from avatar mixer // immediately remove that avatar instead of waiting for the absence of packets from avatar mixer
@ -257,6 +258,9 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) {
emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius(); emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius();
} }
if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble || removalReason == YourAvatarEnteredTheirBubble) {
DependencyManager::get<NodeList>()->radiusIgnoreNodeBySessionID(avatar->getSessionUUID(), true);
}
_avatarFades.push_back(removedAvatar); _avatarFades.push_back(removedAvatar);
} }

View file

@ -2091,10 +2091,10 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const {
glm::vec3 rigMiddleEyePos = DEFAULT_RIG_MIDDLE_EYE_POS; glm::vec3 rigMiddleEyePos = DEFAULT_RIG_MIDDLE_EYE_POS;
if (leftEyeIndex >= 0 && rightEyeIndex >= 0) { if (leftEyeIndex >= 0 && rightEyeIndex >= 0) {
rigMiddleEyePos = (_rig->getAbsoluteDefaultPose(leftEyeIndex).trans + _rig->getAbsoluteDefaultPose(rightEyeIndex).trans) / 2.0f; rigMiddleEyePos = (_rig->getAbsoluteDefaultPose(leftEyeIndex).trans() + _rig->getAbsoluteDefaultPose(rightEyeIndex).trans()) / 2.0f;
} }
glm::vec3 rigNeckPos = neckIndex != -1 ? _rig->getAbsoluteDefaultPose(neckIndex).trans : DEFAULT_RIG_NECK_POS; glm::vec3 rigNeckPos = neckIndex != -1 ? _rig->getAbsoluteDefaultPose(neckIndex).trans() : DEFAULT_RIG_NECK_POS;
glm::vec3 rigHipsPos = hipsIndex != -1 ? _rig->getAbsoluteDefaultPose(hipsIndex).trans : DEFAULT_RIG_HIPS_POS; glm::vec3 rigHipsPos = hipsIndex != -1 ? _rig->getAbsoluteDefaultPose(hipsIndex).trans() : DEFAULT_RIG_HIPS_POS;
glm::vec3 localEyes = (rigMiddleEyePos - rigHipsPos); glm::vec3 localEyes = (rigMiddleEyePos - rigHipsPos);
glm::vec3 localNeck = (rigNeckPos - rigHipsPos); glm::vec3 localNeck = (rigNeckPos - rigHipsPos);
@ -2274,16 +2274,16 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
AnimPose followWorldPose(currentWorldMatrix); AnimPose followWorldPose(currentWorldMatrix);
if (isActive(Rotation)) { if (isActive(Rotation)) {
followWorldPose.rot = glmExtractRotation(desiredWorldMatrix); followWorldPose.rot() = glmExtractRotation(desiredWorldMatrix);
} }
if (isActive(Horizontal)) { if (isActive(Horizontal)) {
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix); glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
followWorldPose.trans.x = desiredTranslation.x; followWorldPose.trans().x = desiredTranslation.x;
followWorldPose.trans.z = desiredTranslation.z; followWorldPose.trans().z = desiredTranslation.z;
} }
if (isActive(Vertical)) { if (isActive(Vertical)) {
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix); glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
followWorldPose.trans.y = desiredTranslation.y; followWorldPose.trans().y = desiredTranslation.y;
} }
myAvatar.getCharacterController()->setFollowParameters(followWorldPose, getMaxTimeRemaining()); myAvatar.getCharacterController()->setFollowParameters(followWorldPose, getMaxTimeRemaining());

View file

@ -127,12 +127,18 @@ void Stats::updateStats(bool force) {
auto displayPlugin = qApp->getActiveDisplayPlugin(); auto displayPlugin = qApp->getActiveDisplayPlugin();
auto stats = displayPlugin->getHardwareStats(); auto stats = displayPlugin->getHardwareStats();
STAT_UPDATE(appdropped, stats["app_dropped_frame_count"].toInt()); STAT_UPDATE(appdropped, stats["app_dropped_frame_count"].toInt());
STAT_UPDATE(longrenders, stats["long_render_count"].toInt());
STAT_UPDATE(longsubmits, stats["long_submit_count"].toInt());
STAT_UPDATE(longframes, stats["long_frame_count"].toInt());
STAT_UPDATE(renderrate, displayPlugin->renderRate()); STAT_UPDATE(renderrate, displayPlugin->renderRate());
STAT_UPDATE(presentrate, displayPlugin->presentRate()); STAT_UPDATE(presentrate, displayPlugin->presentRate());
STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate()); STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
STAT_UPDATE(presentdroprate, displayPlugin->droppedFrameRate()); STAT_UPDATE(presentdroprate, displayPlugin->droppedFrameRate());
STAT_UPDATE(stutterrate, displayPlugin->stutterRate()); STAT_UPDATE(stutterrate, displayPlugin->stutterRate());
} else { } else {
STAT_UPDATE(appdropped, -1);
STAT_UPDATE(longrenders, -1);
STAT_UPDATE(longsubmits, -1);
STAT_UPDATE(presentrate, -1); STAT_UPDATE(presentrate, -1);
STAT_UPDATE(presentnewrate, -1); STAT_UPDATE(presentnewrate, -1);
STAT_UPDATE(presentdroprate, -1); STAT_UPDATE(presentdroprate, -1);

View file

@ -40,6 +40,9 @@ class Stats : public QQuickItem {
STATS_PROPERTY(float, stutterrate, 0) STATS_PROPERTY(float, stutterrate, 0)
STATS_PROPERTY(int, appdropped, 0) STATS_PROPERTY(int, appdropped, 0)
STATS_PROPERTY(int, longsubmits, 0)
STATS_PROPERTY(int, longrenders, 0)
STATS_PROPERTY(int, longframes, 0)
STATS_PROPERTY(float, presentnewrate, 0) STATS_PROPERTY(float, presentnewrate, 0)
STATS_PROPERTY(float, presentdroprate, 0) STATS_PROPERTY(float, presentdroprate, 0)
@ -137,6 +140,9 @@ public slots:
void forceUpdateStats() { updateStats(true); } void forceUpdateStats() { updateStats(true); }
signals: signals:
void longsubmitsChanged();
void longrendersChanged();
void longframesChanged();
void appdroppedChanged(); void appdroppedChanged();
void framerateChanged(); void framerateChanged();
void expandedChanged(); void expandedChanged();

View file

@ -143,13 +143,13 @@ void AnimClip::copyFromNetworkAnim() {
postRot = animSkeleton.getPostRotationPose(animJoint); postRot = animSkeleton.getPostRotationPose(animJoint);
} else { } else {
// In order to support Blender, which does not have preRotation FBX support, we use the models defaultPose as the reference frame for the animations. // In order to support Blender, which does not have preRotation FBX support, we use the models defaultPose as the reference frame for the animations.
preRot = AnimPose(glm::vec3(1.0f), _skeleton->getRelativeBindPose(skeletonJoint).rot, glm::vec3()); preRot = AnimPose(glm::vec3(1.0f), _skeleton->getRelativeBindPose(skeletonJoint).rot(), glm::vec3());
postRot = AnimPose::identity; postRot = AnimPose::identity;
} }
// cancel out scale // cancel out scale
preRot.scale = glm::vec3(1.0f); preRot.scale() = glm::vec3(1.0f);
postRot.scale = glm::vec3(1.0f); postRot.scale() = glm::vec3(1.0f);
AnimPose rot(glm::vec3(1.0f), fbxAnimRot, glm::vec3()); AnimPose rot(glm::vec3(1.0f), fbxAnimRot, glm::vec3());
@ -160,10 +160,10 @@ void AnimClip::copyFromNetworkAnim() {
float boneLengthScale = 1.0f; float boneLengthScale = 1.0f;
const float EPSILON = 0.0001f; const float EPSILON = 0.0001f;
if (fabsf(glm::length(fbxZeroTrans)) > EPSILON) { if (fabsf(glm::length(fbxZeroTrans)) > EPSILON) {
boneLengthScale = glm::length(relDefaultPose.trans) / glm::length(fbxZeroTrans); boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(fbxZeroTrans);
} }
AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans + boneLengthScale * (fbxAnimTrans - fbxZeroTrans)); AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (fbxAnimTrans - fbxZeroTrans));
_anim[frame][skeletonJoint] = trans * preRot * rot * postRot; _anim[frame][skeletonJoint] = trans * preRot * rot * postRot;
} }

View file

@ -101,8 +101,8 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition)); target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition));
if (target.getType() != IKTarget::Type::Unknown) { if (target.getType() != IKTarget::Type::Unknown) {
AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses); AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses);
glm::quat rotation = animVars.lookupRigToGeometry(targetVar.rotationVar, defaultPose.rot); glm::quat rotation = animVars.lookupRigToGeometry(targetVar.rotationVar, defaultPose.rot());
glm::vec3 translation = animVars.lookupRigToGeometry(targetVar.positionVar, defaultPose.trans); glm::vec3 translation = animVars.lookupRigToGeometry(targetVar.positionVar, defaultPose.trans());
if (target.getType() == IKTarget::Type::HipsRelativeRotationAndPosition) { if (target.getType() == IKTarget::Type::HipsRelativeRotationAndPosition) {
translation += _hipsOffset; translation += _hipsOffset;
} }
@ -164,7 +164,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
// harvest accumulated rotations and apply the average // harvest accumulated rotations and apply the average
for (int i = lowestMovedIndex; i < _maxTargetIndex; ++i) { for (int i = lowestMovedIndex; i < _maxTargetIndex; ++i) {
if (_accumulators[i].size() > 0) { if (_accumulators[i].size() > 0) {
_relativePoses[i].rot = _accumulators[i].getAverage(); _relativePoses[i].rot() = _accumulators[i].getAverage();
_accumulators[i].clear(); _accumulators[i].clear();
} }
} }
@ -182,7 +182,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
for (size_t i = 0; i < targets.size(); i++) { for (size_t i = 0; i < targets.size(); i++) {
if (targets[i].getType() == IKTarget::Type::RotationAndPosition || targets[i].getType() == IKTarget::Type::HmdHead || if (targets[i].getType() == IKTarget::Type::RotationAndPosition || targets[i].getType() == IKTarget::Type::HmdHead ||
targets[i].getType() == IKTarget::Type::HipsRelativeRotationAndPosition) { targets[i].getType() == IKTarget::Type::HipsRelativeRotationAndPosition) {
float error = glm::length(absolutePoses[targets[i].getIndex()].trans - targets[i].getTranslation()); float error = glm::length(absolutePoses[targets[i].getIndex()].trans() - targets[i].getTranslation());
if (error > maxError) { if (error > maxError) {
maxError = error; maxError = error;
} }
@ -198,7 +198,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
const glm::quat& targetRotation = target.getRotation(); const glm::quat& targetRotation = target.getRotation();
// compute tip's new parent-relative rotation // compute tip's new parent-relative rotation
// Q = Qp * q --> q' = Qp^ * Q // Q = Qp * q --> q' = Qp^ * Q
glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot) * targetRotation; glm::quat newRelativeRotation = glm::inverse(absolutePoses[parentIndex].rot()) * targetRotation;
RotationConstraint* constraint = getConstraint(tipIndex); RotationConstraint* constraint = getConstraint(tipIndex);
if (constraint) { if (constraint) {
constraint->apply(newRelativeRotation); constraint->apply(newRelativeRotation);
@ -206,8 +206,8 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
// feedback to the IK system so that it can adjust the bones up the skeleton // feedback to the IK system so that it can adjust the bones up the skeleton
// to help this rotation target get met. // to help this rotation target get met.
} }
_relativePoses[tipIndex].rot = newRelativeRotation; _relativePoses[tipIndex].rot() = newRelativeRotation;
absolutePoses[tipIndex].rot = targetRotation; absolutePoses[tipIndex].rot() = targetRotation;
} }
} }
} }
@ -233,11 +233,11 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
} }
// cache tip's absolute orientation // cache tip's absolute orientation
glm::quat tipOrientation = absolutePoses[tipIndex].rot; glm::quat tipOrientation = absolutePoses[tipIndex].rot();
// also cache tip's parent's absolute orientation so we can recompute // also cache tip's parent's absolute orientation so we can recompute
// the tip's parent-relative as we proceed up the chain // the tip's parent-relative as we proceed up the chain
glm::quat tipParentOrientation = absolutePoses[pivotIndex].rot; glm::quat tipParentOrientation = absolutePoses[pivotIndex].rot();
if (targetType == IKTarget::Type::HmdHead) { if (targetType == IKTarget::Type::HmdHead) {
// rotate tip directly to target orientation // rotate tip directly to target orientation
@ -258,12 +258,12 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
} }
// cache tip absolute position // cache tip absolute position
glm::vec3 tipPosition = absolutePoses[tipIndex].trans; glm::vec3 tipPosition = absolutePoses[tipIndex].trans();
// descend toward root, pivoting each joint to get tip closer to target position // descend toward root, pivoting each joint to get tip closer to target position
while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) { while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) {
// compute the two lines that should be aligned // compute the two lines that should be aligned
glm::vec3 jointPosition = absolutePoses[pivotIndex].trans; glm::vec3 jointPosition = absolutePoses[pivotIndex].trans();
glm::vec3 leverArm = tipPosition - jointPosition; glm::vec3 leverArm = tipPosition - jointPosition;
glm::quat deltaRotation; glm::quat deltaRotation;
@ -277,7 +277,7 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
if (constraint && constraint->isLowerSpine()) { if (constraint && constraint->isLowerSpine()) {
// for these types of targets we only allow twist at the lower-spine // for these types of targets we only allow twist at the lower-spine
// (this prevents the hand targets from bending the spine too much and thereby driving the hips too far) // (this prevents the hand targets from bending the spine too much and thereby driving the hips too far)
glm::vec3 twistAxis = absolutePoses[pivotIndex].trans - absolutePoses[pivotsParentIndex].trans; glm::vec3 twistAxis = absolutePoses[pivotIndex].trans() - absolutePoses[pivotsParentIndex].trans();
float twistAxisLength = glm::length(twistAxis); float twistAxisLength = glm::length(twistAxis);
if (twistAxisLength > MIN_AXIS_LENGTH) { if (twistAxisLength > MIN_AXIS_LENGTH) {
// project leverArm and targetLine to the plane // project leverArm and targetLine to the plane
@ -340,9 +340,9 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
// compute joint's new parent-relative rotation after swing // compute joint's new parent-relative rotation after swing
// Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q // Q' = dQ * Q and Q = Qp * q --> q' = Qp^ * dQ * Q
glm::quat newRot = glm::normalize(glm::inverse( glm::quat newRot = glm::normalize(glm::inverse(
absolutePoses[pivotsParentIndex].rot) * absolutePoses[pivotsParentIndex].rot()) *
deltaRotation * deltaRotation *
absolutePoses[pivotIndex].rot); absolutePoses[pivotIndex].rot());
// enforce pivot's constraint // enforce pivot's constraint
RotationConstraint* constraint = getConstraint(pivotIndex); RotationConstraint* constraint = getConstraint(pivotIndex);
@ -352,7 +352,7 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
// the constraint will modify the local rotation of the tip so we must // the constraint will modify the local rotation of the tip so we must
// compute the corresponding model-frame deltaRotation // compute the corresponding model-frame deltaRotation
// Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^ // Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^
deltaRotation = absolutePoses[pivotsParentIndex].rot * newRot * glm::inverse(absolutePoses[pivotIndex].rot); deltaRotation = absolutePoses[pivotsParentIndex].rot() * newRot * glm::inverse(absolutePoses[pivotIndex].rot());
} }
} }
@ -405,15 +405,15 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
const float blend = (1.0f / 60.0f) / (0.25f); // effectively: dt / RELAXATION_TIMESCALE const float blend = (1.0f / 60.0f) / (0.25f); // effectively: dt / RELAXATION_TIMESCALE
int numJoints = (int)_relativePoses.size(); int numJoints = (int)_relativePoses.size();
for (int i = 0; i < numJoints; ++i) { for (int i = 0; i < numJoints; ++i) {
float dotSign = copysignf(1.0f, glm::dot(_relativePoses[i].rot, underPoses[i].rot)); float dotSign = copysignf(1.0f, glm::dot(_relativePoses[i].rot(), underPoses[i].rot()));
if (_accumulators[i].isDirty()) { if (_accumulators[i].isDirty()) {
// this joint is affected by IK --> blend toward underPose rotation // this joint is affected by IK --> blend toward underPose rotation
_relativePoses[i].rot = glm::normalize(glm::lerp(_relativePoses[i].rot, dotSign * underPoses[i].rot, blend)); _relativePoses[i].rot() = glm::normalize(glm::lerp(_relativePoses[i].rot(), dotSign * underPoses[i].rot(), blend));
} else { } else {
// this joint is NOT affected by IK --> slam to underPose rotation // this joint is NOT affected by IK --> slam to underPose rotation
_relativePoses[i].rot = underPoses[i].rot; _relativePoses[i].rot() = underPoses[i].rot();
} }
_relativePoses[i].trans = underPoses[i].trans; _relativePoses[i].trans() = underPoses[i].trans();
} }
if (!_relativePoses.empty()) { if (!_relativePoses.empty()) {
@ -422,7 +422,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
std::map<int, RotationConstraint*>::iterator constraintItr = _constraints.begin(); std::map<int, RotationConstraint*>::iterator constraintItr = _constraints.begin();
while (constraintItr != _constraints.end()) { while (constraintItr != _constraints.end()) {
int index = constraintItr->first; int index = constraintItr->first;
constraintItr->second->dynamicallyAdjustLimits(_relativePoses[index].rot); constraintItr->second->dynamicallyAdjustLimits(_relativePoses[index].rot());
++constraintItr; ++constraintItr;
} }
} }
@ -442,9 +442,9 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
std::map<int, RotationConstraint*>::iterator constraintItr = _constraints.begin(); std::map<int, RotationConstraint*>::iterator constraintItr = _constraints.begin();
while (constraintItr != _constraints.end()) { while (constraintItr != _constraints.end()) {
int index = constraintItr->first; int index = constraintItr->first;
glm::quat rotation = _relativePoses[index].rot; glm::quat rotation = _relativePoses[index].rot();
constraintItr->second->apply(rotation); constraintItr->second->apply(rotation);
_relativePoses[index].rot = rotation; _relativePoses[index].rot() = rotation;
++constraintItr; ++constraintItr;
} }
} else { } else {
@ -460,16 +460,16 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength);
if (_hipsParentIndex == -1) { if (_hipsParentIndex == -1) {
// the hips are the root so _hipsOffset is in the correct frame // the hips are the root so _hipsOffset is in the correct frame
_relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + scaleFactor * _hipsOffset; _relativePoses[_hipsIndex].trans() = underPoses[_hipsIndex].trans() + scaleFactor * _hipsOffset;
} else { } else {
// the hips are NOT the root so we need to transform _hipsOffset into hips local-frame // the hips are NOT the root so we need to transform _hipsOffset into hips local-frame
glm::quat hipsFrameRotation = _relativePoses[_hipsParentIndex].rot; glm::quat hipsFrameRotation = _relativePoses[_hipsParentIndex].rot();
int index = _skeleton->getParentIndex(_hipsParentIndex); int index = _skeleton->getParentIndex(_hipsParentIndex);
while (index != -1) { while (index != -1) {
hipsFrameRotation *= _relativePoses[index].rot; hipsFrameRotation *= _relativePoses[index].rot();
index = _skeleton->getParentIndex(index); index = _skeleton->getParentIndex(index);
} }
_relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans _relativePoses[_hipsIndex].trans() = underPoses[_hipsIndex].trans()
+ glm::inverse(glm::normalize(hipsFrameRotation)) * (scaleFactor * _hipsOffset); + glm::inverse(glm::normalize(hipsFrameRotation)) * (scaleFactor * _hipsOffset);
} }
} }
@ -494,20 +494,20 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
if (target.getType() == IKTarget::Type::RotationOnly) { if (target.getType() == IKTarget::Type::RotationOnly) {
// we want to shift the hips to bring the underPose closer // we want to shift the hips to bring the underPose closer
// to where the head happens to be (overpose) // to where the head happens to be (overpose)
glm::vec3 under = _skeleton->getAbsolutePose(_headIndex, underPoses).trans; glm::vec3 under = _skeleton->getAbsolutePose(_headIndex, underPoses).trans();
glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans; glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans();
const float HEAD_OFFSET_SLAVE_FACTOR = 0.65f; const float HEAD_OFFSET_SLAVE_FACTOR = 0.65f;
newHipsOffset += HEAD_OFFSET_SLAVE_FACTOR * (actual - under); newHipsOffset += HEAD_OFFSET_SLAVE_FACTOR * (actual - under);
} else if (target.getType() == IKTarget::Type::HmdHead) { } else if (target.getType() == IKTarget::Type::HmdHead) {
// we want to shift the hips to bring the head to its designated position // we want to shift the hips to bring the head to its designated position
glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans; glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans();
_hipsOffset += target.getTranslation() - actual; _hipsOffset += target.getTranslation() - actual;
// and ignore all other targets // and ignore all other targets
newHipsOffset = _hipsOffset; newHipsOffset = _hipsOffset;
break; break;
} }
} else if (target.getType() == IKTarget::Type::RotationAndPosition) { } else if (target.getType() == IKTarget::Type::RotationAndPosition) {
glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans; glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans();
glm::vec3 targetPosition = target.getTranslation(); glm::vec3 targetPosition = target.getTranslation();
newHipsOffset += targetPosition - actualPosition; newHipsOffset += targetPosition - actualPosition;
} }
@ -613,7 +613,7 @@ void AnimInverseKinematics::initConstraints() {
RotationConstraint* constraint = nullptr; RotationConstraint* constraint = nullptr;
if (0 == baseName.compare("Arm", Qt::CaseSensitive)) { if (0 == baseName.compare("Arm", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
stConstraint->setTwistLimits(-PI / 2.0f, PI / 2.0f); stConstraint->setTwistLimits(-PI / 2.0f, PI / 2.0f);
/* KEEP THIS CODE for future experimentation /* KEEP THIS CODE for future experimentation
@ -647,7 +647,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (0 == baseName.compare("UpLeg", Qt::CaseSensitive)) { } else if (0 == baseName.compare("UpLeg", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f); stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f);
std::vector<glm::vec3> swungDirections; std::vector<glm::vec3> swungDirections;
@ -670,7 +670,7 @@ void AnimInverseKinematics::initConstraints() {
swungDirections.push_back(glm::vec3(mirror * cosf(theta), 0.5f, sinf(theta))); swungDirections.push_back(glm::vec3(mirror * cosf(theta), 0.5f, sinf(theta)));
// rotate directions into joint-frame // rotate directions into joint-frame
glm::quat invAbsoluteRotation = glm::inverse(absolutePoses[i].rot); glm::quat invAbsoluteRotation = glm::inverse(absolutePoses[i].rot());
int numDirections = (int)swungDirections.size(); int numDirections = (int)swungDirections.size();
for (int j = 0; j < numDirections; ++j) { for (int j = 0; j < numDirections; ++j) {
swungDirections[j] = invAbsoluteRotation * swungDirections[j]; swungDirections[j] = invAbsoluteRotation * swungDirections[j];
@ -680,7 +680,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (0 == baseName.compare("Hand", Qt::CaseSensitive)) { } else if (0 == baseName.compare("Hand", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
stConstraint->setTwistLimits(0.0f, 0.0f); // max == min, disables twist limits stConstraint->setTwistLimits(0.0f, 0.0f); // max == min, disables twist limits
/* KEEP THIS CODE for future experimentation -- twist limits for hands /* KEEP THIS CODE for future experimentation -- twist limits for hands
@ -723,7 +723,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (baseName.startsWith("Shoulder", Qt::CaseSensitive)) { } else if (baseName.startsWith("Shoulder", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
const float MAX_SHOULDER_TWIST = PI / 20.0f; const float MAX_SHOULDER_TWIST = PI / 20.0f;
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST); stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
@ -735,7 +735,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (baseName.startsWith("Spine", Qt::CaseSensitive)) { } else if (baseName.startsWith("Spine", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
const float MAX_SPINE_TWIST = PI / 12.0f; const float MAX_SPINE_TWIST = PI / 12.0f;
stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST); stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST);
@ -751,7 +751,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (baseName.startsWith("Hips2", Qt::CaseSensitive)) { } else if (baseName.startsWith("Hips2", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
const float MAX_SPINE_TWIST = PI / 8.0f; const float MAX_SPINE_TWIST = PI / 8.0f;
stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST); stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST);
@ -763,7 +763,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (0 == baseName.compare("Neck", Qt::CaseSensitive)) { } else if (0 == baseName.compare("Neck", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
const float MAX_NECK_TWIST = PI / 9.0f; const float MAX_NECK_TWIST = PI / 9.0f;
stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST); stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST);
@ -775,7 +775,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(stConstraint); constraint = static_cast<RotationConstraint*>(stConstraint);
} else if (0 == baseName.compare("Head", Qt::CaseSensitive)) { } else if (0 == baseName.compare("Head", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
const float MAX_HEAD_TWIST = PI / 9.0f; const float MAX_HEAD_TWIST = PI / 9.0f;
stConstraint->setTwistLimits(-MAX_HEAD_TWIST, MAX_HEAD_TWIST); stConstraint->setTwistLimits(-MAX_HEAD_TWIST, MAX_HEAD_TWIST);
@ -788,7 +788,7 @@ void AnimInverseKinematics::initConstraints() {
} else if (0 == baseName.compare("ForeArm", Qt::CaseSensitive)) { } else if (0 == baseName.compare("ForeArm", Qt::CaseSensitive)) {
// The elbow joint rotates about the parent-frame's zAxis (-zAxis) for the Right (Left) arm. // The elbow joint rotates about the parent-frame's zAxis (-zAxis) for the Right (Left) arm.
ElbowConstraint* eConstraint = new ElbowConstraint(); ElbowConstraint* eConstraint = new ElbowConstraint();
glm::quat referenceRotation = _defaultRelativePoses[i].rot; glm::quat referenceRotation = _defaultRelativePoses[i].rot();
eConstraint->setReferenceRotation(referenceRotation); eConstraint->setReferenceRotation(referenceRotation);
// we determine the max/min angles by rotating the swing limit lines from parent- to child-frame // we determine the max/min angles by rotating the swing limit lines from parent- to child-frame
@ -819,7 +819,7 @@ void AnimInverseKinematics::initConstraints() {
} else if (0 == baseName.compare("Leg", Qt::CaseSensitive)) { } else if (0 == baseName.compare("Leg", Qt::CaseSensitive)) {
// The knee joint rotates about the parent-frame's -xAxis. // The knee joint rotates about the parent-frame's -xAxis.
ElbowConstraint* eConstraint = new ElbowConstraint(); ElbowConstraint* eConstraint = new ElbowConstraint();
glm::quat referenceRotation = _defaultRelativePoses[i].rot; glm::quat referenceRotation = _defaultRelativePoses[i].rot();
eConstraint->setReferenceRotation(referenceRotation); eConstraint->setReferenceRotation(referenceRotation);
glm::vec3 hingeAxis = -1.0f * Vectors::UNIT_X; glm::vec3 hingeAxis = -1.0f * Vectors::UNIT_X;
@ -849,7 +849,7 @@ void AnimInverseKinematics::initConstraints() {
constraint = static_cast<RotationConstraint*>(eConstraint); constraint = static_cast<RotationConstraint*>(eConstraint);
} else if (0 == baseName.compare("Foot", Qt::CaseSensitive)) { } else if (0 == baseName.compare("Foot", Qt::CaseSensitive)) {
SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); SwingTwistConstraint* stConstraint = new SwingTwistConstraint();
stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot());
stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f); stConstraint->setTwistLimits(-PI / 4.0f, PI / 4.0f);
// these directions are approximate swing limits in parent-frame // these directions are approximate swing limits in parent-frame
@ -861,7 +861,7 @@ void AnimInverseKinematics::initConstraints() {
swungDirections.push_back(glm::vec3(1.0f, 1.0f, -1.0f)); swungDirections.push_back(glm::vec3(1.0f, 1.0f, -1.0f));
// rotate directions into joint-frame // rotate directions into joint-frame
glm::quat invRelativeRotation = glm::inverse(_defaultRelativePoses[i].rot); glm::quat invRelativeRotation = glm::inverse(_defaultRelativePoses[i].rot());
int numDirections = (int)swungDirections.size(); int numDirections = (int)swungDirections.size();
for (int j = 0; j < numDirections; ++j) { for (int j = 0; j < numDirections; ++j) {
swungDirections[j] = invRelativeRotation * swungDirections[j]; swungDirections[j] = invRelativeRotation * swungDirections[j];

View file

@ -103,9 +103,9 @@ AnimPose AnimManipulator::computeRelativePoseFromJointVar(const AnimVariantMap&
if (jointVar.type == JointVar::Type::AbsoluteRotation || jointVar.type == JointVar::Type::AbsolutePosition) { if (jointVar.type == JointVar::Type::AbsoluteRotation || jointVar.type == JointVar::Type::AbsolutePosition) {
if (jointVar.type == JointVar::Type::AbsoluteRotation) { if (jointVar.type == JointVar::Type::AbsoluteRotation) {
defaultAbsPose.rot = animVars.lookupRigToGeometry(jointVar.var, defaultAbsPose.rot); defaultAbsPose.rot() = animVars.lookupRigToGeometry(jointVar.var, defaultAbsPose.rot());
} else if (jointVar.type == JointVar::Type::AbsolutePosition) { } else if (jointVar.type == JointVar::Type::AbsolutePosition) {
defaultAbsPose.trans = animVars.lookupRigToGeometry(jointVar.var, defaultAbsPose.trans); defaultAbsPose.trans() = animVars.lookupRigToGeometry(jointVar.var, defaultAbsPose.trans());
} }
// because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose. // because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose.
@ -123,9 +123,9 @@ AnimPose AnimManipulator::computeRelativePoseFromJointVar(const AnimVariantMap&
// override the default rel pose // override the default rel pose
AnimPose relPose = defaultRelPose; AnimPose relPose = defaultRelPose;
if (jointVar.type == JointVar::Type::RelativeRotation) { if (jointVar.type == JointVar::Type::RelativeRotation) {
relPose.rot = animVars.lookupRigToGeometry(jointVar.var, defaultRelPose.rot); relPose.rot() = animVars.lookupRigToGeometry(jointVar.var, defaultRelPose.rot());
} else if (jointVar.type == JointVar::Type::RelativePosition) { } else if (jointVar.type == JointVar::Type::RelativePosition) {
relPose.trans = animVars.lookupRigToGeometry(jointVar.var, defaultRelPose.trans); relPose.trans() = animVars.lookupRigToGeometry(jointVar.var, defaultRelPose.trans());
} }
return relPose; return relPose;

View file

@ -18,15 +18,21 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
glm::vec3(0.0f)); glm::vec3(0.0f));
AnimPose::AnimPose(const glm::mat4& mat) { AnimPose::AnimPose(const glm::mat4& mat) {
scale = extractScale(mat); static const float EPSILON = 0.0001f;
_scale = extractScale(mat);
// quat_cast doesn't work so well with scaled matrices, so cancel it out. // quat_cast doesn't work so well with scaled matrices, so cancel it out.
glm::mat4 tmp = glm::scale(mat, 1.0f / scale); glm::mat4 tmp = glm::scale(mat, 1.0f / _scale);
rot = glm::normalize(glm::quat_cast(tmp)); _rot = glm::quat_cast(tmp);
trans = extractTranslation(mat); float lengthSquared = glm::length2(_rot);
if (glm::abs(lengthSquared - 1.0f) > EPSILON) {
float oneOverLength = 1.0f / sqrtf(lengthSquared);
_rot = glm::quat(_rot.w * oneOverLength, _rot.x * oneOverLength, _rot.y * oneOverLength, _rot.z * oneOverLength);
}
_trans = extractTranslation(mat);
} }
glm::vec3 AnimPose::operator*(const glm::vec3& rhs) const { glm::vec3 AnimPose::operator*(const glm::vec3& rhs) const {
return trans + (rot * (scale * rhs)); return _trans + (_rot * (_scale * rhs));
} }
glm::vec3 AnimPose::xformPoint(const glm::vec3& rhs) const { glm::vec3 AnimPose::xformPoint(const glm::vec3& rhs) const {
@ -35,16 +41,24 @@ glm::vec3 AnimPose::xformPoint(const glm::vec3& rhs) const {
// really slow // really slow
glm::vec3 AnimPose::xformVector(const glm::vec3& rhs) const { glm::vec3 AnimPose::xformVector(const glm::vec3& rhs) const {
glm::vec3 xAxis = rot * glm::vec3(scale.x, 0.0f, 0.0f); glm::vec3 xAxis = _rot * glm::vec3(_scale.x, 0.0f, 0.0f);
glm::vec3 yAxis = rot * glm::vec3(0.0f, scale.y, 0.0f); glm::vec3 yAxis = _rot * glm::vec3(0.0f, _scale.y, 0.0f);
glm::vec3 zAxis = rot * glm::vec3(0.0f, 0.0f, scale.z); glm::vec3 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale.z);
glm::mat3 mat(xAxis, yAxis, zAxis); glm::mat3 mat(xAxis, yAxis, zAxis);
glm::mat3 transInvMat = glm::inverse(glm::transpose(mat)); glm::mat3 transInvMat = glm::inverse(glm::transpose(mat));
return transInvMat * rhs; return transInvMat * rhs;
} }
AnimPose AnimPose::operator*(const AnimPose& rhs) const { AnimPose AnimPose::operator*(const AnimPose& rhs) const {
#if GLM_ARCH & GLM_ARCH_SSE2
glm::mat4 result;
glm::mat4 lhsMat = *this;
glm::mat4 rhsMat = rhs;
glm_mat4_mul((glm_vec4*)&lhsMat, (glm_vec4*)&rhsMat, (glm_vec4*)&result);
return AnimPose(result);
#else
return AnimPose(static_cast<glm::mat4>(*this) * static_cast<glm::mat4>(rhs)); return AnimPose(static_cast<glm::mat4>(*this) * static_cast<glm::mat4>(rhs));
#endif
} }
AnimPose AnimPose::inverse() const { AnimPose AnimPose::inverse() const {
@ -53,13 +67,13 @@ AnimPose AnimPose::inverse() const {
// mirror about x-axis without applying negative scale. // mirror about x-axis without applying negative scale.
AnimPose AnimPose::mirror() const { AnimPose AnimPose::mirror() const {
return AnimPose(scale, glm::quat(rot.w, rot.x, -rot.y, -rot.z), glm::vec3(-trans.x, trans.y, trans.z)); return AnimPose(_scale, glm::quat(_rot.w, _rot.x, -_rot.y, -_rot.z), glm::vec3(-_trans.x, _trans.y, _trans.z));
} }
AnimPose::operator glm::mat4() const { AnimPose::operator glm::mat4() const {
glm::vec3 xAxis = rot * glm::vec3(scale.x, 0.0f, 0.0f); glm::vec3 xAxis = _rot * glm::vec3(_scale.x, 0.0f, 0.0f);
glm::vec3 yAxis = rot * glm::vec3(0.0f, scale.y, 0.0f); glm::vec3 yAxis = _rot * glm::vec3(0.0f, _scale.y, 0.0f);
glm::vec3 zAxis = rot * glm::vec3(0.0f, 0.0f, scale.z); glm::vec3 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale.z);
return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f), return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f),
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f)); glm::vec4(zAxis, 0.0f), glm::vec4(_trans, 1.0f));
} }

View file

@ -17,10 +17,11 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
struct AnimPose { class AnimPose {
public:
AnimPose() {} AnimPose() {}
explicit AnimPose(const glm::mat4& mat); explicit AnimPose(const glm::mat4& mat);
AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : scale(scaleIn), rot(rotIn), trans(transIn) {} AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : _scale(scaleIn), _rot(rotIn), _trans(transIn) {}
static const AnimPose identity; static const AnimPose identity;
glm::vec3 xformPoint(const glm::vec3& rhs) const; glm::vec3 xformPoint(const glm::vec3& rhs) const;
@ -33,13 +34,24 @@ struct AnimPose {
AnimPose mirror() const; AnimPose mirror() const;
operator glm::mat4() const; operator glm::mat4() const;
glm::vec3 scale; const glm::vec3& scale() const { return _scale; }
glm::quat rot; glm::vec3& scale() { return _scale; }
glm::vec3 trans;
const glm::quat& rot() const { return _rot; }
glm::quat& rot() { return _rot; }
const glm::vec3& trans() const { return _trans; }
glm::vec3& trans() { return _trans; }
private:
friend QDebug operator<<(QDebug debug, const AnimPose& pose);
glm::vec3 _scale { 1.0f };
glm::quat _rot;
glm::vec3 _trans;
}; };
inline QDebug operator<<(QDebug debug, const AnimPose& pose) { inline QDebug operator<<(QDebug debug, const AnimPose& pose) {
debug << "AnimPose, trans = (" << pose.trans.x << pose.trans.y << pose.trans.z << "), rot = (" << pose.rot.x << pose.rot.y << pose.rot.z << pose.rot.w << "), scale = (" << pose.scale.x << pose.scale.y << pose.scale.z << ")"; debug << "AnimPose, trans = (" << pose.trans().x << pose.trans().y << pose.trans().z << "), rot = (" << pose.rot().x << pose.rot().y << pose.rot().z << pose.rot().w << "), scale = (" << pose.scale().x << pose.scale().y << pose.scale().z << ")";
return debug; return debug;
} }

View file

@ -31,16 +31,15 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
} }
int AnimSkeleton::nameToJointIndex(const QString& jointName) const { int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
for (int i = 0; i < (int)_joints.size(); i++) { auto itr = _jointIndicesByName.find(jointName);
if (_joints[i].name == jointName) { if (_jointIndicesByName.end() != itr) {
return i; return itr.value();
}
} }
return -1; return -1;
} }
int AnimSkeleton::getNumJoints() const { int AnimSkeleton::getNumJoints() const {
return (int)_joints.size(); return _jointsSize;
} }
const AnimPose& AnimSkeleton::getAbsoluteBindPose(int jointIndex) const { const AnimPose& AnimSkeleton::getAbsoluteBindPose(int jointIndex) const {
@ -78,7 +77,7 @@ const QString& AnimSkeleton::getJointName(int jointIndex) const {
} }
AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& poses) const { AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& poses) const {
if (jointIndex < 0 || jointIndex >= (int)poses.size() || jointIndex >= (int)_joints.size()) { if (jointIndex < 0 || jointIndex >= (int)poses.size() || jointIndex >= _jointsSize) {
return AnimPose::identity; return AnimPose::identity;
} else { } else {
return getAbsolutePose(_joints[jointIndex].parentIndex, poses) * poses[jointIndex]; return getAbsolutePose(_joints[jointIndex].parentIndex, poses) * poses[jointIndex];
@ -87,7 +86,7 @@ AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& poses)
void AnimSkeleton::convertRelativePosesToAbsolute(AnimPoseVec& poses) const { void AnimSkeleton::convertRelativePosesToAbsolute(AnimPoseVec& poses) const {
// poses start off relative and leave in absolute frame // poses start off relative and leave in absolute frame
int lastIndex = std::min((int)poses.size(), (int)_joints.size()); int lastIndex = std::min((int)poses.size(), _jointsSize);
for (int i = 0; i < lastIndex; ++i) { for (int i = 0; i < lastIndex; ++i) {
int parentIndex = _joints[i].parentIndex; int parentIndex = _joints[i].parentIndex;
if (parentIndex != -1) { if (parentIndex != -1) {
@ -98,7 +97,7 @@ void AnimSkeleton::convertRelativePosesToAbsolute(AnimPoseVec& poses) const {
void AnimSkeleton::convertAbsolutePosesToRelative(AnimPoseVec& poses) const { void AnimSkeleton::convertAbsolutePosesToRelative(AnimPoseVec& poses) const {
// poses start off absolute and leave in relative frame // poses start off absolute and leave in relative frame
int lastIndex = std::min((int)poses.size(), (int)_joints.size()); int lastIndex = std::min((int)poses.size(), _jointsSize);
for (int i = lastIndex - 1; i >= 0; --i) { for (int i = lastIndex - 1; i >= 0; --i) {
int parentIndex = _joints[i].parentIndex; int parentIndex = _joints[i].parentIndex;
if (parentIndex != -1) { if (parentIndex != -1) {
@ -109,7 +108,7 @@ void AnimSkeleton::convertAbsolutePosesToRelative(AnimPoseVec& poses) const {
void AnimSkeleton::convertAbsoluteRotationsToRelative(std::vector<glm::quat>& rotations) const { void AnimSkeleton::convertAbsoluteRotationsToRelative(std::vector<glm::quat>& rotations) const {
// poses start off absolute and leave in relative frame // poses start off absolute and leave in relative frame
int lastIndex = std::min((int)rotations.size(), (int)_joints.size()); int lastIndex = std::min((int)rotations.size(), _jointsSize);
for (int i = lastIndex - 1; i >= 0; --i) { for (int i = lastIndex - 1; i >= 0; --i) {
int parentIndex = _joints[i].parentIndex; int parentIndex = _joints[i].parentIndex;
if (parentIndex != -1) { if (parentIndex != -1) {
@ -149,19 +148,19 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const {
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) { void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) {
_joints = joints; _joints = joints;
_jointsSize = (int)joints.size();
// build a cache of bind poses // build a cache of bind poses
_absoluteBindPoses.reserve(joints.size()); _absoluteBindPoses.reserve(_jointsSize);
_relativeBindPoses.reserve(joints.size()); _relativeBindPoses.reserve(_jointsSize);
// build a chache of default poses // build a chache of default poses
_absoluteDefaultPoses.reserve(joints.size()); _absoluteDefaultPoses.reserve(_jointsSize);
_relativeDefaultPoses.reserve(joints.size()); _relativeDefaultPoses.reserve(_jointsSize);
_relativePreRotationPoses.reserve(joints.size()); _relativePreRotationPoses.reserve(_jointsSize);
_relativePostRotationPoses.reserve(joints.size()); _relativePostRotationPoses.reserve(_jointsSize);
// iterate over FBXJoints and extract the bind pose information. // iterate over FBXJoints and extract the bind pose information.
for (int i = 0; i < (int)joints.size(); i++) { for (int i = 0; i < _jointsSize; i++) {
// build pre and post transforms // build pre and post transforms
glm::mat4 preRotationTransform = _joints[i].preTransform * glm::mat4_cast(_joints[i].preRotation); glm::mat4 preRotationTransform = _joints[i].preTransform * glm::mat4_cast(_joints[i].preRotation);
@ -203,10 +202,14 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
} }
} }
for (int i = 0; i < _jointsSize; i++) {
_jointIndicesByName[_joints[i].name] = i;
}
// build mirror map. // build mirror map.
_nonMirroredIndices.clear(); _nonMirroredIndices.clear();
_mirrorMap.reserve(_joints.size()); _mirrorMap.reserve(_jointsSize);
for (int i = 0; i < (int)joints.size(); i++) { for (int i = 0; i < _jointsSize; i++) {
if (_joints[i].name.endsWith("tEye")) { if (_joints[i].name.endsWith("tEye")) {
// HACK: we don't want to mirror some joints so we remember their indices // HACK: we don't want to mirror some joints so we remember their indices
// so we can restore them after a future mirror operation // so we can restore them after a future mirror operation

View file

@ -70,6 +70,7 @@ protected:
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints); void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints);
std::vector<FBXJoint> _joints; std::vector<FBXJoint> _joints;
int _jointsSize { 0 };
AnimPoseVec _absoluteBindPoses; AnimPoseVec _absoluteBindPoses;
AnimPoseVec _relativeBindPoses; AnimPoseVec _relativeBindPoses;
AnimPoseVec _relativeDefaultPoses; AnimPoseVec _relativeDefaultPoses;
@ -79,6 +80,7 @@ protected:
mutable AnimPoseVec _nonMirroredPoses; mutable AnimPoseVec _nonMirroredPoses;
std::vector<int> _nonMirroredIndices; std::vector<int> _nonMirroredIndices;
std::vector<int> _mirrorMap; std::vector<int> _mirrorMap;
QHash<QString, int> _jointIndicesByName;
// no copies // no copies
AnimSkeleton(const AnimSkeleton&) = delete; AnimSkeleton(const AnimSkeleton&) = delete;

View file

@ -20,16 +20,16 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A
const AnimPose& bPose = b[i]; const AnimPose& bPose = b[i];
// adjust signs if necessary // adjust signs if necessary
const glm::quat& q1 = aPose.rot; const glm::quat& q1 = aPose.rot();
glm::quat q2 = bPose.rot; glm::quat q2 = bPose.rot();
float dot = glm::dot(q1, q2); float dot = glm::dot(q1, q2);
if (dot < 0.0f) { if (dot < 0.0f) {
q2 = -q2; q2 = -q2;
} }
result[i].scale = lerp(aPose.scale, bPose.scale, alpha); result[i].scale() = lerp(aPose.scale(), bPose.scale(), alpha);
result[i].rot = glm::normalize(glm::lerp(aPose.rot, q2, alpha)); result[i].rot() = glm::normalize(glm::lerp(aPose.rot(), q2, alpha));
result[i].trans = lerp(aPose.trans, bPose.trans, alpha); result[i].trans() = lerp(aPose.trans(), bPose.trans(), alpha);
} }
} }

View file

@ -10,8 +10,8 @@
#include "IKTarget.h" #include "IKTarget.h"
void IKTarget::setPose(const glm::quat& rotation, const glm::vec3& translation) { void IKTarget::setPose(const glm::quat& rotation, const glm::vec3& translation) {
_pose.rot = rotation; _pose.rot() = rotation;
_pose.trans = translation; _pose.trans() = translation;
} }
void IKTarget::setType(int type) { void IKTarget::setType(int type) {

View file

@ -26,8 +26,8 @@ public:
IKTarget() {} IKTarget() {}
const glm::vec3& getTranslation() const { return _pose.trans; } const glm::vec3& getTranslation() const { return _pose.trans(); }
const glm::quat& getRotation() const { return _pose.rot; } const glm::quat& getRotation() const { return _pose.rot(); }
int getIndex() const { return _index; } int getIndex() const { return _index; }
Type getType() const { return _type; } Type getType() const { return _type; }

View file

@ -262,9 +262,9 @@ QString Rig::nameOfJoint(int jointIndex) const {
void Rig::setModelOffset(const glm::mat4& modelOffsetMat) { void Rig::setModelOffset(const glm::mat4& modelOffsetMat) {
AnimPose newModelOffset = AnimPose(modelOffsetMat); AnimPose newModelOffset = AnimPose(modelOffsetMat);
if (!isEqual(_modelOffset.trans, newModelOffset.trans) || if (!isEqual(_modelOffset.trans(), newModelOffset.trans()) ||
!isEqual(_modelOffset.rot, newModelOffset.rot) || !isEqual(_modelOffset.rot(), newModelOffset.rot()) ||
!isEqual(_modelOffset.scale, newModelOffset.scale)) { !isEqual(_modelOffset.scale(), newModelOffset.scale())) {
_modelOffset = newModelOffset; _modelOffset = newModelOffset;
@ -334,7 +334,7 @@ void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translatio
_internalPoseSet._overrideFlags[index] = true; _internalPoseSet._overrideFlags[index] = true;
++_numOverrides; ++_numOverrides;
} }
_internalPoseSet._overridePoses[index].trans = translation; _internalPoseSet._overridePoses[index].trans() = translation;
} }
} }
} }
@ -346,8 +346,8 @@ void Rig::setJointState(int index, bool valid, const glm::quat& rotation, const
_internalPoseSet._overrideFlags[index] = true; _internalPoseSet._overrideFlags[index] = true;
++_numOverrides; ++_numOverrides;
} }
_internalPoseSet._overridePoses[index].rot = rotation; _internalPoseSet._overridePoses[index].rot() = rotation;
_internalPoseSet._overridePoses[index].trans = translation; _internalPoseSet._overridePoses[index].trans() = translation;
} }
} }
@ -359,7 +359,7 @@ void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, flo
_internalPoseSet._overrideFlags[index] = true; _internalPoseSet._overrideFlags[index] = true;
++_numOverrides; ++_numOverrides;
} }
_internalPoseSet._overridePoses[index].rot = rotation; _internalPoseSet._overridePoses[index].rot() = rotation;
} }
} }
} }
@ -376,7 +376,7 @@ void Rig::restoreJointTranslation(int index, float fraction, float priority) {
bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm::vec3 translation, glm::quat rotation) const { bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm::vec3 translation, glm::quat rotation) const {
if (isIndexValid(jointIndex)) { if (isIndexValid(jointIndex)) {
position = (rotation * _internalPoseSet._absolutePoses[jointIndex].trans) + translation; position = (rotation * _internalPoseSet._absolutePoses[jointIndex].trans()) + translation;
return true; return true;
} else { } else {
return false; return false;
@ -385,7 +385,7 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm:
bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const { bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const {
if (isIndexValid(jointIndex)) { if (isIndexValid(jointIndex)) {
position = _internalPoseSet._absolutePoses[jointIndex].trans; position = _internalPoseSet._absolutePoses[jointIndex].trans();
return true; return true;
} else { } else {
return false; return false;
@ -394,7 +394,7 @@ bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const {
bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const glm::quat& rotation) const { bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const glm::quat& rotation) const {
if (isIndexValid(jointIndex)) { if (isIndexValid(jointIndex)) {
result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot; result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot();
return true; return true;
} else { } else {
return false; return false;
@ -404,7 +404,7 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const
bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const { bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const {
QReadLocker readLock(&_externalPoseSetLock); QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) { if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) {
rotation = _externalPoseSet._relativePoses[jointIndex].rot; rotation = _externalPoseSet._relativePoses[jointIndex].rot();
return true; return true;
} else { } else {
return false; return false;
@ -414,7 +414,7 @@ bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const {
bool Rig::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const { bool Rig::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const {
QReadLocker readLock(&_externalPoseSetLock); QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) {
rotation = _externalPoseSet._absolutePoses[jointIndex].rot; rotation = _externalPoseSet._absolutePoses[jointIndex].rot();
return true; return true;
} else { } else {
return false; return false;
@ -424,7 +424,7 @@ bool Rig::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation
bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const { bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const {
QReadLocker readLock(&_externalPoseSetLock); QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) { if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) {
translation = _externalPoseSet._relativePoses[jointIndex].trans; translation = _externalPoseSet._relativePoses[jointIndex].trans();
return true; return true;
} else { } else {
return false; return false;
@ -434,7 +434,7 @@ bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const {
bool Rig::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const { bool Rig::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const {
QReadLocker readLock(&_externalPoseSetLock); QReadLocker readLock(&_externalPoseSetLock);
if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) {
translation = _externalPoseSet._absolutePoses[jointIndex].trans; translation = _externalPoseSet._absolutePoses[jointIndex].trans();
return true; return true;
} else { } else {
return false; return false;
@ -498,7 +498,7 @@ const AnimPoseVec& Rig::getAbsoluteDefaultPoses() const {
bool Rig::getRelativeDefaultJointRotation(int index, glm::quat& rotationOut) const { bool Rig::getRelativeDefaultJointRotation(int index, glm::quat& rotationOut) const {
if (_animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints()) { if (_animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints()) {
rotationOut = _animSkeleton->getRelativeDefaultPose(index).rot; rotationOut = _animSkeleton->getRelativeDefaultPose(index).rot();
return true; return true;
} else { } else {
return false; return false;
@ -507,7 +507,7 @@ bool Rig::getRelativeDefaultJointRotation(int index, glm::quat& rotationOut) con
bool Rig::getRelativeDefaultJointTranslation(int index, glm::vec3& translationOut) const { bool Rig::getRelativeDefaultJointTranslation(int index, glm::vec3& translationOut) const {
if (_animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints()) { if (_animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints()) {
translationOut = _animSkeleton->getRelativeDefaultPose(index).trans; translationOut = _animSkeleton->getRelativeDefaultPose(index).trans();
return true; return true;
} else { } else {
return false; return false;
@ -998,8 +998,8 @@ void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositi
glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const { glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const {
// the input hmd values are in avatar/rig space // the input hmd values are in avatar/rig space
const glm::vec3 hmdPosition = hmdPose.trans; const glm::vec3& hmdPosition = hmdPose.trans();
const glm::quat hmdOrientation = hmdPose.rot; const glm::quat& hmdOrientation = hmdPose.rot();
// TODO: cache jointIndices // TODO: cache jointIndices
int rightEyeIndex = indexOfJoint("RightEye"); int rightEyeIndex = indexOfJoint("RightEye");
@ -1007,10 +1007,10 @@ void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositi
int headIndex = indexOfJoint("Head"); int headIndex = indexOfJoint("Head");
int neckIndex = indexOfJoint("Neck"); int neckIndex = indexOfJoint("Neck");
glm::vec3 absRightEyePos = rightEyeIndex != -1 ? getAbsoluteDefaultPose(rightEyeIndex).trans : DEFAULT_RIGHT_EYE_POS; glm::vec3 absRightEyePos = rightEyeIndex != -1 ? getAbsoluteDefaultPose(rightEyeIndex).trans() : DEFAULT_RIGHT_EYE_POS;
glm::vec3 absLeftEyePos = leftEyeIndex != -1 ? getAbsoluteDefaultPose(leftEyeIndex).trans : DEFAULT_LEFT_EYE_POS; glm::vec3 absLeftEyePos = leftEyeIndex != -1 ? getAbsoluteDefaultPose(leftEyeIndex).trans() : DEFAULT_LEFT_EYE_POS;
glm::vec3 absHeadPos = headIndex != -1 ? getAbsoluteDefaultPose(headIndex).trans : DEFAULT_HEAD_POS; glm::vec3 absHeadPos = headIndex != -1 ? getAbsoluteDefaultPose(headIndex).trans() : DEFAULT_HEAD_POS;
glm::vec3 absNeckPos = neckIndex != -1 ? getAbsoluteDefaultPose(neckIndex).trans : DEFAULT_NECK_POS; glm::vec3 absNeckPos = neckIndex != -1 ? getAbsoluteDefaultPose(neckIndex).trans() : DEFAULT_NECK_POS;
glm::vec3 absCenterEyePos = (absRightEyePos + absLeftEyePos) / 2.0f; glm::vec3 absCenterEyePos = (absRightEyePos + absLeftEyePos) / 2.0f;
glm::vec3 eyeOffset = absCenterEyePos - absHeadPos; glm::vec3 eyeOffset = absCenterEyePos - absHeadPos;
@ -1026,7 +1026,7 @@ void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositi
neckPositionOut = hmdPosition - hmdOrientation * (headOffset + eyeOffset); neckPositionOut = hmdPosition - hmdOrientation * (headOffset + eyeOffset);
// slerp between default orientation and hmdOrientation // slerp between default orientation and hmdOrientation
neckOrientationOut = safeMix(hmdOrientation, _animSkeleton->getRelativeDefaultPose(neckIndex).rot, 0.5f); neckOrientationOut = safeMix(hmdOrientation, _animSkeleton->getRelativeDefaultPose(neckIndex).rot(), 0.5f);
} }
void Rig::updateNeckJoint(int index, const HeadParameters& params) { void Rig::updateNeckJoint(int index, const HeadParameters& params) {
@ -1077,14 +1077,14 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
// TODO: does not properly handle avatar scale. // TODO: does not properly handle avatar scale.
if (isIndexValid(index)) { if (isIndexValid(index)) {
glm::mat4 rigToWorld = createMatFromQuatAndPos(modelRotation, modelTranslation); const glm::mat4 rigToWorld = createMatFromQuatAndPos(modelRotation, modelTranslation);
glm::mat4 worldToRig = glm::inverse(rigToWorld); const glm::mat4 worldToRig = glm::inverse(rigToWorld);
glm::vec3 lookAtVector = glm::normalize(transformPoint(worldToRig, lookAtSpot) - _internalPoseSet._absolutePoses[index].trans); const glm::vec3 lookAtVector = glm::normalize(transformPoint(worldToRig, lookAtSpot) - _internalPoseSet._absolutePoses[index].trans());
int headIndex = indexOfJoint("Head"); int headIndex = indexOfJoint("Head");
glm::quat headQuat; glm::quat headQuat;
if (headIndex >= 0) { if (headIndex >= 0) {
headQuat = _internalPoseSet._absolutePoses[headIndex].rot; headQuat = _internalPoseSet._absolutePoses[headIndex].rot();
} }
glm::vec3 headUp = headQuat * Vectors::UNIT_Y; glm::vec3 headUp = headQuat * Vectors::UNIT_Y;
@ -1103,7 +1103,7 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
} }
// directly set absolutePose rotation // directly set absolutePose rotation
_internalPoseSet._absolutePoses[index].rot = deltaQuat * headQuat; _internalPoseSet._absolutePoses[index].rot() = deltaQuat * headQuat;
} }
} }
@ -1114,7 +1114,7 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
int hipsIndex = indexOfJoint("Hips"); int hipsIndex = indexOfJoint("Hips");
glm::vec3 hipsTrans; glm::vec3 hipsTrans;
if (hipsIndex >= 0) { if (hipsIndex >= 0) {
hipsTrans = _internalPoseSet._absolutePoses[hipsIndex].trans; hipsTrans = _internalPoseSet._absolutePoses[hipsIndex].trans();
} }
// Use this capsule to represent the avatar body. // Use this capsule to represent the avatar body.
@ -1188,7 +1188,7 @@ void Rig::initAnimGraph(const QUrl& url) {
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const { bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
if (_animSkeleton && _rootJointIndex >= 0) { if (_animSkeleton && _rootJointIndex >= 0) {
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans; modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans();
return true; return true;
} else { } else {
return false; return false;
@ -1234,10 +1234,11 @@ void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& a
} }
glm::mat4 Rig::getJointTransform(int jointIndex) const { glm::mat4 Rig::getJointTransform(int jointIndex) const {
static const glm::mat4 IDENTITY;
if (isIndexValid(jointIndex)) { if (isIndexValid(jointIndex)) {
return _internalPoseSet._absolutePoses[jointIndex]; return _internalPoseSet._absolutePoses[jointIndex];
} else { } else {
return glm::mat4(); return IDENTITY;
} }
} }
@ -1250,14 +1251,14 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
JointData& data = jointDataVec[i]; JointData& data = jointDataVec[i];
if (isIndexValid(i)) { if (isIndexValid(i)) {
// rotations are in absolute rig frame. // rotations are in absolute rig frame.
glm::quat defaultAbsRot = geometryToRigPose.rot * _animSkeleton->getAbsoluteDefaultPose(i).rot; glm::quat defaultAbsRot = geometryToRigPose.rot() * _animSkeleton->getAbsoluteDefaultPose(i).rot();
data.rotation = _internalPoseSet._absolutePoses[i].rot; data.rotation = _internalPoseSet._absolutePoses[i].rot();
data.rotationSet = !isEqual(data.rotation, defaultAbsRot); data.rotationSet = !isEqual(data.rotation, defaultAbsRot);
// translations are in relative frame but scaled so that they are in meters, // translations are in relative frame but scaled so that they are in meters,
// instead of geometry units. // instead of geometry units.
glm::vec3 defaultRelTrans = _geometryOffset.scale * _animSkeleton->getRelativeDefaultPose(i).trans; glm::vec3 defaultRelTrans = _geometryOffset.scale() * _animSkeleton->getRelativeDefaultPose(i).trans();
data.translation = _geometryOffset.scale * _internalPoseSet._relativePoses[i].trans; data.translation = _geometryOffset.scale() * _internalPoseSet._relativePoses[i].trans();
data.translationSet = !isEqual(data.translation, defaultRelTrans); data.translationSet = !isEqual(data.translation, defaultRelTrans);
} else { } else {
data.translationSet = false; data.translationSet = false;
@ -1272,7 +1273,7 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
// make a vector of rotations in absolute-geometry-frame // make a vector of rotations in absolute-geometry-frame
const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses(); const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses();
std::vector<glm::quat> rotations; std::vector<glm::quat> rotations;
rotations.reserve(_animSkeleton->getAbsoluteDefaultPoses().size()); rotations.reserve(absoluteDefaultPoses.size());
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
for (int i = 0; i < jointDataVec.size(); i++) { for (int i = 0; i < jointDataVec.size(); i++) {
const JointData& data = jointDataVec.at(i); const JointData& data = jointDataVec.at(i);
@ -1280,7 +1281,7 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
// JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame // JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame
rotations.push_back(rigToGeometryRot * data.rotation); rotations.push_back(rigToGeometryRot * data.rotation);
} else { } else {
rotations.push_back(absoluteDefaultPoses[i].rot); rotations.push_back(absoluteDefaultPoses[i].rot());
} }
} }
@ -1291,13 +1292,13 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses(); const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses();
for (int i = 0; i < jointDataVec.size(); i++) { for (int i = 0; i < jointDataVec.size(); i++) {
const JointData& data = jointDataVec.at(i); const JointData& data = jointDataVec.at(i);
_internalPoseSet._relativePoses[i].scale = Vectors::ONE; _internalPoseSet._relativePoses[i].scale() = Vectors::ONE;
_internalPoseSet._relativePoses[i].rot = rotations[i]; _internalPoseSet._relativePoses[i].rot() = rotations[i];
if (data.translationSet) { if (data.translationSet) {
// JointData translations are in scaled relative-frame so we scale back to regular relative-frame // JointData translations are in scaled relative-frame so we scale back to regular relative-frame
_internalPoseSet._relativePoses[i].trans = _invGeometryOffset.scale * data.translation; _internalPoseSet._relativePoses[i].trans() = _invGeometryOffset.scale() * data.translation;
} else { } else {
_internalPoseSet._relativePoses[i].trans = relativeDefaultPoses[i].trans; _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans();
} }
} }
} }
@ -1346,10 +1347,10 @@ void Rig::computeAvatarBoundingCapsule(
} }
AnimVariantMap animVars; AnimVariantMap animVars;
glm::quat handRotation = glm::angleAxis(PI, Vectors::UNIT_X); glm::quat handRotation = glm::angleAxis(PI, Vectors::UNIT_X);
animVars.set("leftHandPosition", hips.trans); animVars.set("leftHandPosition", hips.trans());
animVars.set("leftHandRotation", handRotation); animVars.set("leftHandRotation", handRotation);
animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition); animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
animVars.set("rightHandPosition", hips.trans); animVars.set("rightHandPosition", hips.trans());
animVars.set("rightHandRotation", handRotation); animVars.set("rightHandRotation", handRotation);
animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition); animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
@ -1405,7 +1406,7 @@ void Rig::computeAvatarBoundingCapsule(
radiusOut = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z)); radiusOut = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
heightOut = diagonal.y - 2.0f * radiusOut; heightOut = diagonal.y - 2.0f * radiusOut;
glm::vec3 rootPosition = finalPoses[geometry.rootJointIndex].trans; glm::vec3 rootPosition = finalPoses[geometry.rootJointIndex].trans();
glm::vec3 rigCenter = (geometryToRig * (0.5f * (totalExtents.maximum + totalExtents.minimum))); glm::vec3 rigCenter = (geometryToRig * (0.5f * (totalExtents.maximum + totalExtents.minimum)));
localOffsetOut = rigCenter - (geometryToRig * rootPosition); localOffsetOut = rigCenter - (geometryToRig * rootPosition);
} }

View file

@ -161,6 +161,13 @@ void AvatarHashMap::processKillAvatar(QSharedPointer<ReceivedMessage> message, S
removeAvatar(sessionUUID, reason); removeAvatar(sessionUUID, reason);
} }
void AvatarHashMap::processExitingSpaceBubble(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
// read the node id
QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
auto nodeList = DependencyManager::get<NodeList>();
nodeList->radiusIgnoreNodeBySessionID(sessionUUID, false);
}
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) {
QWriteLocker locker(&_hashLock); QWriteLocker locker(&_hashLock);

View file

@ -57,6 +57,7 @@ private slots:
void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode); void processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
void processExitingSpaceBubble(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
protected: protected:
AvatarHashMap(); AvatarHashMap();

View file

@ -1055,10 +1055,10 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index,
if (!success) { if (!success) {
return false; return false;
} }
jointAbsolutePose.rot = rotation; jointAbsolutePose.rot() = rotation;
AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose; AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose;
return setLocalJointRotation(index, jointRelativePose.rot); return setLocalJointRotation(index, jointRelativePose.rot());
} }
bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) {
@ -1088,10 +1088,10 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind
if (!success) { if (!success) {
return false; return false;
} }
jointAbsolutePose.trans = translation; jointAbsolutePose.trans() = translation;
AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose; AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose;
return setLocalJointTranslation(index, jointRelativePose.trans); return setLocalJointTranslation(index, jointRelativePose.trans());
} }
glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const { glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const {

View file

@ -238,6 +238,10 @@ void NodeList::reset() {
_numNoReplyDomainCheckIns = 0; _numNoReplyDomainCheckIns = 0;
// lock and clear our set of radius ignored IDs
_radiusIgnoredSetLock.lockForWrite();
_radiusIgnoredNodeIDs.clear();
_radiusIgnoredSetLock.unlock();
// lock and clear our set of ignored IDs // lock and clear our set of ignored IDs
_ignoredSetLock.lockForWrite(); _ignoredSetLock.lockForWrite();
_ignoredNodeIDs.clear(); _ignoredNodeIDs.clear();
@ -781,6 +785,22 @@ void NodeList::sendIgnoreRadiusStateToNode(const SharedNodePointer& destinationN
sendPacket(std::move(ignorePacket), *destinationNode); sendPacket(std::move(ignorePacket), *destinationNode);
} }
void NodeList::radiusIgnoreNodeBySessionID(const QUuid& nodeID, bool radiusIgnoreEnabled) {
if (radiusIgnoreEnabled) {
QReadLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // read lock for insert
// add this nodeID to our set of ignored IDs
_radiusIgnoredNodeIDs.insert(nodeID);
} else {
QWriteLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // write lock for unsafe_erase
_radiusIgnoredNodeIDs.unsafe_erase(nodeID);
}
}
bool NodeList::isRadiusIgnoringNode(const QUuid& nodeID) const {
QReadLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // read lock for reading
return _radiusIgnoredNodeIDs.find(nodeID) != _radiusIgnoredNodeIDs.cend();
}
void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) { void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) {
// enumerate the nodes to send a reliable ignore packet to each that can leverage it // enumerate the nodes to send a reliable ignore packet to each that can leverage it
if (!nodeID.isNull() && _sessionUUID != nodeID) { if (!nodeID.isNull() && _sessionUUID != nodeID) {
@ -1020,12 +1040,12 @@ void NodeList::processUsernameFromIDReply(QSharedPointer<ReceivedMessage> messag
} }
void NodeList::setRequestsDomainListData(bool isRequesting) { void NodeList::setRequestsDomainListData(bool isRequesting) {
// Tell the avatar mixer whether I want to receive any additional data to which I might be entitled // Tell the avatar mixer and audio mixer whether I want to receive any additional data to which I might be entitled
if (_requestsDomainListData == isRequesting) { if (_requestsDomainListData == isRequesting) {
return; return;
} }
eachMatchingNode([](const SharedNodePointer& node)->bool { eachMatchingNode([](const SharedNodePointer& node)->bool {
return node->getType() == NodeType::AvatarMixer; return (node->getType() == NodeType::AudioMixer || node->getType() == NodeType::AvatarMixer);
}, [this, isRequesting](const SharedNodePointer& destinationNode) { }, [this, isRequesting](const SharedNodePointer& destinationNode) {
auto packet = NLPacket::create(PacketType::RequestsDomainListData, sizeof(bool), true); // reliable auto packet = NLPacket::create(PacketType::RequestsDomainListData, sizeof(bool), true); // reliable
packet->writePrimitive(isRequesting); packet->writePrimitive(isRequesting);

View file

@ -76,6 +76,8 @@ public:
void toggleIgnoreRadius() { ignoreNodesInRadius(!getIgnoreRadiusEnabled()); } void toggleIgnoreRadius() { ignoreNodesInRadius(!getIgnoreRadiusEnabled()); }
void enableIgnoreRadius() { ignoreNodesInRadius(true); } void enableIgnoreRadius() { ignoreNodesInRadius(true); }
void disableIgnoreRadius() { ignoreNodesInRadius(false); } void disableIgnoreRadius() { ignoreNodesInRadius(false); }
void radiusIgnoreNodeBySessionID(const QUuid& nodeID, bool radiusIgnoreEnabled);
bool isRadiusIgnoringNode(const QUuid& other) const;
void ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled); void ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled);
bool isIgnoringNode(const QUuid& nodeID) const; bool isIgnoringNode(const QUuid& nodeID) const;
void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled); void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled);
@ -159,6 +161,8 @@ private:
QTimer _keepAlivePingTimer; QTimer _keepAlivePingTimer;
bool _requestsDomainListData; bool _requestsDomainListData;
mutable QReadWriteLock _radiusIgnoredSetLock;
tbb::concurrent_unordered_set<QUuid, UUIDHasher> _radiusIgnoredNodeIDs;
mutable QReadWriteLock _ignoredSetLock; mutable QReadWriteLock _ignoredSetLock;
tbb::concurrent_unordered_set<QUuid, UUIDHasher> _ignoredNodeIDs; tbb::concurrent_unordered_set<QUuid, UUIDHasher> _ignoredNodeIDs;
mutable QReadWriteLock _personalMutedSetLock; mutable QReadWriteLock _personalMutedSetLock;

View file

@ -105,7 +105,8 @@ public:
UsernameFromIDReply, UsernameFromIDReply,
ViewFrustum, ViewFrustum,
RequestsDomainListData, RequestsDomainListData,
LAST_PACKET_TYPE = RequestsDomainListData ExitingSpaceBubble,
LAST_PACKET_TYPE = ExitingSpaceBubble
}; };
}; };

View file

@ -168,7 +168,7 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
const uint32_t color = toRGBA(vecColor); const uint32_t color = toRGBA(vecColor);
AnimPose finalPose = rootPose * pose; AnimPose finalPose = rootPose * pose;
glm::vec3 base = rootPose * pose.trans; glm::vec3 base = rootPose * pose.trans();
glm::vec3 xRing[NUM_CIRCLE_SLICES + 1]; // one extra for last index. glm::vec3 xRing[NUM_CIRCLE_SLICES + 1]; // one extra for last index.
glm::vec3 yRing[NUM_CIRCLE_SLICES + 1]; glm::vec3 yRing[NUM_CIRCLE_SLICES + 1];
@ -245,7 +245,7 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, const AnimPo
AnimPose pose0 = rootPose * parentPose; AnimPose pose0 = rootPose * parentPose;
AnimPose pose1 = rootPose * pose; AnimPose pose1 = rootPose * pose;
glm::vec3 boneAxisWorld = glm::normalize(pose1.trans - pose0.trans); glm::vec3 boneAxisWorld = glm::normalize(pose1.trans() - pose0.trans());
glm::vec3 boneAxis0 = glm::normalize(pose0.inverse().xformVector(boneAxisWorld)); glm::vec3 boneAxis0 = glm::normalize(pose0.inverse().xformVector(boneAxisWorld));
glm::vec3 boneAxis1 = glm::normalize(pose1.inverse().xformVector(boneAxisWorld)); glm::vec3 boneAxis1 = glm::normalize(pose1.inverse().xformVector(boneAxisWorld));
@ -255,7 +255,7 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, const AnimPo
const int NUM_BASE_CORNERS = 4; const int NUM_BASE_CORNERS = 4;
// make sure there's room between the two bones to draw a nice bone link. // make sure there's room between the two bones to draw a nice bone link.
if (glm::dot(boneTip - pose0.trans, boneAxisWorld) > glm::dot(boneBase - pose0.trans, boneAxisWorld)) { if (glm::dot(boneTip - pose0.trans(), boneAxisWorld) > glm::dot(boneBase - pose0.trans(), boneAxisWorld)) {
// there is room, so lets draw a nice bone // there is room, so lets draw a nice bone
@ -290,10 +290,10 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, const AnimPo
// just draw a line between the two bone centers. // just draw a line between the two bone centers.
// We add the same line multiple times, so the vertex count is correct. // We add the same line multiple times, so the vertex count is correct.
for (int i = 0; i < NUM_BASE_CORNERS * 2; i++) { for (int i = 0; i < NUM_BASE_CORNERS * 2; i++) {
v->pos = pose0.trans; v->pos = pose0.trans();
v->rgba = color; v->rgba = color;
v++; v++;
v->pos = pose1.trans; v->pos = pose1.trans();
v->rgba = color; v->rgba = color;
v++; v++;
} }
@ -365,7 +365,7 @@ void AnimDebugDraw::update() {
glm::vec4 color = std::get<3>(iter.second); glm::vec4 color = std::get<3>(iter.second);
for (int i = 0; i < skeleton->getNumJoints(); i++) { for (int i = 0; i < skeleton->getNumJoints(); i++) {
const float radius = BONE_RADIUS / (absPoses[i].scale.x * rootPose.scale.x); const float radius = BONE_RADIUS / (absPoses[i].scale().x * rootPose.scale().x);
// draw bone // draw bone
addBone(rootPose, absPoses[i], radius, color, v); addBone(rootPose, absPoses[i], radius, color, v);

View file

@ -140,8 +140,8 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, _drawMaterial->getSchemaBuffer()); batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, _drawMaterial->getSchemaBuffer());
batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::TEXMAPARRAY, _drawMaterial->getTexMapArrayBuffer()); batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::TEXMAPARRAY, _drawMaterial->getTexMapArrayBuffer());
auto materialKey = _drawMaterial->getKey(); const auto& materialKey = _drawMaterial->getKey();
auto textureMaps = _drawMaterial->getTextureMaps(); const auto& textureMaps = _drawMaterial->getTextureMaps();
int numUnlit = 0; int numUnlit = 0;
if (materialKey.isUnlit()) { if (materialKey.isUnlit()) {
@ -150,9 +150,9 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Albedo // Albedo
if (materialKey.isAlbedoMap()) { if (materialKey.isAlbedoMap()) {
auto albedoMap = textureMaps[model::MaterialKey::ALBEDO_MAP]; auto itr = textureMaps.find(model::MaterialKey::ALBEDO_MAP);
if (albedoMap && albedoMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, albedoMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, itr->second->getTextureView());
} else { } else {
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getGrayTexture()); batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getGrayTexture());
} }
@ -162,9 +162,9 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Roughness map // Roughness map
if (materialKey.isRoughnessMap()) { if (materialKey.isRoughnessMap()) {
auto roughnessMap = textureMaps[model::MaterialKey::ROUGHNESS_MAP]; auto itr = textureMaps.find(model::MaterialKey::ROUGHNESS_MAP);
if (roughnessMap && roughnessMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, roughnessMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, itr->second->getTextureView());
// texcoord are assumed to be the same has albedo // texcoord are assumed to be the same has albedo
} else { } else {
@ -176,9 +176,9 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Normal map // Normal map
if (materialKey.isNormalMap()) { if (materialKey.isNormalMap()) {
auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP]; auto itr = textureMaps.find(model::MaterialKey::NORMAL_MAP);
if (normalMap && normalMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, normalMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, itr->second->getTextureView());
// texcoord are assumed to be the same has albedo // texcoord are assumed to be the same has albedo
} else { } else {
@ -190,9 +190,9 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Metallic map // Metallic map
if (materialKey.isMetallicMap()) { if (materialKey.isMetallicMap()) {
auto specularMap = textureMaps[model::MaterialKey::METALLIC_MAP]; auto itr = textureMaps.find(model::MaterialKey::METALLIC_MAP);
if (specularMap && specularMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, specularMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, itr->second->getTextureView());
// texcoord are assumed to be the same has albedo // texcoord are assumed to be the same has albedo
} else { } else {
@ -204,9 +204,9 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Occlusion map // Occlusion map
if (materialKey.isOcclusionMap()) { if (materialKey.isOcclusionMap()) {
auto specularMap = textureMaps[model::MaterialKey::OCCLUSION_MAP]; auto itr = textureMaps.find(model::MaterialKey::OCCLUSION_MAP);
if (specularMap && specularMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, specularMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, itr->second->getTextureView());
// texcoord are assumed to be the same has albedo // texcoord are assumed to be the same has albedo
} else { } else {
@ -218,9 +218,9 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Scattering map // Scattering map
if (materialKey.isScatteringMap()) { if (materialKey.isScatteringMap()) {
auto scatteringMap = textureMaps[model::MaterialKey::SCATTERING_MAP]; auto itr = textureMaps.find(model::MaterialKey::SCATTERING_MAP);
if (scatteringMap && scatteringMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, scatteringMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, itr->second->getTextureView());
// texcoord are assumed to be the same has albedo // texcoord are assumed to be the same has albedo
} else { } else {
@ -232,18 +232,18 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
// Emissive / Lightmap // Emissive / Lightmap
if (materialKey.isLightmapMap()) { if (materialKey.isLightmapMap()) {
auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; auto itr = textureMaps.find(model::MaterialKey::LIGHTMAP_MAP);
if (lightmapMap && lightmapMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, lightmapMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
} else { } else {
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture()); batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture());
} }
} else if (materialKey.isEmissiveMap()) { } else if (materialKey.isEmissiveMap()) {
auto emissiveMap = textureMaps[model::MaterialKey::EMISSIVE_MAP]; auto itr = textureMaps.find(model::MaterialKey::EMISSIVE_MAP);
if (emissiveMap && emissiveMap->isDefined()) { if (itr != textureMaps.end() && itr->second->isDefined()) {
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, emissiveMap->getTextureView()); batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
} else { } else {
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture()); batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture());
} }

View file

@ -25,8 +25,13 @@ Q_LOGGING_CATEGORY(trace_simulation_physics, "trace.simulation.physics")
#define NSIGHT_TRACING #define NSIGHT_TRACING
#endif #endif
Duration::Duration(const QLoggingCategory& category, const QString& name, uint32_t argbColor, uint64_t payload, QVariantMap args) : _name(name), _category(category) { static bool tracingEnabled() {
if (_category.isDebugEnabled()) { return DependencyManager::get<tracing::Tracer>()->isEnabled();
}
Duration::Duration(const QLoggingCategory& category, const QString& name, uint32_t argbColor, uint64_t payload, const QVariantMap& baseArgs) : _name(name), _category(category) {
if (tracingEnabled() && category.isDebugEnabled()) {
QVariantMap args = baseArgs;
args["nv_payload"] = QVariant::fromValue(payload); args["nv_payload"] = QVariant::fromValue(payload);
tracing::traceEvent(_category, _name, tracing::DurationBegin, "", args); tracing::traceEvent(_category, _name, tracing::DurationBegin, "", args);
@ -47,7 +52,7 @@ Duration::Duration(const QLoggingCategory& category, const QString& name, uint32
} }
Duration::~Duration() { Duration::~Duration() {
if (_category.isDebugEnabled()) { if (tracingEnabled() && _category.isDebugEnabled()) {
tracing::traceEvent(_category, _name, tracing::DurationEnd); tracing::traceEvent(_category, _name, tracing::DurationEnd);
#ifdef NSIGHT_TRACING #ifdef NSIGHT_TRACING
nvtxRangePop(); nvtxRangePop();
@ -58,7 +63,7 @@ Duration::~Duration() {
// FIXME // FIXME
uint64_t Duration::beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor) { uint64_t Duration::beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor) {
#ifdef NSIGHT_TRACING #ifdef NSIGHT_TRACING
if (category.isDebugEnabled()) { if (tracingEnabled() && category.isDebugEnabled()) {
nvtxEventAttributes_t eventAttrib = { 0 }; nvtxEventAttributes_t eventAttrib = { 0 };
eventAttrib.version = NVTX_VERSION; eventAttrib.version = NVTX_VERSION;
eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
@ -75,7 +80,7 @@ uint64_t Duration::beginRange(const QLoggingCategory& category, const char* name
// FIXME // FIXME
void Duration::endRange(const QLoggingCategory& category, uint64_t rangeId) { void Duration::endRange(const QLoggingCategory& category, uint64_t rangeId) {
#ifdef NSIGHT_TRACING #ifdef NSIGHT_TRACING
if (category.isDebugEnabled()) { if (tracingEnabled() && category.isDebugEnabled()) {
nvtxRangeEnd(rangeId); nvtxRangeEnd(rangeId);
} }
#endif #endif

View file

@ -26,7 +26,7 @@ Q_DECLARE_LOGGING_CATEGORY(trace_simulation_physics)
class Duration { class Duration {
public: public:
Duration(const QLoggingCategory& category, const QString& name, uint32_t argbColor = 0xff0000ff, uint64_t payload = 0, QVariantMap args = QVariantMap()); Duration(const QLoggingCategory& category, const QString& name, uint32_t argbColor = 0xff0000ff, uint64_t payload = 0, const QVariantMap& args = QVariantMap());
~Duration(); ~Duration();
static uint64_t beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor); static uint64_t beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor);

View file

@ -31,6 +31,10 @@ OculusDisplayPlugin::OculusDisplayPlugin() {
bool OculusDisplayPlugin::internalActivate() { bool OculusDisplayPlugin::internalActivate() {
bool result = Parent::internalActivate(); bool result = Parent::internalActivate();
_longSubmits = 0;
_longRenders = 0;
_longFrames = 0;
currentDebugMode = ovrPerfHud_Off; currentDebugMode = ovrPerfHud_Off;
if (result && _session) { if (result && _session) {
ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode); ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
@ -112,35 +116,43 @@ void OculusDisplayPlugin::uncustomizeContext() {
Parent::uncustomizeContext(); Parent::uncustomizeContext();
} }
static const uint64_t FRAME_BUDGET = (11 * USECS_PER_MSEC);
static const uint64_t FRAME_OVER_BUDGET = (15 * USECS_PER_MSEC);
void OculusDisplayPlugin::hmdPresent() { void OculusDisplayPlugin::hmdPresent() {
static uint64_t lastSubmitEnd = 0;
if (!_customized) { if (!_customized) {
return; return;
} }
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
int curIndex; {
ovr_GetTextureSwapChainCurrentIndex(_session, _textureSwapChain, &curIndex); PROFILE_RANGE_EX(render, "Oculus Blit", 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
GLuint curTexId; int curIndex;
ovr_GetTextureSwapChainBufferGL(_session, _textureSwapChain, curIndex, &curTexId); ovr_GetTextureSwapChainCurrentIndex(_session, _textureSwapChain, &curIndex);
GLuint curTexId;
ovr_GetTextureSwapChainBufferGL(_session, _textureSwapChain, curIndex, &curTexId);
// Manually bind the texture to the FBO // Manually bind the texture to the FBO
// FIXME we should have a way of wrapping raw GL ids in GPU objects without // FIXME we should have a way of wrapping raw GL ids in GPU objects without
// taking ownership of the object // taking ownership of the object
auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer);
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0); glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0);
render([&](gpu::Batch& batch) { render([&](gpu::Batch& batch) {
batch.enableStereo(false); batch.enableStereo(false);
batch.setFramebuffer(_outputFramebuffer); batch.setFramebuffer(_outputFramebuffer);
batch.setViewportTransform(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.setViewportTransform(ivec4(uvec2(), _outputFramebuffer->getSize()));
batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize()));
batch.resetViewTransform(); batch.resetViewTransform();
batch.setProjectionTransform(mat4()); batch.setProjectionTransform(mat4());
batch.setPipeline(_presentPipeline); batch.setPipeline(_presentPipeline);
batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0));
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
}); });
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, 0, 0); glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, 0, 0);
}
{ {
auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain); auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain);
@ -148,8 +160,33 @@ void OculusDisplayPlugin::hmdPresent() {
_sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime; _sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose); _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose); _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
auto submitStart = usecTimestampNow();
uint64_t nonSubmitInterval = 0;
if (lastSubmitEnd != 0) {
nonSubmitInterval = submitStart - lastSubmitEnd;
if (nonSubmitInterval > FRAME_BUDGET) {
++_longRenders;
}
}
ovrLayerHeader* layers = &_sceneLayer.Header; ovrLayerHeader* layers = &_sceneLayer.Header;
result = ovr_SubmitFrame(_session, _currentFrame->frameIndex, &_viewScaleDesc, &layers, 1); {
PROFILE_RANGE_EX(render, "Oculus Submit", 0xff00ff00, (uint64_t)_currentFrame->frameIndex)
result = ovr_SubmitFrame(_session, _currentFrame->frameIndex, &_viewScaleDesc, &layers, 1);
}
lastSubmitEnd = usecTimestampNow();
if (nonSubmitInterval != 0) {
auto submitInterval = lastSubmitEnd - submitStart;
if (nonSubmitInterval < FRAME_BUDGET && submitInterval > FRAME_BUDGET) {
++_longSubmits;
}
if ((nonSubmitInterval + submitInterval) > FRAME_OVER_BUDGET) {
++_longFrames;
}
}
if (!OVR_SUCCESS(result)) { if (!OVR_SUCCESS(result)) {
logWarning("Failed to present"); logWarning("Failed to present");
} }
@ -168,6 +205,7 @@ void OculusDisplayPlugin::hmdPresent() {
_appDroppedFrames.store(appDroppedFrames); _appDroppedFrames.store(appDroppedFrames);
_compositorDroppedFrames.store(compositorDroppedFrames); _compositorDroppedFrames.store(compositorDroppedFrames);
} }
_presentRate.increment(); _presentRate.increment();
} }
@ -176,6 +214,9 @@ QJsonObject OculusDisplayPlugin::getHardwareStats() const {
QJsonObject hardwareStats; QJsonObject hardwareStats;
hardwareStats["app_dropped_frame_count"] = _appDroppedFrames.load(); hardwareStats["app_dropped_frame_count"] = _appDroppedFrames.load();
hardwareStats["compositor_dropped_frame_count"] = _compositorDroppedFrames.load(); hardwareStats["compositor_dropped_frame_count"] = _compositorDroppedFrames.load();
hardwareStats["long_render_count"] = _longRenders.load();
hardwareStats["long_submit_count"] = _longSubmits.load();
hardwareStats["long_frame_count"] = _longFrames.load();
return hardwareStats; return hardwareStats;
} }

View file

@ -41,5 +41,8 @@ private:
std::atomic_int _compositorDroppedFrames; std::atomic_int _compositorDroppedFrames;
std::atomic_int _appDroppedFrames; std::atomic_int _appDroppedFrames;
std::atomic_int _longSubmits;
std::atomic_int _longRenders;
std::atomic_int _longFrames;
}; };

View file

@ -18,7 +18,7 @@ var DEFAULT_SCRIPTS = [
"system/mute.js", "system/mute.js",
"system/goto.js", "system/goto.js",
"system/hmd.js", "system/hmd.js",
"system/marketplaces/marketplace.js", "system/marketplaces/marketplaces.js",
"system/edit.js", "system/edit.js",
"system/pal.js", //"system/mod.js", // older UX, if you prefer "system/pal.js", //"system/mod.js", // older UX, if you prefer
"system/selectAudioDevice.js", "system/selectAudioDevice.js",