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:
parent
5c7ecb865c
commit
ed3426cf2f
7 changed files with 52 additions and 48 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue