Merge branch 'master' of github.com:highfidelity/hifi into fix-imported-children-querybox

This commit is contained in:
Seth Alves 2017-05-18 09:10:58 -07:00
commit b8567e0550
11 changed files with 166 additions and 60 deletions

View file

@ -56,43 +56,64 @@
"jointName": "Hips",
"positionVar": "hipsPosition",
"rotationVar": "hipsRotation",
"typeVar": "hipsType"
"typeVar": "hipsType",
"weightVar": "hipsWeight",
"weight": 1.0,
"flexCoefficients": [1]
},
{
"jointName": "RightHand",
"positionVar": "rightHandPosition",
"rotationVar": "rightHandRotation",
"typeVar": "rightHandType"
"typeVar": "rightHandType",
"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"
"typeVar": "leftHandType",
"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"
"typeVar": "rightFootType",
"weightVar": "rightFootWeight",
"weight": 1.0,
"flexCoefficients": [1, 0.45, 0.45]
},
{
"jointName": "LeftFoot",
"positionVar": "leftFootPosition",
"rotationVar": "leftFootRotation",
"typeVar": "leftFootType"
"typeVar": "leftFootType",
"weightVar": "leftFootWeight",
"weight": 1.0,
"flexCoefficients": [1, 0.45, 0.45]
},
{
"jointName": "Spine2",
"positionVar": "spine2Position",
"rotationVar": "spine2Rotation",
"typeVar": "spine2Type"
"typeVar": "spine2Type",
"weightVar": "spine2Weight",
"weight": 1.0,
"flexCoefficients": [0.45, 0.45]
},
{
"jointName": "Head",
"positionVar": "headPosition",
"rotationVar": "headRotation",
"typeVar": "headType"
"typeVar": "headType",
"weightVar": "headWeight",
"weight": 4.0,
"flexCoefficients": [1, 0.5, 0.5, 0.5, 0.5]
}
]
},

View file

@ -21,6 +21,39 @@
#include "SwingTwistConstraint.h"
#include "AnimationLogging.h"
AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, const QString& positionVarIn, const QString& rotationVarIn,
const QString& typeVarIn, const QString& weightVarIn, float weightIn, const std::vector<float>& flexCoefficientsIn) :
jointName(jointNameIn),
positionVar(positionVarIn),
rotationVar(rotationVarIn),
typeVar(typeVarIn),
weightVar(weightVarIn),
weight(weightIn),
numFlexCoefficients(flexCoefficientsIn.size()),
jointIndex(-1)
{
numFlexCoefficients = std::min(numFlexCoefficients, (size_t)MAX_FLEX_COEFFICIENTS);
for (size_t i = 0; i < numFlexCoefficients; i++) {
flexCoefficients[i] = flexCoefficientsIn[i];
}
}
AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) :
jointName(orig.jointName),
positionVar(orig.positionVar),
rotationVar(orig.rotationVar),
typeVar(orig.typeVar),
weightVar(orig.weightVar),
weight(orig.weight),
numFlexCoefficients(orig.numFlexCoefficients),
jointIndex(orig.jointIndex)
{
numFlexCoefficients = std::min(numFlexCoefficients, (size_t)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 +93,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 QString& weightVar, float weight, const std::vector<float>& flexCoefficients) {
IKTargetVar targetVar(jointName, positionVar, rotationVar, typeVar, weightVar, weight, 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);
}
}
@ -107,10 +136,15 @@ 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);
if (targetVar.jointIndex > _maxTargetIndex) {
_maxTargetIndex = targetVar.jointIndex;
}
@ -271,6 +305,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
// cache tip absolute position
glm::vec3 tipPosition = absolutePoses[tipIndex].trans();
size_t 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 +348,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 +420,8 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
pivotIndex = pivotsParentIndex;
pivotsParentIndex = _skeleton->getParentIndex(pivotIndex);
chainDepth++;
}
return lowestMovedIndex;
}
@ -806,7 +843,7 @@ void AnimInverseKinematics::initConstraints() {
stConstraint->setTwistLimits(-MAX_SHOULDER_TWIST, MAX_SHOULDER_TWIST);
std::vector<float> 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);

View file

@ -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 QString& weightVar, float weight, const std::vector<float>& 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,20 @@ protected:
AnimInverseKinematics(const AnimInverseKinematics&) = delete;
AnimInverseKinematics& operator=(const AnimInverseKinematics&) = delete;
enum FlexCoefficients { 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 QString& weightVarIn, float weightIn, const std::vector<float>& flexCoefficientsIn);
IKTargetVar(const IKTargetVar& orig);
QString jointName;
QString positionVar;
QString rotationVar;
QString typeVar;
QString jointName;
QString weightVar;
float weight;
float flexCoefficients[MAX_FLEX_COEFFICIENTS];
size_t numFlexCoefficients;
int jointIndex; // cached joint index
};

View file

@ -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,8 +477,21 @@ 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);
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<float> flexCoefficients;
for (const auto& value : flexCoefficientsArray) {
flexCoefficients.push_back((float)value.toDouble());
}
node->setTargetVars(jointName, positionVar, rotationVar, typeVar, weightVar, weight, flexCoefficients);
};
READ_OPTIONAL_STRING(solutionSource, jsonObj);

View file

@ -14,6 +14,23 @@ 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, (size_t)MAX_FLEX_COEFFICIENTS);
for (size_t i = 0; i < _numFlexCoefficients; i++) {
_flexCoefficients[i] = flexCoefficientsIn[i];
}
}
float IKTarget::getFlexCoefficient(size_t chainDepth) const {
const float DEFAULT_FLEX_COEFFICIENT = 0.5f;
if (chainDepth < _numFlexCoefficients) {
return _flexCoefficients[chainDepth];
} else {
return DEFAULT_FLEX_COEFFICIENT;
}
}
void IKTarget::setType(int type) {
switch (type) {
case (int)Type::RotationAndPosition:

View file

@ -35,15 +35,21 @@ 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(size_t 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; }
enum FlexCoefficients { MAX_FLEX_COEFFICIENTS = 10 };
private:
AnimPose _pose;
int _index{-1};
Type _type{Type::RotationAndPosition};
float _weight;
float _flexCoefficients[MAX_FLEX_COEFFICIENTS];
size_t _numFlexCoefficients;
};
#endif // hifi_IKTarget_h

View file

@ -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");
@ -1400,22 +1402,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", "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;

View file

@ -1692,7 +1692,7 @@ void EntityItem::updateVelocity(const glm::vec3& value) {
}
} else {
float speed = glm::length(value);
if (!isnan(speed)) {
if (!glm::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) {
@ -1730,7 +1730,7 @@ void EntityItem::updateGravity(const glm::vec3& value) {
_gravity = Vectors::ZERO;
} else {
float magnitude = glm::length(value);
if (!isnan(magnitude)) {
if (!glm::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;
@ -1750,7 +1750,7 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) {
setLocalAngularVelocity(Vectors::ZERO);
} else {
float speed = glm::length(value);
if (!isnan(speed)) {
if (!glm::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) {

View file

@ -210,7 +210,16 @@ PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const {
auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face);
if (faceSize != 0 && faceOffset != 0) {
auto file = maybeOpenFile();
result = file->createView(faceSize, faceOffset)->toMemoryStorage();
if (file) {
auto storageView = file->createView(faceSize, faceOffset);
if (storageView) {
return storageView->toMemoryStorage();
} else {
qWarning() << "Failed to get a valid storageView for faceSize=" << faceSize << " faceOffset=" << faceOffset << "out of valid file " << QString::fromStdString(_filename);
}
} else {
qWarning() << "Failed to get a valid file out of maybeOpenFile " << QString::fromStdString(_filename);
}
}
return result;
}

View file

@ -126,19 +126,8 @@ QJsonDocument variantMapToJsonDocument(const QSettings::SettingsMap& map) {
}
switch (variantType) {
case QVariant::Map: {
auto varmap = variant.toMap();
for (auto mapit = varmap.cbegin(); mapit != varmap.cend(); ++mapit) {
auto& mapkey = mapit.key();
auto& mapvariant = mapit.value();
object.insert(key + "/" + mapkey, QJsonValue::fromVariant(mapvariant));
}
break;
}
case QVariant::List:
case QVariant::Hash: {
qCritical() << "Unsupported variant type" << variant.typeName();
qCritical() << "Unsupported variant type" << variant.typeName() << ";" << key << variant;
Q_ASSERT(false);
break;
}
@ -152,6 +141,8 @@ QJsonDocument variantMapToJsonDocument(const QSettings::SettingsMap& map) {
case QVariant::UInt:
case QVariant::Bool:
case QVariant::Double:
case QVariant::Map:
case QVariant::List:
object.insert(key, QJsonValue::fromVariant(variant));
break;

View file

@ -25,7 +25,9 @@ StoragePointer Storage::createView(size_t viewSize, size_t offset) const {
viewSize = selfSize;
}
if ((viewSize + offset) > selfSize) {
throw std::runtime_error("Invalid mapping range");
return StoragePointer();
//TODO: Disable te exception for now and return an empty storage instead.
//throw std::runtime_error("Invalid mapping range");
}
return std::make_shared<ViewStorage>(shared_from_this(), viewSize, data() + offset);
}