From 67fbb15faab1e5547ae8899f1cce067760771005 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 10 May 2017 18:11:34 -0700 Subject: [PATCH 01/11] WIP: initial implementation of flexCoefficients --- .../resources/avatar/avatar-animation.json | 21 ++++--- .../animation/src/AnimInverseKinematics.cpp | 61 ++++++++++++++----- .../animation/src/AnimInverseKinematics.h | 19 +++--- libraries/animation/src/AnimNodeLoader.cpp | 13 +++- libraries/animation/src/IKTarget.cpp | 16 +++++ libraries/animation/src/IKTarget.h | 6 +- libraries/animation/src/Rig.cpp | 10 +-- 7 files changed, 107 insertions(+), 39 deletions(-) diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index eb8403634a..a402358478 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -56,43 +56,50 @@ "jointName": "Hips", "positionVar": "hipsPosition", "rotationVar": "hipsRotation", - "typeVar": "hipsType" + "typeVar": "hipsType", + "flexCoefficients": [1] }, { "jointName": "RightHand", "positionVar": "rightHandPosition", "rotationVar": "rightHandRotation", - "typeVar": "rightHandType" + "typeVar": "rightHandType", + "flexCoefficients": [1, 0.5, 0.5, 0.5, 0.25, 0.1, 0.1, 0.1, 0.1] }, { "jointName": "LeftHand", "positionVar": "leftHandPosition", "rotationVar": "leftHandRotation", - "typeVar": "leftHandType" + "typeVar": "leftHandType", + "flexCoefficients": [1, 0.5, 0.5, 0.5, 0.25, 0.1, 0.1, 0.1, 0.1] }, { "jointName": "RightFoot", "positionVar": "rightFootPosition", "rotationVar": "rightFootRotation", - "typeVar": "rightFootType" + "typeVar": "rightFootType", + "flexCoefficients": [1, 0.45, 0.45] }, { "jointName": "LeftFoot", "positionVar": "leftFootPosition", "rotationVar": "leftFootRotation", - "typeVar": "leftFootType" + "typeVar": "leftFootType", + "flexCoefficients": [1, 0.45, 0.45] }, { "jointName": "Spine2", "positionVar": "spine2Position", "rotationVar": "spine2Rotation", - "typeVar": "spine2Type" + "typeVar": "spine2Type", + "flexCoefficients": [0.45, 0.45] }, { "jointName": "Head", "positionVar": "headPosition", "rotationVar": "headRotation", - "typeVar": "headType" + "typeVar": "headType", + "flexCoefficients": [1, 0.5, 0.25, 0.25, 0.25] } ] }, diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 5e6927afcb..2ab4282177 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -21,6 +21,35 @@ #include "SwingTwistConstraint.h" #include "AnimationLogging.h" +AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, + const QString& typeVarIn, const std::vector& flexCoefficientsIn) : + positionVar(positionVarIn), + rotationVar(rotationVarIn), + typeVar(typeVarIn), + jointName(jointNameIn), + numFlexCoefficients(flexCoefficientsIn.size()), + jointIndex(-1) +{ + numFlexCoefficients = std::min(numFlexCoefficients, MAX_FLEX_COEFFICIENTS); + for (size_t i = 0; i < numFlexCoefficients; i++) { + flexCoefficients[i] = flexCoefficientsIn[i]; + } +} + +AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) : + positionVar(orig.positionVar), + rotationVar(orig.rotationVar), + typeVar(orig.typeVar), + jointName(orig.jointName), + numFlexCoefficients(orig.numFlexCoefficients), + jointIndex(orig.jointIndex) +{ + numFlexCoefficients = std::min(numFlexCoefficients, MAX_FLEX_COEFFICIENTS); + for (size_t i = 0; i < numFlexCoefficients; i++) { + flexCoefficients[i] = orig.flexCoefficients[i]; + } +} + AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) { } @@ -60,26 +89,22 @@ void AnimInverseKinematics::computeAbsolutePoses(AnimPoseVec& absolutePoses) con } } -void AnimInverseKinematics::setTargetVars( - const QString& jointName, - const QString& positionVar, - const QString& rotationVar, - const QString& typeVar) { +void AnimInverseKinematics::setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, + const QString& typeVar, const std::vector& flexCoefficients) { + IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, flexCoefficients); + // if there are dups, last one wins. bool found = false; - for (auto& targetVar: _targetVarVec) { - if (targetVar.jointName == jointName) { - // update existing targetVar - targetVar.positionVar = positionVar; - targetVar.rotationVar = rotationVar; - targetVar.typeVar = typeVar; + for (auto& targetVarIter: _targetVarVec) { + if (targetVarIter.jointName == jointName) { + targetVarIter = targetVar; found = true; break; } } if (!found) { // create a new entry - _targetVarVec.push_back(IKTargetVar(jointName, positionVar, rotationVar, typeVar)); + _targetVarVec.push_back(targetVar); } } @@ -110,7 +135,10 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: target.setPose(rotation, translation); target.setIndex(targetVar.jointIndex); + target.setFlexCoefficients(targetVar.numFlexCoefficients, targetVar.flexCoefficients); + targets.push_back(target); + if (targetVar.jointIndex > _maxTargetIndex) { _maxTargetIndex = targetVar.jointIndex; } @@ -271,6 +299,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe // cache tip absolute position glm::vec3 tipPosition = absolutePoses[tipIndex].trans(); + int chainDepth = 1; + // descend toward root, pivoting each joint to get tip closer to target position while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) { // compute the two lines that should be aligned @@ -312,9 +342,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe float angle = acosf(cosAngle); const float MIN_ADJUSTMENT_ANGLE = 1.0e-4f; if (angle > MIN_ADJUSTMENT_ANGLE) { - // reduce angle by a fraction (for stability) - const float STABILITY_FRACTION = 0.5f; - angle *= STABILITY_FRACTION; + // reduce angle by a flexCoefficient + angle *= target.getFlexCoefficient(chainDepth); deltaRotation = glm::angleAxis(angle, axis); // The swing will re-orient the tip but there will tend to be be a non-zero delta between the tip's @@ -385,6 +414,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe pivotIndex = pivotsParentIndex; pivotsParentIndex = _skeleton->getParentIndex(pivotIndex); + + chainDepth++; } return lowestMovedIndex; } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index f73ed95935..ddbb420012 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -32,7 +32,8 @@ public: void loadPoses(const AnimPoseVec& poses); void computeAbsolutePoses(AnimPoseVec& absolutePoses) const; - void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, const QString& typeVar); + void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, + const QString& typeVar, const std::vector& flexCoefficients); virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimNode::Triggers& triggersOut) override; virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; @@ -77,22 +78,18 @@ protected: AnimInverseKinematics(const AnimInverseKinematics&) = delete; AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete; + static const size_t MAX_FLEX_COEFFICIENTS = 10; struct IKTargetVar { - IKTargetVar(const QString& jointNameIn, - const QString& positionVarIn, - const QString& rotationVarIn, - const QString& typeVarIn) : - positionVar(positionVarIn), - rotationVar(rotationVarIn), - typeVar(typeVarIn), - jointName(jointNameIn), - jointIndex(-1) - {} + IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, + const QString& typeVarIn, const std::vector& flexCoefficientsIn); + IKTargetVar(const IKTargetVar& orig); QString positionVar; QString rotationVar; QString typeVar; QString jointName; + float flexCoefficients[MAX_FLEX_COEFFICIENTS]; + size_t numFlexCoefficients; int jointIndex; // cached joint index }; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 6bc7342d7f..e4ffaec5b7 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -471,7 +471,18 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS READ_STRING(rotationVar, targetObj, id, jsonUrl, nullptr); READ_OPTIONAL_STRING(typeVar, targetObj); - node->setTargetVars(jointName, positionVar, rotationVar, typeVar); + auto flexCoefficientsValue = targetObj.value("flexCoefficients"); + if (!flexCoefficientsValue.isArray()) { + qCCritical(animation) << "AnimNodeLoader, bad or missing flexCoefficients array in \"targets\", id =" << id << ", url =" << jsonUrl.toDisplayString(); + return nullptr; + } + auto flexCoefficientsArray = flexCoefficientsValue.toArray(); + std::vector flexCoefficients; + for (const auto& value : flexCoefficientsArray) { + flexCoefficients.push_back((float)value.toDouble()); + } + + node->setTargetVars(jointName, positionVar, rotationVar, typeVar, flexCoefficients); }; READ_OPTIONAL_STRING(solutionSource, jsonObj); diff --git a/libraries/animation/src/IKTarget.cpp b/libraries/animation/src/IKTarget.cpp index fa4030ca6d..868293fdb8 100644 --- a/libraries/animation/src/IKTarget.cpp +++ b/libraries/animation/src/IKTarget.cpp @@ -14,6 +14,22 @@ void IKTarget::setPose(const glm::quat& rotation, const glm::vec3& translation) _pose.trans() = translation; } +void IKTarget::setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn) { + _numFlexCoefficients = std::min(numFlexCoefficientsIn, MAX_FLEX_COEFFICIENTS); + for (size_t i = 0; i < _numFlexCoefficients; i++) { + _flexCoefficients[i] = flexCoefficientsIn[i]; + } +} + +float IKTarget::getFlexCoefficient(int chainDepth) const { + const float DEFAULT_FLEX_COEFFICIENT = 0.5f; + if (chainDepth >= 0 && chainDepth < _numFlexCoefficients) { + return _flexCoefficients[chainDepth]; + } else { + return DEFAULT_FLEX_COEFFICIENT; + } +} + void IKTarget::setType(int type) { switch (type) { case (int)Type::RotationAndPosition: diff --git a/libraries/animation/src/IKTarget.h b/libraries/animation/src/IKTarget.h index acb01d9861..63a4b901a6 100644 --- a/libraries/animation/src/IKTarget.h +++ b/libraries/animation/src/IKTarget.h @@ -35,15 +35,19 @@ public: void setPose(const glm::quat& rotation, const glm::vec3& translation); void setIndex(int index) { _index = index; } void setType(int); + void setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn); + float getFlexCoefficient(int chainDepth) const; // HACK: give HmdHead targets more "weight" during IK algorithm float getWeight() const { return _type == Type::HmdHead ? HACK_HMD_TARGET_WEIGHT : 1.0f; } + static const size_t MAX_FLEX_COEFFICIENTS = 10; private: AnimPose _pose; int _index{-1}; Type _type{Type::RotationAndPosition}; - + float _flexCoefficients[MAX_FLEX_COEFFICIENTS]; + size_t _numFlexCoefficients; }; #endif // hifi_IKTarget_h diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index cb5aebe930..f5a9008ce1 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1400,22 +1400,24 @@ void Rig::computeAvatarBoundingCapsule( AnimInverseKinematics ikNode("boundingShape"); ikNode.setSkeleton(_animSkeleton); + + // AJT: FIX ME!!!!! ensure that empty weights vector does something reasonable.... ikNode.setTargetVars("LeftHand", "leftHandPosition", "leftHandRotation", - "leftHandType"); + "leftHandType", {}); ikNode.setTargetVars("RightHand", "rightHandPosition", "rightHandRotation", - "rightHandType"); + "rightHandType", {}); ikNode.setTargetVars("LeftFoot", "leftFootPosition", "leftFootRotation", - "leftFootType"); + "leftFootType", {}); ikNode.setTargetVars("RightFoot", "rightFootPosition", "rightFootRotation", - "rightFootType"); + "rightFootType", {}); AnimPose geometryToRig = _modelOffset * _geometryOffset; From 1e276d113cf792305df60607479a07307fd3daab Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 12 May 2017 11:45:22 -0700 Subject: [PATCH 02/11] Added support for weights per target --- .../resources/avatar/avatar-animation.json | 20 ++++++++++++++++--- .../animation/src/AnimInverseKinematics.cpp | 14 +++++++++---- .../animation/src/AnimInverseKinematics.h | 6 ++++-- libraries/animation/src/AnimNodeLoader.cpp | 11 +++++++++- libraries/animation/src/IKTarget.cpp | 1 + libraries/animation/src/IKTarget.h | 5 +++-- libraries/animation/src/Rig.cpp | 10 ++++++---- 7 files changed, 51 insertions(+), 16 deletions(-) diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index a402358478..b18599d8a9 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -57,6 +57,8 @@ "positionVar": "hipsPosition", "rotationVar": "hipsRotation", "typeVar": "hipsType", + "weightVar": "hipsWeight", + "weight": 1.0, "flexCoefficients": [1] }, { @@ -64,20 +66,26 @@ "positionVar": "rightHandPosition", "rotationVar": "rightHandRotation", "typeVar": "rightHandType", - "flexCoefficients": [1, 0.5, 0.5, 0.5, 0.25, 0.1, 0.1, 0.1, 0.1] + "weightVar": "rightHandWeight", + "weight": 1.0, + "flexCoefficients": [1, 0.5, 0.5, 0.25, 0.1, 0.05, 0.01, 0.0, 0.0] }, { "jointName": "LeftHand", "positionVar": "leftHandPosition", "rotationVar": "leftHandRotation", "typeVar": "leftHandType", - "flexCoefficients": [1, 0.5, 0.5, 0.5, 0.25, 0.1, 0.1, 0.1, 0.1] + "weightVar": "leftHandWeight", + "weight": 1.0, + "flexCoefficients": [1, 0.5, 0.5, 0.25, 0.1, 0.05, 0.01, 0.0, 0.0] }, { "jointName": "RightFoot", "positionVar": "rightFootPosition", "rotationVar": "rightFootRotation", "typeVar": "rightFootType", + "weightVar": "rightFootWeight", + "weight": 1.0, "flexCoefficients": [1, 0.45, 0.45] }, { @@ -85,6 +93,8 @@ "positionVar": "leftFootPosition", "rotationVar": "leftFootRotation", "typeVar": "leftFootType", + "weightVar": "leftFootWeight", + "weight": 1.0, "flexCoefficients": [1, 0.45, 0.45] }, { @@ -92,6 +102,8 @@ "positionVar": "spine2Position", "rotationVar": "spine2Rotation", "typeVar": "spine2Type", + "weightVar": "spine2Weight", + "weight": 1.0, "flexCoefficients": [0.45, 0.45] }, { @@ -99,7 +111,9 @@ "positionVar": "headPosition", "rotationVar": "headRotation", "typeVar": "headType", - "flexCoefficients": [1, 0.5, 0.25, 0.25, 0.25] + "weightVar": "headWeight", + "weight": 4.0, + "flexCoefficients": [1, 0.5, 0.5, 0.5, 0.5] } ] }, diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 2ab4282177..11c143db23 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -22,10 +22,12 @@ #include "AnimationLogging.h" AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, - const QString& typeVarIn, const std::vector& flexCoefficientsIn) : + const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector& flexCoefficientsIn) : positionVar(positionVarIn), rotationVar(rotationVarIn), typeVar(typeVarIn), + weightVar(weightVarIn), + weight(weightIn), jointName(jointNameIn), numFlexCoefficients(flexCoefficientsIn.size()), jointIndex(-1) @@ -40,6 +42,8 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) : positionVar(orig.positionVar), rotationVar(orig.rotationVar), typeVar(orig.typeVar), + weightVar(orig.weightVar), + weight(orig.weight), jointName(orig.jointName), numFlexCoefficients(orig.numFlexCoefficients), jointIndex(orig.jointIndex) @@ -90,8 +94,8 @@ void AnimInverseKinematics::computeAbsolutePoses(AnimPoseVec& absolutePoses) con } void AnimInverseKinematics::setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, - const QString& typeVar, const std::vector& flexCoefficients) { - IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, flexCoefficients); + const QString& typeVar, const QString& weightVar, float weight, const std::vector& flexCoefficients) { + IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, weightVar, weight, flexCoefficients); // if there are dups, last one wins. bool found = false; @@ -132,9 +136,11 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses); glm::quat rotation = animVars.lookupRigToGeometry(targetVar.rotationVar, defaultPose.rot()); glm::vec3 translation = animVars.lookupRigToGeometry(targetVar.positionVar, defaultPose.trans()); + float weight = animVars.lookup(targetVar.weightVar, targetVar.weight); target.setPose(rotation, translation); target.setIndex(targetVar.jointIndex); + target.setWeight(weight); target.setFlexCoefficients(targetVar.numFlexCoefficients, targetVar.flexCoefficients); targets.push_back(target); @@ -837,7 +843,7 @@ void AnimInverseKinematics::initConstraints() { stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST); std::vector minDots; - const float MAX_SHOULDER_SWING = PI / 20.0f; + const float MAX_SHOULDER_SWING = PI / 16.0f; minDots.push_back(cosf(MAX_SHOULDER_SWING)); stConstraint->setSwingLimits(minDots); diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index ddbb420012..b798319ca9 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -33,7 +33,7 @@ public: void computeAbsolutePoses(AnimPoseVec& absolutePoses) const; void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, - const QString& typeVar, const std::vector& flexCoefficients); + const QString& typeVar, const QString& weightVar, float weight, const std::vector& flexCoefficients); virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimNode::Triggers& triggersOut) override; virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; @@ -81,13 +81,15 @@ protected: static const size_t MAX_FLEX_COEFFICIENTS = 10; struct IKTargetVar { IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, - const QString& typeVarIn, const std::vector& flexCoefficientsIn); + const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector& flexCoefficientsIn); IKTargetVar(const IKTargetVar& orig); QString positionVar; QString rotationVar; QString typeVar; + QString weightVar; QString jointName; + float weight; float flexCoefficients[MAX_FLEX_COEFFICIENTS]; size_t numFlexCoefficients; int jointIndex; // cached joint index diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index e4ffaec5b7..44ed8c6053 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -173,6 +173,13 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) { } \ float NAME = (float)NAME##_VAL.toDouble() +#define READ_OPTIONAL_FLOAT(NAME, JSON_OBJ, DEFAULT) \ + auto NAME##_VAL = JSON_OBJ.value(#NAME); \ + float NAME = (float)DEFAULT; \ + if (NAME##_VAL.isDouble()) { \ + NAME = (float)NAME##_VAL.toDouble(); \ + } \ + do {} while (0) static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUrl) { auto idVal = jsonObj.value("id"); @@ -470,6 +477,8 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS READ_STRING(positionVar, targetObj, id, jsonUrl, nullptr); READ_STRING(rotationVar, targetObj, id, jsonUrl, nullptr); READ_OPTIONAL_STRING(typeVar, targetObj); + READ_OPTIONAL_STRING(weightVar, targetObj); + READ_OPTIONAL_FLOAT(weight, targetObj, 1.0f); auto flexCoefficientsValue = targetObj.value("flexCoefficients"); if (!flexCoefficientsValue.isArray()) { @@ -482,7 +491,7 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS flexCoefficients.push_back((float)value.toDouble()); } - node->setTargetVars(jointName, positionVar, rotationVar, typeVar, flexCoefficients); + node->setTargetVars(jointName, positionVar, rotationVar, typeVar, weightVar, weight, flexCoefficients); }; READ_OPTIONAL_STRING(solutionSource, jsonObj); diff --git a/libraries/animation/src/IKTarget.cpp b/libraries/animation/src/IKTarget.cpp index 868293fdb8..ae23d9548f 100644 --- a/libraries/animation/src/IKTarget.cpp +++ b/libraries/animation/src/IKTarget.cpp @@ -23,6 +23,7 @@ void IKTarget::setFlexCoefficients(size_t numFlexCoefficientsIn, const float* fl float IKTarget::getFlexCoefficient(int chainDepth) const { const float DEFAULT_FLEX_COEFFICIENT = 0.5f; + if (chainDepth >= 0 && chainDepth < _numFlexCoefficients) { return _flexCoefficients[chainDepth]; } else { diff --git a/libraries/animation/src/IKTarget.h b/libraries/animation/src/IKTarget.h index 63a4b901a6..0e8bb614ea 100644 --- a/libraries/animation/src/IKTarget.h +++ b/libraries/animation/src/IKTarget.h @@ -38,14 +38,15 @@ public: void setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn); float getFlexCoefficient(int chainDepth) const; - // HACK: give HmdHead targets more "weight" during IK algorithm - float getWeight() const { return _type == Type::HmdHead ? HACK_HMD_TARGET_WEIGHT : 1.0f; } + void setWeight(float weight) { _weight = weight; } + float getWeight() const { return _weight; } static const size_t MAX_FLEX_COEFFICIENTS = 10; private: AnimPose _pose; int _index{-1}; Type _type{Type::RotationAndPosition}; + float _weight; float _flexCoefficients[MAX_FLEX_COEFFICIENTS]; size_t _numFlexCoefficients; }; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index f5a9008ce1..23db05eb73 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1088,10 +1088,12 @@ void Rig::updateHeadAnimVars(const HeadParameters& params) { // Since there is an explicit hips ik target, switch the head to use the more generic RotationAndPosition IK chain type. // this will allow the spine to bend more, ensuring that it can reach the head target position. _animVars.set("headType", (int)IKTarget::Type::RotationAndPosition); + _animVars.unset("headWeight"); // use the default weight for this target. } else { // When there is no hips IK target, use the HmdHead IK chain type. This will make the spine very stiff, // but because the IK _hipsOffset is enabled, the hips will naturally follow underneath the head. _animVars.set("headType", (int)IKTarget::Type::HmdHead); + _animVars.set("headWeight", 8.0f); } } else { _animVars.unset("headPosition"); @@ -1405,19 +1407,19 @@ void Rig::computeAvatarBoundingCapsule( ikNode.setTargetVars("LeftHand", "leftHandPosition", "leftHandRotation", - "leftHandType", {}); + "leftHandType", "leftHandWeight", 1.0f, {}); ikNode.setTargetVars("RightHand", "rightHandPosition", "rightHandRotation", - "rightHandType", {}); + "rightHandType", "rightHandWeight", 1.0f, {}); ikNode.setTargetVars("LeftFoot", "leftFootPosition", "leftFootRotation", - "leftFootType", {}); + "leftFootType", "leftFootWeight", 1.0f, {}); ikNode.setTargetVars("RightFoot", "rightFootPosition", "rightFootRotation", - "rightFootType", {}); + "rightFootType", "rightFootWeight", 1.0f, {}); AnimPose geometryToRig = _modelOffset * _geometryOffset; From be7a9a2383aaa1cc9b84537458750d53f48acd4f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 16 May 2017 11:00:25 -0700 Subject: [PATCH 03/11] warning fixes --- libraries/animation/src/AnimInverseKinematics.cpp | 6 +++--- libraries/animation/src/AnimInverseKinematics.h | 2 +- libraries/animation/src/IKTarget.cpp | 4 ++-- libraries/animation/src/IKTarget.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 11c143db23..c43d7b76dd 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -23,12 +23,12 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector& flexCoefficientsIn) : + jointName(jointNameIn), positionVar(positionVarIn), rotationVar(rotationVarIn), typeVar(typeVarIn), weightVar(weightVarIn), weight(weightIn), - jointName(jointNameIn), numFlexCoefficients(flexCoefficientsIn.size()), jointIndex(-1) { @@ -39,12 +39,12 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, cons } AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) : + jointName(orig.jointName), positionVar(orig.positionVar), rotationVar(orig.rotationVar), typeVar(orig.typeVar), weightVar(orig.weightVar), weight(orig.weight), - jointName(orig.jointName), numFlexCoefficients(orig.numFlexCoefficients), jointIndex(orig.jointIndex) { @@ -305,7 +305,7 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe // cache tip absolute position glm::vec3 tipPosition = absolutePoses[tipIndex].trans(); - int chainDepth = 1; + size_t chainDepth = 1; // descend toward root, pivoting each joint to get tip closer to target position while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) { diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index b798319ca9..cf03005b68 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -84,11 +84,11 @@ protected: const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector& flexCoefficientsIn); IKTargetVar(const IKTargetVar& orig); + QString jointName; QString positionVar; QString rotationVar; QString typeVar; QString weightVar; - QString jointName; float weight; float flexCoefficients[MAX_FLEX_COEFFICIENTS]; size_t numFlexCoefficients; diff --git a/libraries/animation/src/IKTarget.cpp b/libraries/animation/src/IKTarget.cpp index ae23d9548f..18e656f583 100644 --- a/libraries/animation/src/IKTarget.cpp +++ b/libraries/animation/src/IKTarget.cpp @@ -21,10 +21,10 @@ void IKTarget::setFlexCoefficients(size_t numFlexCoefficientsIn, const float* fl } } -float IKTarget::getFlexCoefficient(int chainDepth) const { +float IKTarget::getFlexCoefficient(size_t chainDepth) const { const float DEFAULT_FLEX_COEFFICIENT = 0.5f; - if (chainDepth >= 0 && chainDepth < _numFlexCoefficients) { + if (chainDepth < _numFlexCoefficients) { return _flexCoefficients[chainDepth]; } else { return DEFAULT_FLEX_COEFFICIENT; diff --git a/libraries/animation/src/IKTarget.h b/libraries/animation/src/IKTarget.h index 0e8bb614ea..1951d3ba7b 100644 --- a/libraries/animation/src/IKTarget.h +++ b/libraries/animation/src/IKTarget.h @@ -36,7 +36,7 @@ public: void setIndex(int index) { _index = index; } void setType(int); void setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn); - float getFlexCoefficient(int chainDepth) const; + float getFlexCoefficient(size_t chainDepth) const; void setWeight(float weight) { _weight = weight; } float getWeight() const { return _weight; } From 805d23567dd17277c812a33f79377d881e817ced Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 16 May 2017 16:02:37 -0700 Subject: [PATCH 04/11] fix simple typo --- interface/src/avatar/MyAvatar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cbd51aaaf9..521d6e195c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -125,7 +125,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(controller::Pose rightHandTipPose READ getRightHandTipPose) Q_PROPERTY(float energy READ getEnergy WRITE setEnergy) - Q_PROPERTY(float isAway READ getIsAway WRITE setAway) + Q_PROPERTY(bool isAway READ getIsAway WRITE setAway) Q_PROPERTY(bool hmdLeanRecenterEnabled READ getHMDLeanRecenterEnabled WRITE setHMDLeanRecenterEnabled) Q_PROPERTY(bool collisionsEnabled READ getCollisionsEnabled WRITE setCollisionsEnabled) From d065b569d388340ae9ff0df5902067c4b3994859 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 16 May 2017 16:03:13 -0700 Subject: [PATCH 05/11] support for variable avatar mass by size --- interface/src/avatar/AvatarManager.cpp | 1 + interface/src/avatar/AvatarMotionState.cpp | 3 -- interface/src/avatar/MyAvatar.cpp | 1 + .../src/avatar/MyCharacterController.cpp | 30 +++++++++++--- interface/src/avatar/MyCharacterController.h | 4 ++ .../src/avatars-renderer/Avatar.cpp | 11 +++++ .../src/avatars-renderer/Avatar.h | 1 + libraries/avatars/src/AvatarData.cpp | 4 +- libraries/avatars/src/AvatarData.h | 3 ++ libraries/physics/src/CharacterController.cpp | 7 +++- libraries/physics/src/CharacterController.h | 1 + libraries/physics/src/ObjectMotionState.cpp | 41 +++++++++++++++++-- libraries/physics/src/ObjectMotionState.h | 12 +++--- 13 files changed, 98 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 1306ce03ea..d47e4cfd10 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -189,6 +189,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { btCollisionShape* shape = const_cast(ObjectMotionState::getShapeManager()->getShape(shapeInfo)); if (shape) { AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); + motionState->setMass(avatar->computeMass()); avatar->setPhysicsCallback([=] (uint32_t flags) { motionState->addDirtyFlags(flags); }); _motionStates.insert(avatar.get(), motionState); _motionStatesToAddToPhysics.insert(motionState); diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 0305634400..91c83afcbd 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -19,9 +19,6 @@ AvatarMotionState::AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) { assert(_avatar); _type = MOTIONSTATE_TYPE_AVATAR; - if (_shape) { - _mass = 100.0f; // HACK - } } AvatarMotionState::~AvatarMotionState() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3da9b8a214..ec4da2c2a1 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -236,6 +236,7 @@ MyAvatar::MyAvatar(QThread* thread, RigPointer rig) : }); connect(rig.get(), SIGNAL(onLoadComplete()), this, SIGNAL(onLoadComplete())); + _characterController.setDensity(_density); } MyAvatar::~MyAvatar() { diff --git a/interface/src/avatar/MyCharacterController.cpp b/interface/src/avatar/MyCharacterController.cpp index 0cdbc77626..3d98a0e604 100755 --- a/interface/src/avatar/MyCharacterController.cpp +++ b/interface/src/avatar/MyCharacterController.cpp @@ -49,12 +49,9 @@ void MyCharacterController::updateShapeIfNecessary() { // create RigidBody if it doesn't exist if (!_rigidBody) { btCollisionShape* shape = computeShape(); - - // HACK: use some simple mass property defaults for now - const btScalar DEFAULT_AVATAR_MASS = 100.0f; - const btVector3 DEFAULT_AVATAR_INERTIA_TENSOR(30.0f, 8.0f, 30.0f); - - _rigidBody = new btRigidBody(DEFAULT_AVATAR_MASS, nullptr, shape, DEFAULT_AVATAR_INERTIA_TENSOR); + btScalar mass = 1.0f; + btVector3 inertia(1.0f, 1.0f, 1.0f); + _rigidBody = new btRigidBody(mass, nullptr, shape, inertia); } else { btCollisionShape* shape = _rigidBody->getCollisionShape(); if (shape) { @@ -63,6 +60,7 @@ void MyCharacterController::updateShapeIfNecessary() { shape = computeShape(); _rigidBody->setCollisionShape(shape); } + updateMassProperties(); _rigidBody->setSleepingThresholds(0.0f, 0.0f); _rigidBody->setAngularFactor(0.0f); @@ -331,3 +329,23 @@ void MyCharacterController::initRayShotgun(const btCollisionWorld* world) { } } } + +void MyCharacterController::updateMassProperties() { + assert(_rigidBody); + // the inertia tensor of a capsule with Y-axis of symmetry, radius R and cylinder height H is: + // Ix = density * (volumeCylinder * (H^2 / 12 + R^2 / 4) + volumeSphere * (2R^2 / 5 + H^2 / 2 + 3HR / 8)) + // Iy = density * (volumeCylinder * (R^2 / 2) + volumeSphere * (2R^2 / 5) + btScalar r2 = _radius * _radius; + btScalar h2 = 4.0f * _halfHeight * _halfHeight; + btScalar volumeSphere = 4.0f * PI * r2 * _radius / 3.0f; + btScalar volumeCylinder = TWO_PI * r2 * 2.0f * _halfHeight; + btScalar cylinderXZ = volumeCylinder * (h2 / 12.0f + r2 / 4.0f); + btScalar capsXZ = volumeSphere * (2.0f * r2 / 5.0f + h2 / 2.0f + 6.0f * _halfHeight * _radius / 8.0f); + btScalar inertiaXZ = _density * (cylinderXZ + capsXZ); + btScalar inertiaY = _density * ((volumeCylinder * r2 / 2.0f) + volumeSphere * (2.0f * r2 / 5.0f)); + btVector3 inertia(inertiaXZ, inertiaY, inertiaXZ); + + btScalar mass = _density * (volumeCylinder + volumeSphere); + + _rigidBody->setMassProps(mass, inertia); +} diff --git a/interface/src/avatar/MyCharacterController.h b/interface/src/avatar/MyCharacterController.h index 6b38736352..fd9caface2 100644 --- a/interface/src/avatar/MyCharacterController.h +++ b/interface/src/avatar/MyCharacterController.h @@ -40,8 +40,11 @@ public: /// return true if RayShotgun hits anything bool testRayShotgun(const glm::vec3& position, const glm::vec3& step, RayShotgunResult& result); + void setDensity(btScalar density) { _density = density; } + protected: void initRayShotgun(const btCollisionWorld* world); + void updateMassProperties() override; private: btConvexHullShape* computeShape() const; @@ -52,6 +55,7 @@ protected: // shotgun scan data btAlignedObjectArray _topPoints; btAlignedObjectArray _bottomPoints; + btScalar _density { 1.0f }; }; #endif // hifi_MyCharacterController_h diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 664b0094f4..82e571d0e8 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1293,6 +1293,17 @@ void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) { radius = halfExtents.x; } +float Avatar::computeMass() { + float radius; + glm::vec3 start, end; + getCapsule(start, end, radius); + // NOTE: + // volumeOfCapsule = volumeOfCylinder + volumeOfSphere + // volumeOfCapsule = (2PI * R^2 * H) + (4PI * R^3 / 3) + // volumeOfCapsule = 2PI * R^2 * (H + 2R/3) + return _density * TWO_PI * radius * radius * (glm::length(end - start) + 2.0f * radius / 3.0f); +} + // virtual void Avatar::rebuildCollisionShape() { addPhysicsFlags(Simulation::DIRTY_SHAPE); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 20704a08b2..148821db1e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -196,6 +196,7 @@ public: virtual void computeShapeInfo(ShapeInfo& shapeInfo); void getCapsule(glm::vec3& start, glm::vec3& end, float& radius); + float computeMass(); using SpatiallyNestable::setPosition; virtual void setPosition(const glm::vec3& position) override; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 26afed152f..c23363e6b6 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -52,6 +52,7 @@ const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData"; static const int TRANSLATION_COMPRESSION_RADIX = 12; static const int SENSOR_TO_WORLD_SCALE_RADIX = 10; static const float AUDIO_LOUDNESS_SCALE = 1024.0f; +static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water #define ASSERT(COND) do { if (!(COND)) { abort(); } } while(0) @@ -65,7 +66,8 @@ AvatarData::AvatarData() : _headData(NULL), _errorLogExpiry(0), _owningAvatarMixer(), - _targetVelocity(0.0f) + _targetVelocity(0.0f), + _density(DEFAULT_AVATAR_DENSITY) { setBodyPitch(0.0f); setBodyYaw(-90.0f); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e6e0571878..c2bf98287a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -626,6 +626,8 @@ public: _identityUpdatedAt = usecTimestampNow(); } + float getDensity() const { return _density; } + signals: void displayNameChanged(); @@ -782,6 +784,7 @@ protected: bool _identityDataChanged { false }; quint64 _identityUpdatedAt { 0 }; + float _density; private: friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index e4ff1b0b44..ee240a6aac 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -112,6 +112,9 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { _dynamicsWorld = nullptr; } int16_t collisionGroup = computeCollisionGroup(); + if (_rigidBody) { + updateMassProperties(); + } if (world && _rigidBody) { // add to new world _dynamicsWorld = world; @@ -127,7 +130,9 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { _ghost.setCollisionGroupAndMask(collisionGroup, BULLET_COLLISION_MASK_MY_AVATAR & (~ collisionGroup)); _ghost.setCollisionWorld(_dynamicsWorld); _ghost.setRadiusAndHalfHeight(_radius, _halfHeight); - _ghost.setWorldTransform(_rigidBody->getWorldTransform()); + if (_rigidBody) { + _ghost.setWorldTransform(_rigidBody->getWorldTransform()); + } } if (_dynamicsWorld) { if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) { diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 0a11fad0b7..6790495ff8 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -128,6 +128,7 @@ protected: void setState(State state); #endif + virtual void updateMassProperties() = 0; void updateGravity(); void updateUpAxis(const glm::quat& rotation); bool checkForSupport(btCollisionWorld* collisionWorld); diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 503b39dc1c..5a36d69035 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -63,10 +63,7 @@ ShapeManager* ObjectMotionState::getShapeManager() { } ObjectMotionState::ObjectMotionState(const btCollisionShape* shape) : - _motionType(MOTION_TYPE_STATIC), _shape(shape), - _body(nullptr), - _mass(0.0f), _lastKinematicStep(worldSimulationStep) { } @@ -74,7 +71,43 @@ ObjectMotionState::ObjectMotionState(const btCollisionShape* shape) : ObjectMotionState::~ObjectMotionState() { assert(!_body); setShape(nullptr); - _type = MOTIONSTATE_TYPE_INVALID; +} + +void ObjectMotionState::setMass(float mass) { + _density = 1.0f; + if (_shape) { + // we compute the density for the current shape's Aabb volume + // and save that instead of the total mass + btTransform transform; + transform.setIdentity(); + btVector3 minCorner, maxCorner; + _shape->getAabb(transform, minCorner, maxCorner); + btVector3 diagonal = maxCorner - minCorner; + float volume = diagonal.getX() * diagonal.getY() * diagonal.getZ(); + if (volume > EPSILON) { + _density = fabsf(mass) / volume; + } + } +} + +float ObjectMotionState::getMass() const { + if (_shape) { + // scale the density by the current Aabb volume to get mass + btTransform transform; + transform.setIdentity(); + btVector3 minCorner, maxCorner; + _shape->getAabb(transform, minCorner, maxCorner); + btVector3 diagonal = maxCorner - minCorner; + float volume = diagonal.getX() * diagonal.getY() * diagonal.getZ(); + + // cap the max mass for numerical stability + const float MIN_OBJECT_MASS = 0.0f; + const float MAX_OBJECT_DENSITY = 20000.0f; // kg/m^3 density of Tungsten + const float MAX_OBJECT_VOLUME = 1.0e6f; + const float MAX_OBJECT_MASS = MAX_OBJECT_DENSITY * MAX_OBJECT_VOLUME; + return glm::clamp(_density * volume, MIN_OBJECT_MASS, MAX_OBJECT_MASS); + } + return 0.0f; } void ObjectMotionState::setBodyLinearVelocity(const glm::vec3& velocity) const { diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 645bd6fc14..1e582ea854 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -93,8 +93,8 @@ public: MotionStateType getType() const { return _type; } virtual PhysicsMotionType getMotionType() const { return _motionType; } - void setMass(float mass) { _mass = fabsf(mass); } - float getMass() { return _mass; } + void setMass(float mass); + float getMass() const; void setBodyLinearVelocity(const glm::vec3& velocity) const; void setBodyAngularVelocity(const glm::vec3& velocity) const; @@ -159,12 +159,12 @@ protected: void setRigidBody(btRigidBody* body); virtual void setShape(const btCollisionShape* shape); - MotionStateType _type = MOTIONSTATE_TYPE_INVALID; // type of MotionState - PhysicsMotionType _motionType; // type of motion: KINEMATIC, DYNAMIC, or STATIC + MotionStateType _type { MOTIONSTATE_TYPE_INVALID }; // type of MotionState + PhysicsMotionType _motionType { MOTION_TYPE_STATIC }; // type of motion: KINEMATIC, DYNAMIC, or STATIC const btCollisionShape* _shape; - btRigidBody* _body; - float _mass; + btRigidBody* _body { nullptr }; + float _density { 1.0f }; uint32_t _lastKinematicStep; bool _hasInternalKinematicChanges { false }; From 97ed7195069c864544ff56daa97960b954779455 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 17 May 2017 10:40:45 -0700 Subject: [PATCH 06/11] cap scripted linear and angular velocity inputs --- libraries/entities/src/EntityItem.cpp | 52 ++++++++++++++++++--------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a6de541958..3e858f48be 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1691,14 +1691,20 @@ void EntityItem::updateVelocity(const glm::vec3& value) { setLocalVelocity(Vectors::ZERO); } } else { - const float MIN_LINEAR_SPEED = 0.001f; - if (glm::length(value) < MIN_LINEAR_SPEED) { - velocity = ENTITY_ITEM_ZERO_VEC3; - } else { - velocity = value; + float speed = glm::length(value); + if (!isnan(speed)) { + const float MIN_LINEAR_SPEED = 0.001f; + const float MAX_LINEAR_SPEED = 270.0f; // 3m per step at 90Hz + if (speed < MIN_LINEAR_SPEED) { + velocity = ENTITY_ITEM_ZERO_VEC3; + } else if (speed > MAX_LINEAR_SPEED) { + velocity = (MAX_LINEAR_SPEED / speed) * value; + } else { + velocity = value; + } + setLocalVelocity(velocity); + _dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY; } - setLocalVelocity(velocity); - _dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY; } } } @@ -1723,8 +1729,16 @@ void EntityItem::updateGravity(const glm::vec3& value) { if (getShapeType() == SHAPE_TYPE_STATIC_MESH) { _gravity = Vectors::ZERO; } else { - _gravity = value; - _dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY; + float magnitude = glm::length(value); + if (!isnan(magnitude)) { + const float MAX_ACCELERATION_OF_GRAVITY = 10.0f * 9.8f; // 10g + if (magnitude > MAX_ACCELERATION_OF_GRAVITY) { + _gravity = (MAX_ACCELERATION_OF_GRAVITY / magnitude) * value; + } else { + _gravity = value; + } + _dirtyFlags |= Simulation::DIRTY_LINEAR_VELOCITY; + } } } } @@ -1735,14 +1749,20 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) { if (getShapeType() == SHAPE_TYPE_STATIC_MESH) { setLocalAngularVelocity(Vectors::ZERO); } else { - const float MIN_ANGULAR_SPEED = 0.0002f; - if (glm::length(value) < MIN_ANGULAR_SPEED) { - angularVelocity = ENTITY_ITEM_ZERO_VEC3; - } else { - angularVelocity = value; + float speed = glm::length(value); + if (!isnan(speed)) { + const float MIN_ANGULAR_SPEED = 0.0002f; + const float MAX_ANGULAR_SPEED = 9.0f * TWO_PI; // 1/10 rotation per step at 90Hz + if (speed < MIN_ANGULAR_SPEED) { + angularVelocity = ENTITY_ITEM_ZERO_VEC3; + } else if (speed > MAX_ANGULAR_SPEED) { + angularVelocity = (MAX_ANGULAR_SPEED / speed) * value; + } else { + angularVelocity = value; + } + setLocalAngularVelocity(angularVelocity); + _dirtyFlags |= Simulation::DIRTY_ANGULAR_VELOCITY; } - setLocalAngularVelocity(angularVelocity); - _dirtyFlags |= Simulation::DIRTY_ANGULAR_VELOCITY; } } } From 0f0ad11344c50f9e6c2f09548318127556e9c982 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 17 May 2017 13:47:24 -0700 Subject: [PATCH 07/11] Ensure avatar identity packet at mixer. --- assignment-client/src/avatars/AvatarMixerClientData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 1449005246..76519466b5 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -145,7 +145,7 @@ private: std::unordered_map> _lastOtherAvatarSentJoints; uint64_t _identityChangeTimestamp; - bool _avatarSessionDisplayNameMustChange{ false }; + bool _avatarSessionDisplayNameMustChange{ true }; int _numAvatarsSentLastFrame = 0; int _numFramesSinceAdjustment = 0; From d4752926b8f35d6ff093d9702e6bda8082fba812 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 17 May 2017 13:11:37 -0700 Subject: [PATCH 08/11] First pass - checking performance --- interface/src/Application.cpp | 3 +-- libraries/avatars/src/AvatarData.cpp | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3a09a2181c..1d31a84ed4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5258,9 +5258,8 @@ void Application::nodeActivated(SharedNodePointer node) { } if (node->getType() == NodeType::AvatarMixer) { - // new avatar mixer, send off our identity packet right away + // new avatar mixer, send off our identity packet on next update loop getMyAvatar()->markIdentityDataChanged(); - getMyAvatar()->sendIdentityPacket(); getMyAvatar()->resetLastSent(); } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index eebb9c2633..7ea48db745 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1588,8 +1588,6 @@ void AvatarData::setDisplayName(const QString& displayName) { _displayName = displayName; _sessionDisplayName = ""; - sendIdentityPacket(); - qCDebug(avatars) << "Changing display name for avatar to" << displayName; markIdentityDataChanged(); } From 78dd30f65636d42cb1766d2af299b1092e3adc28 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 17 May 2017 15:22:39 -0700 Subject: [PATCH 09/11] macosx warning fix --- libraries/animation/src/IKTarget.cpp | 2 +- libraries/animation/src/IKTarget.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/IKTarget.cpp b/libraries/animation/src/IKTarget.cpp index 18e656f583..c67c0621c3 100644 --- a/libraries/animation/src/IKTarget.cpp +++ b/libraries/animation/src/IKTarget.cpp @@ -15,7 +15,7 @@ void IKTarget::setPose(const glm::quat& rotation, const glm::vec3& translation) } void IKTarget::setFlexCoefficients(size_t numFlexCoefficientsIn, const float* flexCoefficientsIn) { - _numFlexCoefficients = std::min(numFlexCoefficientsIn, MAX_FLEX_COEFFICIENTS); + _numFlexCoefficients = std::min(numFlexCoefficientsIn, (size_t)MAX_FLEX_COEFFICIENTS); for (size_t i = 0; i < _numFlexCoefficients; i++) { _flexCoefficients[i] = flexCoefficientsIn[i]; } diff --git a/libraries/animation/src/IKTarget.h b/libraries/animation/src/IKTarget.h index 1951d3ba7b..4f464c103c 100644 --- a/libraries/animation/src/IKTarget.h +++ b/libraries/animation/src/IKTarget.h @@ -41,7 +41,8 @@ public: void setWeight(float weight) { _weight = weight; } float getWeight() const { return _weight; } - static const size_t MAX_FLEX_COEFFICIENTS = 10; + enum FlexCoefficients { MAX_FLEX_COEFFICIENTS = 10 }; + private: AnimPose _pose; int _index{-1}; From 2ac5fbf91dda6e86de6b051835f0e0919fae503f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 17 May 2017 15:26:29 -0700 Subject: [PATCH 10/11] set wireless scan interval to -1 --- libraries/shared/src/SharedUtil.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 81a0eed9f3..a68d27e620 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -768,9 +768,10 @@ bool similarStrings(const QString& stringA, const QString& stringB) { } void disableQtBearerPoll() { - // to work around the Qt constant wireless scanning, set the env for polling interval very high - const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT16_MAX).toLocal8Bit(); - qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT); + // to disable the Qt constant wireless scanning, set the env for polling interval + qDebug() << "Disabling Qt wireless polling by using a negative value for QTimer::setInterval"; + const QByteArray DISABLE_BEARER_POLL_TIMEOUT = QString::number(-1).toLocal8Bit(); + qputenv("QT_BEARER_POLL_TIMEOUT", DISABLE_BEARER_POLL_TIMEOUT); } void printSystemInformation() { From 0018224fefb72e6c50041effe7b89e676fd2ef8b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 17 May 2017 16:23:39 -0700 Subject: [PATCH 11/11] moar warning fixes --- libraries/animation/src/AnimInverseKinematics.cpp | 4 ++-- libraries/animation/src/AnimInverseKinematics.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index c43d7b76dd..4471f11857 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -32,7 +32,7 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, cons numFlexCoefficients(flexCoefficientsIn.size()), jointIndex(-1) { - numFlexCoefficients = std::min(numFlexCoefficients, MAX_FLEX_COEFFICIENTS); + numFlexCoefficients = std::min(numFlexCoefficients, (size_t)MAX_FLEX_COEFFICIENTS); for (size_t i = 0; i < numFlexCoefficients; i++) { flexCoefficients[i] = flexCoefficientsIn[i]; } @@ -48,7 +48,7 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) : numFlexCoefficients(orig.numFlexCoefficients), jointIndex(orig.jointIndex) { - numFlexCoefficients = std::min(numFlexCoefficients, MAX_FLEX_COEFFICIENTS); + numFlexCoefficients = std::min(numFlexCoefficients, (size_t)MAX_FLEX_COEFFICIENTS); for (size_t i = 0; i < numFlexCoefficients; i++) { flexCoefficients[i] = orig.flexCoefficients[i]; } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index cf03005b68..74face6d0b 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -78,7 +78,7 @@ protected: AnimInverseKinematics(const AnimInverseKinematics&) = delete; AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete; - static const size_t MAX_FLEX_COEFFICIENTS = 10; + enum FlexCoefficients { MAX_FLEX_COEFFICIENTS = 10 }; struct IKTargetVar { IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn, const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector& flexCoefficientsIn);