1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 23:49:55 +00:00

Character movement following VR movement

This commit is contained in:
Mads Buvik Sandvei 2020-02-23 12:56:48 +01:00
parent bdade49129
commit 1d47807419
4 changed files with 96 additions and 12 deletions

View file

@ -42,6 +42,7 @@
#ifdef USE_OPENXR
#include "../mwvr/openxrsession.hpp"
#include "../mwvr/openxrinputmanager.hpp"
#endif
#include "collisiontype.hpp"
@ -383,6 +384,81 @@ namespace MWPhysics
Stepper stepper(collisionWorld, colobj);
osg::Vec3f origVelocity = velocity;
osg::Vec3f newPosition = position;
#ifdef USE_OPENXR
if (isPlayer)
{
auto inputManager = MWBase::Environment::get().getXRInputManager();
osg::Vec3 trackingOffset = inputManager->mHeadOffset;
// Player's tracking height should not affect character position
trackingOffset.z() = 0;
float remainingTime = time;
float remainder = 1.f;
for (int iterations = 0; iterations < sMaxIterations && remainingTime > 0.01f && remainder > 0.01; ++iterations)
{
osg::Vec3 toMove = trackingOffset * remainder;
osg::Vec3 nextpos = newPosition + toMove;
if ((newPosition - nextpos).length2() > 0.0001)
{
// trace to where character would go if there were no obstructions
tracer.doTrace(colobj, newPosition, nextpos, collisionWorld);
// check for obstructions
if (tracer.mFraction >= 1.0f)
{
newPosition = tracer.mEndPos; // ok to move, so set newPosition
remainder = 0.f;
break;
}
}
else
{
// The current position and next position are nearly the same, so just exit.
// Note: Bullet can trigger an assert in debug modes if the positions
// are the same, since that causes it to attempt to normalize a zero
// length vector (which can also happen with nearly identical vectors, since
// precision can be lost due to any math Bullet does internally). Since we
// aren't performing any collision detection, we want to reject the next
// position, so that we don't slowly move inside another object.
remainder = 0.f;
break;
}
// We are touching something.
if (tracer.mFraction < 1E-9f)
{
// Try to separate by backing off slighly to unstuck the solver
osg::Vec3f backOff = (newPosition - tracer.mHitPoint) * 1E-2f;
newPosition += backOff;
}
// We hit something. Check if we can step up.
float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + halfExtents.z();
osg::Vec3f oldPosition = newPosition;
bool result = false;
if (hitHeight < sStepSizeUp && !isActor(tracer.mHitObject))
{
// Try to step up onto it.
// NOTE: stepMove does not allow stepping over, modifies newPosition if successful
result = stepper.step(newPosition, toMove, remainingTime);
remainder = remainingTime / time;
}
}
// Best effort attempt and not losing any tracking
osg::Vec3 moved = newPosition - position;
inputManager->mHeadOffset.x() -= moved.x();
inputManager->mHeadOffset.y() -= moved.y();
Log(Debug::Verbose) << "trackingOffset: " << trackingOffset << ", remainder=" << remainder << ", moved=" << moved;
}
#endif
/*
* A loop to find newPosition using tracer, if successful different from the starting position.
* nextpos is the local variable used to find potential newPosition, using velocity and remainingTime
@ -391,7 +467,7 @@ namespace MWPhysics
float remainingTime = time;
for(int iterations = 0; iterations < sMaxIterations && remainingTime > 0.01f; ++iterations)
{
osg::Vec3f nextpos = newPosition + velocity * remainingTime;
osg::Vec3 nextpos = newPosition + velocity * remainingTime;
// If not able to fly, don't allow to swim up into the air
if(!isFlying && // can't fly

View file

@ -116,22 +116,24 @@ namespace MWRender
if (mTrackingPtr.isEmpty())
return;
osg::Vec3d position = getFocalPoint();
osg::Quat orient = osg::Quat(getPitch(), osg::Vec3d(1,0,0)) * osg::Quat(getRoll(), osg::Vec3d(0, 1, 0)) * osg::Quat(getYaw(), osg::Vec3d(0,0,1));
osg::Vec3d position = getFocalPoint();
#ifdef USE_OPENXR
auto inputManager = MWBase::Environment::get().getXRInputManager();
if (inputManager)
{
position += inputManager->mHeadOffset;
// To show the body, we'll need a neck offset for comfort
// This won't do as it will mess with tracking when the player turns his head
//position += orient * osg::Vec3(0, 15, 0);
}
#endif
osg::Quat orient = osg::Quat(getPitch(), osg::Vec3d(1,0,0)) * osg::Quat(getRoll(), osg::Vec3d(0, 1, 0)) * osg::Quat(getYaw(), osg::Vec3d(0,0,1));
#else
osg::Vec3d offset = orient * osg::Vec3d(0, isFirstPerson() ? 0 : -mCameraDistance, 0);
position += offset;
#endif
osg::Vec3d forward = orient * osg::Vec3d(0,1,0);
osg::Vec3d up = orient * osg::Vec3d(0,0,1);
@ -343,10 +345,6 @@ namespace MWRender
void Camera::setPitch(float angle)
{
//#ifdef USE_OPENXR
// // Pitch is defined purely by the HMD.
// return (void)angle;
//#endif
const float epsilon = 0.000001f;
float limit = osg::PI_2 - epsilon;
if(mPreviewMode)

View file

@ -194,6 +194,15 @@ void OpenXRAnimation::updateParts()
removeIndividualPart(ESM::PartReferenceType::PRT_RForearm);
removeIndividualPart(ESM::PartReferenceType::PRT_RUpperarm);
removeIndividualPart(ESM::PartReferenceType::PRT_RWrist);
removeIndividualPart(ESM::PartReferenceType::PRT_Cuirass);
removeIndividualPart(ESM::PartReferenceType::PRT_Groin);
removeIndividualPart(ESM::PartReferenceType::PRT_Neck);
removeIndividualPart(ESM::PartReferenceType::PRT_Skirt);
removeIndividualPart(ESM::PartReferenceType::PRT_Tail);
removeIndividualPart(ESM::PartReferenceType::PRT_LLeg);
removeIndividualPart(ESM::PartReferenceType::PRT_RLeg);
removeIndividualPart(ESM::PartReferenceType::PRT_LAnkle);
removeIndividualPart(ESM::PartReferenceType::PRT_RAnkle);
}
void OpenXRAnimation::setPointForward(bool enabled)
{

View file

@ -971,6 +971,7 @@ namespace MWVR
auto* session = MWBase::Environment::get().getXRSession();
auto currentHeadPose = session->predictedPoses().head[(int)TrackedSpace::STAGE];
session->mXR->playerScale(currentHeadPose);
currentHeadPose.position *= session->unitsPerMeter();
osg::Vec3 vrMovement = currentHeadPose.position - mPreviousHeadPose.position;
mPreviousHeadPose = currentHeadPose;
@ -999,7 +1000,7 @@ namespace MWVR
world->rotateObject(player, rot[0], rot[1], rot[2], MWBase::RotationFlag_none);
}
// Z will and should not be caught by the characyer
// Z should not be affected
mHeadOffset.z() = currentHeadPose.position.z();
}
}