mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:19:55 +00:00
Apply third person camera distance to the camera node instead of only the camera itself (Fixes #1705)
This commit is contained in:
parent
f9b6cc468d
commit
85f5754bb6
6 changed files with 86 additions and 41 deletions
|
@ -19,6 +19,7 @@ namespace MWRender
|
|||
Camera::Camera (Ogre::Camera *camera)
|
||||
: mCamera(camera),
|
||||
mCameraNode(NULL),
|
||||
mCameraPosNode(NULL),
|
||||
mAnimation(NULL),
|
||||
mFirstPersonView(true),
|
||||
mPreviewMode(false),
|
||||
|
@ -66,12 +67,16 @@ namespace MWRender
|
|||
}
|
||||
|
||||
Ogre::Quaternion xr(Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_X);
|
||||
if (!mVanity.enabled && !mPreviewMode) {
|
||||
mCamera->getParentNode()->setOrientation(xr);
|
||||
} else {
|
||||
Ogre::Quaternion orient = xr;
|
||||
if (mVanity.enabled || mPreviewMode) {
|
||||
Ogre::Quaternion zr(Ogre::Radian(getYaw()), Ogre::Vector3::UNIT_Z);
|
||||
mCamera->getParentNode()->setOrientation(zr * xr);
|
||||
orient = zr * xr;
|
||||
}
|
||||
|
||||
if (isFirstPerson())
|
||||
mCamera->getParentNode()->setOrientation(orient);
|
||||
else
|
||||
mCameraNode->setOrientation(orient);
|
||||
}
|
||||
|
||||
const std::string &Camera::getHandle() const
|
||||
|
@ -79,20 +84,40 @@ namespace MWRender
|
|||
return mTrackingPtr.getRefData().getHandle();
|
||||
}
|
||||
|
||||
void Camera::attachTo(const MWWorld::Ptr &ptr)
|
||||
Ogre::SceneNode* Camera::attachTo(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
mTrackingPtr = ptr;
|
||||
Ogre::SceneNode *node = mTrackingPtr.getRefData().getBaseNode()->createChildSceneNode(Ogre::Vector3(0.0f, 0.0f, mHeight));
|
||||
node->setInheritScale(false);
|
||||
Ogre::SceneNode *posNode = node->createChildSceneNode();
|
||||
posNode->setInheritScale(false);
|
||||
if(mCameraNode)
|
||||
{
|
||||
node->setOrientation(mCameraNode->getOrientation());
|
||||
node->setPosition(mCameraNode->getPosition());
|
||||
node->setScale(mCameraNode->getScale());
|
||||
posNode->setPosition(mCameraPosNode->getPosition());
|
||||
mCameraNode->getCreator()->destroySceneNode(mCameraNode);
|
||||
mCameraNode->getCreator()->destroySceneNode(mCameraPosNode);
|
||||
}
|
||||
mCameraNode = node;
|
||||
if(!mCamera->isAttached())
|
||||
mCameraNode->attachObject(mCamera);
|
||||
mCameraPosNode = posNode;
|
||||
|
||||
if (!isFirstPerson())
|
||||
{
|
||||
mCamera->detachFromParent();
|
||||
mCameraPosNode->attachObject(mCamera);
|
||||
}
|
||||
|
||||
return mCameraPosNode;
|
||||
}
|
||||
|
||||
void Camera::setPosition(const Ogre::Vector3& position)
|
||||
{
|
||||
mCameraPosNode->setPosition(position);
|
||||
}
|
||||
|
||||
void Camera::setPosition(float x, float y, float z)
|
||||
{
|
||||
setPosition(Ogre::Vector3(x,y,z));
|
||||
}
|
||||
|
||||
void Camera::updateListener()
|
||||
|
@ -155,9 +180,9 @@ namespace MWRender
|
|||
processViewChange();
|
||||
|
||||
if (mFirstPersonView) {
|
||||
mCamera->setPosition(0.f, 0.f, 0.f);
|
||||
setPosition(0.f, 0.f, 0.f);
|
||||
} else {
|
||||
mCamera->setPosition(0.f, 0.f, mCameraDistance);
|
||||
setPosition(0.f, 0.f, mCameraDistance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,14 +216,14 @@ namespace MWRender
|
|||
Ogre::Vector3 rot(0.f, 0.f, 0.f);
|
||||
if (mVanity.enabled) {
|
||||
rot.x = Ogre::Degree(-30.f).valueRadians();
|
||||
mMainCam.offset = mCamera->getPosition().z;
|
||||
mMainCam.offset = mCameraPosNode->getPosition().z;
|
||||
} else {
|
||||
rot.x = getPitch();
|
||||
offset = mMainCam.offset;
|
||||
}
|
||||
rot.z = getYaw();
|
||||
|
||||
mCamera->setPosition(0.f, 0.f, offset);
|
||||
setPosition(0.f, 0.f, offset);
|
||||
rotateCamera(rot, false);
|
||||
|
||||
return true;
|
||||
|
@ -215,7 +240,7 @@ namespace MWRender
|
|||
mPreviewMode = enable;
|
||||
processViewChange();
|
||||
|
||||
float offset = mCamera->getPosition().z;
|
||||
float offset = mCameraPosNode->getPosition().z;
|
||||
if (mPreviewMode) {
|
||||
mMainCam.offset = offset;
|
||||
offset = mPreviewCam.offset;
|
||||
|
@ -224,7 +249,7 @@ namespace MWRender
|
|||
offset = mMainCam.offset;
|
||||
}
|
||||
|
||||
mCamera->setPosition(0.f, 0.f, offset);
|
||||
setPosition(0.f, 0.f, offset);
|
||||
}
|
||||
|
||||
void Camera::setSneakOffset(float offset)
|
||||
|
@ -283,7 +308,7 @@ namespace MWRender
|
|||
|
||||
float Camera::getCameraDistance() const
|
||||
{
|
||||
return mCamera->getPosition().z;
|
||||
return mCameraPosNode->getPosition().z;
|
||||
}
|
||||
|
||||
void Camera::setCameraDistance(float dist, bool adjust, bool override)
|
||||
|
@ -295,7 +320,7 @@ namespace MWRender
|
|||
|
||||
Ogre::Vector3 v(0.f, 0.f, dist);
|
||||
if (adjust) {
|
||||
v += mCamera->getPosition();
|
||||
v += mCameraPosNode->getPosition();
|
||||
}
|
||||
if (v.z >= mFurthest) {
|
||||
v.z = mFurthest;
|
||||
|
@ -305,7 +330,7 @@ namespace MWRender
|
|||
v.z = mNearest;
|
||||
mIsNearest = true;
|
||||
}
|
||||
mCamera->setPosition(v);
|
||||
setPosition(v);
|
||||
|
||||
if (override) {
|
||||
if (mVanity.enabled || mPreviewMode) {
|
||||
|
@ -322,9 +347,9 @@ namespace MWRender
|
|||
{
|
||||
if (mDistanceAdjusted) {
|
||||
if (mVanity.enabled || mPreviewMode) {
|
||||
mCamera->setPosition(0, 0, mPreviewCam.offset);
|
||||
setPosition(0, 0, mPreviewCam.offset);
|
||||
} else if (!mFirstPersonView) {
|
||||
mCamera->setPosition(0, 0, mCameraDistance);
|
||||
setPosition(0, 0, mCameraDistance);
|
||||
}
|
||||
}
|
||||
mDistanceAdjusted = false;
|
||||
|
@ -355,10 +380,10 @@ namespace MWRender
|
|||
Ogre::TagPoint *tag = mAnimation->attachObjectToBone("Head", mCamera);
|
||||
tag->setInheritOrientation(false);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
mAnimation->setViewMode(NpcAnimation::VM_Normal);
|
||||
mCameraNode->attachObject(mCamera);
|
||||
mCameraPosNode->attachObject(mCamera);
|
||||
}
|
||||
rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false);
|
||||
}
|
||||
|
@ -368,8 +393,7 @@ namespace MWRender
|
|||
mCamera->getParentSceneNode()->needUpdate(true);
|
||||
|
||||
camera = mCamera->getRealPosition();
|
||||
focal = Ogre::Vector3((mCamera->getParentNode()->_getFullTransform() *
|
||||
Ogre::Vector4(0.0f, 0.0f, 0.0f, 1.0f)).ptr());
|
||||
focal = mCameraNode->_getDerivedPosition();
|
||||
}
|
||||
|
||||
void Camera::togglePlayerLooking(bool enable)
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace MWRender
|
|||
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::SceneNode *mCameraNode;
|
||||
Ogre::SceneNode *mCameraPosNode;
|
||||
|
||||
NpcAnimation *mAnimation;
|
||||
|
||||
|
@ -52,6 +53,9 @@ namespace MWRender
|
|||
/// Updates sound manager listener data
|
||||
void updateListener();
|
||||
|
||||
void setPosition(const Ogre::Vector3& position);
|
||||
void setPosition(float x, float y, float z);
|
||||
|
||||
public:
|
||||
Camera(Ogre::Camera *camera);
|
||||
~Camera();
|
||||
|
@ -72,7 +76,7 @@ namespace MWRender
|
|||
const std::string &getHandle() const;
|
||||
|
||||
/// Attach camera to object
|
||||
void attachTo(const MWWorld::Ptr &);
|
||||
Ogre::SceneNode* attachTo(const MWWorld::Ptr &);
|
||||
|
||||
/// @param Force view mode switch, even if currently not allowed by the animation.
|
||||
void toggleViewMode(bool force=false);
|
||||
|
|
|
@ -312,7 +312,7 @@ void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr)
|
|||
if(mPlayerAnimation)
|
||||
mPlayerAnimation->updatePtr(ptr);
|
||||
if(mCamera->getHandle() == ptr.getRefData().getHandle())
|
||||
mCamera->attachTo(ptr);
|
||||
attachCameraTo(ptr);
|
||||
}
|
||||
|
||||
void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
|
||||
|
@ -327,7 +327,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
|
|||
anim->rebuild();
|
||||
if(mCamera->getHandle() == ptr.getRefData().getHandle())
|
||||
{
|
||||
mCamera->attachTo(ptr);
|
||||
attachCameraTo(ptr);
|
||||
mCamera->setAnimation(anim);
|
||||
}
|
||||
}
|
||||
|
@ -869,7 +869,13 @@ void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned i
|
|||
void RenderingManager::setupPlayer(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
ptr.getRefData().setBaseNode(mRendering.getScene()->getSceneNode("player"));
|
||||
mCamera->attachTo(ptr);
|
||||
attachCameraTo(ptr);
|
||||
}
|
||||
|
||||
void RenderingManager::attachCameraTo(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
Ogre::SceneNode* cameraNode = mCamera->attachTo(ptr);
|
||||
mSkyManager->attachToNode(cameraNode);
|
||||
}
|
||||
|
||||
void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)
|
||||
|
|
|
@ -221,6 +221,8 @@ private:
|
|||
void setAmbientMode();
|
||||
void applyFog(bool underwater);
|
||||
|
||||
void attachCameraTo(const MWWorld::Ptr& ptr);
|
||||
|
||||
void setMenuTransparency(float val);
|
||||
|
||||
bool mSunEnabled;
|
||||
|
|
|
@ -382,9 +382,7 @@ void SkyManager::clearRain()
|
|||
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end();)
|
||||
{
|
||||
it->second.setNull();
|
||||
Ogre::SceneNode* parent = it->first->getParentSceneNode();
|
||||
mSceneMgr->destroySceneNode(it->first);
|
||||
mSceneMgr->destroySceneNode(parent);
|
||||
mRainModels.erase(it++);
|
||||
}
|
||||
}
|
||||
|
@ -402,9 +400,7 @@ void SkyManager::updateRain(float dt)
|
|||
if (pos.z < -minHeight)
|
||||
{
|
||||
it->second.setNull();
|
||||
Ogre::SceneNode* parent = it->first->getParentSceneNode();
|
||||
mSceneMgr->destroySceneNode(it->first);
|
||||
mSceneMgr->destroySceneNode(parent);
|
||||
mRainModels.erase(it++);
|
||||
}
|
||||
else
|
||||
|
@ -420,17 +416,20 @@ void SkyManager::updateRain(float dt)
|
|||
{
|
||||
mRainTimer = 0;
|
||||
|
||||
// TODO: handle rain settings from Morrowind.ini
|
||||
const float rangeRandom = 100;
|
||||
float xOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2);
|
||||
float yOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2);
|
||||
Ogre::SceneNode* sceneNode = mCamera->getParentSceneNode()->createChildSceneNode();
|
||||
sceneNode->setInheritOrientation(false);
|
||||
|
||||
// Create a separate node to control the offset, since a node with setInheritOrientation(false) will still
|
||||
// consider the orientation of the parent node for its position, just not for its orientation
|
||||
float startHeight = 700;
|
||||
Ogre::SceneNode* offsetNode = sceneNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight));
|
||||
Ogre::SceneNode* offsetNode = mParticleNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight));
|
||||
|
||||
// Spawn a new rain object for each instance.
|
||||
// TODO: this is inefficient. We could try to use an Ogre::ParticleSystem instead, but then we would need to make assumptions
|
||||
// about the rain meshes being Quads and their dimensions.
|
||||
// Or we could clone meshes into one vertex buffer manually.
|
||||
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(offsetNode, mRainEffect);
|
||||
for (unsigned int i=0; i<objects->mEntities.size(); ++i)
|
||||
{
|
||||
|
@ -562,12 +561,6 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!mParticleNode)
|
||||
{
|
||||
mParticleNode = mCamera->getParentSceneNode()->createChildSceneNode();
|
||||
mParticleNode->setInheritOrientation(false);
|
||||
}
|
||||
|
||||
mParticle = NifOgre::Loader::createObjects(mParticleNode, mCurrentParticleEffect);
|
||||
for(size_t i = 0; i < mParticle->mParticles.size(); ++i)
|
||||
{
|
||||
|
@ -783,3 +776,16 @@ void SkyManager::setGlareEnabled (bool enabled)
|
|||
return;
|
||||
mSunGlare->setVisible (mSunEnabled && enabled);
|
||||
}
|
||||
|
||||
void SkyManager::attachToNode(SceneNode *sceneNode)
|
||||
{
|
||||
if (!mParticleNode)
|
||||
{
|
||||
mParticleNode = sceneNode->createChildSceneNode();
|
||||
mParticleNode->setInheritOrientation(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
sceneNode->addChild(mParticleNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,9 @@ namespace MWRender
|
|||
SkyManager(Ogre::SceneNode* root, Ogre::Camera* pCamera);
|
||||
~SkyManager();
|
||||
|
||||
/// Attach weather particle effects to this scene node (should be the Camera's parent node)
|
||||
void attachToNode(Ogre::SceneNode* sceneNode);
|
||||
|
||||
void update(float duration);
|
||||
|
||||
void enable();
|
||||
|
|
Loading…
Reference in a new issue