From 6c27569e9b0a2ab978d12404f0cd1239c4b1492d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 Jan 2014 13:23:15 -0800 Subject: [PATCH 1/2] Fix arm bending, compile warning. --- interface/src/avatar/Avatar.cpp | 104 +----------------- interface/src/avatar/Avatar.h | 3 - interface/src/avatar/MyAvatar.cpp | 12 +- interface/src/renderer/Model.cpp | 8 ++ interface/src/renderer/Model.h | 12 +- .../voxels/src/VoxelsScriptingInterface.h | 2 +- 6 files changed, 29 insertions(+), 112 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 5a9a689775..02141d3252 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -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; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b0448563cf..39df62f603 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -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 diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0efa8b09cf..cdcaeb2b0e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -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 diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9660c05095..e5c23532d8 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -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()); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 3550410492..2a97345db0 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -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; diff --git a/libraries/voxels/src/VoxelsScriptingInterface.h b/libraries/voxels/src/VoxelsScriptingInterface.h index 5df814065e..c725b93493 100644 --- a/libraries/voxels/src/VoxelsScriptingInterface.h +++ b/libraries/voxels/src/VoxelsScriptingInterface.h @@ -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: From 0461335887817f97b9be60229f5453fd267d7145 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 Jan 2014 14:56:29 -0800 Subject: [PATCH 2/2] Align hand with forearm in mouse-pointing mode. --- interface/src/avatar/SkeletonModel.cpp | 25 ++++++++++++++++++++++++- interface/src/avatar/SkeletonModel.h | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b7af35c632..6723b766e8 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -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& fingerJointIndices, const QVector& fingertipJointIndices, PalmData& palm) { if (jointIndex == -1) { diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 1d7a7cc9c0..caf08c823b 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -28,6 +28,8 @@ public: protected: + void applyHandPosition(int jointIndex, const glm::vec3& position); + void applyPalmData(int jointIndex, const QVector& fingerJointIndices, const QVector& fingertipJointIndices, PalmData& palm);