mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 16:41:02 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
97dd90507b
16 changed files with 277 additions and 180 deletions
|
@ -20,21 +20,21 @@ var jointMappings = "\n# Joint list start";
|
||||||
for (var i = 0; i < jointList.length; i++) {
|
for (var i = 0; i < jointList.length; i++) {
|
||||||
jointMappings = jointMappings + "\njointIndex = " + jointList[i] + " = " + i;
|
jointMappings = jointMappings + "\njointIndex = " + jointList[i] + " = " + i;
|
||||||
}
|
}
|
||||||
print(jointMappings + "\n# Joint list end");
|
print(jointMappings + "\n# Joint list end");
|
||||||
|
|
||||||
Script.update.connect(function(deltaTime) {
|
Script.update.connect(function(deltaTime) {
|
||||||
cumulativeTime += deltaTime;
|
cumulativeTime += deltaTime;
|
||||||
MyAvatar.setJointData("joint_R_hip", Quat.fromPitchYawRollDegrees(0.0, 0.0, AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
|
MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees(AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY), 0.0, 0.0));
|
||||||
MyAvatar.setJointData("joint_L_hip", Quat.fromPitchYawRollDegrees(0.0, 0.0, -AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
|
MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees(-AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY), 0.0, 0.0));
|
||||||
MyAvatar.setJointData("joint_R_knee", Quat.fromPitchYawRollDegrees(0.0, 0.0,
|
MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees(
|
||||||
AMPLITUDE * (1.0 + Math.sin(cumulativeTime * FREQUENCY))));
|
AMPLITUDE * (1.0 + Math.sin(cumulativeTime * FREQUENCY)),0.0, 0.0));
|
||||||
MyAvatar.setJointData("joint_L_knee", Quat.fromPitchYawRollDegrees(0.0, 0.0,
|
MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees(
|
||||||
AMPLITUDE * (1.0 - Math.sin(cumulativeTime * FREQUENCY))));
|
AMPLITUDE * (1.0 - Math.sin(cumulativeTime * FREQUENCY)),0.0, 0.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
MyAvatar.clearJointData("joint_R_hip");
|
MyAvatar.clearJointData("RightUpLeg");
|
||||||
MyAvatar.clearJointData("joint_L_hip");
|
MyAvatar.clearJointData("LeftUpLeg");
|
||||||
MyAvatar.clearJointData("joint_R_knee");
|
MyAvatar.clearJointData("RightLeg");
|
||||||
MyAvatar.clearJointData("joint_L_knee");
|
MyAvatar.clearJointData("LeftLeg");
|
||||||
});
|
});
|
||||||
|
|
49
examples/squeezeHands.js
Normal file
49
examples/squeezeHands.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// squeezeHands.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on June 4, 2014
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var rightHandAnimation = "https://s3-us-west-1.amazonaws.com/highfidelity-public/animations/HandAnim.fbx";
|
||||||
|
var leftHandAnimation = "";
|
||||||
|
|
||||||
|
var LEFT = 0;
|
||||||
|
var RIGHT = 1;
|
||||||
|
|
||||||
|
var lastLeftFrame = 0;
|
||||||
|
var lastRightFrame = 0;
|
||||||
|
|
||||||
|
var LAST_FRAME = 15.0; // What is the number of the last frame we want to use in the animation?
|
||||||
|
|
||||||
|
Script.update.connect(function(deltaTime) {
|
||||||
|
var leftTriggerValue = Controller.getTriggerValue(LEFT);
|
||||||
|
var rightTriggerValue = Controller.getTriggerValue(RIGHT);
|
||||||
|
|
||||||
|
var leftFrame, rightFrame;
|
||||||
|
|
||||||
|
// Average last two trigger frames together for a bit of smoothing
|
||||||
|
leftFrame = (leftTriggerValue * LAST_FRAME) * 0.5 + lastLeftFrame * 0.5;
|
||||||
|
rightFrame = (rightTriggerValue * LAST_FRAME) * 0.5 + lastRightFrame * 0.5;
|
||||||
|
|
||||||
|
if ((leftFrame != lastLeftFrame) && leftHandAnimation.length){
|
||||||
|
MyAvatar.stopAnimation(leftHandAnimation);
|
||||||
|
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
|
||||||
|
}
|
||||||
|
if ((rightFrame != lastRightFrame) && rightHandAnimation.length) {
|
||||||
|
MyAvatar.stopAnimation(rightHandAnimation);
|
||||||
|
MyAvatar.startAnimation(rightHandAnimation, 30.0, 1.0, false, true, rightFrame, rightFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastLeftFrame = leftFrame;
|
||||||
|
lastRightFrame = rightFrame;
|
||||||
|
});
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
MyAvatar.stopAnimation(leftHandAnimation);
|
||||||
|
MyAvatar.stopAnimation(rightHandAnimation);
|
||||||
|
});
|
|
@ -1848,7 +1848,8 @@ void Application::updateMyAvatarLookAtPosition() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// I am not looking at anyone else, so just look forward
|
// I am not looking at anyone else, so just look forward
|
||||||
lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() + (_myAvatar->getHead()->getFinalOrientation() * glm::vec3(0.f, 0.f, -TREE_SCALE));
|
lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() +
|
||||||
|
(_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.f, 0.f, -TREE_SCALE));
|
||||||
}
|
}
|
||||||
// TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it)
|
// TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it)
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -603,7 +603,7 @@ void Audio::handleAudioInput() {
|
||||||
if (audioMixer && audioMixer->getActiveSocket()) {
|
if (audioMixer && audioMixer->getActiveSocket()) {
|
||||||
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
|
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
|
||||||
glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition();
|
glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition();
|
||||||
glm::quat headOrientation = interfaceAvatar->getHead()->getFinalOrientation();
|
glm::quat headOrientation = interfaceAvatar->getHead()->getFinalOrientationInWorldFrame();
|
||||||
|
|
||||||
// we need the amount of bytes in the buffer + 1 for type
|
// we need the amount of bytes in the buffer + 1 for type
|
||||||
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
|
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
|
||||||
|
|
|
@ -459,7 +459,7 @@ void AudioReflector::calculateAllReflections() {
|
||||||
// only recalculate when we've moved, or if the attributes have changed
|
// only recalculate when we've moved, or if the attributes have changed
|
||||||
// TODO: what about case where new voxels are added in front of us???
|
// TODO: what about case where new voxels are added in front of us???
|
||||||
bool wantHeadOrientation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented);
|
bool wantHeadOrientation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented);
|
||||||
glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientation() : _myAvatar->getOrientation();
|
glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientationInWorldFrame() : _myAvatar->getOrientation();
|
||||||
glm::vec3 origin = _myAvatar->getHead()->getPosition();
|
glm::vec3 origin = _myAvatar->getHead()->getPosition();
|
||||||
glm::vec3 listenerPosition = _myAvatar->getHead()->getPosition();
|
glm::vec3 listenerPosition = _myAvatar->getHead()->getPosition();
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ void Avatar::simulateAttachments(float deltaTime) {
|
||||||
if (!isMyAvatar()) {
|
if (!isMyAvatar()) {
|
||||||
model->setLODDistance(getLODDistance());
|
model->setLODDistance(getLODDistance());
|
||||||
}
|
}
|
||||||
if (_skeletonModel.getJointPosition(jointIndex, jointPosition) &&
|
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
||||||
_skeletonModel.getJointCombinedRotation(jointIndex, jointRotation)) {
|
_skeletonModel.getJointCombinedRotation(jointIndex, jointRotation)) {
|
||||||
model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale);
|
model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale);
|
||||||
model->setRotation(jointRotation * attachment.rotation);
|
model->setRotation(jointRotation * attachment.rotation);
|
||||||
|
@ -713,7 +713,7 @@ glm::vec3 Avatar::getJointPosition(int index) const {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
_skeletonModel.getJointPosition(index, position);
|
_skeletonModel.getJointPositionInWorldFrame(index, position);
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +725,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
_skeletonModel.getJointPosition(getJointIndex(name), position);
|
_skeletonModel.getJointPositionInWorldFrame(getJointIndex(name), position);
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,10 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
|
|
||||||
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||||
// get the rotation axes in joint space and use them to adjust the rotation
|
// get the rotation axes in joint space and use them to adjust the rotation
|
||||||
glm::mat3 axes = glm::mat3_cast(_rotation);
|
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
||||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
||||||
state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
|
state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
|
||||||
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1]))
|
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1]))
|
||||||
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0]))
|
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0]))
|
||||||
* joint.rotation;
|
* joint.rotation;
|
||||||
|
@ -59,14 +59,16 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
|
||||||
|
|
||||||
void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||||
// likewise with the eye joints
|
// likewise with the eye joints
|
||||||
glm::mat4 inverse = glm::inverse(parentState._transform * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
glm::mat4 inverse = glm::inverse(glm::mat4_cast(_rotation) * parentState.getTransform() *
|
||||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f));
|
glm::translate(state.getDefaultTranslationInParentFrame()) *
|
||||||
|
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||||
|
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f));
|
||||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
||||||
_owningHead->getSaccade() - _translation, 1.0f));
|
_owningHead->getSaccade() - _translation, 1.0f));
|
||||||
glm::quat between = rotationBetween(front, lookAt);
|
glm::quat between = rotationBetween(front, lookAt);
|
||||||
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
|
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
|
||||||
state._rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
state._rotationInParentFrame = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||||
joint.rotation;
|
joint.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +94,6 @@ bool FaceModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
|
return getJointPositionInWorldFrame(geometry.leftEyeJointIndex, firstEyePosition) &&
|
||||||
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
|
getJointPositionInWorldFrame(geometry.rightEyeJointIndex, secondEyePosition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,9 +188,12 @@ void Head::setScale (float scale) {
|
||||||
_scale = scale;
|
_scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Head::getFinalOrientation() const {
|
glm::quat Head::getFinalOrientationInWorldFrame() const {
|
||||||
return _owningAvatar->getOrientation() * glm::quat(glm::radians(
|
return _owningAvatar->getOrientation() * getFinalOrientationInLocalFrame();
|
||||||
glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() )));
|
}
|
||||||
|
|
||||||
|
glm::quat Head::getFinalOrientationInLocalFrame() const {
|
||||||
|
return glm::quat(glm::radians(glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() )));
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Head::getCameraOrientation () const {
|
glm::quat Head::getCameraOrientation () const {
|
||||||
|
|
|
@ -50,9 +50,13 @@ public:
|
||||||
void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; }
|
void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; }
|
||||||
void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; }
|
void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; }
|
||||||
void setLeanForward(float leanForward) { _leanForward = leanForward; }
|
void setLeanForward(float leanForward) { _leanForward = leanForward; }
|
||||||
|
|
||||||
|
/// \return orientationBase+Delta
|
||||||
|
glm::quat getFinalOrientationInLocalFrame() const;
|
||||||
|
|
||||||
/// \return orientationBody * orientationBase+Delta
|
/// \return orientationBody * (orientationBase+Delta)
|
||||||
glm::quat getFinalOrientation() const;
|
glm::quat getFinalOrientationInWorldFrame() const;
|
||||||
|
|
||||||
|
|
||||||
/// \return orientationBody * orientationBasePitch
|
/// \return orientationBody * orientationBasePitch
|
||||||
glm::quat getCameraOrientation () const;
|
glm::quat getCameraOrientation () const;
|
||||||
|
|
|
@ -236,7 +236,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
||||||
estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation()));
|
estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate the body if the head is turned beyond the screen
|
// Rotate the body if the head is turned beyond the screen
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) {
|
||||||
const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f;
|
const float TRACKER_YAW_TURN_SENSITIVITY = 0.5f;
|
||||||
|
@ -724,7 +724,8 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
||||||
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
||||||
avatar->setIsLookAtTarget(false);
|
avatar->setIsLookAtTarget(false);
|
||||||
if (!avatar->isMyAvatar()) {
|
if (!avatar->isMyAvatar()) {
|
||||||
float angleTo = glm::angle(getHead()->getFinalOrientation() * glm::vec3(0.0f, 0.0f, -1.0f),
|
glm::vec3 DEFAULT_GAZE_IN_HEAD_FRAME = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
float angleTo = glm::angle(getHead()->getFinalOrientationInWorldFrame() * DEFAULT_GAZE_IN_HEAD_FRAME,
|
||||||
glm::normalize(avatar->getHead()->getEyePosition() - getHead()->getEyePosition()));
|
glm::normalize(avatar->getHead()->getEyePosition() - getHead()->getEyePosition()));
|
||||||
if (angleTo < smallestAngleTo) {
|
if (angleTo < smallestAngleTo) {
|
||||||
_lookAtTargetAvatar = avatarPointer;
|
_lookAtTargetAvatar = avatarPointer;
|
||||||
|
|
|
@ -46,7 +46,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex);
|
int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex);
|
||||||
if (jointIndex != -1) {
|
if (jointIndex != -1) {
|
||||||
JointState& state = _jointStates[jointIndex];
|
JointState& state = _jointStates[jointIndex];
|
||||||
state.setRotation(_rotation * prioVR->getJointRotations().at(i), PALM_PRIORITY);
|
state.setRotationFromBindFrame(prioVR->getJointRotations().at(i), PALM_PRIORITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -63,7 +63,9 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
if (_owningAvatar->getHandState() == HAND_STATE_NULL) {
|
if (_owningAvatar->getHandState() == HAND_STATE_NULL) {
|
||||||
restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY);
|
restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY);
|
||||||
} else {
|
} else {
|
||||||
applyHandPosition(geometry.rightHandJointIndex, _owningAvatar->getHandPosition());
|
// transform into model-frame
|
||||||
|
glm::vec3 handPosition = glm::inverse(_rotation) * (_owningAvatar->getHandPosition() - _translation);
|
||||||
|
applyHandPosition(geometry.rightHandJointIndex, handPosition);
|
||||||
}
|
}
|
||||||
restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY);
|
restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY);
|
||||||
|
|
||||||
|
@ -135,6 +137,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position)
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// NOTE: 'position' is in model-frame
|
||||||
setJointPosition(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
setJointPosition(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
||||||
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
@ -147,7 +150,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JointState& state = _jointStates[jointIndex];
|
JointState& state = _jointStates[jointIndex];
|
||||||
glm::quat handRotation = state.getJointRotation(true);
|
glm::quat handRotation = state.getRotation();
|
||||||
|
|
||||||
// align hand with forearm
|
// align hand with forearm
|
||||||
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
|
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
|
||||||
|
@ -167,36 +170,41 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
||||||
|
|
||||||
// rotate palm to align with its normal (normal points out of hand's palm)
|
// rotate palm to align with its normal (normal points out of hand's palm)
|
||||||
glm::quat palmRotation;
|
glm::quat palmRotation;
|
||||||
|
glm::quat r0, r1;
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) &&
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK) &&
|
||||||
Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||||
JointState parentState = _jointStates[parentJointIndex];
|
JointState parentState = _jointStates[parentJointIndex];
|
||||||
palmRotation = parentState.getJointRotation(true);
|
palmRotation = parentState.getRotationFromBindToModelFrame();
|
||||||
|
r0 = palmRotation;
|
||||||
} else {
|
} else {
|
||||||
JointState state = _jointStates[jointIndex];
|
JointState state = _jointStates[jointIndex];
|
||||||
palmRotation = state.getJointRotation(true);
|
palmRotation = state.getRotationFromBindToModelFrame();
|
||||||
}
|
}
|
||||||
palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation;
|
glm::quat inverseRotation = glm::inverse(_rotation);
|
||||||
|
glm::vec3 palmNormal = inverseRotation * palm.getNormal();
|
||||||
|
palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palmNormal) * palmRotation;
|
||||||
|
r1 = palmRotation;
|
||||||
|
|
||||||
// rotate palm to align with finger direction
|
// rotate palm to align with finger direction
|
||||||
glm::vec3 direction = palm.getFingerDirection();
|
glm::vec3 direction = inverseRotation * palm.getFingerDirection();
|
||||||
palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation;
|
palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation;
|
||||||
|
|
||||||
// set hand position, rotation
|
// set hand position, rotation
|
||||||
|
glm::vec3 palmPosition = inverseRotation * (palm.getPosition() - _translation);
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) {
|
||||||
setHandPosition(jointIndex, palm.getPosition(), palmRotation);
|
setHandPosition(jointIndex, palmPosition, palmRotation);
|
||||||
|
|
||||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
} else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||||
glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f);
|
glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f);
|
||||||
setJointPosition(parentJointIndex, palm.getPosition() + forearmVector *
|
setJointPosition(parentJointIndex, palmPosition + forearmVector *
|
||||||
geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale),
|
geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale),
|
||||||
glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
||||||
JointState& parentState = _jointStates[parentJointIndex];
|
JointState& parentState = _jointStates[parentJointIndex];
|
||||||
parentState.setRotation(palmRotation, PALM_PRIORITY);
|
parentState.setRotationFromBindFrame(palmRotation, PALM_PRIORITY);
|
||||||
// slam parent-relative rotation to identity
|
// lock hand to forearm by slamming its rotation (in parent-frame) to identity
|
||||||
_jointStates[jointIndex]._rotation = glm::quat();
|
_jointStates[jointIndex]._rotationInParentFrame = glm::quat();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setJointPosition(jointIndex, palm.getPosition(), palmRotation,
|
setJointPosition(jointIndex, palmPosition, palmRotation,
|
||||||
true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,9 +229,7 @@ void SkeletonModel::updateJointState(int index) {
|
||||||
Model::updateJointState(index);
|
Model::updateJointState(index);
|
||||||
|
|
||||||
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
||||||
state._transform[3][0] = 0.0f;
|
state.clearTransformTranslation();
|
||||||
state._transform[3][1] = 0.0f;
|
|
||||||
state._transform[3][2] = 0.0f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,10 +238,10 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get the rotation axes in joint space and use them to adjust the rotation
|
// get the rotation axes in joint space and use them to adjust the rotation
|
||||||
glm::mat3 axes = glm::mat3_cast(_rotation);
|
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
||||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
|
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
|
||||||
state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
|
state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
|
||||||
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(),
|
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(),
|
||||||
glm::normalize(inverse * axes[0])) * joint.rotation;
|
glm::normalize(inverse * axes[0])) * joint.rotation;
|
||||||
}
|
}
|
||||||
|
@ -259,11 +265,11 @@ void SkeletonModel::renderJointConstraints(int jointIndex) {
|
||||||
do {
|
do {
|
||||||
const FBXJoint& joint = geometry.joints.at(jointIndex);
|
const FBXJoint& joint = geometry.joints.at(jointIndex);
|
||||||
const JointState& jointState = _jointStates.at(jointIndex);
|
const JointState& jointState = _jointStates.at(jointIndex);
|
||||||
glm::vec3 position = extractTranslation(jointState._transform) + _translation;
|
glm::vec3 position = _rotation * jointState.getPosition() + _translation;
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex)._combinedRotation;
|
glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _rotation * _jointStates.at(joint.parentIndex).getRotation();
|
||||||
glm::vec3 rotationAxis = glm::axis(parentRotation);
|
glm::vec3 rotationAxis = glm::axis(parentRotation);
|
||||||
glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
float fanScale = directionSize * 0.75f;
|
float fanScale = directionSize * 0.75f;
|
||||||
|
@ -296,7 +302,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) {
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
renderOrientationDirections(position, jointState._combinedRotation, directionSize);
|
renderOrientationDirections(position, _rotation * jointState.getRotation(), directionSize);
|
||||||
jointIndex = joint.parentIndex;
|
jointIndex = joint.parentIndex;
|
||||||
|
|
||||||
} while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree);
|
} while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree);
|
||||||
|
@ -359,21 +365,21 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c
|
||||||
glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
|
glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
|
||||||
|
|
||||||
JointState& shoulderState = _jointStates[shoulderJointIndex];
|
JointState& shoulderState = _jointStates[shoulderJointIndex];
|
||||||
shoulderState.setRotation(shoulderRotation, PALM_PRIORITY);
|
shoulderState.setRotationFromBindFrame(shoulderRotation, PALM_PRIORITY);
|
||||||
|
|
||||||
JointState& elbowState = _jointStates[elbowJointIndex];
|
JointState& elbowState = _jointStates[elbowJointIndex];
|
||||||
elbowState.setRotation(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY);
|
elbowState.setRotationFromBindFrame(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY);
|
||||||
|
|
||||||
JointState& handState = _jointStates[jointIndex];
|
JointState& handState = _jointStates[jointIndex];
|
||||||
handState.setRotation(rotation, PALM_PRIORITY);
|
handState.setRotationFromBindFrame(rotation, PALM_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
|
bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
|
||||||
return getJointPosition(getLeftHandJointIndex(), position);
|
return getJointPositionInWorldFrame(getLeftHandJointIndex(), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getRightHandPosition(glm::vec3& position) const {
|
bool SkeletonModel::getRightHandPosition(glm::vec3& position) const {
|
||||||
return getJointPosition(getRightHandJointIndex(), position);
|
return getJointPositionInWorldFrame(getRightHandJointIndex(), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::restoreLeftHandPosition(float fraction, float priority) {
|
bool SkeletonModel::restoreLeftHandPosition(float fraction, float priority) {
|
||||||
|
@ -381,7 +387,7 @@ bool SkeletonModel::restoreLeftHandPosition(float fraction, float priority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getLeftShoulderPosition(glm::vec3& position) const {
|
bool SkeletonModel::getLeftShoulderPosition(glm::vec3& position) const {
|
||||||
return getJointPosition(getLastFreeJointIndex(getLeftHandJointIndex()), position);
|
return getJointPositionInWorldFrame(getLastFreeJointIndex(getLeftHandJointIndex()), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SkeletonModel::getLeftArmLength() const {
|
float SkeletonModel::getLeftArmLength() const {
|
||||||
|
@ -393,7 +399,7 @@ bool SkeletonModel::restoreRightHandPosition(float fraction, float priority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
|
bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
|
||||||
return getJointPosition(getLastFreeJointIndex(getRightHandJointIndex()), position);
|
return getJointPositionInWorldFrame(getLastFreeJointIndex(getRightHandJointIndex()), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SkeletonModel::getRightArmLength() const {
|
float SkeletonModel::getRightArmLength() const {
|
||||||
|
@ -401,11 +407,11 @@ float SkeletonModel::getRightArmLength() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
|
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
|
||||||
return isActive() && getJointPosition(_geometry->getFBXGeometry().headJointIndex, headPosition);
|
return isActive() && getJointPositionInWorldFrame(_geometry->getFBXGeometry().headJointIndex, headPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
|
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
|
||||||
return isActive() && getJointPosition(_geometry->getFBXGeometry().neckJointIndex, neckPosition);
|
return isActive() && getJointPositionInWorldFrame(_geometry->getFBXGeometry().neckJointIndex, neckPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const {
|
bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const {
|
||||||
|
@ -416,7 +422,7 @@ bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const {
|
||||||
if (geometry.neckJointIndex == -1) {
|
if (geometry.neckJointIndex == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return getJointRotation(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation);
|
return getJointRotationInWorldFrame(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
||||||
|
@ -424,18 +430,18 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
if (getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
|
if (getJointPositionInWorldFrame(geometry.leftEyeJointIndex, firstEyePosition) &&
|
||||||
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition)) {
|
getJointPositionInWorldFrame(geometry.rightEyeJointIndex, secondEyePosition)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// no eye joints; try to estimate based on head/neck joints
|
// no eye joints; try to estimate based on head/neck joints
|
||||||
glm::vec3 neckPosition, headPosition;
|
glm::vec3 neckPosition, headPosition;
|
||||||
if (getJointPosition(geometry.neckJointIndex, neckPosition) &&
|
if (getJointPositionInWorldFrame(geometry.neckJointIndex, neckPosition) &&
|
||||||
getJointPosition(geometry.headJointIndex, headPosition)) {
|
getJointPositionInWorldFrame(geometry.headJointIndex, headPosition)) {
|
||||||
const float EYE_PROPORTION = 0.6f;
|
const float EYE_PROPORTION = 0.6f;
|
||||||
glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION);
|
glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION);
|
||||||
glm::quat headRotation;
|
glm::quat headRotation;
|
||||||
getJointRotation(geometry.headJointIndex, headRotation);
|
getJointRotationInWorldFrame(geometry.headJointIndex, headRotation);
|
||||||
const float EYES_FORWARD = 0.25f;
|
const float EYES_FORWARD = 0.25f;
|
||||||
const float EYE_SEPARATION = 0.1f;
|
const float EYE_SEPARATION = 0.1f;
|
||||||
float headHeight = glm::distance(neckPosition, headPosition);
|
float headHeight = glm::distance(neckPosition, headPosition);
|
||||||
|
|
|
@ -91,6 +91,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/// \param jointIndex index of joint in model
|
||||||
|
/// \param position position of joint in model-frame
|
||||||
void applyHandPosition(int jointIndex, const glm::vec3& position);
|
void applyHandPosition(int jointIndex, const glm::vec3& position);
|
||||||
|
|
||||||
void applyPalmData(int jointIndex, PalmData& palm);
|
void applyPalmData(int jointIndex, PalmData& palm);
|
||||||
|
@ -105,6 +107,10 @@ protected:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void renderJointConstraints(int jointIndex);
|
void renderJointConstraints(int jointIndex);
|
||||||
|
|
||||||
|
/// \param jointIndex index of joint in model
|
||||||
|
/// \param position position of joint in model-frame
|
||||||
|
/// \param rotation rotation of joint in model-frame
|
||||||
void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation);
|
void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation);
|
||||||
|
|
||||||
Avatar* _owningAvatar;
|
Avatar* _owningAvatar;
|
||||||
|
|
|
@ -92,7 +92,7 @@ static void setPalm(float deltaTime, int index) {
|
||||||
skeletonModel->getJointRotation(jointIndex, rotation, true);
|
skeletonModel->getJointRotation(jointIndex, rotation, true);
|
||||||
rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f));
|
rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f));
|
||||||
}
|
}
|
||||||
skeletonModel->getJointPosition(jointIndex, position);
|
skeletonModel->getJointPositionInWorldFrame(jointIndex, position);
|
||||||
position = inverseRotation * (position - skeletonModel->getTranslation());
|
position = inverseRotation * (position - skeletonModel->getTranslation());
|
||||||
|
|
||||||
palm->setRawRotation(rotation);
|
palm->setRawRotation(rotation);
|
||||||
|
|
|
@ -166,38 +166,21 @@ QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
||||||
jointStates.append(state);
|
jointStates.append(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute transforms
|
// compute model transforms
|
||||||
// Unfortunately, the joints are not neccessarily in order from parents to children,
|
|
||||||
// so we must iterate over the list multiple times until all are set correctly.
|
|
||||||
QVector<bool> jointIsSet;
|
|
||||||
int numJoints = jointStates.size();
|
int numJoints = jointStates.size();
|
||||||
jointIsSet.fill(false, numJoints);
|
for (int i = 0; i < numJoints; ++i) {
|
||||||
int numJointsSet = 0;
|
JointState& state = jointStates[i];
|
||||||
int lastNumJointsSet = -1;
|
const FBXJoint& joint = state.getFBXJoint();
|
||||||
while (numJointsSet < numJoints && numJointsSet != lastNumJointsSet) {
|
int parentIndex = joint.parentIndex;
|
||||||
lastNumJointsSet = numJointsSet;
|
if (parentIndex == -1) {
|
||||||
for (int i = 0; i < numJoints; ++i) {
|
_rootIndex = i;
|
||||||
if (jointIsSet[i]) {
|
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||||
continue;
|
state.computeTransform(parentTransform);
|
||||||
}
|
} else {
|
||||||
JointState& state = jointStates[i];
|
const JointState& parentState = jointStates.at(parentIndex);
|
||||||
const FBXJoint& joint = state.getFBXJoint();
|
state.computeTransform(parentState.getTransform());
|
||||||
int parentIndex = joint.parentIndex;
|
|
||||||
if (parentIndex == -1) {
|
|
||||||
_rootIndex = i;
|
|
||||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
|
||||||
state.computeTransforms(baseTransform, _rotation);
|
|
||||||
++numJointsSet;
|
|
||||||
jointIsSet[i] = true;
|
|
||||||
} else if (jointIsSet[parentIndex]) {
|
|
||||||
const JointState& parentState = jointStates.at(parentIndex);
|
|
||||||
state.computeTransforms(parentState._transform, parentState._combinedRotation);
|
|
||||||
++numJointsSet;
|
|
||||||
jointIsSet[i] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return jointStates;
|
return jointStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +459,7 @@ void Model::reset() {
|
||||||
}
|
}
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
_jointStates[i]._rotation = geometry.joints.at(i).rotation;
|
_jointStates[i]._rotationInParentFrame = geometry.joints.at(i).rotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +669,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
|
||||||
if (index == -1 || index >= _jointStates.size()) {
|
if (index == -1 || index >= _jointStates.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rotation = _jointStates.at(index)._rotation;
|
rotation = _jointStates.at(index)._rotationInParentFrame;
|
||||||
const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
||||||
return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
|
return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
|
||||||
glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
|
glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
|
||||||
|
@ -699,7 +682,7 @@ void Model::setJointState(int index, bool valid, const glm::quat& rotation, floa
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
if (priority >= state._animationPriority) {
|
if (priority >= state._animationPriority) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
state._rotation = rotation;
|
state._rotationInParentFrame = rotation;
|
||||||
state._animationPriority = priority;
|
state._animationPriority = priority;
|
||||||
} else {
|
} else {
|
||||||
state.restoreRotation(1.0f, priority);
|
state.restoreRotation(1.0f, priority);
|
||||||
|
@ -731,19 +714,29 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
|
||||||
|
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// position is in world-frame
|
||||||
|
position = _translation + _rotation * _jointStates[jointIndex].getPosition();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
|
bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
position = _translation + extractTranslation(_jointStates[jointIndex]._transform);
|
// position is in model-frame
|
||||||
|
position = extractTranslation(_jointStates[jointIndex].getTransform());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind) const {
|
bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const {
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rotation = _jointStates[jointIndex].getJointRotation(fromBind);
|
rotation = _rotation * _jointStates[jointIndex].getRotation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,7 +744,7 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const
|
||||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rotation = _jointStates[jointIndex]._combinedRotation;
|
rotation = _rotation * _jointStates[jointIndex].getRotation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,15 +956,16 @@ void Model::updateShapePositions() {
|
||||||
glm::vec3 rootPosition(0.0f);
|
glm::vec3 rootPosition(0.0f);
|
||||||
_boundingRadius = 0.0f;
|
_boundingRadius = 0.0f;
|
||||||
float uniformScale = extractUniformScale(_scale);
|
float uniformScale = extractUniformScale(_scale);
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
const FBXJoint& joint = geometry.joints[i];
|
const JointState& state = _jointStates[i];
|
||||||
|
const FBXJoint& joint = state.getFBXJoint();
|
||||||
// shape position and rotation need to be in world-frame
|
// shape position and rotation need to be in world-frame
|
||||||
glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i]._combinedRotation * joint.shapePosition);
|
glm::quat stateRotation = state.getRotation();
|
||||||
glm::vec3 worldPosition = extractTranslation(_jointStates[i]._transform) + jointToShapeOffset + _translation;
|
glm::vec3 shapeOffset = uniformScale * (stateRotation * joint.shapePosition);
|
||||||
|
glm::vec3 worldPosition = _translation + _rotation * (state.getPosition() + shapeOffset);
|
||||||
Shape* shape = _jointShapes[i];
|
Shape* shape = _jointShapes[i];
|
||||||
shape->setPosition(worldPosition);
|
shape->setPosition(worldPosition);
|
||||||
shape->setRotation(_jointStates[i]._combinedRotation * joint.shapeRotation);
|
shape->setRotation(_rotation * stateRotation * joint.shapeRotation);
|
||||||
float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius();
|
float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius();
|
||||||
if (distance > _boundingRadius) {
|
if (distance > _boundingRadius) {
|
||||||
_boundingRadius = distance;
|
_boundingRadius = distance;
|
||||||
|
@ -993,12 +987,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
float radiusScale = extractUniformScale(_scale);
|
float radiusScale = extractUniformScale(_scale);
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
const FBXJoint& joint = geometry.joints[i];
|
const FBXJoint& joint = geometry.joints[i];
|
||||||
glm::vec3 end = extractTranslation(_jointStates[i]._transform);
|
glm::vec3 end = _translation + _rotation * _jointStates[i].getPosition();
|
||||||
float endRadius = joint.boneRadius * radiusScale;
|
float endRadius = joint.boneRadius * radiusScale;
|
||||||
glm::vec3 start = end;
|
glm::vec3 start = end;
|
||||||
float startRadius = joint.boneRadius * radiusScale;
|
float startRadius = joint.boneRadius * radiusScale;
|
||||||
if (joint.parentIndex != -1) {
|
if (joint.parentIndex != -1) {
|
||||||
start = extractTranslation(_jointStates[joint.parentIndex]._transform);
|
start = _translation + _rotation * _jointStates[joint.parentIndex].getPosition();
|
||||||
startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale;
|
startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale;
|
||||||
}
|
}
|
||||||
// for now, use average of start and end radii
|
// for now, use average of start and end radii
|
||||||
|
@ -1208,8 +1202,8 @@ void Model::simulateInternal(float deltaTime) {
|
||||||
|
|
||||||
glm::vec3 jointTranslation = _translation;
|
glm::vec3 jointTranslation = _translation;
|
||||||
glm::quat jointRotation = _rotation;
|
glm::quat jointRotation = _rotation;
|
||||||
getJointPosition(attachment.jointIndex, jointTranslation);
|
getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
|
||||||
getJointRotation(attachment.jointIndex, jointRotation);
|
getJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
|
||||||
|
|
||||||
model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale);
|
model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale);
|
||||||
model->setRotation(jointRotation * attachment.rotation);
|
model->setRotation(jointRotation * attachment.rotation);
|
||||||
|
@ -1220,12 +1214,13 @@ void Model::simulateInternal(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
|
||||||
for (int i = 0; i < _meshStates.size(); i++) {
|
for (int i = 0; i < _meshStates.size(); i++) {
|
||||||
MeshState& state = _meshStates[i];
|
MeshState& state = _meshStates[i];
|
||||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
state.clusterMatrices[j] = _jointStates[cluster.jointIndex]._transform * cluster.inverseBindMatrix;
|
state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1239,22 +1234,23 @@ void Model::updateJointState(int index) {
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
const FBXJoint& joint = state.getFBXJoint();
|
const FBXJoint& joint = state.getFBXJoint();
|
||||||
|
|
||||||
if (joint.parentIndex == -1) {
|
// compute model transforms
|
||||||
|
int parentIndex = joint.parentIndex;
|
||||||
|
if (parentIndex == -1) {
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||||
state.computeTransforms(baseTransform, _rotation);
|
state.computeTransform(parentTransform);
|
||||||
} else {
|
} else {
|
||||||
const JointState& parentState = _jointStates.at(joint.parentIndex);
|
const JointState& parentState = _jointStates.at(parentIndex);
|
||||||
state.computeTransforms(parentState._transform, parentState._combinedRotation);
|
state.computeTransform(parentState.getTransform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation, bool useRotation,
|
bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation,
|
||||||
int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
|
int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
|
||||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
glm::vec3 relativePosition = translation - _translation;
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
|
const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
|
||||||
if (freeLineage.isEmpty()) {
|
if (freeLineage.isEmpty()) {
|
||||||
|
@ -1267,21 +1263,19 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
||||||
// this is a cyclic coordinate descent algorithm: see
|
// this is a cyclic coordinate descent algorithm: see
|
||||||
// http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d
|
// http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d
|
||||||
const int ITERATION_COUNT = 1;
|
const int ITERATION_COUNT = 1;
|
||||||
glm::vec3 worldAlignment = _rotation * alignment;
|
glm::vec3 worldAlignment = alignment;
|
||||||
for (int i = 0; i < ITERATION_COUNT; i++) {
|
for (int i = 0; i < ITERATION_COUNT; i++) {
|
||||||
// first, try to rotate the end effector as close as possible to the target rotation, if any
|
// first, try to rotate the end effector as close as possible to the target rotation, if any
|
||||||
glm::quat endRotation;
|
glm::quat endRotation;
|
||||||
if (useRotation) {
|
if (useRotation) {
|
||||||
JointState& state = _jointStates[jointIndex];
|
JointState& state = _jointStates[jointIndex];
|
||||||
|
|
||||||
// TODO: figure out what this is trying to do and combine it into one JointState method
|
state.setRotation(rotation, true, priority);
|
||||||
endRotation = state.getJointRotation(true);
|
endRotation = state.getRotation();
|
||||||
state.applyRotationDelta(rotation * glm::inverse(endRotation), true, priority);
|
|
||||||
endRotation = state.getJointRotation(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// then, we go from the joint upwards, rotating the end as close as possible to the target
|
// then, we go from the joint upwards, rotating the end as close as possible to the target
|
||||||
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex]._transform);
|
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getTransform());
|
||||||
for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) {
|
for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) {
|
||||||
int index = freeLineage.at(j);
|
int index = freeLineage.at(j);
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
|
@ -1289,18 +1283,18 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
||||||
if (!(joint.isFree || allIntermediatesFree)) {
|
if (!(joint.isFree || allIntermediatesFree)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
glm::vec3 jointPosition = extractTranslation(state._transform);
|
glm::vec3 jointPosition = extractTranslation(state.getTransform());
|
||||||
glm::vec3 jointVector = endPosition - jointPosition;
|
glm::vec3 jointVector = endPosition - jointPosition;
|
||||||
glm::quat oldCombinedRotation = state._combinedRotation;
|
glm::quat oldCombinedRotation = state.getRotation();
|
||||||
glm::quat combinedDelta;
|
glm::quat combinedDelta;
|
||||||
float combinedWeight;
|
float combinedWeight;
|
||||||
if (useRotation) {
|
if (useRotation) {
|
||||||
combinedDelta = safeMix(rotation * glm::inverse(endRotation),
|
combinedDelta = safeMix(rotation * glm::inverse(endRotation),
|
||||||
rotationBetween(jointVector, relativePosition - jointPosition), 0.5f);
|
rotationBetween(jointVector, position - jointPosition), 0.5f);
|
||||||
combinedWeight = 2.0f;
|
combinedWeight = 2.0f;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
combinedDelta = rotationBetween(jointVector, relativePosition - jointPosition);
|
combinedDelta = rotationBetween(jointVector, position - jointPosition);
|
||||||
combinedWeight = 1.0f;
|
combinedWeight = 1.0f;
|
||||||
}
|
}
|
||||||
if (alignment != glm::vec3() && j > 1) {
|
if (alignment != glm::vec3() && j > 1) {
|
||||||
|
@ -1309,7 +1303,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
||||||
for (int k = j - 1; k > 0; k--) {
|
for (int k = j - 1; k > 0; k--) {
|
||||||
int index = freeLineage.at(k);
|
int index = freeLineage.at(k);
|
||||||
updateJointState(index);
|
updateJointState(index);
|
||||||
positionSum += extractTranslation(_jointStates.at(index)._transform);
|
positionSum += extractTranslation(_jointStates.at(index).getTransform());
|
||||||
}
|
}
|
||||||
glm::vec3 projectedCenterOfMass = glm::cross(jointVector,
|
glm::vec3 projectedCenterOfMass = glm::cross(jointVector,
|
||||||
glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector));
|
glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector));
|
||||||
|
@ -1321,7 +1315,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.applyRotationDelta(combinedDelta, true, priority);
|
state.applyRotationDelta(combinedDelta, true, priority);
|
||||||
glm::quat actualDelta = state._combinedRotation * glm::inverse(oldCombinedRotation);
|
glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation);
|
||||||
endPosition = actualDelta * jointVector + jointPosition;
|
endPosition = actualDelta * jointVector + jointPosition;
|
||||||
if (useRotation) {
|
if (useRotation) {
|
||||||
endRotation = actualDelta * endRotation;
|
endRotation = actualDelta * endRotation;
|
||||||
|
@ -1470,12 +1464,12 @@ void Model::applyCollision(CollisionInfo& collision) {
|
||||||
|
|
||||||
glm::vec3 jointPosition(0.0f);
|
glm::vec3 jointPosition(0.0f);
|
||||||
int jointIndex = collision._intData;
|
int jointIndex = collision._intData;
|
||||||
if (getJointPosition(jointIndex, jointPosition)) {
|
if (getJointPositionInWorldFrame(jointIndex, jointPosition)) {
|
||||||
const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex];
|
const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex];
|
||||||
if (joint.parentIndex != -1) {
|
if (joint.parentIndex != -1) {
|
||||||
// compute the approximate distance (travel) that the joint needs to move
|
// compute the approximate distance (travel) that the joint needs to move
|
||||||
glm::vec3 start;
|
glm::vec3 start;
|
||||||
getJointPosition(joint.parentIndex, start);
|
getJointPositionInWorldFrame(joint.parentIndex, start);
|
||||||
glm::vec3 contactPoint = collision._contactPoint - start;
|
glm::vec3 contactPoint = collision._contactPoint - start;
|
||||||
glm::vec3 penetrationEnd = contactPoint + collision._penetration;
|
glm::vec3 penetrationEnd = contactPoint + collision._penetration;
|
||||||
glm::vec3 axis = glm::cross(contactPoint, penetrationEnd);
|
glm::vec3 axis = glm::cross(contactPoint, penetrationEnd);
|
||||||
|
@ -1486,8 +1480,9 @@ void Model::applyCollision(CollisionInfo& collision) {
|
||||||
float angle = asinf(travel / (glm::length(contactPoint) * glm::length(penetrationEnd)));
|
float angle = asinf(travel / (glm::length(contactPoint) * glm::length(penetrationEnd)));
|
||||||
axis = glm::normalize(axis);
|
axis = glm::normalize(axis);
|
||||||
glm::vec3 end;
|
glm::vec3 end;
|
||||||
getJointPosition(jointIndex, end);
|
getJointPositionInWorldFrame(jointIndex, end);
|
||||||
glm::vec3 newEnd = start + glm::angleAxis(angle, axis) * (end - start);
|
// transform into model-frame
|
||||||
|
glm::vec3 newEnd = glm::inverse(_rotation) * (start + glm::angleAxis(angle, axis) * (end - start) - _translation);
|
||||||
// try to move it
|
// try to move it
|
||||||
setJointPosition(jointIndex, newEnd, glm::quat(), false, -1, true);
|
setJointPosition(jointIndex, newEnd, glm::quat(), false, -1, true);
|
||||||
}
|
}
|
||||||
|
@ -1960,7 +1955,7 @@ void AnimationHandle::applyFrame(float frameIndex) {
|
||||||
if (mapping != -1) {
|
if (mapping != -1) {
|
||||||
JointState& state = _model->_jointStates[mapping];
|
JointState& state = _model->_jointStates[mapping];
|
||||||
if (_priority >= state._animationPriority) {
|
if (_priority >= state._animationPriority) {
|
||||||
state._rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
state._rotationInParentFrame = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||||
state._animationPriority = _priority;
|
state._animationPriority = _priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1989,49 +1984,59 @@ JointState::JointState() :
|
||||||
|
|
||||||
void JointState::setFBXJoint(const FBXJoint* joint) {
|
void JointState::setFBXJoint(const FBXJoint* joint) {
|
||||||
assert(joint != NULL);
|
assert(joint != NULL);
|
||||||
_rotation = joint->rotation;
|
_rotationInParentFrame = joint->rotation;
|
||||||
// NOTE: JointState does not own the FBXJoint to which it points.
|
// NOTE: JointState does not own the FBXJoint to which it points.
|
||||||
_fbxJoint = joint;
|
_fbxJoint = joint;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::copyState(const JointState& state) {
|
void JointState::copyState(const JointState& state) {
|
||||||
_rotation = state._rotation;
|
_rotationInParentFrame = state._rotationInParentFrame;
|
||||||
_transform = state._transform;
|
_transform = state._transform;
|
||||||
_combinedRotation = state._combinedRotation;
|
_rotation = extractRotation(_transform);
|
||||||
_animationPriority = state._animationPriority;
|
_animationPriority = state._animationPriority;
|
||||||
// DO NOT copy _fbxJoint
|
// DO NOT copy _fbxJoint
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation) {
|
void JointState::computeTransform(const glm::mat4& parentTransform) {
|
||||||
assert(_fbxJoint != NULL);
|
glm::quat modifiedRotation = _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation;
|
||||||
glm::quat combinedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation;
|
glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform;
|
||||||
_transform = baseTransform * glm::translate(_fbxJoint->translation) * _fbxJoint->preTransform
|
_transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
|
||||||
* glm::mat4_cast(combinedRotation) * _fbxJoint->postTransform;
|
_rotation = extractRotation(_transform);
|
||||||
_combinedRotation = baseRotation * combinedRotation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat JointState::getJointRotation(bool fromBind) const {
|
glm::quat JointState::getRotationFromBindToModelFrame() const {
|
||||||
assert(_fbxJoint != NULL);
|
return _rotation * _fbxJoint->inverseBindRotation;
|
||||||
return _combinedRotation * (fromBind ? _fbxJoint->inverseBindRotation : _fbxJoint->inverseDefaultRotation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::restoreRotation(float fraction, float priority) {
|
void JointState::restoreRotation(float fraction, float priority) {
|
||||||
assert(_fbxJoint != NULL);
|
assert(_fbxJoint != NULL);
|
||||||
if (priority == _animationPriority || _animationPriority == 0.0f) {
|
if (priority == _animationPriority || _animationPriority == 0.0f) {
|
||||||
_rotation = safeMix(_rotation, _fbxJoint->rotation, fraction);
|
_rotationInParentFrame = safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction);
|
||||||
_animationPriority = 0.0f;
|
_animationPriority = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::setRotation(const glm::quat& rotation, float priority) {
|
void JointState::setRotationFromBindFrame(const glm::quat& rotation, float priority) {
|
||||||
assert(_fbxJoint != NULL);
|
assert(_fbxJoint != NULL);
|
||||||
if (priority >= _animationPriority) {
|
if (priority >= _animationPriority) {
|
||||||
_rotation = _rotation * glm::inverse(_combinedRotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
|
// rotation is from bind- to model-frame
|
||||||
|
_rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JointState::clearTransformTranslation() {
|
||||||
|
_transform[3][0] = 0.0f;
|
||||||
|
_transform[3][1] = 0.0f;
|
||||||
|
_transform[3][2] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JointState::setRotation(const glm::quat& rotation, bool constrain, float priority) {
|
||||||
|
applyRotationDelta(rotation * glm::inverse(_rotation), true, priority);
|
||||||
|
}
|
||||||
|
|
||||||
void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
|
void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
|
||||||
|
// NOTE: delta is in jointParent-frame
|
||||||
assert(_fbxJoint != NULL);
|
assert(_fbxJoint != NULL);
|
||||||
if (priority < _animationPriority) {
|
if (priority < _animationPriority) {
|
||||||
return;
|
return;
|
||||||
|
@ -2040,15 +2045,15 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa
|
||||||
if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) &&
|
if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) &&
|
||||||
_fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) {
|
_fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) {
|
||||||
// no constraints
|
// no constraints
|
||||||
_rotation = _rotation * glm::inverse(_combinedRotation) * delta * _combinedRotation;
|
_rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
|
||||||
_combinedRotation = delta * _combinedRotation;
|
_rotation = delta * _rotation;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glm::quat targetRotation = delta * _combinedRotation;
|
glm::quat targetRotation = delta * _rotation;
|
||||||
glm::vec3 eulers = safeEulerAngles(_rotation * glm::inverse(_combinedRotation) * targetRotation);
|
glm::vec3 eulers = safeEulerAngles(_rotationInParentFrame * glm::inverse(_rotation) * targetRotation);
|
||||||
glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax));
|
glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax));
|
||||||
_combinedRotation = _combinedRotation * glm::inverse(_rotation) * newRotation;
|
_rotation = _rotation * glm::inverse(_rotationInParentFrame) * newRotation;
|
||||||
_rotation = newRotation;
|
_rotationInParentFrame = newRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const glm::vec3& JointState::getDefaultTranslationInParentFrame() const {
|
const glm::vec3& JointState::getDefaultTranslationInParentFrame() const {
|
||||||
|
|
|
@ -40,28 +40,39 @@ public:
|
||||||
|
|
||||||
void copyState(const JointState& state);
|
void copyState(const JointState& state);
|
||||||
|
|
||||||
/// computes new _transform and _combinedRotation
|
void computeTransform(const glm::mat4& parentTransform);
|
||||||
void computeTransforms(const glm::mat4& baseTransform, const glm::quat& baseRotation);
|
const glm::mat4& getTransform() const { return _transform; }
|
||||||
|
|
||||||
/// \return rotation from the joint's default (or bind) frame to world frame
|
glm::quat getRotation() const { return _rotation; }
|
||||||
glm::quat getJointRotation(bool fromBind = false) const;
|
glm::vec3 getPosition() const { return extractTranslation(_transform); }
|
||||||
|
|
||||||
|
/// \return rotation from bind to model frame
|
||||||
|
glm::quat getRotationFromBindToModelFrame() const;
|
||||||
|
|
||||||
|
/// \param rotation rotation of joint in model-frame
|
||||||
|
void setRotation(const glm::quat& rotation, bool constrain, float priority);
|
||||||
|
|
||||||
|
/// \param delta is in the jointParent-frame
|
||||||
void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f);
|
void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f);
|
||||||
|
|
||||||
const glm::vec3& getDefaultTranslationInParentFrame() const;
|
const glm::vec3& getDefaultTranslationInParentFrame() const;
|
||||||
|
|
||||||
void restoreRotation(float fraction, float priority);
|
void restoreRotation(float fraction, float priority);
|
||||||
|
|
||||||
/// \param rotation is from bind- to world-frame
|
/// \param rotation is from bind- to model-frame
|
||||||
/// computes parent relative _rotation and sets that
|
/// computes and sets new _rotationInParentFrame
|
||||||
void setRotation(const glm::quat& rotation, float priority);
|
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
||||||
|
void setRotationFromBindFrame(const glm::quat& rotation, float priority);
|
||||||
|
|
||||||
glm::quat _rotation; // rotation relative to parent
|
void clearTransformTranslation();
|
||||||
glm::mat4 _transform; // rotation to world frame + translation in model frame
|
|
||||||
glm::quat _combinedRotation; // rotation from joint local to world frame
|
glm::quat _rotationInParentFrame; // joint- to parentJoint-frame
|
||||||
float _animationPriority; // the priority of the animation affecting this joint
|
float _animationPriority; // the priority of the animation affecting this joint
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
glm::mat4 _transform; // joint- to model-frame
|
||||||
|
glm::quat _rotation; // joint- to model-frame
|
||||||
|
|
||||||
const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
|
const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,10 +166,15 @@ public:
|
||||||
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
|
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
|
||||||
int getLastFreeJointIndex(int jointIndex) const;
|
int getLastFreeJointIndex(int jointIndex) const;
|
||||||
|
|
||||||
bool getJointPosition(int jointIndex, glm::vec3& position) const;
|
bool getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const;
|
||||||
bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const;
|
bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const;
|
||||||
bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const;
|
bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const;
|
||||||
|
|
||||||
|
/// \param jointIndex index of joint in model structure
|
||||||
|
/// \param position[out] position of joint in model-frame
|
||||||
|
/// \return true if joint exists
|
||||||
|
bool getJointPosition(int jointIndex, glm::vec3& position) const;
|
||||||
|
|
||||||
QStringList getJointNames() const;
|
QStringList getJointNames() const;
|
||||||
|
|
||||||
AnimationHandlePointer createAnimationHandle();
|
AnimationHandlePointer createAnimationHandle();
|
||||||
|
@ -244,7 +260,15 @@ protected:
|
||||||
/// Updates the state of the joint at the specified index.
|
/// Updates the state of the joint at the specified index.
|
||||||
virtual void updateJointState(int index);
|
virtual void updateJointState(int index);
|
||||||
|
|
||||||
bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(),
|
/// \param jointIndex index of joint in model structure
|
||||||
|
/// \param position position of joint in model-frame
|
||||||
|
/// \param rotation rotation of joint in model-frame
|
||||||
|
/// \param useRotation false if rotation should be ignored
|
||||||
|
/// \param lastFreeIndex
|
||||||
|
/// \param allIntermediatesFree
|
||||||
|
/// \param alignment
|
||||||
|
/// \return true if joint exists
|
||||||
|
bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation = glm::quat(),
|
||||||
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
|
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
|
||||||
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
|
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
|
||||||
|
|
||||||
|
|
|
@ -324,7 +324,6 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
|
||||||
|
|
||||||
// Get vertical FoV of the displayed overlay texture
|
// Get vertical FoV of the displayed overlay texture
|
||||||
const float halfVerticalAngle = _oculusAngle / 2.0f;
|
const float halfVerticalAngle = _oculusAngle / 2.0f;
|
||||||
const float verticalAngle = halfVerticalAngle * 2.0f;
|
|
||||||
const float overlayAspectRatio = glWidget->width() / (float)glWidget->height();
|
const float overlayAspectRatio = glWidget->width() / (float)glWidget->height();
|
||||||
const float halfOverlayHeight = _distance * tan(halfVerticalAngle);
|
const float halfOverlayHeight = _distance * tan(halfVerticalAngle);
|
||||||
|
|
||||||
|
@ -393,7 +392,6 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
|
||||||
|
|
||||||
float newWidth = magnifyWidth * magnification;
|
float newWidth = magnifyWidth * magnification;
|
||||||
float newHeight = magnifyHeight * magnification;
|
float newHeight = magnifyHeight * magnification;
|
||||||
float tmp;
|
|
||||||
|
|
||||||
// Magnification Texture Coordinates
|
// Magnification Texture Coordinates
|
||||||
float magnifyULeft = mouseX / (float)widgetWidth;
|
float magnifyULeft = mouseX / (float)widgetWidth;
|
||||||
|
@ -409,8 +407,6 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
|
||||||
float leftAngle = (newMouseX / (float)widgetWidth) * horizontalAngle - halfHorizontalAngle;
|
float leftAngle = (newMouseX / (float)widgetWidth) * horizontalAngle - halfHorizontalAngle;
|
||||||
float rightAngle = ((newMouseX + newWidth) / (float)widgetWidth) * horizontalAngle - halfHorizontalAngle;
|
float rightAngle = ((newMouseX + newWidth) / (float)widgetWidth) * horizontalAngle - halfHorizontalAngle;
|
||||||
|
|
||||||
float halfMagnifyHeight = magnifyHeight / 2.0f;
|
|
||||||
|
|
||||||
float leftX, rightX, leftZ, rightZ;
|
float leftX, rightX, leftZ, rightZ;
|
||||||
|
|
||||||
// Get position on hemisphere using angle
|
// Get position on hemisphere using angle
|
||||||
|
|
Loading…
Reference in a new issue