mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:37:51 +02:00
Merge pull request #5813 from hyperlogic/tony/anim-hand-state-machines
Added point and grab support to the AnimGraph
This commit is contained in:
commit
848bb4fccb
10 changed files with 588 additions and 220 deletions
|
@ -2868,8 +2868,8 @@ void Application::update(float deltaTime) {
|
||||||
UserInputMapper::PoseValue leftHand = userInputMapper->getPoseState(UserInputMapper::LEFT_HAND);
|
UserInputMapper::PoseValue leftHand = userInputMapper->getPoseState(UserInputMapper::LEFT_HAND);
|
||||||
UserInputMapper::PoseValue rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND);
|
UserInputMapper::PoseValue rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND);
|
||||||
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
Hand* hand = DependencyManager::get<AvatarManager>()->getMyAvatar()->getHand();
|
||||||
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX);
|
setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK));
|
||||||
setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX);
|
setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(UserInputMapper::RIGHT_HAND_CLICK));
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) {
|
||||||
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK),
|
||||||
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX);
|
||||||
|
@ -4951,7 +4951,7 @@ mat4 Application::getHMDSensorPose() const {
|
||||||
return mat4();
|
return mat4();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) {
|
void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index, float triggerValue) {
|
||||||
PalmData* palm;
|
PalmData* palm;
|
||||||
bool foundHand = false;
|
bool foundHand = false;
|
||||||
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||||
|
@ -5021,6 +5021,7 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float
|
||||||
palm->setTipVelocity(glm::vec3(0.0f));
|
palm->setTipVelocity(glm::vec3(0.0f));
|
||||||
}
|
}
|
||||||
palm->setTipPosition(newTipPosition);
|
palm->setTipPosition(newTipPosition);
|
||||||
|
palm->setTrigger(triggerValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::emulateMouse(Hand* hand, float click, float shift, int index) {
|
void Application::emulateMouse(Hand* hand, float click, float shift, int index) {
|
||||||
|
|
|
@ -485,7 +485,7 @@ private:
|
||||||
|
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
|
|
||||||
void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index);
|
void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index, float triggerValue);
|
||||||
void emulateMouse(Hand* hand, float click, float shift, int index);
|
void emulateMouse(Hand* hand, float click, float shift, int index);
|
||||||
|
|
||||||
// Various helper functions called during update()
|
// Various helper functions called during update()
|
||||||
|
|
|
@ -1296,10 +1296,13 @@ void MyAvatar::initAnimGraph() {
|
||||||
// ik-avatar.json
|
// ik-avatar.json
|
||||||
// https://gist.github.com/hyperlogic/e58e0a24cc341ad5d060
|
// https://gist.github.com/hyperlogic/e58e0a24cc341ad5d060
|
||||||
//
|
//
|
||||||
|
// ik-avatar-hands.json
|
||||||
|
// https://gist.githubusercontent.com/hyperlogic/04a02c47eb56d8bfaebb
|
||||||
|
//
|
||||||
// or run a local web-server
|
// or run a local web-server
|
||||||
// python -m SimpleHTTPServer&
|
// python -m SimpleHTTPServer&
|
||||||
// auto graphUrl = QUrl("http://localhost:8000/avatar.json");
|
//auto graphUrl = QUrl("http://localhost:8000/avatar.json");
|
||||||
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/e58e0a24cc341ad5d060/raw/8f824da2908fd89ad1befadd1d8f5d7b3b6efa66/ik-avatar.json");
|
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/04a02c47eb56d8bfaebb/raw/883c7ce8e75ad3f72a0d513c317fe4b74a41c3b8/ik-avatar-hands.json");
|
||||||
_rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry());
|
_rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,17 @@ void SkeletonModel::initJointStates(QVector<JointState> states) {
|
||||||
emit skeletonLoaded();
|
emit skeletonLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const PalmData* getPalmWithIndex(Hand* hand, int index) {
|
||||||
|
const PalmData* palm = nullptr;
|
||||||
|
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||||
|
if (hand->getPalms()[j].getSixenseID() == index) {
|
||||||
|
palm = &(hand->getPalms()[j]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return palm;
|
||||||
|
}
|
||||||
|
|
||||||
const float PALM_PRIORITY = DEFAULT_PRIORITY;
|
const float PALM_PRIORITY = DEFAULT_PRIORITY;
|
||||||
// Called within Model::simulate call, below.
|
// Called within Model::simulate call, below.
|
||||||
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
@ -108,34 +119,59 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
|
||||||
Rig::HeadParameters params;
|
Rig::HeadParameters headParams;
|
||||||
params.modelRotation = getRotation();
|
headParams.modelRotation = getRotation();
|
||||||
params.modelTranslation = getTranslation();
|
headParams.modelTranslation = getTranslation();
|
||||||
params.enableLean = qApp->getAvatarUpdater()->isHMDMode() && !myAvatar->getStandingHMDSensorMode();
|
headParams.enableLean = qApp->getAvatarUpdater()->isHMDMode() && !myAvatar->getStandingHMDSensorMode();
|
||||||
params.leanSideways = head->getFinalLeanSideways();
|
headParams.leanSideways = head->getFinalLeanSideways();
|
||||||
params.leanForward = head->getFinalLeanForward();
|
headParams.leanForward = head->getFinalLeanForward();
|
||||||
params.torsoTwist = head->getTorsoTwist();
|
headParams.torsoTwist = head->getTorsoTwist();
|
||||||
params.localHeadOrientation = head->getFinalOrientationInLocalFrame();
|
headParams.localHeadOrientation = head->getFinalOrientationInLocalFrame();
|
||||||
params.localHeadPitch = head->getFinalPitch();
|
headParams.localHeadPitch = head->getFinalPitch();
|
||||||
params.localHeadYaw = head->getFinalYaw();
|
headParams.localHeadYaw = head->getFinalYaw();
|
||||||
params.localHeadRoll = head->getFinalRoll();
|
headParams.localHeadRoll = head->getFinalRoll();
|
||||||
params.isInHMD = qApp->getAvatarUpdater()->isHMDMode();
|
headParams.isInHMD = qApp->getAvatarUpdater()->isHMDMode();
|
||||||
|
|
||||||
// get HMD position from sensor space into world space, and back into model space
|
// get HMD position from sensor space into world space, and back into model space
|
||||||
glm::mat4 worldToModel = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()));
|
glm::mat4 worldToModel = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()));
|
||||||
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||||
glm::vec3 hmdPosition = glm::angleAxis((float)M_PI, yAxis) * transformPoint(worldToModel * myAvatar->getSensorToWorldMatrix(), myAvatar->getHMDSensorPosition());
|
glm::vec3 hmdPosition = glm::angleAxis((float)M_PI, yAxis) * transformPoint(worldToModel * myAvatar->getSensorToWorldMatrix(), myAvatar->getHMDSensorPosition());
|
||||||
params.localHeadPosition = hmdPosition;
|
headParams.localHeadPosition = hmdPosition;
|
||||||
|
|
||||||
params.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
|
headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
|
||||||
params.eyeLookAt = head->getLookAtPosition();
|
headParams.eyeLookAt = head->getLookAtPosition();
|
||||||
params.eyeSaccade = head->getSaccade();
|
headParams.eyeSaccade = head->getSaccade();
|
||||||
params.leanJointIndex = geometry.leanJointIndex;
|
headParams.leanJointIndex = geometry.leanJointIndex;
|
||||||
params.neckJointIndex = geometry.neckJointIndex;
|
headParams.neckJointIndex = geometry.neckJointIndex;
|
||||||
params.leftEyeJointIndex = geometry.leftEyeJointIndex;
|
headParams.leftEyeJointIndex = geometry.leftEyeJointIndex;
|
||||||
params.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
headParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||||
|
|
||||||
|
_rig->updateFromHeadParameters(headParams, deltaTime);
|
||||||
|
|
||||||
|
Rig::HandParameters handParams;
|
||||||
|
|
||||||
|
const PalmData* leftPalm = getPalmWithIndex(myAvatar->getHand(), LEFT_HAND_INDEX);
|
||||||
|
if (leftPalm && leftPalm->isActive()) {
|
||||||
|
handParams.isLeftEnabled = true;
|
||||||
|
handParams.leftPosition = leftPalm->getRawPosition();
|
||||||
|
handParams.leftOrientation = leftPalm->getRawRotation();
|
||||||
|
handParams.leftTrigger = leftPalm->getTrigger();
|
||||||
|
} else {
|
||||||
|
handParams.isLeftEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PalmData* rightPalm = getPalmWithIndex(myAvatar->getHand(), RIGHT_HAND_INDEX);
|
||||||
|
if (rightPalm && rightPalm->isActive()) {
|
||||||
|
handParams.isRightEnabled = true;
|
||||||
|
handParams.rightPosition = rightPalm->getRawPosition();
|
||||||
|
handParams.rightOrientation = rightPalm->getRawRotation();
|
||||||
|
handParams.rightTrigger = rightPalm->getTrigger();
|
||||||
|
} else {
|
||||||
|
handParams.isRightEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rig->updateFromHandParameters(handParams, deltaTime);
|
||||||
|
|
||||||
_rig->updateFromHeadParameters(params);
|
|
||||||
} else {
|
} else {
|
||||||
// This is a little more work than we really want.
|
// This is a little more work than we really want.
|
||||||
//
|
//
|
||||||
|
|
|
@ -172,7 +172,12 @@ static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUr
|
||||||
qCCritical(animation) << "AnimNodeLoader, bad object in \"children\", id =" << id << ", url =" << jsonUrl.toDisplayString();
|
qCCritical(animation) << "AnimNodeLoader, bad object in \"children\", id =" << id << ", url =" << jsonUrl.toDisplayString();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
node->addChild(loadNode(childValue.toObject(), jsonUrl));
|
AnimNode::Pointer child = loadNode(childValue.toObject(), jsonUrl);
|
||||||
|
if (child) {
|
||||||
|
node->addChild(child);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((animNodeTypeToProcessFunc(type))(node, dataObj, id, jsonUrl)) {
|
if ((animNodeTypeToProcessFunc(type))(node, dataObj, id, jsonUrl)) {
|
||||||
|
@ -232,13 +237,15 @@ static const char* boneSetStrings[AnimOverlay::NumBoneSets] = {
|
||||||
"fullBody",
|
"fullBody",
|
||||||
"upperBody",
|
"upperBody",
|
||||||
"lowerBody",
|
"lowerBody",
|
||||||
"rightArm",
|
|
||||||
"leftArm",
|
"leftArm",
|
||||||
|
"rightArm",
|
||||||
"aboveTheHead",
|
"aboveTheHead",
|
||||||
"belowTheHead",
|
"belowTheHead",
|
||||||
"headOnly",
|
"headOnly",
|
||||||
"spineOnly",
|
"spineOnly",
|
||||||
"empty"
|
"empty",
|
||||||
|
"leftHand",
|
||||||
|
"rightHand"
|
||||||
};
|
};
|
||||||
|
|
||||||
static AnimOverlay::BoneSet stringToBoneSetEnum(const QString& str) {
|
static AnimOverlay::BoneSet stringToBoneSetEnum(const QString& str) {
|
||||||
|
|
|
@ -26,12 +26,14 @@ void AnimOverlay::buildBoneSet(BoneSet boneSet) {
|
||||||
case FullBodyBoneSet: buildFullBodyBoneSet(); break;
|
case FullBodyBoneSet: buildFullBodyBoneSet(); break;
|
||||||
case UpperBodyBoneSet: buildUpperBodyBoneSet(); break;
|
case UpperBodyBoneSet: buildUpperBodyBoneSet(); break;
|
||||||
case LowerBodyBoneSet: buildLowerBodyBoneSet(); break;
|
case LowerBodyBoneSet: buildLowerBodyBoneSet(); break;
|
||||||
case RightArmBoneSet: buildRightArmBoneSet(); break;
|
|
||||||
case LeftArmBoneSet: buildLeftArmBoneSet(); break;
|
case LeftArmBoneSet: buildLeftArmBoneSet(); break;
|
||||||
|
case RightArmBoneSet: buildRightArmBoneSet(); break;
|
||||||
case AboveTheHeadBoneSet: buildAboveTheHeadBoneSet(); break;
|
case AboveTheHeadBoneSet: buildAboveTheHeadBoneSet(); break;
|
||||||
case BelowTheHeadBoneSet: buildBelowTheHeadBoneSet(); break;
|
case BelowTheHeadBoneSet: buildBelowTheHeadBoneSet(); break;
|
||||||
case HeadOnlyBoneSet: buildHeadOnlyBoneSet(); break;
|
case HeadOnlyBoneSet: buildHeadOnlyBoneSet(); break;
|
||||||
case SpineOnlyBoneSet: buildSpineOnlyBoneSet(); break;
|
case SpineOnlyBoneSet: buildSpineOnlyBoneSet(); break;
|
||||||
|
case LeftHandBoneSet: buildLeftHandBoneSet(); break;
|
||||||
|
case RightHandBoneSet: buildRightHandBoneSet(); break;
|
||||||
default:
|
default:
|
||||||
case EmptyBoneSet: buildEmptyBoneSet(); break;
|
case EmptyBoneSet: buildEmptyBoneSet(); break;
|
||||||
}
|
}
|
||||||
|
@ -110,15 +112,6 @@ void AnimOverlay::buildLowerBodyBoneSet() {
|
||||||
_boneSetVec[hipsJoint] = 0.0f;
|
_boneSetVec[hipsJoint] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimOverlay::buildRightArmBoneSet() {
|
|
||||||
assert(_skeleton);
|
|
||||||
buildEmptyBoneSet();
|
|
||||||
int rightShoulderJoint = _skeleton->nameToJointIndex("RightShoulder");
|
|
||||||
for_each_child_joint(_skeleton, rightShoulderJoint, [&](int i) {
|
|
||||||
_boneSetVec[i] = 1.0f;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimOverlay::buildLeftArmBoneSet() {
|
void AnimOverlay::buildLeftArmBoneSet() {
|
||||||
assert(_skeleton);
|
assert(_skeleton);
|
||||||
buildEmptyBoneSet();
|
buildEmptyBoneSet();
|
||||||
|
@ -128,6 +121,15 @@ void AnimOverlay::buildLeftArmBoneSet() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimOverlay::buildRightArmBoneSet() {
|
||||||
|
assert(_skeleton);
|
||||||
|
buildEmptyBoneSet();
|
||||||
|
int rightShoulderJoint = _skeleton->nameToJointIndex("RightShoulder");
|
||||||
|
for_each_child_joint(_skeleton, rightShoulderJoint, [&](int i) {
|
||||||
|
_boneSetVec[i] = 1.0f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void AnimOverlay::buildAboveTheHeadBoneSet() {
|
void AnimOverlay::buildAboveTheHeadBoneSet() {
|
||||||
assert(_skeleton);
|
assert(_skeleton);
|
||||||
buildEmptyBoneSet();
|
buildEmptyBoneSet();
|
||||||
|
@ -168,13 +170,31 @@ void AnimOverlay::buildEmptyBoneSet() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimOverlay::buildLeftHandBoneSet() {
|
||||||
|
assert(_skeleton);
|
||||||
|
buildEmptyBoneSet();
|
||||||
|
int headJoint = _skeleton->nameToJointIndex("LeftHand");
|
||||||
|
for_each_child_joint(_skeleton, headJoint, [&](int i) {
|
||||||
|
_boneSetVec[i] = 1.0f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimOverlay::buildRightHandBoneSet() {
|
||||||
|
assert(_skeleton);
|
||||||
|
buildEmptyBoneSet();
|
||||||
|
int headJoint = _skeleton->nameToJointIndex("RightHand");
|
||||||
|
for_each_child_joint(_skeleton, headJoint, [&](int i) {
|
||||||
|
_boneSetVec[i] = 1.0f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// for AnimDebugDraw rendering
|
// for AnimDebugDraw rendering
|
||||||
const AnimPoseVec& AnimOverlay::getPosesInternal() const {
|
const AnimPoseVec& AnimOverlay::getPosesInternal() const {
|
||||||
return _poses;
|
return _poses;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimOverlay::setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) {
|
void AnimOverlay::setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) {
|
||||||
_skeleton = skeleton;
|
AnimNode::setSkeletonInternal(skeleton);
|
||||||
|
|
||||||
// we have to re-build the bone set when the skeleton changes.
|
// we have to re-build the bone set when the skeleton changes.
|
||||||
buildBoneSet(_boneSet);
|
buildBoneSet(_boneSet);
|
||||||
|
|
|
@ -28,14 +28,16 @@ public:
|
||||||
FullBodyBoneSet = 0,
|
FullBodyBoneSet = 0,
|
||||||
UpperBodyBoneSet,
|
UpperBodyBoneSet,
|
||||||
LowerBodyBoneSet,
|
LowerBodyBoneSet,
|
||||||
RightArmBoneSet,
|
|
||||||
LeftArmBoneSet,
|
LeftArmBoneSet,
|
||||||
|
RightArmBoneSet,
|
||||||
AboveTheHeadBoneSet,
|
AboveTheHeadBoneSet,
|
||||||
BelowTheHeadBoneSet,
|
BelowTheHeadBoneSet,
|
||||||
HeadOnlyBoneSet,
|
HeadOnlyBoneSet,
|
||||||
SpineOnlyBoneSet,
|
SpineOnlyBoneSet,
|
||||||
EmptyBoneSet,
|
EmptyBoneSet,
|
||||||
NumBoneSets,
|
LeftHandBoneSet,
|
||||||
|
RightHandBoneSet,
|
||||||
|
NumBoneSets
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimOverlay(const std::string& id, BoneSet boneSet, float alpha);
|
AnimOverlay(const std::string& id, BoneSet boneSet, float alpha);
|
||||||
|
@ -64,13 +66,15 @@ public:
|
||||||
void buildFullBodyBoneSet();
|
void buildFullBodyBoneSet();
|
||||||
void buildUpperBodyBoneSet();
|
void buildUpperBodyBoneSet();
|
||||||
void buildLowerBodyBoneSet();
|
void buildLowerBodyBoneSet();
|
||||||
void buildRightArmBoneSet();
|
|
||||||
void buildLeftArmBoneSet();
|
void buildLeftArmBoneSet();
|
||||||
|
void buildRightArmBoneSet();
|
||||||
void buildAboveTheHeadBoneSet();
|
void buildAboveTheHeadBoneSet();
|
||||||
void buildBelowTheHeadBoneSet();
|
void buildBelowTheHeadBoneSet();
|
||||||
void buildHeadOnlyBoneSet();
|
void buildHeadOnlyBoneSet();
|
||||||
void buildSpineOnlyBoneSet();
|
void buildSpineOnlyBoneSet();
|
||||||
void buildEmptyBoneSet();
|
void buildEmptyBoneSet();
|
||||||
|
void buildLeftHandBoneSet();
|
||||||
|
void buildRightHandBoneSet();
|
||||||
|
|
||||||
// no copies
|
// no copies
|
||||||
AnimOverlay(const AnimOverlay&) = delete;
|
AnimOverlay(const AnimOverlay&) = delete;
|
||||||
|
|
|
@ -952,7 +952,7 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
||||||
return _jointStates[jointIndex].getDefaultRotationInParentFrame();
|
return _jointStates[jointIndex].getDefaultRotationInParentFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::updateFromHeadParameters(const HeadParameters& params) {
|
void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) {
|
||||||
if (params.enableLean) {
|
if (params.enableLean) {
|
||||||
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
|
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
|
||||||
}
|
}
|
||||||
|
@ -1048,6 +1048,52 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Rig::updateFromHandParameters(const HandParameters& params, float dt) {
|
||||||
|
|
||||||
|
if (_enableAnimGraph && _animSkeleton) {
|
||||||
|
|
||||||
|
// set leftHand grab vars
|
||||||
|
_animVars.set("isLeftHandIdle", false);
|
||||||
|
_animVars.set("isLeftHandPoint", false);
|
||||||
|
_animVars.set("isLeftHandGrab", false);
|
||||||
|
|
||||||
|
// Split the trigger range into three zones.
|
||||||
|
bool rampOut = false;
|
||||||
|
if (params.leftTrigger > 0.6666f) {
|
||||||
|
_animVars.set("isLeftHandGrab", true);
|
||||||
|
} else if (params.leftTrigger > 0.3333f) {
|
||||||
|
_animVars.set("isLeftHandPoint", true);
|
||||||
|
} else {
|
||||||
|
_animVars.set("isLeftHandIdle", true);
|
||||||
|
rampOut = true;
|
||||||
|
}
|
||||||
|
const float OVERLAY_RAMP_OUT_SPEED = 6.0f; // ramp in and out over 1/6th of a sec
|
||||||
|
_leftHandOverlayAlpha = glm::clamp(_leftHandOverlayAlpha + (rampOut ? -1.0f : 1.0f) * OVERLAY_RAMP_OUT_SPEED * dt, 0.0f, 1.0f);
|
||||||
|
_animVars.set("leftHandOverlayAlpha", _leftHandOverlayAlpha);
|
||||||
|
_animVars.set("leftHandGrabBlend", params.leftTrigger);
|
||||||
|
|
||||||
|
|
||||||
|
// set leftHand grab vars
|
||||||
|
_animVars.set("isRightHandIdle", false);
|
||||||
|
_animVars.set("isRightHandPoint", false);
|
||||||
|
_animVars.set("isRightHandGrab", false);
|
||||||
|
|
||||||
|
// Split the trigger range into three zones
|
||||||
|
rampOut = false;
|
||||||
|
if (params.rightTrigger > 0.6666f) {
|
||||||
|
_animVars.set("isRightHandGrab", true);
|
||||||
|
} else if (params.rightTrigger > 0.3333f) {
|
||||||
|
_animVars.set("isRightHandPoint", true);
|
||||||
|
} else {
|
||||||
|
_animVars.set("isRightHandIdle", true);
|
||||||
|
rampOut = true;
|
||||||
|
}
|
||||||
|
_rightHandOverlayAlpha = glm::clamp(_rightHandOverlayAlpha + (rampOut ? -1.0f : 1.0f) * OVERLAY_RAMP_OUT_SPEED * dt, 0.0f, 1.0f);
|
||||||
|
_animVars.set("rightHandOverlayAlpha", _rightHandOverlayAlpha);
|
||||||
|
_animVars.set("rightHandGrabBlend", params.rightTrigger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Rig::initAnimGraph(const QUrl& url, const FBXGeometry& fbxGeometry) {
|
void Rig::initAnimGraph(const QUrl& url, const FBXGeometry& fbxGeometry) {
|
||||||
if (!_enableAnimGraph) {
|
if (!_enableAnimGraph) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -76,6 +76,17 @@ public:
|
||||||
void dump() const;
|
void dump() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct HandParameters {
|
||||||
|
bool isLeftEnabled;
|
||||||
|
bool isRightEnabled;
|
||||||
|
glm::vec3 leftPosition = glm::vec3();
|
||||||
|
glm::quat leftOrientation = glm::quat();
|
||||||
|
glm::vec3 rightPosition = glm::vec3();
|
||||||
|
glm::quat rightOrientation = glm::quat();
|
||||||
|
float leftTrigger = 0.0f;
|
||||||
|
float rightTrigger = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~Rig() {}
|
virtual ~Rig() {}
|
||||||
|
|
||||||
RigPointer getRigPointer() { return shared_from_this(); }
|
RigPointer getRigPointer() { return shared_from_this(); }
|
||||||
|
@ -168,10 +179,12 @@ public:
|
||||||
void setEnableAnimGraph(bool isEnabled) { _enableAnimGraph = isEnabled; }
|
void setEnableAnimGraph(bool isEnabled) { _enableAnimGraph = isEnabled; }
|
||||||
bool getEnableAnimGraph() const { return _enableAnimGraph; }
|
bool getEnableAnimGraph() const { return _enableAnimGraph; }
|
||||||
|
|
||||||
void updateFromHeadParameters(const HeadParameters& params);
|
void updateFromHeadParameters(const HeadParameters& params, float dt);
|
||||||
void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation,
|
void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation,
|
||||||
const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade = glm::vec3(0.0f));
|
const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade = glm::vec3(0.0f));
|
||||||
|
|
||||||
|
void updateFromHandParameters(const HandParameters& params, float dt);
|
||||||
|
|
||||||
virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
||||||
float scale, float priority) = 0;
|
float scale, float priority) = 0;
|
||||||
|
|
||||||
|
@ -215,6 +228,8 @@ public:
|
||||||
Move
|
Move
|
||||||
};
|
};
|
||||||
RigRole _state = RigRole::Idle;
|
RigRole _state = RigRole::Idle;
|
||||||
|
float _leftHandOverlayAlpha = 0.0f;
|
||||||
|
float _rightHandOverlayAlpha = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__Rig__) */
|
#endif /* defined(__hifi__Rig__) */
|
||||||
|
|
|
@ -52,190 +52,426 @@
|
||||||
"children": []
|
"children": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "mainStateMachine",
|
"id": "rightHandOverlay",
|
||||||
"type": "stateMachine",
|
"type": "overlay",
|
||||||
"data": {
|
"data": {
|
||||||
"currentState": "idle",
|
"alpha": 1.0,
|
||||||
"states": [
|
"boneSet": "rightHand",
|
||||||
{
|
"alphaVar": "rightHandOverlayAlpha"
|
||||||
"id": "idle",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
|
||||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
|
||||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "walkFwd",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isNotMoving", "state": "idle" },
|
|
||||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
|
||||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "walkBwd",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isNotMoving", "state": "idle" },
|
|
||||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
|
||||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "strafeRight",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isNotMoving", "state": "idle" },
|
|
||||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
|
||||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "strafeLeft",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isNotMoving", "state": "idle" },
|
|
||||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
|
||||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
|
||||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
|
||||||
{ "var": "isTurningRight", "state": "turnRight" },
|
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "turnRight",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isNotTurning", "state": "idle" },
|
|
||||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
|
||||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
|
||||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
|
||||||
{ "var": "isTurningLeft", "state": "turnLeft" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "turnLeft",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "isNotTurning", "state": "idle" },
|
|
||||||
{ "var": "isMovingForward", "state": "walkFwd" },
|
|
||||||
{ "var": "isMovingBackward", "state": "walkBwd" },
|
|
||||||
{ "var": "isMovingRight", "state": "strafeRight" },
|
|
||||||
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
|
||||||
{ "var": "isTurningRight", "state": "turnRight" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "idle",
|
"id": "rightHandStateMachine",
|
||||||
"type": "clip",
|
"type": "stateMachine",
|
||||||
"data": {
|
"data": {
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx",
|
"currentState": "rightHandIdle",
|
||||||
"startFrame": 0.0,
|
"states": [
|
||||||
"endFrame": 90.0,
|
{
|
||||||
"timeScale": 1.0,
|
"id": "rightHandIdle",
|
||||||
"loopFlag": true
|
"interpTarget": 3,
|
||||||
|
"interpDuration": 3,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isRightHandPoint", "state": "rightHandPointIntro" },
|
||||||
|
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandPointIntro",
|
||||||
|
"interpTarget": 3,
|
||||||
|
"interpDuration": 3,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isRightHandIdle", "state": "rightHandIdle" },
|
||||||
|
{ "var": "isRightHandPointIntroOnDone", "state": "rightHandPointHold" },
|
||||||
|
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandPointHold",
|
||||||
|
"interpTarget": 3,
|
||||||
|
"interpDuration": 3,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isRightHandIdle", "state": "rightHandPointOutro" },
|
||||||
|
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandPointOutro",
|
||||||
|
"interpTarget": 3,
|
||||||
|
"interpDuration": 3,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isRightHandPointOutroOnDone", "state": "rightHandIdle" },
|
||||||
|
{ "var": "isRightHandGrab", "state": "rightHandGrab" },
|
||||||
|
{ "var": "isRightHandPoint", "state": "rightHandPointHold" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandGrab",
|
||||||
|
"interpTarget": 3,
|
||||||
|
"interpDuration": 3,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isRightHandIdle", "state": "rightHandIdle" },
|
||||||
|
{ "var": "isRightHandPoint_DISABLED", "state": "rightHandPointHold" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"children": []
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "rightHandIdle",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 0.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandPointHold",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||||
|
"startFrame": 12.0,
|
||||||
|
"endFrame": 12.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandPointIntro",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 12.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandPointOutro",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 65.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandGrab",
|
||||||
|
"type": "blendLinear",
|
||||||
|
"data": {
|
||||||
|
"alpha": 0.0,
|
||||||
|
"alphaVar": "rightHandGrabBlend"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "rightHandOpen",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/right_hand_point.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 0.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rightHandClose",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
|
||||||
|
"startFrame": 15.0,
|
||||||
|
"endFrame": 15.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "walkFwd",
|
"id": "leftHandOverlay",
|
||||||
"type": "clip",
|
"type": "overlay",
|
||||||
"data": {
|
"data": {
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx",
|
"alpha": 1.0,
|
||||||
"startFrame": 0.0,
|
"boneSet": "leftHand",
|
||||||
"endFrame": 35.0,
|
"alphaVar" : "leftHandOverlay"
|
||||||
"timeScale": 1.0,
|
|
||||||
"loopFlag": true,
|
|
||||||
"timeScaleVar": "walkTimeScale"
|
|
||||||
},
|
},
|
||||||
"children": []
|
"children": [
|
||||||
},
|
{
|
||||||
{
|
"id": "leftHandStateMachine",
|
||||||
"id": "walkBwd",
|
"type": "stateMachine",
|
||||||
"type": "clip",
|
"data": {
|
||||||
"data": {
|
"currentState": "leftHandIdle",
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx",
|
"states": [
|
||||||
"startFrame": 0.0,
|
{
|
||||||
"endFrame": 37.0,
|
"id": "leftHandIdle",
|
||||||
"timeScale": 1.0,
|
"interpTarget": 6,
|
||||||
"loopFlag": true,
|
"interpDuration": 6,
|
||||||
"timeScaleVar": "walkTimeScale"
|
"transitions": [
|
||||||
},
|
{ "var": "isLeftHandPoint", "state": "leftHandPoint" },
|
||||||
"children": []
|
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"id": "turnLeft",
|
{
|
||||||
"type": "clip",
|
"id": "leftHandPoint",
|
||||||
"data": {
|
"interpTarget": 6,
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx",
|
"interpDuration": 6,
|
||||||
"startFrame": 0.0,
|
"transitions": [
|
||||||
"endFrame": 28.0,
|
{ "var": "isLeftHandIdle", "state": "leftHandIdle" },
|
||||||
"timeScale": 1.0,
|
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
|
||||||
"loopFlag": true
|
]
|
||||||
},
|
},
|
||||||
"children": []
|
{
|
||||||
},
|
"id": "leftHandGrab",
|
||||||
{
|
"interpTarget": 6,
|
||||||
"id": "turnRight",
|
"interpDuration": 6,
|
||||||
"type": "clip",
|
"transitions": [
|
||||||
"data": {
|
{ "var": "isLeftHandIdle", "state": "leftHandIdle" },
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx",
|
{ "var": "isLeftHandPoint", "state": "leftHandPoint" }
|
||||||
"startFrame": 0.0,
|
]
|
||||||
"endFrame": 30.0,
|
}
|
||||||
"timeScale": 1.0,
|
]
|
||||||
"loopFlag": true
|
},
|
||||||
},
|
"children": [
|
||||||
"children": []
|
{
|
||||||
},
|
"id": "leftHandIdle",
|
||||||
{
|
"type": "clip",
|
||||||
"id": "strafeLeft",
|
"data": {
|
||||||
"type": "clip",
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx",
|
||||||
"data": {
|
"startFrame": 30.0,
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_left.fbx",
|
"endFrame": 30.0,
|
||||||
"startFrame": 0.0,
|
"timeScale": 1.0,
|
||||||
"endFrame": 31.0,
|
"loopFlag": true
|
||||||
"timeScale": 1.0,
|
},
|
||||||
"loopFlag": true
|
"children": []
|
||||||
},
|
},
|
||||||
"children": []
|
{
|
||||||
},
|
"id": "leftHandPoint",
|
||||||
{
|
"type": "clip",
|
||||||
"id": "strafeRight",
|
"data": {
|
||||||
"type": "clip",
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx",
|
||||||
"data": {
|
"startFrame": 0.0,
|
||||||
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_right.fbx",
|
"endFrame": 0.0,
|
||||||
"startFrame": 0.0,
|
"timeScale": 1.0,
|
||||||
"endFrame": 31.0,
|
"loopFlag": true
|
||||||
"timeScale": 1.0,
|
},
|
||||||
"loopFlag": true
|
"children": []
|
||||||
},
|
},
|
||||||
"children": []
|
{
|
||||||
|
"id": "leftHandGrab",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx",
|
||||||
|
"startFrame": 15.0,
|
||||||
|
"endFrame": 15.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mainStateMachine",
|
||||||
|
"type": "stateMachine",
|
||||||
|
"data": {
|
||||||
|
"currentState": "idle",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"id": "idle",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||||
|
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||||
|
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||||
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
|
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "walkFwd",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isNotMoving", "state": "idle" },
|
||||||
|
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||||
|
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||||
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
|
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "walkBwd",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isNotMoving", "state": "idle" },
|
||||||
|
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||||
|
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||||
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
|
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "strafeRight",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isNotMoving", "state": "idle" },
|
||||||
|
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||||
|
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||||
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
|
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "strafeLeft",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isNotMoving", "state": "idle" },
|
||||||
|
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||||
|
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||||
|
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||||
|
{ "var": "isTurningRight", "state": "turnRight" },
|
||||||
|
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "turnRight",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isNotTurning", "state": "idle" },
|
||||||
|
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||||
|
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||||
|
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||||
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
|
{ "var": "isTurningLeft", "state": "turnLeft" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "turnLeft",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "isNotTurning", "state": "idle" },
|
||||||
|
{ "var": "isMovingForward", "state": "walkFwd" },
|
||||||
|
{ "var": "isMovingBackward", "state": "walkBwd" },
|
||||||
|
{ "var": "isMovingRight", "state": "strafeRight" },
|
||||||
|
{ "var": "isMovingLeft", "state": "strafeLeft" },
|
||||||
|
{ "var": "isTurningRight", "state": "turnRight" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "idle",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "walkFwd",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 35.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true,
|
||||||
|
"timeScaleVar": "walkTimeScale"
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "walkBwd",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 37.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true,
|
||||||
|
"timeScaleVar": "walkTimeScale"
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "turnLeft",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 28.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "turnRight",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 30.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "strafeLeft",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_left.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 31.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "strafeRight",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_right.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 31.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue