mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-17 23:26:50 +02:00
Improved shoulder calibration using hard-coded measured shoulder width
This commit is contained in:
parent
33a1d6e225
commit
c81875a280
4 changed files with 67 additions and 11 deletions
|
@ -1862,15 +1862,40 @@ void AnimInverseKinematics::preconditionRelativePosesToAvoidLimbLock(const AnimC
|
|||
|
||||
// overwrites _relativePoses with secondary poses.
|
||||
void AnimInverseKinematics::setSecondaryTargets(const AnimContext& context) {
|
||||
|
||||
if (_secondaryTargetsInRigFrame.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// shoulder joint should look-at position of arm joint.
|
||||
const int leftArmIndex = _skeleton->nameToJointIndex("LeftArm");
|
||||
const int rightArmIndex = _skeleton->nameToJointIndex("RightArm");
|
||||
|
||||
AnimPose rigToGeometryPose = AnimPose(glm::inverse(context.getGeometryToRigMatrix()));
|
||||
for (auto& iter : _secondaryTargetsInRigFrame) {
|
||||
AnimPose absPose = rigToGeometryPose * iter.second;
|
||||
absPose.scale() = glm::vec3(1.0f);
|
||||
|
||||
AnimPose parentAbsPose;
|
||||
int parentIndex = _skeleton->getParentIndex(iter.first);
|
||||
if (parentIndex >= 0) {
|
||||
parentAbsPose = _skeleton->getAbsolutePose(parentIndex, _relativePoses);
|
||||
}
|
||||
|
||||
// if parent should "look-at" child joint position.
|
||||
if (iter.first == leftArmIndex || iter.first == rightArmIndex) {
|
||||
|
||||
AnimPose grandParentAbsPose;
|
||||
int grandParentIndex = _skeleton->getParentIndex(parentIndex);
|
||||
if (parentIndex >= 0) {
|
||||
grandParentAbsPose = _skeleton->getAbsolutePose(grandParentIndex, _relativePoses);
|
||||
}
|
||||
|
||||
// the shoulder should rotate toward the arm joint via "look-at" constraint
|
||||
parentAbsPose = boneLookAt(absPose.trans(), parentAbsPose);
|
||||
_relativePoses[parentIndex] = grandParentAbsPose.inverse() * parentAbsPose;
|
||||
}
|
||||
|
||||
// AJT: for now ignore translation on secondary poses.
|
||||
glm::vec3 origTrans = _relativePoses[iter.first].trans();
|
||||
_relativePoses[iter.first] = parentAbsPose.inverse() * absPose;
|
||||
|
|
|
@ -96,3 +96,14 @@ float accumulateTime(float startFrame, float endFrame, float timeScale, float cu
|
|||
return frame;
|
||||
}
|
||||
|
||||
// rotate bone's y-axis with target.
|
||||
AnimPose boneLookAt(const glm::vec3& target, const AnimPose& bone) {
|
||||
glm::vec3 u, v, w;
|
||||
generateBasisVectors(target - bone.trans(), bone.rot() * Vectors::UNIT_X, u, v, w);
|
||||
glm::mat4 lookAt(glm::vec4(v, 0.0f),
|
||||
glm::vec4(u, 0.0f),
|
||||
// AJT: TODO REVISIT THIS, this could be -w.
|
||||
glm::vec4(glm::normalize(glm::cross(v, u)), 0.0f),
|
||||
glm::vec4(bone.trans(), 1.0f));
|
||||
return AnimPose(lookAt);
|
||||
}
|
||||
|
|
|
@ -31,4 +31,6 @@ inline glm::quat safeLerp(const glm::quat& a, const glm::quat& b, float alpha) {
|
|||
return glm::normalize(glm::lerp(a, bTemp, alpha));
|
||||
}
|
||||
|
||||
AnimPose boneLookAt(const glm::vec3& target, const AnimPose& bone);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -644,17 +644,8 @@ void ViveControllerManager::InputDevice::updateCalibratedLimbs() {
|
|||
_poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT);
|
||||
_poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS);
|
||||
_poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2);
|
||||
controller::Pose rightArmPose = addOffsetToPuckPose(controller::RIGHT_ARM);
|
||||
_poseStateMap[controller::RIGHT_ARM] = rightArmPose;
|
||||
if (rightArmPose.isValid()) {
|
||||
// AJT: TODO: compute rotation for RIGHT_SHOULDER AS WELL.
|
||||
}
|
||||
|
||||
controller::Pose leftArmPose = addOffsetToPuckPose(controller::LEFT_ARM);
|
||||
_poseStateMap[controller::LEFT_ARM] = leftArmPose;
|
||||
if (leftArmPose.isValid()) {
|
||||
// AJT: TODO: compute rotation for LEFT_SHOULDER AS WELL.
|
||||
}
|
||||
_poseStateMap[controller::RIGHT_ARM] = addOffsetToPuckPose(controller::RIGHT_ARM);
|
||||
_poseStateMap[controller::LEFT_ARM] = addOffsetToPuckPose(controller::LEFT_ARM);
|
||||
|
||||
if (_overrideHead) {
|
||||
_poseStateMap[controller::HEAD] = addOffsetToPuckPose(controller::HEAD);
|
||||
|
@ -1146,6 +1137,25 @@ static glm::vec3 computeUserShoulderPositionFromHistory(const glm::mat4& headMat
|
|||
return transformPoint(headMat, center);
|
||||
}
|
||||
|
||||
// y axis comes out of puck usb port/green light
|
||||
// -z axis comes out of puck center/vive logo
|
||||
static glm::vec3 computeUserShoulderPositionFromMeasurements(const glm::mat4& headMat, const controller::Pose& armPuck, bool isLeftHand) {
|
||||
// AJT: TODO measurments are hard coded!
|
||||
const float ARM_CIRC = 0.33f; // 13 inches
|
||||
const float SHOULDER_SPAN = 0.4826; // 19 inches
|
||||
|
||||
float armRadius = ARM_CIRC / TWO_PI;
|
||||
|
||||
float sign = isLeftHand ? 1.0f : -1.0f;
|
||||
float localArmX = sign * SHOULDER_SPAN / 2.0f;
|
||||
|
||||
controller::Pose localPuck = armPuck.transform(glm::inverse(headMat));
|
||||
glm::mat4 localPuckMat = localPuck.getMatrix();
|
||||
glm::vec3 localArmCenter = extractTranslation(localPuckMat) + armRadius * transformVectorFast(localPuckMat, Vectors::UNIT_Z);
|
||||
|
||||
return transformPoint(headMat, glm::vec3(localArmX, localArmCenter.y, localArmCenter.z));
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::calibrateShoulders(const glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration,
|
||||
int firstShoulderIndex, int secondShoulderIndex) {
|
||||
const PuckPosePair& firstShoulder = _validTrackedObjects[firstShoulderIndex];
|
||||
|
@ -1160,13 +1170,18 @@ void ViveControllerManager::InputDevice::calibrateShoulders(const glm::mat4& def
|
|||
glm::mat4 userRefRightArm = refRightArm;
|
||||
|
||||
glm::mat4 headMat = defaultToReferenceMat * inputCalibration.defaultHeadMat;
|
||||
/* AJT: TODO REMOVE
|
||||
userRefLeftArm[3] = glm::vec4(computeUserShoulderPositionFromHistory(headMat, _leftControllerHistory), 1.0f);
|
||||
userRefRightArm[3] = glm::vec4(computeUserShoulderPositionFromHistory(headMat, _rightControllerHistory), 1.0f);
|
||||
*/
|
||||
|
||||
if (firstShoulderPose.translation.x < secondShoulderPose.translation.x) {
|
||||
_jointToPuckMap[controller::LEFT_ARM] = firstShoulder.first;
|
||||
_jointToPuckMap[controller::RIGHT_ARM] = secondShoulder.first;
|
||||
|
||||
userRefLeftArm[3] = glm::vec4(computeUserShoulderPositionFromMeasurements(headMat, firstShoulderPose, true), 1.0f);
|
||||
userRefRightArm[3] = glm::vec4(computeUserShoulderPositionFromMeasurements(headMat, secondShoulderPose, false), 1.0f);
|
||||
|
||||
// compute the post offset from the userRefArm
|
||||
_pucksPostOffset[firstShoulder.first] = computeOffset(Matrices::IDENTITY, userRefLeftArm, firstShoulderPose);
|
||||
_pucksPostOffset[secondShoulder.first] = computeOffset(Matrices::IDENTITY, userRefRightArm, secondShoulderPose);
|
||||
|
@ -1179,6 +1194,9 @@ void ViveControllerManager::InputDevice::calibrateShoulders(const glm::mat4& def
|
|||
_jointToPuckMap[controller::LEFT_ARM] = secondShoulder.first;
|
||||
_jointToPuckMap[controller::RIGHT_ARM] = firstShoulder.first;
|
||||
|
||||
userRefLeftArm[3] = glm::vec4(computeUserShoulderPositionFromMeasurements(headMat, secondShoulderPose, true), 1.0f);
|
||||
userRefRightArm[3] = glm::vec4(computeUserShoulderPositionFromMeasurements(headMat, firstShoulderPose, false), 1.0f);
|
||||
|
||||
// compute the post offset from the userRefArm
|
||||
_pucksPostOffset[secondShoulder.first] = computeOffset(Matrices::IDENTITY, userRefLeftArm, secondShoulderPose);
|
||||
_pucksPostOffset[firstShoulder.first] = computeOffset(Matrices::IDENTITY, userRefRightArm, firstShoulderPose);
|
||||
|
|
Loading…
Reference in a new issue