1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-28 20:36:42 +00:00

Move third person camera collision check from World::updatePlayer() to Camera::updatePosition()

This commit is contained in:
Petr Mikheev 2020-07-25 21:12:50 +02:00
parent 5c7ecb865c
commit ed3426cf2f
7 changed files with 52 additions and 48 deletions

View file

@ -51,6 +51,11 @@ namespace ESM
struct TimeStamp; struct TimeStamp;
} }
namespace MWPhysics
{
class PhysicsSystem;
}
namespace MWRender namespace MWRender
{ {
class Animation; class Animation;
@ -115,6 +120,8 @@ namespace MWBase
virtual void readRecord (ESM::ESMReader& reader, uint32_t type, virtual void readRecord (ESM::ESMReader& reader, uint32_t type,
const std::map<int, int>& contentFileMap) = 0; const std::map<int, int>& contentFileMap) = 0;
virtual const MWPhysics::PhysicsSystem* getPhysics() const = 0;
virtual MWWorld::CellStore *getExterior (int x, int y) = 0; virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
virtual MWWorld::CellStore *getInterior (const std::string& name) = 0; virtual MWWorld::CellStore *getInterior (const std::string& name) = 0;

View file

@ -311,7 +311,7 @@ namespace MWPhysics
return result; return result;
} }
PhysicsSystem::RayResult PhysicsSystem::castSphere(const osg::Vec3f &from, const osg::Vec3f &to, float radius) PhysicsSystem::RayResult PhysicsSystem::castSphere(const osg::Vec3f &from, const osg::Vec3f &to, float radius) const
{ {
btCollisionWorld::ClosestConvexResultCallback callback(Misc::Convert::toBullet(from), Misc::Convert::toBullet(to)); btCollisionWorld::ClosestConvexResultCallback callback(Misc::Convert::toBullet(from), Misc::Convert::toBullet(to));
callback.m_collisionFilterGroup = 0xff; callback.m_collisionFilterGroup = 0xff;

View file

@ -123,7 +123,7 @@ namespace MWPhysics
std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>(), std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>(),
int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const; int mask = CollisionType_World|CollisionType_HeightMap|CollisionType_Actor|CollisionType_Door, int group=0xff) const;
RayResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius); RayResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius) const;
/// Return true if actor1 can see actor2. /// Return true if actor1 can see actor2.
bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const; bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const;

View file

@ -7,6 +7,7 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
@ -16,6 +17,8 @@
#include "../mwmechanics/movement.hpp" #include "../mwmechanics/movement.hpp"
#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/npcstats.hpp"
#include "../mwphysics/physicssystem.hpp"
#include "npcanimation.hpp" #include "npcanimation.hpp"
namespace namespace
@ -195,6 +198,7 @@ namespace MWRender
rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true); rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true);
updateFocalPointOffset(duration); updateFocalPointOffset(duration);
updatePosition();
float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr); float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr);
speed /= (1.f + speed / 500.f); speed /= (1.f + speed / 500.f);
@ -205,6 +209,42 @@ namespace MWRender
updateStandingPreviewMode(); updateStandingPreviewMode();
} }
void Camera::updatePosition()
{
mFocalPointAdjustment = osg::Vec3d();
if (isFirstPerson())
return;
const float cameraObstacleLimit = 5.0f;
const float focalObstacleLimit = 10.f;
const MWPhysics::PhysicsSystem* physics = MWBase::Environment::get().getWorld()->getPhysics();
// Adjust focal point to prevent clipping.
osg::Vec3d focal = getFocalPoint();
osg::Vec3d focalOffset = getFocalPointOffset();
float offsetLen = focalOffset.length();
if (offsetLen > 0)
{
MWPhysics::PhysicsSystem::RayResult result = physics->castSphere(focal - focalOffset, focal, focalObstacleLimit);
if (result.mHit)
{
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
mFocalPointAdjustment = focalOffset * std::max(-1.0, adjustmentCoef);
}
}
// Calculate camera distance.
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
if (mDynamicCameraDistanceEnabled)
mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance);
osg::Vec3d cameraPos;
getPosition(focal, cameraPos);
MWPhysics::PhysicsSystem::RayResult result = physics->castSphere(focal, cameraPos, cameraObstacleLimit);
if (result.mHit)
mCameraDistance = (result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length();
}
void Camera::updateStandingPreviewMode() void Camera::updateStandingPreviewMode()
{ {
if (!mStandingPreviewAllowed) if (!mStandingPreviewAllowed)
@ -389,7 +429,6 @@ namespace MWRender
mIsNearest = dist <= mNearest; mIsNearest = dist <= mNearest;
mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest); mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest);
Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance); Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance);
setCameraDistance();
} }
void Camera::setCameraDistance(float dist, bool adjust) void Camera::setCameraDistance(float dist, bool adjust)
@ -414,16 +453,6 @@ namespace MWRender
return pitchCorrection + speedCorrection; return pitchCorrection + speedCorrection;
} }
void Camera::setCameraDistance()
{
mFocalPointAdjustment = osg::Vec3d();
if (isFirstPerson())
return;
mCameraDistance = mBaseCameraDistance + getCameraDistanceCorrection();
if (mDynamicCameraDistanceEnabled)
mCameraDistance = std::min(mCameraDistance, mMaxNextCameraDistance);
}
void Camera::setAnimation(NpcAnimation *anim) void Camera::setAnimation(NpcAnimation *anim)
{ {
mAnimation = anim; mAnimation = anim;

View file

@ -73,6 +73,7 @@ namespace MWRender
bool mShowCrosshairInThirdPersonMode; bool mShowCrosshairInThirdPersonMode;
void updateFocalPointOffset(float duration); void updateFocalPointOffset(float duration);
void updatePosition();
float getCameraDistanceCorrection() const; float getCameraDistanceCorrection() const;
osg::ref_ptr<osg::NodeCallback> mUpdateCallback; osg::ref_ptr<osg::NodeCallback> mUpdateCallback;
@ -144,16 +145,12 @@ namespace MWRender
/// Default distance can be restored with setCameraDistance(). /// Default distance can be restored with setCameraDistance().
void setCameraDistance(float dist, bool adjust = false); void setCameraDistance(float dist, bool adjust = false);
/// Restore default camera distance and offset for current mode.
void setCameraDistance();
float getCameraDistance() const; float getCameraDistance() const;
void setAnimation(NpcAnimation *anim); void setAnimation(NpcAnimation *anim);
osg::Vec3d getFocalPoint() const; osg::Vec3d getFocalPoint() const;
osg::Vec3d getFocalPointOffset() const; osg::Vec3d getFocalPointOffset() const;
void adjustFocalPoint(osg::Vec3d adjustment) { mFocalPointAdjustment = adjustment; }
/// Stores focal and camera world positions in passed arguments /// Stores focal and camera world positions in passed arguments
void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const; void getPosition(osg::Vec3d &focal, osg::Vec3d &camera) const;

View file

@ -1863,37 +1863,6 @@ namespace MWWorld
int nightEye = static_cast<int>(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude()); int nightEye = static_cast<int>(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude());
mRendering->setNightEyeFactor(std::min(1.f, (nightEye/100.f))); mRendering->setNightEyeFactor(std::min(1.f, (nightEye/100.f)));
auto* camera = mRendering->getCamera();
camera->setCameraDistance();
if(!mRendering->getCamera()->isFirstPerson())
{
float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f;
float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f);
// Adjust focal point.
osg::Vec3d focal = camera->getFocalPoint();
osg::Vec3d focalOffset = camera->getFocalPointOffset();
float offsetLen = focalOffset.length();
if (offsetLen > 0)
{
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit);
if (result.mHit)
{
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
if (adjustmentCoef < -1)
adjustmentCoef = -1;
camera->adjustFocalPoint(focalOffset * adjustmentCoef);
}
}
// Adjust camera position.
osg::Vec3d cameraPos;
camera->getPosition(focal, cameraPos);
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal, cameraPos, cameraObstacleLimit);
if (result.mHit)
mRendering->getCamera()->setCameraDistance((result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length(), false);
}
} }
void World::preloadSpells() void World::preloadSpells()

View file

@ -214,6 +214,8 @@ namespace MWWorld
void readRecord (ESM::ESMReader& reader, uint32_t type, void readRecord (ESM::ESMReader& reader, uint32_t type,
const std::map<int, int>& contentFileMap) override; const std::map<int, int>& contentFileMap) override;
const MWPhysics::PhysicsSystem* getPhysics() const override { return mPhysics.get(); }
CellStore *getExterior (int x, int y) override; CellStore *getExterior (int x, int y) override;
CellStore *getInterior (const std::string& name) override; CellStore *getInterior (const std::string& name) override;