mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-10 10:34:56 +02:00
Fix eyelid behaviour
This commit is contained in:
parent
e7d5ea561b
commit
2264425f9f
3 changed files with 66 additions and 32 deletions
|
@ -220,30 +220,56 @@ void Head::calculateMouthShapes(float deltaTime) {
|
|||
|
||||
void Head::applyEyelidOffset(glm::quat headOrientation) {
|
||||
// Adjusts the eyelid blendshape coefficients so that the eyelid follows the iris as the head pitches.
|
||||
|
||||
if (disableEyelidAdjustment) {
|
||||
bool isBlinking = (_rightEyeBlinkVelocity != 0.0f && _rightEyeBlinkVelocity != 0.0f);
|
||||
if (disableEyelidAdjustment || isBlinking) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::vector<QString> eyeBlinkBlendShapes = { "EyeBlink_L", "EyeBlink_R" };
|
||||
const std::vector<QString> eyeOpenBlendShapes = { "EyeOpen_L", "EyeOpen_R" };
|
||||
const std::vector<QString> browsBlendShapes = { "BrowsU_L", "BrowsU_R" };
|
||||
|
||||
const float EYE_PITCH_TO_COEFFICIENT = 3.5f; // Empirically determined
|
||||
const float MAX_EYELID_OFFSET = 1.5f;
|
||||
const float BLINK_DOWN_MULTIPLIER = 0.25f;
|
||||
const float OPEN_DOWN_MULTIPLIER = 0.3f;
|
||||
const float BROW_UP_MULTIPLIER = 0.5f;
|
||||
|
||||
glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FORWARD, getLookAtPosition() - _eyePosition);
|
||||
eyeRotation = eyeRotation * glm::angleAxis(safeEulerAngles(headOrientation).y, IDENTITY_UP); // Rotation w.r.t. head
|
||||
float eyePitch = safeEulerAngles(eyeRotation).x;
|
||||
float eyelidOffset = glm::clamp(abs(eyePitch * EYE_PITCH_TO_COEFFICIENT), 0.0f, MAX_EYELID_OFFSET);
|
||||
|
||||
const float EYE_PITCH_TO_COEFFICIENT = 1.6f; // Empirically determined
|
||||
const float MAX_EYELID_OFFSET = 0.8f; // So that don't fully close eyes when looking way down
|
||||
float eyelidOffset = glm::clamp(-eyePitch * EYE_PITCH_TO_COEFFICIENT, -1.0f, MAX_EYELID_OFFSET);
|
||||
std::vector<int> eyeBlinkIndices, eyeOpenIndices, browsIndices;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const int LEFT_EYE = 8;
|
||||
float eyeCoefficient = _transientBlendshapeCoefficients[i] - _transientBlendshapeCoefficients[LEFT_EYE + i];
|
||||
eyeCoefficient = glm::clamp(eyelidOffset + eyeCoefficient * (1.0f - eyelidOffset), -1.0f, 1.0f);
|
||||
if (eyeCoefficient > 0.0f) {
|
||||
_transientBlendshapeCoefficients[i] = eyeCoefficient;
|
||||
_transientBlendshapeCoefficients[LEFT_EYE + i] = 0.0f;
|
||||
getBlendshapeIndices(eyeBlinkBlendShapes, eyeBlinkIndices);
|
||||
getBlendshapeIndices(eyeOpenBlendShapes, eyeOpenIndices);
|
||||
getBlendshapeIndices(browsBlendShapes, browsIndices);
|
||||
|
||||
} else {
|
||||
_transientBlendshapeCoefficients[i] = 0.0f;
|
||||
_transientBlendshapeCoefficients[LEFT_EYE + i] = -eyeCoefficient;
|
||||
bool isLookingUp = (eyePitch > 0);
|
||||
|
||||
for (auto& blinkIndex : eyeBlinkIndices) {
|
||||
float lookingUpCoefficient = -eyelidOffset;
|
||||
float lookingDownCoefficient = BLINK_DOWN_MULTIPLIER * eyelidOffset;
|
||||
if (blinkIndex >= 0 && blinkIndex < _transientBlendshapeCoefficients.size()) {
|
||||
_transientBlendshapeCoefficients[blinkIndex] = isLookingUp ? lookingUpCoefficient : lookingDownCoefficient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (auto& openIndex : eyeOpenIndices) {
|
||||
float lookingUpCoefficient = eyelidOffset;
|
||||
float lookingDownCoefficient = OPEN_DOWN_MULTIPLIER * eyelidOffset;
|
||||
if (openIndex >= 0 && openIndex < _transientBlendshapeCoefficients.size()) {
|
||||
_transientBlendshapeCoefficients[openIndex] = isLookingUp ? lookingUpCoefficient : lookingDownCoefficient;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& browIndex : browsIndices) {
|
||||
float lookingUpCoefficient = BROW_UP_MULTIPLIER * eyelidOffset;
|
||||
float lookingDownCoefficient = 0.0f;
|
||||
if (browIndex >= 0 && browIndex < _transientBlendshapeCoefficients.size()) {
|
||||
_transientBlendshapeCoefficients[browIndex] = isLookingUp ? lookingUpCoefficient : lookingDownCoefficient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
|
|||
_summedBlendshapeCoefficients(QVector<float>(0, 0.0f)),
|
||||
_owningAvatar(owningAvatar)
|
||||
{
|
||||
|
||||
computeBlendshapesLookupMap();
|
||||
}
|
||||
|
||||
glm::quat HeadData::getRawOrientation() const {
|
||||
|
@ -71,16 +71,10 @@ void HeadData::setOrientation(const glm::quat& orientation) {
|
|||
setHeadOrientation(orientation);
|
||||
}
|
||||
|
||||
//Lazily construct a lookup map from the blendshapes
|
||||
static const QMap<QString, int>& getBlendshapesLookupMap() {
|
||||
static std::once_flag once;
|
||||
static QMap<QString, int> blendshapeLookupMap;
|
||||
std::call_once(once, [&] {
|
||||
for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
|
||||
blendshapeLookupMap[FACESHIFT_BLENDSHAPES[i]] = i;
|
||||
}
|
||||
});
|
||||
return blendshapeLookupMap;
|
||||
void HeadData::computeBlendshapesLookupMap(){
|
||||
for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
|
||||
_blendshapeLookupMap[FACESHIFT_BLENDSHAPES[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int HeadData::getNumSummedBlendshapeCoefficients() const {
|
||||
|
@ -108,11 +102,10 @@ const QVector<float>& HeadData::getSummedBlendshapeCoefficients() {
|
|||
}
|
||||
|
||||
void HeadData::setBlendshape(QString name, float val) {
|
||||
const auto& blendshapeLookupMap = getBlendshapesLookupMap();
|
||||
|
||||
//Check to see if the named blendshape exists, and then set its value if it does
|
||||
auto it = blendshapeLookupMap.find(name);
|
||||
if (it != blendshapeLookupMap.end()) {
|
||||
auto it = _blendshapeLookupMap.find(name);
|
||||
if (it != _blendshapeLookupMap.end()) {
|
||||
if (_blendshapeCoefficients.size() <= it.value()) {
|
||||
_blendshapeCoefficients.resize(it.value() + 1);
|
||||
}
|
||||
|
@ -123,6 +116,18 @@ void HeadData::setBlendshape(QString name, float val) {
|
|||
}
|
||||
}
|
||||
|
||||
int HeadData::getBlendshapeIndex(const QString& name) {
|
||||
auto it = _blendshapeLookupMap.find(name);
|
||||
int index = it != _blendshapeLookupMap.end() ? it.value() : -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
void HeadData::getBlendshapeIndices(const std::vector<QString>& blendShapeNames, std::vector<int>& indexes) {
|
||||
for (auto& name : blendShapeNames) {
|
||||
indexes.push_back(getBlendshapeIndex(name));
|
||||
}
|
||||
}
|
||||
|
||||
static const QString JSON_AVATAR_HEAD_ROTATION = QStringLiteral("rotation");
|
||||
static const QString JSON_AVATAR_HEAD_BLENDSHAPE_COEFFICIENTS = QStringLiteral("blendShapes");
|
||||
static const QString JSON_AVATAR_HEAD_LEAN_FORWARD = QStringLiteral("leanForward");
|
||||
|
@ -131,10 +136,9 @@ static const QString JSON_AVATAR_HEAD_LOOKAT = QStringLiteral("lookAt");
|
|||
|
||||
QJsonObject HeadData::toJson() const {
|
||||
QJsonObject headJson;
|
||||
const auto& blendshapeLookupMap = getBlendshapesLookupMap();
|
||||
QJsonObject blendshapesJson;
|
||||
for (auto name : blendshapeLookupMap.keys()) {
|
||||
auto index = blendshapeLookupMap[name];
|
||||
for (auto name : _blendshapeLookupMap.keys()) {
|
||||
auto index = _blendshapeLookupMap[name];
|
||||
float value = 0.0f;
|
||||
if (index < _blendshapeCoefficients.size()) {
|
||||
value += _blendshapeCoefficients[index];
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
void setOrientation(const glm::quat& orientation);
|
||||
|
||||
void setBlendshape(QString name, float val);
|
||||
int getBlendshapeIndex(const QString& name);
|
||||
void getBlendshapeIndices(const std::vector<QString>& blendShapeNames, std::vector<int>& indexes);
|
||||
const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
|
||||
const QVector<float>& getSummedBlendshapeCoefficients();
|
||||
int getNumSummedBlendshapeCoefficients() const;
|
||||
|
@ -114,6 +116,7 @@ protected:
|
|||
QVector<float> _blendshapeCoefficients;
|
||||
QVector<float> _transientBlendshapeCoefficients;
|
||||
QVector<float> _summedBlendshapeCoefficients;
|
||||
QMap<QString, int> _blendshapeLookupMap;
|
||||
AvatarData* _owningAvatar;
|
||||
|
||||
private:
|
||||
|
@ -122,6 +125,7 @@ private:
|
|||
HeadData& operator= (const HeadData&);
|
||||
|
||||
void setHeadOrientation(const glm::quat& orientation);
|
||||
void computeBlendshapesLookupMap();
|
||||
};
|
||||
|
||||
#endif // hifi_HeadData_h
|
||||
|
|
Loading…
Reference in a new issue