Merge pull request #1437 from ey6es/master

Restore bent arm behavior when pointing (lost in ball removal).  Fix compile warning.
This commit is contained in:
Philip Rosedale 2014-01-02 15:26:33 -08:00
commit 8f48ca0e95
8 changed files with 55 additions and 113 deletions

View file

@ -190,13 +190,10 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
// update avatar skeleton
_skeleton.update(deltaTime, getOrientation(), _position);
// if this is not my avatar, then hand position comes from transmitted data
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition;
//update the movement of the hand and process handshaking with other avatars...
updateHandMovementAndTouching(deltaTime, enableHandMovement);
_hand.simulate(deltaTime, false);
_skeletonModel.simulate(deltaTime);
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
@ -227,18 +224,6 @@ void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) {
_mouseRayDirection = direction;
}
void Avatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovement) {
// reset hand and arm positions according to hand movement
enableHandMovement |= updateLeapHandPositions();
//constrain right arm length and re-adjust elbow position as it bends
// NOTE - the following must be called on all avatars - not just _isMine
if (enableHandMovement) {
updateArmIKAndConstraints(deltaTime, AVATAR_JOINT_RIGHT_FINGERTIPS);
updateArmIKAndConstraints(deltaTime, AVATAR_JOINT_LEFT_FINGERTIPS);
}
}
static TextRenderer* textRenderer() {
static TextRenderer* renderer = new TextRenderer(SANS_FONT_FAMILY, 24, -1, false, TextRenderer::SHADOW_EFFECT);
return renderer;
@ -314,93 +299,6 @@ void Avatar::render(bool forceRenderHead) {
}
}
// returns true if the Leap controls any of the avatar's hands.
bool Avatar::updateLeapHandPositions() {
bool returnValue = false;
// If there are leap-interaction hands visible, see if we can use them as the endpoints for IK
if (getHand().getPalms().size() > 0) {
PalmData const* leftLeapHand = NULL;
PalmData const* rightLeapHand = NULL;
// Look through all of the palms available (there may be more than two), and pick
// the leftmost and rightmost. If there's only one, we'll use a heuristic below
// to decode whether it's the left or right.
for (size_t i = 0; i < getHand().getPalms().size(); ++i) {
PalmData& palm = getHand().getPalms()[i];
if (palm.isActive()) {
if (!rightLeapHand || !leftLeapHand) {
rightLeapHand = leftLeapHand = &palm;
}
else if (palm.getRawPosition().x > rightLeapHand->getRawPosition().x) {
rightLeapHand = &palm;
}
else if (palm.getRawPosition().x < leftLeapHand->getRawPosition().x) {
leftLeapHand = &palm;
}
}
}
// If there's only one palm visible. Decide if it's the left or right
if (leftLeapHand == rightLeapHand && leftLeapHand) {
if (leftLeapHand->getRawPosition().x > 0) {
leftLeapHand = NULL;
}
else {
rightLeapHand = NULL;
}
}
if (leftLeapHand) {
_skeleton.joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].position = leftLeapHand->getPosition();
returnValue = true;
}
if (rightLeapHand) {
_skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = rightLeapHand->getPosition();
returnValue = true;
}
}
return returnValue;
}
void Avatar::updateArmIKAndConstraints(float deltaTime, AvatarJointID fingerTipJointID) {
Skeleton::AvatarJoint& fingerJoint = _skeleton.joint[fingerTipJointID];
Skeleton::AvatarJoint& wristJoint = _skeleton.joint[fingerJoint.parent];
Skeleton::AvatarJoint& elbowJoint = _skeleton.joint[wristJoint.parent];
Skeleton::AvatarJoint& shoulderJoint = _skeleton.joint[elbowJoint.parent];
// determine the arm vector
glm::vec3 armVector = fingerJoint.position;
armVector -= shoulderJoint.position;
// test to see if right hand is being dragged beyond maximum arm length
float distance = glm::length(armVector);
// don't let right hand get dragged beyond maximum arm length...
float armLength = _skeletonModel.isActive() ?
_skeletonModel.getRightArmLength() : _skeleton.getArmLength();
const float ARM_RETRACTION = 0.75f;
float retractedArmLength = armLength * ARM_RETRACTION;
if (distance > retractedArmLength) {
// reset right hand to be constrained to maximum arm length
fingerJoint.position = shoulderJoint.position;
glm::vec3 armNormal = armVector / distance;
armVector = armNormal * retractedArmLength;
distance = retractedArmLength;
glm::vec3 constrainedPosition = shoulderJoint.position;
constrainedPosition += armVector;
fingerJoint.position = constrainedPosition;
}
// set elbow position
glm::vec3 newElbowPosition = shoulderJoint.position + armVector * ONE_HALF;
glm::vec3 perpendicular = glm::cross(getBodyRightDirection(), armVector);
newElbowPosition += perpendicular * (1.0f - (_maxArmLength / distance)) * ONE_HALF;
elbowJoint.position = newElbowPosition;
// set wrist position
const float wristPosRatio = 0.7f;
wristJoint.position = elbowJoint.position + (fingerJoint.position - elbowJoint.position) * wristPosRatio;
}
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
glm::quat orientation = getOrientation();
glm::vec3 currentUp = orientation * IDENTITY_UP;

View file

@ -227,8 +227,6 @@ protected:
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
bool updateLeapHandPositions();
void updateArmIKAndConstraints(float deltaTime, AvatarJointID fingerTipJointID);
void setScale(const float scale);
@ -249,7 +247,6 @@ private:
void renderBody(bool forceRenderHead);
void initializeBodyBalls();
void resetBodyBalls();
void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement);
};
#endif

View file

@ -746,9 +746,15 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMov
pointDirection = glm::normalize(projectedVector);
}
}
const float FAR_AWAY_POINT = TREE_SCALE;
_skeleton.joint[AVATAR_JOINT_RIGHT_FINGERTIPS].position = _mouseRayOrigin + pointDirection * FAR_AWAY_POINT;
pointing = true;
glm::vec3 shoulderPosition;
if (_skeletonModel.getRightShoulderPosition(shoulderPosition)) {
glm::vec3 farVector = _mouseRayOrigin + pointDirection * (float)TREE_SCALE - shoulderPosition;
const float ARM_RETRACTION = 0.75f;
float retractedLength = _skeletonModel.getRightArmLength() * ARM_RETRACTION;
_skeleton.joint[AVATAR_JOINT_RIGHT_FINGERTIPS].position = shoulderPosition +
glm::normalize(farVector) * retractedLength;
pointing = true;
}
}
//Set right hand position and state to be transmitted, and also tell AvatarTouch about it

View file

@ -42,7 +42,7 @@ void SkeletonModel::simulate(float deltaTime) {
if (_owningAvatar->getHandState() == HAND_STATE_NULL) {
restoreRightHandPosition(HAND_RESTORATION_RATE);
} else {
setRightHandPosition(_owningAvatar->getHandPosition());
applyHandPosition(geometry.rightHandJointIndex, _owningAvatar->getHandPosition());
}
restoreLeftHandPosition(HAND_RESTORATION_RATE);
@ -125,6 +125,29 @@ bool operator<(const IndexValue& firstIndex, const IndexValue& secondIndex) {
return firstIndex.value < secondIndex.value;
}
void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) {
if (jointIndex == -1) {
return;
}
setJointPosition(jointIndex, position);
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::vec3 handPosition, elbowPosition;
getJointPosition(jointIndex, handPosition);
getJointPosition(geometry.joints.at(jointIndex).parentIndex, elbowPosition);
glm::vec3 forearmVector = handPosition - elbowPosition;
float forearmLength = glm::length(forearmVector);
if (forearmLength < EPSILON) {
return;
}
glm::quat handRotation;
getJointRotation(jointIndex, handRotation, true);
// align hand with forearm
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
applyRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), false);
}
void SkeletonModel::applyPalmData(int jointIndex, const QVector<int>& fingerJointIndices,
const QVector<int>& fingertipJointIndices, PalmData& palm) {
if (jointIndex == -1) {

View file

@ -28,6 +28,8 @@ public:
protected:
void applyHandPosition(int jointIndex, const glm::vec3& position);
void applyPalmData(int jointIndex, const QVector<int>& fingerJointIndices,
const QVector<int>& fingertipJointIndices, PalmData& palm);

View file

@ -500,6 +500,10 @@ bool Model::setLeftHandRotation(const glm::quat& rotation) {
return setJointRotation(getLeftHandJointIndex(), rotation);
}
bool Model::getLeftShoulderPosition(glm::vec3& position) const {
return getJointPosition(getLastFreeJointIndex(getLeftHandJointIndex()), position);
}
float Model::getLeftArmLength() const {
return getLimbLength(getLeftHandJointIndex());
}
@ -516,6 +520,10 @@ bool Model::setRightHandRotation(const glm::quat& rotation) {
return setJointRotation(getRightHandJointIndex(), rotation);
}
bool Model::getRightShoulderPosition(glm::vec3& position) const {
return getJointPosition(getLastFreeJointIndex(getRightHandJointIndex()), position);
}
float Model::getRightArmLength() const {
return getLimbLength(getRightHandJointIndex());
}

View file

@ -63,7 +63,7 @@ public:
/// Returns the index of the parent of the indexed joint, or -1 if not found.
int getParentJointIndex(int jointIndex) const;
/// Returns the index of the last free ancestor or 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;
/// Returns the position of the head joint.
@ -95,7 +95,11 @@ public:
/// \return whether or not the left hand joint was found
bool setLeftHandRotation(const glm::quat& rotation);
/// Returns the extended length from the left hand to its first free ancestor.
/// Gets the position of the left shoulder.
/// \return whether or not the left shoulder joint was found
bool getLeftShoulderPosition(glm::vec3& position) const;
/// Returns the extended length from the left hand to its last free ancestor.
float getLeftArmLength() const;
/// Sets the position of the right hand using inverse kinematics.
@ -111,6 +115,10 @@ public:
/// \return whether or not the right hand joint was found
bool setRightHandRotation(const glm::quat& rotation);
/// Gets the position of the right shoulder.
/// \return whether or not the right shoulder joint was found
bool getRightShoulderPosition(glm::vec3& position) const;
/// Returns the extended length from the right hand to its first free ancestor.
float getRightArmLength() const;

View file

@ -63,7 +63,7 @@ public:
public slots:
glm::vec3 getPosition() const { return glm::vec3(_voxelDetail->x, _voxelDetail->y, _voxelDetail->z); }
xColor getColor() const { return { _voxelDetail->red, _voxelDetail->green, _voxelDetail->blue }; }
xColor getColor() const { xColor color = { _voxelDetail->red, _voxelDetail->green, _voxelDetail->blue }; return color; }
float getScale() const { return _voxelDetail->s; }
private: