mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Head input action will override the HMD for IK.
This commit is contained in:
parent
ef43ff4b99
commit
764f6c69ea
6 changed files with 97 additions and 104 deletions
|
@ -83,21 +83,21 @@ const float MyAvatar::ZOOM_MIN = 0.5f;
|
|||
const float MyAvatar::ZOOM_MAX = 25.0f;
|
||||
const float MyAvatar::ZOOM_DEFAULT = 1.5f;
|
||||
|
||||
// 2 meter tall dude (in avatar coordinates)
|
||||
static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.9f, 0.0f };
|
||||
// default values, used when avatar is missing joints... (avatar space)
|
||||
static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 };
|
||||
static const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.8f, 0.0f };
|
||||
static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f };
|
||||
static const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 };
|
||||
static const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.7f, 0.0f };
|
||||
static const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f };
|
||||
static const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.445f, 0.025f };
|
||||
static const glm::quat DEFAULT_AVATAR_NECK_ROT { Quaternions::Y_180 };
|
||||
static const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.5f, 0.0f };
|
||||
static const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.32f, 0.02f };
|
||||
static const glm::quat DEFAULT_AVATAR_SPINE2_ROT { Quaternions::Y_180};
|
||||
static const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.05f, 0.0f };
|
||||
static const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.0f, 0.0f };
|
||||
static const glm::quat DEFAULT_AVATAR_HIPS_ROT { Quaternions::Y_180 };
|
||||
static const glm::vec3 DEFAULT_AVATAR_LEFTFOOT_POS { -0.1f, -0.9f, 0.0f }; // AJT: TODO: WRONG FIX ME
|
||||
static const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { Quaternions::IDENTITY }; // AJT: TODO: WRONG FIX ME
|
||||
static const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.1f, -0.9f, 0.0f }; // AJT: TODO: WRONG FIX ME
|
||||
static const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { Quaternions::IDENTITY }; // AJT: TODO: WRONG FIX ME
|
||||
static const glm::vec3 DEFAULT_AVATAR_LEFTFOOT_POS { -0.08f, -0.96f, 0.029f};
|
||||
static const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { -0.40167322754859924f, 0.9154590368270874f, -0.005437685176730156f, -0.023744143545627594f };
|
||||
static const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.08f, -0.96f, 0.029f };
|
||||
static const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.9154615998268127f, 0.0053307069465518f, 0.023696165531873703f };
|
||||
|
||||
MyAvatar::MyAvatar(RigPointer rig) :
|
||||
Avatar(rig),
|
||||
|
@ -1433,14 +1433,12 @@ controller::Pose MyAvatar::getSpine2ControllerPoseInAvatarFrame() const {
|
|||
return getSpine2ControllerPoseInWorldFrame().transform(invAvatarMatrix);
|
||||
}
|
||||
|
||||
void MyAvatar::setHeadControllerPoseInSensorFrame(const controller::Pose& headPose) {
|
||||
bool inHmd = qApp->isHMDMode();
|
||||
Head* head = getHead();
|
||||
if (inHmd) {
|
||||
_headControllerPoseInSensorFrameCache.set(headPose);
|
||||
head->setDeltaPitch(headPose.rotation.x);
|
||||
head->setDeltaYaw(headPose.rotation.y);
|
||||
head->setDeltaRoll(headPose.rotation.z);
|
||||
void MyAvatar::setHeadControllerPoseInSensorFrame(const controller::Pose& head) {
|
||||
if (controller::InputDevice::getLowVelocityFilter()) {
|
||||
auto oldHeadPose = getHeadControllerPoseInSensorFrame();
|
||||
_headControllerPoseInSensorFrameCache.set(applyLowVelocityFilter(oldHeadPose, head));
|
||||
} else {
|
||||
_headControllerPoseInSensorFrameCache.set(head);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -460,7 +460,7 @@ public:
|
|||
controller::Pose getHipsControllerPoseInAvatarFrame() const;
|
||||
controller::Pose getSpine2ControllerPoseInAvatarFrame() const;
|
||||
|
||||
void setHeadControllerPoseInSensorFrame(const controller::Pose& headPose);
|
||||
void setHeadControllerPoseInSensorFrame(const controller::Pose& head);
|
||||
controller::Pose getHeadControllerPoseInSensorFrame() const;
|
||||
controller::Pose getHeadControllerPoseInWorldFrame() const;
|
||||
controller::Pose getHeadControllerPoseInAvatarFrame() const;
|
||||
|
|
|
@ -107,29 +107,27 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
Rig::HeadParameters headParams;
|
||||
|
||||
if (qApp->isHMDMode()) {
|
||||
// get HMD position from sensor space into world space, and back into rig space
|
||||
glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation());
|
||||
glm::mat4 worldToRig = glm::inverse(rigToWorld);
|
||||
glm::mat4 rigHMDMat = worldToRig * worldHMDMat;
|
||||
|
||||
headParams.rigHeadPosition = extractTranslation(rigHMDMat);
|
||||
headParams.rigHeadOrientation = extractRotation(rigHMDMat);
|
||||
headParams.worldHeadOrientation = extractRotation(worldHMDMat);
|
||||
// input action is the highest priority source for head orientation.
|
||||
auto avatarHeadPose = myAvatar->getHeadControllerPoseInAvatarFrame();
|
||||
if (avatarHeadPose.isValid()) {
|
||||
glm::mat4 rigHeadMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation());
|
||||
headParams.rigHeadPosition = extractTranslation(rigHeadMat);
|
||||
headParams.rigHeadOrientation = glmExtractRotation(rigHeadMat);
|
||||
headParams.headEnabled = true;
|
||||
} else {
|
||||
auto avatarHeadPose = myAvatar->getHeadControllerPoseInAvatarFrame();
|
||||
if (avatarHeadPose.isValid()) {
|
||||
glm::mat4 rigHeadMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation());
|
||||
headParams.rigHeadPosition = extractTranslation(rigHeadMat);
|
||||
headParams.rigHeadOrientation = glmExtractRotation(rigHeadMat);
|
||||
headParams.worldHeadOrientation = myAvatar->getHeadControllerPoseInWorldFrame().getTranslation();
|
||||
if (qApp->isHMDMode()) {
|
||||
// get HMD position from sensor space into world space, and back into rig space
|
||||
glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation());
|
||||
glm::mat4 worldToRig = glm::inverse(rigToWorld);
|
||||
glm::mat4 rigHMDMat = worldToRig * worldHMDMat;
|
||||
_rig->computeHeadFromHMD(AnimPose(rigHMDMat), headParams.rigHeadPosition, headParams.rigHeadOrientation);
|
||||
headParams.headEnabled = true;
|
||||
} else {
|
||||
// even though full head IK is disabled, the rig still needs the head orientation to rotate the head up and down in desktop mode.
|
||||
headParams.rigHeadOrientation = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame();
|
||||
headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
|
||||
// preMult 180 is necessary to convert from avatar to rig coordinates.
|
||||
// postMult 180 is necessary to convert head from -z forward to z forward.
|
||||
headParams.rigHeadOrientation = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180;
|
||||
headParams.headEnabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +150,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
headParams.spine2Enabled = false;
|
||||
}
|
||||
|
||||
headParams.neckJointIndex = geometry.neckJointIndex;
|
||||
headParams.isTalking = head->getTimeWithoutTalking() <= 1.5f;
|
||||
|
||||
_rig->updateFromHeadParameters(headParams, deltaTime);
|
||||
|
@ -212,7 +209,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
Model::updateRig(deltaTime, parentTransform);
|
||||
|
||||
Rig::EyeParameters eyeParams;
|
||||
eyeParams.worldHeadOrientation = headParams.worldHeadOrientation;
|
||||
eyeParams.eyeLookAt = lookAt;
|
||||
eyeParams.eyeSaccade = head->getSaccade();
|
||||
eyeParams.modelRotation = getRotation();
|
||||
|
@ -244,7 +240,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
head->setBaseRoll(glm::degrees(-eulers.z));
|
||||
|
||||
Rig::EyeParameters eyeParams;
|
||||
eyeParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
|
||||
eyeParams.eyeLookAt = lookAt;
|
||||
eyeParams.eyeSaccade = glm::vec3(0.0f);
|
||||
eyeParams.modelRotation = getRotation();
|
||||
|
|
|
@ -46,7 +46,6 @@ static bool isEqual(const glm::quat& p, const glm::quat& q) {
|
|||
const glm::vec3 DEFAULT_RIGHT_EYE_POS(-0.3f, 0.9f, 0.0f);
|
||||
const glm::vec3 DEFAULT_LEFT_EYE_POS(0.3f, 0.9f, 0.0f);
|
||||
const glm::vec3 DEFAULT_HEAD_POS(0.0f, 0.75f, 0.0f);
|
||||
const glm::vec3 DEFAULT_NECK_POS(0.0f, 0.70f, 0.0f);
|
||||
|
||||
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||
|
||||
|
@ -1020,7 +1019,7 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
|||
}
|
||||
|
||||
void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) {
|
||||
updateNeckJoint(params.neckJointIndex, params);
|
||||
updateHeadAnimVars(params);
|
||||
|
||||
_animVars.set("isTalking", params.isTalking);
|
||||
_animVars.set("notIsTalking", !params.isTalking);
|
||||
|
@ -1043,74 +1042,40 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) {
|
|||
}
|
||||
|
||||
void Rig::updateFromEyeParameters(const EyeParameters& params) {
|
||||
updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation,
|
||||
params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
|
||||
updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation,
|
||||
params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
|
||||
updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation, params.eyeLookAt, params.eyeSaccade);
|
||||
updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, params.eyeLookAt, params.eyeSaccade);
|
||||
}
|
||||
|
||||
void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut,
|
||||
glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const {
|
||||
void Rig::computeHeadFromHMD(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut) const {
|
||||
|
||||
// the input hmd values are in avatar/rig space
|
||||
const glm::vec3& hmdPosition = hmdPose.trans();
|
||||
const glm::quat& hmdOrientation = hmdPose.rot();
|
||||
|
||||
// the HMD looks down the negative z axis, but the head bone looks down the z axis, so apply a 180 degree rotation.
|
||||
const glm::quat& hmdOrientation = hmdPose.rot() * Quaternions::Y_180;
|
||||
|
||||
// TODO: cache jointIndices
|
||||
int rightEyeIndex = indexOfJoint("RightEye");
|
||||
int leftEyeIndex = indexOfJoint("LeftEye");
|
||||
int headIndex = indexOfJoint("Head");
|
||||
int neckIndex = indexOfJoint("Neck");
|
||||
|
||||
glm::vec3 absRightEyePos = rightEyeIndex != -1 ? getAbsoluteDefaultPose(rightEyeIndex).trans() : DEFAULT_RIGHT_EYE_POS;
|
||||
glm::vec3 absLeftEyePos = leftEyeIndex != -1 ? getAbsoluteDefaultPose(leftEyeIndex).trans() : DEFAULT_LEFT_EYE_POS;
|
||||
glm::vec3 absHeadPos = headIndex != -1 ? getAbsoluteDefaultPose(headIndex).trans() : DEFAULT_HEAD_POS;
|
||||
glm::vec3 absNeckPos = neckIndex != -1 ? getAbsoluteDefaultPose(neckIndex).trans() : DEFAULT_NECK_POS;
|
||||
|
||||
glm::vec3 absCenterEyePos = (absRightEyePos + absLeftEyePos) / 2.0f;
|
||||
glm::vec3 eyeOffset = absCenterEyePos - absHeadPos;
|
||||
glm::vec3 headOffset = absHeadPos - absNeckPos;
|
||||
|
||||
// apply simplistic head/neck model
|
||||
|
||||
// head
|
||||
headPositionOut = hmdPosition - hmdOrientation * eyeOffset;
|
||||
|
||||
headOrientationOut = hmdOrientation;
|
||||
|
||||
// neck
|
||||
neckPositionOut = hmdPosition - hmdOrientation * (headOffset + eyeOffset);
|
||||
|
||||
// slerp between default orientation and hmdOrientation
|
||||
neckOrientationOut = safeMix(hmdOrientation, _animSkeleton->getRelativeDefaultPose(neckIndex).rot(), 0.5f);
|
||||
}
|
||||
|
||||
void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
||||
if (_animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints()) {
|
||||
glm::quat yFlip180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
void Rig::updateHeadAnimVars(const HeadParameters& params) {
|
||||
if (_animSkeleton) {
|
||||
if (params.headEnabled) {
|
||||
glm::vec3 headPos, neckPos;
|
||||
glm::quat headRot, neckRot;
|
||||
|
||||
AnimPose hmdPose(glm::vec3(1.0f), params.rigHeadOrientation * yFlip180, params.rigHeadPosition);
|
||||
computeHeadNeckAnimVars(hmdPose, headPos, headRot, neckPos, neckRot);
|
||||
|
||||
// debug rendering
|
||||
#ifdef DEBUG_RENDERING
|
||||
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
const glm::vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
|
||||
// transform from bone into avatar space
|
||||
AnimPose headPose(glm::vec3(1), headRot, headPos);
|
||||
DebugDraw::getInstance().addMyAvatarMarker("headTarget", headPose.rot, headPose.trans, red);
|
||||
|
||||
// transform from bone into avatar space
|
||||
AnimPose neckPose(glm::vec3(1), neckRot, neckPos);
|
||||
DebugDraw::getInstance().addMyAvatarMarker("neckTarget", neckPose.rot, neckPose.trans, green);
|
||||
#endif
|
||||
|
||||
_animVars.set("headPosition", headPos);
|
||||
_animVars.set("headRotation", headRot);
|
||||
|
||||
_animVars.set("headPosition", params.rigHeadPosition);
|
||||
_animVars.set("headRotation", params.rigHeadOrientation);
|
||||
if (params.hipsEnabled) {
|
||||
// Since there is an explicit hips ik target, switch the head to use the more generic RotationAndPosition IK chain type.
|
||||
// this will allow the spine to bend more, ensuring that it can reach the head target position.
|
||||
|
@ -1120,23 +1085,15 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
|||
// but because the IK _hipsOffset is enabled, the hips will naturally follow underneath the head.
|
||||
_animVars.set("headType", (int)IKTarget::Type::HmdHead);
|
||||
}
|
||||
_animVars.set("neckPosition", neckPos);
|
||||
_animVars.set("neckRotation", neckRot);
|
||||
_animVars.set("neckType", (int)IKTarget::Type::Unknown); // 'Unknown' disables the target
|
||||
|
||||
} else {
|
||||
_animVars.unset("headPosition");
|
||||
_animVars.set("headRotation", params.rigHeadOrientation * yFlip180);
|
||||
_animVars.set("headAndNeckType", (int)IKTarget::Type::RotationOnly);
|
||||
_animVars.set("headRotation", params.rigHeadOrientation);
|
||||
_animVars.set("headType", (int)IKTarget::Type::RotationOnly);
|
||||
_animVars.unset("neckPosition");
|
||||
_animVars.unset("neckRotation");
|
||||
_animVars.set("neckType", (int)IKTarget::Type::RotationOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) {
|
||||
void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) {
|
||||
|
||||
// TODO: does not properly handle avatar scale.
|
||||
|
||||
|
|
|
@ -44,18 +44,15 @@ public:
|
|||
struct HeadParameters {
|
||||
glm::mat4 hipsMatrix = glm::mat4(); // rig space
|
||||
glm::mat4 spine2Matrix = glm::mat4(); // rig space
|
||||
glm::quat worldHeadOrientation = glm::quat(); // world space (-z forward)
|
||||
glm::quat rigHeadOrientation = glm::quat(); // rig space (-z forward)
|
||||
glm::vec3 rigHeadPosition = glm::vec3(); // rig space
|
||||
bool hipsEnabled = false;
|
||||
bool headEnabled = false;
|
||||
bool spine2Enabled = false;
|
||||
int neckJointIndex = -1;
|
||||
bool isTalking = false;
|
||||
};
|
||||
|
||||
struct EyeParameters {
|
||||
glm::quat worldHeadOrientation = glm::quat();
|
||||
glm::vec3 eyeLookAt = glm::vec3(); // world space
|
||||
glm::vec3 eyeSaccade = glm::vec3(); // world space
|
||||
glm::vec3 modelTranslation = glm::vec3();
|
||||
|
@ -232,6 +229,9 @@ public:
|
|||
|
||||
void setEnableDebugDrawIKTargets(bool enableDebugDrawIKTargets) { _enableDebugDrawIKTargets = enableDebugDrawIKTargets; }
|
||||
|
||||
// input assumed to be in rig space
|
||||
void computeHeadFromHMD(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut) const;
|
||||
|
||||
signals:
|
||||
void onLoadComplete();
|
||||
|
||||
|
@ -241,10 +241,9 @@ protected:
|
|||
void applyOverridePoses();
|
||||
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut);
|
||||
|
||||
void updateNeckJoint(int index, const HeadParameters& params);
|
||||
void computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut,
|
||||
glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const;
|
||||
void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
|
||||
void updateHeadAnimVars(const HeadParameters& params);
|
||||
|
||||
void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::vec3& lookAt, const glm::vec3& saccade);
|
||||
void calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut) const;
|
||||
|
||||
AnimPose _modelOffset; // model to rig space
|
||||
|
|
|
@ -26,6 +26,7 @@ Controller.enableMapping(TRIGGER_MAPPING_NAME);
|
|||
var CONTROLLER_MAPPING_NAME = "com.highfidelity.viveMotionCapture.controller";
|
||||
var controllerMapping;
|
||||
|
||||
var head;
|
||||
var leftFoot;
|
||||
var rightFoot;
|
||||
var hips;
|
||||
|
@ -77,8 +78,29 @@ function computeDefaultToReferenceXform() {
|
|||
}
|
||||
}
|
||||
|
||||
function computeHeadOffsetXform() {
|
||||
var leftEyeIndex = MyAvatar.getJointIndex("LeftEye");
|
||||
var rightEyeIndex = MyAvatar.getJointIndex("RightEye");
|
||||
var headIndex = MyAvatar.getJointIndex("Head");
|
||||
if (leftEyeIndex > 0 && rightEyeIndex > 0 && headIndex > 0) {
|
||||
var defaultHeadXform = new Xform(MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame(headIndex),
|
||||
MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(headIndex));
|
||||
var defaultLeftEyeXform = new Xform(MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame(leftEyeIndex),
|
||||
MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(leftEyeIndex));
|
||||
var defaultRightEyeXform = new Xform(MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame(rightEyeIndex),
|
||||
MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame(rightEyeIndex));
|
||||
var defaultCenterEyePos = Vec3.multiply(0.5, Vec3.sum(defaultLeftEyeXform.pos, defaultRightEyeXform.pos));
|
||||
var defaultCenterEyeXform = new Xform(defaultLeftEyeXform.rot, defaultCenterEyePos);
|
||||
|
||||
return Xform.mul(defaultCenterEyeXform.inv(), defaultHeadXform);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function calibrate() {
|
||||
|
||||
head = undefined;
|
||||
leftFoot = undefined;
|
||||
rightFoot = undefined;
|
||||
hips = undefined;
|
||||
|
@ -86,6 +108,13 @@ function calibrate() {
|
|||
|
||||
var defaultToReferenceXform = computeDefaultToReferenceXform();
|
||||
|
||||
var headOffsetXform = computeHeadOffsetXform();
|
||||
print("AJT: computed headOffsetXform " + (headOffsetXform ? JSON.stringify(headOffsetXform) : "undefined"));
|
||||
|
||||
if (headOffsetXform) {
|
||||
head = { offsetXform: headOffsetXform };
|
||||
}
|
||||
|
||||
var poses = [];
|
||||
if (Controller.Hardware.Vive) {
|
||||
TRACKED_OBJECT_POSES.forEach(function (key) {
|
||||
|
@ -202,6 +231,7 @@ function update(dt) {
|
|||
// go back to normal, vive pucks will be ignored.
|
||||
print("AJT: UN-CALIBRATE!");
|
||||
|
||||
head = undefined;
|
||||
leftFoot = undefined;
|
||||
rightFoot = undefined;
|
||||
hips = undefined;
|
||||
|
@ -217,6 +247,20 @@ function update(dt) {
|
|||
|
||||
controllerMapping = Controller.newMapping(CONTROLLER_MAPPING_NAME + calibrationCount);
|
||||
|
||||
if (head) {
|
||||
controllerMapping.from(function () {
|
||||
var worldToAvatarXform = (new Xform(MyAvatar.orientation, MyAvatar.position)).inv();
|
||||
head.latestPose = {
|
||||
valid: true,
|
||||
translation: worldToAvatarXform.xformPoint(HMD.position),
|
||||
rotation: Quat.multiply(worldToAvatarXform.rot, Quat.multiply(HMD.orientation, Y_180)), // postMult 180 rot flips head direction
|
||||
velocity: {x: 0, y: 0, z: 0}, // TODO: currently this is unused anyway...
|
||||
angularVelocity: {x: 0, y: 0, z: 0}
|
||||
};
|
||||
return convertJointInfoToPose(head);
|
||||
}).to(Controller.Standard.Head);
|
||||
}
|
||||
|
||||
if (leftFoot) {
|
||||
controllerMapping.from(leftFoot.channel).to(function (pose) {
|
||||
leftFoot.latestPose = pose;
|
||||
|
|
Loading…
Reference in a new issue