From aba031a1259936eca0bbda55a6ffb72d9b8c33fe Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 23 Jul 2014 16:25:45 -0700 Subject: [PATCH] Proper blendshape JS api. --- assignment-client/src/Agent.cpp | 3 ++- libraries/avatars/src/AvatarData.cpp | 4 ++++ libraries/avatars/src/AvatarData.h | 6 +++++- libraries/avatars/src/HeadData.cpp | 22 ++++++++++++++++++++++ libraries/avatars/src/HeadData.h | 1 + libraries/fbx/src/FBXReader.cpp | 2 ++ libraries/fbx/src/FBXReader.h | 2 ++ 7 files changed, 38 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 0449e0d682..c961d8f19c 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -229,7 +229,8 @@ void Agent::run() { // setup an Avatar for the script to use AvatarData scriptedAvatar; - + scriptedAvatar.setForceFaceshiftConnected(true); + // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setSkeletonModelURL(QUrl()); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6cfa4ba488..c3ea2f8b50 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -43,6 +43,7 @@ AvatarData::AvatarData() : _handState(0), _keyState(NO_KEY_DOWN), _isChatCirclingEnabled(false), + _forceFaceshiftConnected(false), _hasNewJointRotations(true), _headData(NULL), _handData(NULL), @@ -80,6 +81,9 @@ QByteArray AvatarData::toByteArray() { // lazily allocate memory for HeadData in case we're not an Avatar instance if (!_headData) { _headData = new HeadData(this); + if (_forceFaceshiftConnected) { + _headData->_isFaceshiftConnected = true; + } } QByteArray avatarDataByteArray; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 1b8f6e6007..768633c366 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -206,6 +206,10 @@ public: Q_INVOKABLE virtual QStringList getJointNames() const { return _jointNames; } + Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } + + void setForceFaceshiftConnected(bool connected) { _forceFaceshiftConnected = connected; } + // key state void setKeyState(KeyState s) { _keyState = s; } KeyState keyState() const { return _keyState; } @@ -300,7 +304,7 @@ protected: std::string _chatMessage; bool _isChatCirclingEnabled; - + bool _forceFaceshiftConnected; bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar HeadData* _headData; diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index c691a2c28a..31001bf162 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -16,6 +16,8 @@ #include "AvatarData.h" #include "HeadData.h" +#include "../fbx/src/FBXReader.h" + HeadData::HeadData(AvatarData* owningAvatar) : _baseYaw(0.0f), _basePitch(0.0f), @@ -52,6 +54,26 @@ void HeadData::setOrientation(const glm::quat& orientation) { _baseRoll = eulers.z; } +void HeadData::setBlendshape(QString name, float val) { + static bool hasInitializedLookupMap = false; + static QMap blendshapeLookupMap; + //Lazily construct a lookup map from the blendshapes + if (!hasInitializedLookupMap) { + for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) { + blendshapeLookupMap[FACESHIFT_BLENDSHAPES[i]] = i; + } + } + + //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()) { + if (_blendshapeCoefficients.size() <= it.value()) { + _blendshapeCoefficients.resize(it.value() + 1); + } + _blendshapeCoefficients[it.value()] = val; + } +} + void HeadData::addYaw(float yaw) { setBaseYaw(_baseYaw + yaw); } diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 9e2920ae85..782386c649 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -54,6 +54,7 @@ public: float getAudioAverageLoudness() const { return _audioAverageLoudness; } void setAudioAverageLoudness(float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; } + void setBlendshape(QString name, float val); const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } float getPupilDilation() const { return _pupilDilation; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index f366b6a5c3..cf726800a1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -577,6 +577,8 @@ const char* FACESHIFT_BLENDSHAPES[] = { "" }; +const int NUM_FACESHIFT_BLENDSHAPES = sizeof(FACESHIFT_BLENDSHAPES) / sizeof(char*); + const char* HUMANIK_JOINTS[] = { "RightHand", "RightForeArm", diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c336252574..b5340978c1 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -29,6 +29,8 @@ typedef QList FBXNodeList; /// The names of the blendshapes expected by Faceshift, terminated with an empty string. extern const char* FACESHIFT_BLENDSHAPES[]; +/// The size of FACESHIFT_BLENDSHAPES +extern const int NUM_FACESHIFT_BLENDSHAPES; /// The names of the joints in the Maya HumanIK rig, terminated with an empty string. extern const char* HUMANIK_JOINTS[];