diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index b7b412b577..1c190a2b79 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -42,6 +42,8 @@ Rectangle { property var activeTab: "nearbyTab"; property bool currentlyEditingDisplayName: false property bool punctuationMode: false; + property double loudSortTime: 0.0; + readonly property double kLOUD_SORT_PERIOD_MS: 1000.0; HifiConstants { id: hifi; } RootHttpRequest { id: http; } @@ -1247,6 +1249,11 @@ Rectangle { } } } + if (nearbyTable.sortIndicatorColumn == 0 && Date.now() - pal.loudSortTime >= pal.kLOUD_SORT_PERIOD_MS) { + // Current sort by loudness so re-sort. + sortModel(); + pal.loudSortTime = Date.now(); + } break; case 'clearLocalQMLData': ignored = {}; diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index a1826076fa..5fb9c9a0ee 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -569,7 +569,7 @@ void AvatarActionHold::lateAvatarUpdate(const AnimPose& prePhysicsRoomPose, cons } btTransform worldTrans = rigidBody->getWorldTransform(); - AnimPose worldBodyPose(1.0f, bulletToGLM(worldTrans.getRotation()), bulletToGLM(worldTrans.getOrigin())); + AnimPose worldBodyPose(glm::vec3(1), bulletToGLM(worldTrans.getRotation()), bulletToGLM(worldTrans.getOrigin())); // transform the body transform into sensor space with the prePhysics sensor-to-world matrix. // then transform it back into world uisng the postAvatarUpdate sensor-to-world matrix. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index aa47c63572..817c870244 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2983,7 +2983,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { auto animSkeleton = _skeletonModel->getRig().getAnimSkeleton(); // the rig is in the skeletonModel frame - AnimPose xform(1.0f, _skeletonModel->getRotation(), _skeletonModel->getTranslation()); + AnimPose xform(glm::vec3(1), _skeletonModel->getRotation(), _skeletonModel->getTranslation()); if (_enableDebugDrawDefaultPose && animSkeleton) { glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f); @@ -3028,7 +3028,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { updateHoldActions(_prePhysicsRoomPose, postUpdateRoomPose); if (_enableDebugDrawDetailedCollision) { - AnimPose rigToWorldPose(1.0f, getWorldOrientation() * Quaternions::Y_180, getWorldPosition()); + AnimPose rigToWorldPose(glm::vec3(1.0f), getWorldOrientation() * Quaternions::Y_180, getWorldPosition()); const int NUM_DEBUG_COLORS = 8; const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = { glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), @@ -4824,7 +4824,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat swingTwistDecomposition(hipsinWorldSpace, avatarUpWorld, resultingSwingInWorld, resultingTwistInWorld); // remove scale present from sensorToWorldMatrix - followWorldPose.scale() = 1.0f; + followWorldPose.scale() = glm::vec3(1.0f); if (isActive(Rotation)) { //use the hmd reading for the hips follow diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 9b0e2fb7f8..51a2c3767b 100755 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -55,7 +55,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { if (myAvatar->isJointPinned(hipsIndex)) { Transform avatarTransform = myAvatar->getTransform(); AnimPose result = AnimPose(worldToSensorMat * avatarTransform.getMatrix() * Matrices::Y_180); - result.scale() = 1.0f; + result.scale() = glm::vec3(1.0f, 1.0f, 1.0f); return result; } @@ -122,7 +122,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::ControllerParameters params; - AnimPose avatarToRigPose(1.0f, Quaternions::Y_180, glm::vec3(0.0f)); + AnimPose avatarToRigPose(glm::vec3(1.0f), Quaternions::Y_180, glm::vec3(0.0f)); glm::mat4 rigToAvatarMatrix = Matrices::Y_180; glm::mat4 avatarToWorldMatrix = createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()); @@ -141,7 +141,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { // preMult 180 is necessary to convert from avatar to rig coordinates. // postMult 180 is necessary to convert head from -z forward to z forward. glm::quat headRot = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180; - params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(1.0f, headRot, glm::vec3(0.0f)); + params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(glm::vec3(1.0f), headRot, glm::vec3(0.0f)); params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = 0; } diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 71b876ff8c..1adc04ee1b 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -140,10 +140,10 @@ void AnimClip::copyFromNetworkAnim() { postRot = animSkeleton.getPostRotationPose(animJoint); // cancel out scale - preRot.scale() = 1.0f; - postRot.scale() = 1.0f; + preRot.scale() = glm::vec3(1.0f); + postRot.scale() = glm::vec3(1.0f); - AnimPose rot(1.0f, hfmAnimRot, glm::vec3()); + AnimPose rot(glm::vec3(1.0f), hfmAnimRot, glm::vec3()); // adjust translation offsets, so large translation animatons on the reference skeleton // will be adjusted when played on a skeleton with short limbs. @@ -155,7 +155,7 @@ void AnimClip::copyFromNetworkAnim() { boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(hfmZeroTrans); } - AnimPose trans = AnimPose(1.0f, glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans)); + AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans)); _anim[frame][skeletonJoint] = trans * preRot * rot * postRot; } diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 7af9e81889..a1809f3438 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -552,7 +552,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const AnimPose accum = absolutePoses[_hipsIndex]; AnimPose baseParentPose = absolutePoses[_hipsIndex]; for (int i = (int)chainDepth - 1; i >= 0; i--) { - accum = accum * AnimPose(1.0f, jointChainInfoOut.jointInfoVec[i].rot, jointChainInfoOut.jointInfoVec[i].trans); + accum = accum * AnimPose(glm::vec3(1.0f), jointChainInfoOut.jointInfoVec[i].rot, jointChainInfoOut.jointInfoVec[i].trans); postAbsPoses[i] = accum; if (jointChainInfoOut.jointInfoVec[i].jointIndex == topJointIndex) { topChainIndex = i; @@ -734,7 +734,7 @@ void AnimInverseKinematics::computeAndCacheSplineJointInfosForIKTarget(const Ani glm::mat3 m(u, v, glm::cross(u, v)); glm::quat rot = glm::normalize(glm::quat_cast(m)); - AnimPose pose(1.0f, rot, spline(t)); + AnimPose pose(glm::vec3(1.0f), rot, spline(t)); AnimPose offsetPose = pose.inverse() * defaultPose; SplineJointInfo splineJointInfo = { index, ratio, offsetPose }; @@ -767,7 +767,7 @@ void AnimInverseKinematics::solveTargetWithSpline(const AnimContext& context, co const int baseIndex = _hipsIndex; // build spline from tip to base - AnimPose tipPose = AnimPose(1.0f, target.getRotation(), target.getTranslation()); + AnimPose tipPose = AnimPose(glm::vec3(1.0f), target.getRotation(), target.getTranslation()); AnimPose basePose = absolutePoses[baseIndex]; CubicHermiteSplineFunctorWithArcLength spline; if (target.getIndex() == _headIndex) { @@ -815,7 +815,7 @@ void AnimInverseKinematics::solveTargetWithSpline(const AnimContext& context, co glm::mat3 m(u, v, glm::cross(u, v)); glm::quat rot = glm::normalize(glm::quat_cast(m)); - AnimPose desiredAbsPose = AnimPose(1.0f, rot, trans) * splineJointInfo.offsetPose; + AnimPose desiredAbsPose = AnimPose(glm::vec3(1.0f), rot, trans) * splineJointInfo.offsetPose; // apply flex coefficent AnimPose flexedAbsPose; @@ -965,7 +965,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars } _relativePoses[_hipsIndex] = parentAbsPose.inverse() * absPose; - _relativePoses[_hipsIndex].scale() = 1.0f; + _relativePoses[_hipsIndex].scale() = glm::vec3(1.0f); } // if there is an active jointChainInfo for the hips store the post shifted hips into it. @@ -1753,7 +1753,7 @@ void AnimInverseKinematics::setSecondaryTargets(const AnimContext& context) { AnimPose rigToGeometryPose = AnimPose(glm::inverse(context.getGeometryToRigMatrix())); for (auto& iter : _secondaryTargetsInRigFrame) { AnimPose absPose = rigToGeometryPose * iter.second; - absPose.scale() = 1.0f; + absPose.scale() = glm::vec3(1.0f); AnimPose parentAbsPose; int parentIndex = _skeleton->getParentIndex(iter.first); @@ -1825,7 +1825,7 @@ void AnimInverseKinematics::debugDrawSpineSplines(const AnimContext& context, co const int baseIndex = _hipsIndex; // build spline - AnimPose tipPose = AnimPose(1.0f, target.getRotation(), target.getTranslation()); + AnimPose tipPose = AnimPose(glm::vec3(1.0f), target.getRotation(), target.getTranslation()); AnimPose basePose = _skeleton->getAbsolutePose(baseIndex, _relativePoses); CubicHermiteSplineFunctorWithArcLength spline; diff --git a/libraries/animation/src/AnimManipulator.cpp b/libraries/animation/src/AnimManipulator.cpp index c75c9865bb..1146cbb19a 100644 --- a/libraries/animation/src/AnimManipulator.cpp +++ b/libraries/animation/src/AnimManipulator.cpp @@ -172,5 +172,5 @@ AnimPose AnimManipulator::computeRelativePoseFromJointVar(const AnimVariantMap& break; } - return AnimPose(1.0f, relRot, relTrans); + return AnimPose(glm::vec3(1), relRot, relTrans); } diff --git a/libraries/animation/src/AnimPoleVectorConstraint.cpp b/libraries/animation/src/AnimPoleVectorConstraint.cpp index 4b91985b0b..d575ddabe4 100644 --- a/libraries/animation/src/AnimPoleVectorConstraint.cpp +++ b/libraries/animation/src/AnimPoleVectorConstraint.cpp @@ -99,7 +99,7 @@ const AnimPoseVec& AnimPoleVectorConstraint::evaluate(const AnimVariantMap& anim AnimPose tipPose = ikChain.getAbsolutePoseFromJointIndex(_tipJointIndex); // Look up refVector from animVars, make sure to convert into geom space. - glm::vec3 refVector = midPose.xformVector(_referenceVector); + glm::vec3 refVector = midPose.xformVectorFast(_referenceVector); float refVectorLength = glm::length(refVector); glm::vec3 axis = basePose.trans() - tipPose.trans(); diff --git a/libraries/animation/src/AnimPose.cpp b/libraries/animation/src/AnimPose.cpp index 366d863c3d..d77514e691 100644 --- a/libraries/animation/src/AnimPose.cpp +++ b/libraries/animation/src/AnimPose.cpp @@ -14,14 +14,15 @@ #include #include "AnimUtil.h" -const AnimPose AnimPose::identity = AnimPose(1.0f, glm::quat(), glm::vec3(0.0f)); +const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), + glm::quat(), + glm::vec3(0.0f)); AnimPose::AnimPose(const glm::mat4& mat) { static const float EPSILON = 0.0001f; - glm::vec3 scale = extractScale(mat); + _scale = extractScale(mat); // quat_cast doesn't work so well with scaled matrices, so cancel it out. - glm::mat4 tmp = glm::scale(mat, 1.0f / scale); - _scale = extractUniformScale(scale); + glm::mat4 tmp = glm::scale(mat, 1.0f / _scale); _rot = glm::quat_cast(tmp); float lengthSquared = glm::length2(_rot); if (glm::abs(lengthSquared - 1.0f) > EPSILON) { @@ -39,22 +40,29 @@ glm::vec3 AnimPose::xformPoint(const glm::vec3& rhs) const { return *this * rhs; } +// really slow, but accurate for transforms with non-uniform scale glm::vec3 AnimPose::xformVector(const glm::vec3& rhs) const { + 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 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale.z); + glm::mat3 mat(xAxis, yAxis, zAxis); + glm::mat3 transInvMat = glm::inverse(glm::transpose(mat)); + return transInvMat * rhs; +} + +// faster, but does not handle non-uniform scale correctly. +glm::vec3 AnimPose::xformVectorFast(const glm::vec3& rhs) const { return _rot * (_scale * rhs); } AnimPose AnimPose::operator*(const AnimPose& rhs) const { - float scale = _scale * rhs._scale; - glm::quat rot = _rot * rhs._rot; - glm::vec3 trans = _trans + (_rot * (_scale * rhs._trans)); - return AnimPose(scale, rot, trans); + glm::mat4 result; + glm_mat4u_mul(*this, rhs, result); + return AnimPose(result); } AnimPose AnimPose::inverse() const { - float invScale = 1.0f / _scale; - glm::quat invRot = glm::inverse(_rot); - glm::vec3 invTrans = invScale * (invRot * -_trans); - return AnimPose(invScale, invRot, invTrans); + return AnimPose(glm::inverse(static_cast(*this))); } // mirror about x-axis without applying negative scale. @@ -63,10 +71,11 @@ AnimPose AnimPose::mirror() const { } AnimPose::operator glm::mat4() const { - glm::vec3 xAxis = _rot * glm::vec3(_scale, 0.0f, 0.0f); - glm::vec3 yAxis = _rot * glm::vec3(0.0f, _scale, 0.0f); - glm::vec3 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale); - return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f), glm::vec4(zAxis, 0.0f), glm::vec4(_trans, 1.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 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale.z); + return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f), + glm::vec4(zAxis, 0.0f), glm::vec4(_trans, 1.0f)); } void AnimPose::blend(const AnimPose& srcPose, float alpha) { diff --git a/libraries/animation/src/AnimPose.h b/libraries/animation/src/AnimPose.h index 4d6dee1987..fb693dc31d 100644 --- a/libraries/animation/src/AnimPose.h +++ b/libraries/animation/src/AnimPose.h @@ -21,13 +21,16 @@ class AnimPose { public: AnimPose() {} explicit AnimPose(const glm::mat4& mat); - explicit AnimPose(const glm::quat& rotIn) : _rot(rotIn), _trans(0.0f), _scale(1.0f) {} - AnimPose(const glm::quat& rotIn, const glm::vec3& transIn) : _rot(rotIn), _trans(transIn), _scale(1.0f) {} - AnimPose(float scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : _rot(rotIn), _trans(transIn), _scale(scaleIn) {} + + explicit AnimPose(const glm::quat& rotIn) : _scale(1.0f), _rot(rotIn), _trans(0.0f) {} + AnimPose(const glm::quat& rotIn, const glm::vec3& transIn) : _scale(1.0f), _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; glm::vec3 xformPoint(const glm::vec3& rhs) const; glm::vec3 xformVector(const glm::vec3& rhs) const; // really slow, but accurate for transforms with non-uniform scale + glm::vec3 xformVectorFast(const glm::vec3& rhs) const; // faster, but does not handle non-uniform scale correctly. glm::vec3 operator*(const glm::vec3& rhs) const; // same as xformPoint AnimPose operator*(const AnimPose& rhs) const; @@ -36,8 +39,8 @@ public: AnimPose mirror() const; operator glm::mat4() const; - float scale() const { return _scale; } - float& scale() { return _scale; } + const glm::vec3& scale() const { return _scale; } + glm::vec3& scale() { return _scale; } const glm::quat& rot() const { return _rot; } glm::quat& rot() { return _rot; } @@ -49,13 +52,13 @@ public: private: friend QDebug operator<<(QDebug debug, const AnimPose& pose); + glm::vec3 _scale { 1.0f }; glm::quat _rot; glm::vec3 _trans; - float _scale { 1.0f }; // uniform scale only. }; 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(); + 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; } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index e3b997e8cc..27ae8858d7 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1355,7 +1355,7 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh } if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) { // we are within the k-dop so push the point along the minimum displacement found - displacementOut = shapePose.xformVector(minDisplacement); + displacementOut = shapePose.xformVectorFast(minDisplacement); return true; } else { // point is outside of kdop @@ -1364,7 +1364,7 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh } else { // point is directly on top of shapeInfo.avgPoint. // push the point out along the x axis. - displacementOut = shapePose.xformVector(shapeInfo.points[0]); + displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]); return true; } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 9882fd6371..ff99f0dc29 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -2014,12 +2014,12 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const { auto& rig = _skeletonModel->getRig(); // Normally the model offset transform will contain the avatar scale factor, we explicitly remove it here. - AnimPose modelOffsetWithoutAvatarScale(1.0f, rig.getModelOffsetPose().rot(), rig.getModelOffsetPose().trans()); + AnimPose modelOffsetWithoutAvatarScale(glm::vec3(1.0f), rig.getModelOffsetPose().rot(), rig.getModelOffsetPose().trans()); AnimPose geomToRigWithoutAvatarScale = modelOffsetWithoutAvatarScale * rig.getGeometryOffsetPose(); // This factor can be used to scale distances in the geometry frame into the unscaled rig frame. // Typically it will be the unit conversion from cm to m. - float scaleFactor = geomToRigWithoutAvatarScale.scale(); + float scaleFactor = geomToRigWithoutAvatarScale.scale().x; // in practice this always a uniform scale factor. int headTopJoint = rig.indexOfJoint("HeadTop_End"); int headJoint = rig.indexOfJoint("Head"); diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 8944ae7996..bf528ee5f0 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -374,7 +374,7 @@ void AnimDebugDraw::update() { glm::vec4 color = std::get<3>(iter.second); for (int i = 0; i < skeleton->getNumJoints(); i++) { - const float radius = BONE_RADIUS / (absPoses[i].scale() * rootPose.scale()); + const float radius = BONE_RADIUS / (absPoses[i].scale().x * rootPose.scale().x); // draw bone addBone(rootPose, absPoses[i], radius, color, v); @@ -394,16 +394,16 @@ void AnimDebugDraw::update() { glm::vec3 pos = std::get<1>(iter.second); glm::vec4 color = std::get<2>(iter.second); const float radius = POSE_RADIUS; - addBone(AnimPose::identity, AnimPose(1.0f, rot, pos), radius, color, v); + addBone(AnimPose::identity, AnimPose(glm::vec3(1), rot, pos), radius, color, v); } - AnimPose myAvatarPose(1.0f, DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos()); + AnimPose myAvatarPose(glm::vec3(1), DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos()); for (auto& iter : myAvatarMarkerMap) { glm::quat rot = std::get<0>(iter.second); glm::vec3 pos = std::get<1>(iter.second); glm::vec4 color = std::get<2>(iter.second); const float radius = POSE_RADIUS; - addBone(myAvatarPose, AnimPose(1.0f, rot, pos), radius, color, v); + addBone(myAvatarPose, AnimPose(glm::vec3(1), rot, pos), radius, color, v); } // draw rays from shared DebugDraw singleton diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index b70925201a..81a81c5602 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -122,7 +122,7 @@ void CauterizedModel::updateClusterMatrices() { if (_useDualQuaternionSkinning) { auto jointPose = _rig.getJointPose(cluster.jointIndex); - Transform jointTransform(jointPose.rot(), glm::vec3(jointPose.scale()), jointPose.trans()); + Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); Transform clusterTransform; Transform::mult(clusterTransform, jointTransform, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindTransform); state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); @@ -138,7 +138,7 @@ void CauterizedModel::updateClusterMatrices() { if (!_cauterizeBoneSet.empty()) { AnimPose cauterizePose = _rig.getJointPose(_rig.indexOfJoint("Neck")); - cauterizePose.scale() = 0.0001f; + cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f); static const glm::mat4 zeroScale( glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f), @@ -161,7 +161,7 @@ void CauterizedModel::updateClusterMatrices() { // not cauterized so just copy the value from the non-cauterized version. state.clusterDualQuaternions[j] = _meshStates[i].clusterDualQuaternions[j]; } else { - Transform jointTransform(cauterizePose.rot(), glm::vec3(cauterizePose.scale()), cauterizePose.trans()); + Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans()); Transform clusterTransform; Transform::mult(clusterTransform, jointTransform, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindTransform); state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 260e25009e..0206bd6963 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1364,7 +1364,7 @@ void Model::updateClusterMatrices() { if (_useDualQuaternionSkinning) { auto jointPose = _rig.getJointPose(cluster.jointIndex); - Transform jointTransform(jointPose.rot(), glm::vec3(jointPose.scale()), jointPose.trans()); + Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); Transform clusterTransform; Transform::mult(clusterTransform, jointTransform, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindTransform); state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c55178a21a..aadfca78ba 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -298,9 +298,9 @@ public: TransformDualQuaternion() {} TransformDualQuaternion(const glm::mat4& m) { AnimPose p(m); - _scale.x = p.scale(); - _scale.y = p.scale(); - _scale.z = p.scale(); + _scale.x = p.scale().x; + _scale.y = p.scale().y; + _scale.z = p.scale().z; _scale.w = 0.0f; _dq = DualQuaternion(p.rot(), p.trans()); } diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 6a0e7c8343..926eeaeeb3 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1210,6 +1210,26 @@ div#grid-section, body#entity-list-body { width: 200px; padding-top: 1px; } +#filter-type-options-buttons { + top: -22px; + width: 224px; + z-index: 2; + background-color: #afafaf; + padding-bottom: 6px; +} +#filter-type-options input[type=button] { + position: relative; + left: 16px; + z-index: 3; + height: 23px; + min-width: 60px; + font-size: 10px; + color: #000; + background: linear-gradient(#afafaf 20%, #808080 100%); +} +#filter-type-options input[type=button]:enabled:hover { + background: linear-gradient(#afafaf 20%, #575757 100%); +} #filter-search-and-icon { position: relative; diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index f525c84cbc..986e5c09b0 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -44,6 +44,10 @@
+
+ + +
diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index b19873a049..8482591771 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -188,6 +188,7 @@ let renameTimeout = null; let renameLastBlur = null; let renameLastEntityID = null; let isRenameFieldBeingMoved = false; +let elFilterTypeInputs = {}; let elEntityTable, elEntityTableHeader, @@ -201,6 +202,9 @@ let elEntityTable, elFilterTypeMultiselectBox, elFilterTypeText, elFilterTypeOptions, + elFilterTypeOptionsButtons, + elFilterTypeSelectAll, + elFilterTypeClearAll, elFilterSearch, elFilterInView, elFilterRadius, @@ -243,6 +247,9 @@ function loaded() { elFilterTypeMultiselectBox = document.getElementById("filter-type-multiselect-box"); elFilterTypeText = document.getElementById("filter-type-text"); elFilterTypeOptions = document.getElementById("filter-type-options"); + elFilterTypeOptionsButtons = document.getElementById("filter-type-options-buttons"); + elFilterTypeSelectAll = document.getElementById('filter-type-select-all'); + elFilterTypeClearAll = document.getElementById('filter-type-clear-all'); elFilterSearch = document.getElementById("filter-search"); elFilterInView = document.getElementById("filter-in-view"); elFilterRadius = document.getElementById("filter-radius"); @@ -276,6 +283,8 @@ function loaded() { }; elRefresh.onclick = refreshEntities; elFilterTypeMultiselectBox.onclick = onToggleTypeDropdown; + elFilterTypeSelectAll.onclick = onSelectAllTypes; + elFilterTypeClearAll.onclick = onClearAllTypes; elFilterSearch.onkeyup = refreshEntityList; elFilterSearch.onsearch = refreshEntityList; elFilterInView.onclick = onToggleFilterInView; @@ -290,13 +299,14 @@ function loaded() { let elDiv = document.createElement('div'); elDiv.onclick = onToggleTypeFilter; - elFilterTypeOptions.appendChild(elDiv); + elFilterTypeOptions.insertBefore(elDiv, elFilterTypeOptionsButtons); let elInput = document.createElement('input'); elInput.setAttribute("type", "checkbox"); elInput.setAttribute("id", typeFilterID); elInput.setAttribute("filterType", type); elInput.checked = true; // all types are checked initially + elFilterTypeInputs[type] = elInput; elDiv.appendChild(elInput); let elLabel = document.createElement('label'); @@ -1065,7 +1075,21 @@ function loaded() { event.stopPropagation(); } - function toggleTypeFilter(elInput, refresh) { + function refreshTypeFilter(refreshList) { + if (typeFilters.length === 0) { + elFilterTypeText.innerText = "No Types"; + } else if (typeFilters.length === FILTER_TYPES.length) { + elFilterTypeText.innerText = "All Types"; + } else { + elFilterTypeText.innerText = "Types..."; + } + + if (refreshList) { + refreshEntityList(); + } + } + + function toggleTypeFilter(elInput, refreshList) { let type = elInput.getAttribute("filterType"); let typeChecked = elInput.checked; @@ -1076,17 +1100,7 @@ function loaded() { typeFilters.push(type); } - if (typeFilters.length === 0) { - elFilterTypeText.innerText = "No Types"; - } else if (typeFilters.length === FILTER_TYPES.length) { - elFilterTypeText.innerText = "All Types"; - } else { - elFilterTypeText.innerText = "Types..."; - } - - if (refresh) { - refreshEntityList(); - } + refreshTypeFilter(refreshList); } function onToggleTypeFilter(event) { @@ -1097,6 +1111,24 @@ function loaded() { event.stopPropagation(); } + function onSelectAllTypes(event) { + for (let type in elFilterTypeInputs) { + elFilterTypeInputs[type].checked = true; + } + typeFilters = FILTER_TYPES; + refreshTypeFilter(true); + event.stopPropagation(); + } + + function onClearAllTypes(event) { + for (let type in elFilterTypeInputs) { + elFilterTypeInputs[type].checked = false; + } + typeFilters = []; + refreshTypeFilter(true); + event.stopPropagation(); + } + function onBodyClick(event) { // if clicking anywhere outside of the multiselect dropdowns (since click event bubbled up to onBodyClick and // propagation wasn't stopped in the toggle type/column callbacks) and the dropdown is open then close it diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index b1926efb71..0cd9571e22 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -22,11 +22,9 @@ #include #include #include -#include QTEST_MAIN(AnimTests) - const float TEST_EPSILON = 0.001f; void AnimTests::initTestCase() { @@ -374,10 +372,16 @@ void AnimTests::testAnimPose() { const glm::quat ROT_Y_180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0, 0.0f)); const glm::quat ROT_Z_30 = glm::angleAxis(PI / 6.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - std::vector scaleVec = { - 1.0f, - 2.0f, - 0.5f + std::vector scaleVec = { + glm::vec3(1), + glm::vec3(2.0f, 1.0f, 1.0f), + glm::vec3(1.0f, 0.5f, 1.0f), + glm::vec3(1.0f, 1.0f, 1.5f), + glm::vec3(2.0f, 0.5f, 1.5f), + glm::vec3(-2.0f, 0.5f, 1.5f), + glm::vec3(2.0f, -0.5f, 1.5f), + glm::vec3(2.0f, 0.5f, -1.5f), + glm::vec3(-2.0f, -0.5f, -1.5f), }; std::vector rotVec = { @@ -407,7 +411,7 @@ void AnimTests::testAnimPose() { for (auto& trans : transVec) { // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); + glm::mat4 scaleMat = glm::scale(glm::mat4(), scale); glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); glm::mat4 rawMat = rotTransMat * scaleMat; @@ -425,7 +429,7 @@ void AnimTests::testAnimPose() { for (auto& trans : transVec) { // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); + glm::mat4 scaleMat = glm::scale(glm::mat4(), scale); glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); glm::mat4 rawMat = rotTransMat * scaleMat; @@ -441,145 +445,6 @@ void AnimTests::testAnimPose() { } } -void AnimTests::testAnimPoseMultiply() { - const float PI = (float)M_PI; - const glm::quat ROT_X_90 = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - const glm::quat ROT_Y_180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0, 0.0f)); - const glm::quat ROT_Z_30 = glm::angleAxis(PI / 6.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - - std::vector scaleVec = { - 1.0f, - 2.0f, - 0.5f, - }; - - std::vector rotVec = { - glm::quat(), - ROT_X_90, - ROT_Y_180, - ROT_Z_30, - ROT_X_90 * ROT_Y_180 * ROT_Z_30, - -ROT_Y_180 - }; - - std::vector transVec = { - glm::vec3(), - glm::vec3(10.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 5.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 7.5f), - glm::vec3(10.0f, 5.0f, 7.5f), - glm::vec3(-10.0f, 5.0f, 7.5f), - glm::vec3(10.0f, -5.0f, 7.5f), - glm::vec3(10.0f, 5.0f, -7.5f) - }; - - const float TEST_EPSILON = 0.001f; - - std::vector matrixVec; - std::vector poseVec; - - for (auto& scale : scaleVec) { - for (auto& rot : rotVec) { - for (auto& trans : transVec) { - - // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); - glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); - glm::mat4 rawMat = rotTransMat * scaleMat; - - matrixVec.push_back(rawMat); - - // use an anim pose to build a matrix by parts. - AnimPose pose(scale, rot, trans); - poseVec.push_back(pose); - } - } - } - - for (int i = 0; i < matrixVec.size(); i++) { - for (int j = 0; j < matrixVec.size(); j++) { - - // multiply the matrices together - glm::mat4 matrix = matrixVec[i] * matrixVec[j]; - - // convert to matrix (note this will remove sheer from the matrix) - AnimPose resultA(matrix); - - // multiply the poses together directly - AnimPose resultB = poseVec[i] * poseVec[j]; - - /* - qDebug() << "matrixVec[" << i << "] =" << matrixVec[i]; - qDebug() << "matrixVec[" << j << "] =" << matrixVec[j]; - qDebug() << "matrixResult =" << resultA; - - qDebug() << "poseVec[" << i << "] =" << poseVec[i]; - qDebug() << "poseVec[" << j << "] =" << poseVec[j]; - qDebug() << "poseResult =" << resultB; - */ - - // compare results. - QCOMPARE_WITH_ABS_ERROR(resultA.scale(), resultB.scale(), TEST_EPSILON); - QCOMPARE_WITH_ABS_ERROR(resultA.rot(), resultB.rot(), TEST_EPSILON); - QCOMPARE_WITH_ABS_ERROR(resultA.trans(), resultB.trans(), TEST_EPSILON); - } - } -} - -void AnimTests::testAnimPoseInverse() { - const float PI = (float)M_PI; - const glm::quat ROT_X_90 = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - const glm::quat ROT_Y_180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0, 0.0f)); - const glm::quat ROT_Z_30 = glm::angleAxis(PI / 6.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - - std::vector scaleVec = { - 1.0f, - 2.0f, - 0.5f - }; - - std::vector rotVec = { - glm::quat(), - ROT_X_90, - ROT_Y_180, - ROT_Z_30, - ROT_X_90 * ROT_Y_180 * ROT_Z_30, - -ROT_Y_180 - }; - - std::vector transVec = { - glm::vec3(), - glm::vec3(10.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 5.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 7.5f), - glm::vec3(10.0f, 5.0f, 7.5f), - glm::vec3(-10.0f, 5.0f, 7.5f), - glm::vec3(10.0f, -5.0f, 7.5f), - glm::vec3(10.0f, 5.0f, -7.5f) - }; - - const float TEST_EPSILON = 0.001f; - - for (auto& scale : scaleVec) { - for (auto& rot : rotVec) { - for (auto& trans : transVec) { - - // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); - glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); - glm::mat4 rawMat = glm::inverse(rotTransMat * scaleMat); - - // use an anim pose to build a matrix by parts. - AnimPose pose(scale, rot, trans); - glm::mat4 poseMat = pose.inverse(); - - QCOMPARE_WITH_ABS_ERROR(rawMat, poseMat, TEST_EPSILON); - } - } - } -} - - void AnimTests::testExpressionTokenizer() { QString str = "(10 + x) >= 20.1 && (y != !z)"; AnimExpression e("x"); diff --git a/tests/animation/src/AnimTests.h b/tests/animation/src/AnimTests.h index 326545b0a9..439793f21d 100644 --- a/tests/animation/src/AnimTests.h +++ b/tests/animation/src/AnimTests.h @@ -27,8 +27,6 @@ private slots: void testVariant(); void testAccumulateTime(); void testAnimPose(); - void testAnimPoseMultiply(); - void testAnimPoseInverse(); void testExpressionTokenizer(); void testExpressionParser(); void testExpressionEvaluator();