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

pull/593/head
Petr Mikheev 5 years ago
parent 5c7ecb865c
commit ed3426cf2f

@ -51,6 +51,11 @@ namespace ESM
struct TimeStamp;
}
namespace MWPhysics
{
class PhysicsSystem;
}
namespace MWRender
{
class Animation;
@ -115,6 +120,8 @@ namespace MWBase
virtual void readRecord (ESM::ESMReader& reader, uint32_t type,
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 *getInterior (const std::string& name) = 0;

@ -311,7 +311,7 @@ namespace MWPhysics
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));
callback.m_collisionFilterGroup = 0xff;

@ -123,7 +123,7 @@ namespace MWPhysics
std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>(),
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.
bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const;

@ -7,6 +7,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/ptr.hpp"
@ -16,6 +17,8 @@
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwphysics/physicssystem.hpp"
#include "npcanimation.hpp"
namespace
@ -195,6 +198,7 @@ namespace MWRender
rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true);
updateFocalPointOffset(duration);
updatePosition();
float speed = mTrackingPtr.getClass().getSpeed(mTrackingPtr);
speed /= (1.f + speed / 500.f);
@ -205,6 +209,42 @@ namespace MWRender
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()
{
if (!mStandingPreviewAllowed)
@ -389,7 +429,6 @@ namespace MWRender
mIsNearest = dist <= mNearest;
mBaseCameraDistance = osg::clampBetween(dist, mNearest, mFurthest);
Settings::Manager::setFloat("third person camera distance", "Camera", mBaseCameraDistance);
setCameraDistance();
}
void Camera::setCameraDistance(float dist, bool adjust)
@ -414,16 +453,6 @@ namespace MWRender
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)
{
mAnimation = anim;

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

@ -1863,37 +1863,6 @@ namespace MWWorld
int nightEye = static_cast<int>(player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).getMagnitude());
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()

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

Loading…
Cancel
Save