Full legacy API and FST support

This commit is contained in:
Anthony J. Thibault 2019-10-18 16:30:32 -07:00
parent 389f5a1d33
commit 92f1b59cc8
11 changed files with 60 additions and 34 deletions

View file

@ -279,18 +279,6 @@ void ScriptableAvatar::setJointMappingsFromNetworkReply() {
networkReply->deleteLater();
}
void ScriptableAvatar::setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement) {
_headData->setHasProceduralBlinkFaceMovement(hasProceduralBlinkFaceMovement);
}
void ScriptableAvatar::setHasProceduralEyeFaceMovement(bool hasProceduralEyeFaceMovement) {
_headData->setHasProceduralEyeFaceMovement(hasProceduralEyeFaceMovement);
}
void ScriptableAvatar::setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement) {
_headData->setHasAudioEnabledFaceMovement(hasAudioEnabledFaceMovement);
}
AvatarEntityMap ScriptableAvatar::getAvatarEntityData() const {
// DANGER: Now that we store the AvatarEntityData in packed format this call is potentially Very Expensive!
// Avoid calling this method if possible.

View file

@ -153,13 +153,6 @@ public:
virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking = false) override;
void setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement);
bool getHasProceduralBlinkFaceMovement() const override { return _headData->getHasProceduralBlinkFaceMovement(); }
void setHasProceduralEyeFaceMovement(bool hasProceduralEyeFaceMovement);
bool getHasProceduralEyeFaceMovement() const override { return _headData->getHasProceduralEyeFaceMovement(); }
void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement);
bool getHasAudioEnabledFaceMovement() const override { return _headData->getHasAudioEnabledFaceMovement(); }
/**jsdoc
* Gets details of all avatar entities.
* <p><strong>Warning:</strong> Potentially an expensive call. Do not use if possible.</p>

View file

@ -27,6 +27,9 @@ HeadData::HeadData(AvatarData* owningAvatar) :
_basePitch(0.0f),
_baseRoll(0.0f),
_lookAtPosition(0.0f, 0.0f, 0.0f),
_blendshapeCoefficients((int)Blendshapes::BlendshapeCount, 0.0f),
_transientBlendshapeCoefficients((int)Blendshapes::BlendshapeCount, 0.0f),
_summedBlendshapeCoefficients((int)Blendshapes::BlendshapeCount, 0.0f),
_owningAvatar(owningAvatar)
{
_userProceduralAnimationFlags.assign((size_t)ProceduralAnimaitonTypeCount, true);

View file

@ -121,9 +121,9 @@ protected:
float _averageLoudness { 0.0f };
float _browAudioLift { 0.0f };
QVector<float> _blendshapeCoefficients { (int)Blendshapes::BlendshapeCount, 0.0f };
QVector<float> _transientBlendshapeCoefficients { (int)Blendshapes::BlendshapeCount, 0.0f };
QVector<float> _summedBlendshapeCoefficients { (int)Blendshapes::BlendshapeCount, 0.0f };
QVector<float> _blendshapeCoefficients;
QVector<float> _transientBlendshapeCoefficients;
QVector<float> _summedBlendshapeCoefficients;
QMap<QString, int> _blendshapeLookupMap;
AvatarData* _owningAvatar;

View file

@ -350,7 +350,7 @@ namespace controller {
makePosePair(Action::LEFT_EYE, "LeftEye"),
makePosePair(Action::RIGHT_EYE, "RightEye"),
// AJT: blendshapes
// blendshapes
makeAxisPair(Action::EYEBLINK_L, "EyeBlink_L"),
makeAxisPair(Action::EYEBLINK_R, "EyeBlink_R"),
makeAxisPair(Action::EYESQUINT_L, "EyeSquint_L"),

View file

@ -184,7 +184,7 @@ enum class Action {
LEFT_EYE,
RIGHT_EYE,
// AJT: blendshapes
// blendshapes
EYEBLINK_L,
EYEBLINK_R,
EYESQUINT_L,

View file

@ -356,7 +356,7 @@ Input::NamedVector StandardController::getAvailableInputs() const {
makePair(LEFT_EYE, "LeftEye"),
makePair(RIGHT_EYE, "RightEye"),
// AJT: blendshapes
// blendshapes
makePair(EYEBLINK_L, "EyeBlink_L"),
makePair(EYEBLINK_R, "EyeBlink_R"),
makePair(EYESQUINT_L, "EyeSquint_L"),

View file

@ -91,7 +91,7 @@ namespace controller {
LEFT_GRIP,
RIGHT_GRIP,
// AJT: blendshapes
// blendshapes
EYEBLINK_L,
EYEBLINK_R,
EYESQUINT_L,

View file

@ -21,7 +21,7 @@
QVariantHash FSTReader::parseMapping(QIODevice* device) {
QVariantHash properties;
QByteArray line;
while (!(line = device->readLine()).isEmpty()) {
if ((line = line.trimmed()).startsWith('#')) {
@ -34,12 +34,10 @@ QVariantHash FSTReader::parseMapping(QIODevice* device) {
QByteArray name = sections.at(0).trimmed();
if (sections.size() == 2) {
properties.insertMulti(name, sections.at(1).trimmed());
} else if (sections.size() == 3) {
QVariantHash heading = properties.value(name).toHash();
heading.insertMulti(sections.at(1).trimmed(), sections.at(2).trimmed());
properties.insert(name, heading);
} else if (sections.size() >= 4) {
QVariantHash heading = properties.value(name).toHash();
QVariantList contents;
@ -50,14 +48,56 @@ QVariantHash FSTReader::parseMapping(QIODevice* device) {
properties.insert(name, heading);
}
}
return properties;
}
static void removeBlendshape(QVariantHash& bs, const QString& key) {
if (bs.contains(key)) {
bs.remove(key);
}
}
static void splitBlendshapes(QVariantHash& bs, const QString& key, const QString& leftKey, const QString& rightKey) {
if (bs.contains(key) && !(bs.contains(leftKey) || bs.contains(rightKey))) {
// key has been split into leftKey and rightKey blendshapes
QVariantList origShapes = bs.values(key);
QVariantList halfShapes;
for (int i = 0; i < origShapes.size(); i++) {
QVariantList origShape = origShapes[i].toList();
QVariantList halfShape;
halfShape.append(origShape[0]);
halfShape.append(QVariant(0.5f * origShape[1].toFloat()));
bs.insertMulti(leftKey, halfShape);
bs.insertMulti(rightKey, halfShape);
}
}
}
// convert legacy blendshapes to arkit blendshapes
static void fixUpLegacyBlendshapes(QVariantHash& properties) {
QVariantHash bs = properties.value("bs").toHash();
// These blendshapes have no ARKit equivalent, so we remove them.
removeBlendshape(bs, "JawChew");
removeBlendshape(bs, "ChinLowerRaise");
removeBlendshape(bs, "ChinUpperRaise");
// These blendshapes are split in ARKit, we replace them with their left and right sides with a weight of 1/2.
splitBlendshapes(bs, "LipsUpperUp", "MouthUpperUp_L", "MouthUpperUp_R");
splitBlendshapes(bs, "LipsLowerDown", "MouthLowerDown_L", "MouthLowerDown_R");
splitBlendshapes(bs, "Sneer", "NoseSneer_L", "NoseSneer_R");
// re-insert new mutated bs hash into mapping properties.
properties.insert("bs", bs);
}
QVariantHash FSTReader::readMapping(const QByteArray& data) {
QBuffer buffer(const_cast<QByteArray*>(&data));
buffer.open(QIODevice::ReadOnly);
return FSTReader::parseMapping(&buffer);
QVariantHash mapping = FSTReader::parseMapping(&buffer);
fixUpLegacyBlendshapes(mapping);
return mapping;
}
void FSTReader::writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) {

View file

@ -39,6 +39,8 @@
#include "RenderUtilsLogging.h"
#include <Trace.h>
#include <BlendshapeConstants.h>
using namespace std;
int nakedModelPointerTypeId = qRegisterMetaType<ModelPointer>();

View file

@ -109,10 +109,10 @@ enum class LegacyBlendshpaes : int {
// Legacy shapes
// * JawChew (not in ARKit)
// * MouthUpperUp (split in ARKit)
// * MouthLowerDown (split in ARKit)
// * LipsUpperUp (split in ARKit)
// * LipsLowerDown (split in ARKit)
// * Sneer (split in ARKit)
// * ChinLowerRaise (not in ARKit)
// * ChinUpperRase (not in ARKit)
// * ChinUpperRaise (not in ARKit)
#endif // hifi_BlendshapeConstants_h