mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 02:49:55 +00:00
Character movement following VR movement
This commit is contained in:
parent
bdade49129
commit
1d47807419
4 changed files with 96 additions and 12 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue