1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-30 11:06:43 +00:00

Apply third person camera distance to the camera node instead of only the camera itself (Fixes #1705)

This commit is contained in:
scrawl 2014-10-01 18:55:35 +02:00
parent f9b6cc468d
commit 85f5754bb6
6 changed files with 86 additions and 41 deletions

View file

@ -19,6 +19,7 @@ namespace MWRender
Camera::Camera (Ogre::Camera *camera) Camera::Camera (Ogre::Camera *camera)
: mCamera(camera), : mCamera(camera),
mCameraNode(NULL), mCameraNode(NULL),
mCameraPosNode(NULL),
mAnimation(NULL), mAnimation(NULL),
mFirstPersonView(true), mFirstPersonView(true),
mPreviewMode(false), mPreviewMode(false),
@ -66,12 +67,16 @@ namespace MWRender
} }
Ogre::Quaternion xr(Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_X); Ogre::Quaternion xr(Ogre::Radian(getPitch() + Ogre::Math::HALF_PI), Ogre::Vector3::UNIT_X);
if (!mVanity.enabled && !mPreviewMode) { Ogre::Quaternion orient = xr;
mCamera->getParentNode()->setOrientation(xr); if (mVanity.enabled || mPreviewMode) {
} else {
Ogre::Quaternion zr(Ogre::Radian(getYaw()), Ogre::Vector3::UNIT_Z); 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 const std::string &Camera::getHandle() const
@ -79,20 +84,40 @@ namespace MWRender
return mTrackingPtr.getRefData().getHandle(); return mTrackingPtr.getRefData().getHandle();
} }
void Camera::attachTo(const MWWorld::Ptr &ptr) Ogre::SceneNode* Camera::attachTo(const MWWorld::Ptr &ptr)
{ {
mTrackingPtr = ptr; mTrackingPtr = ptr;
Ogre::SceneNode *node = mTrackingPtr.getRefData().getBaseNode()->createChildSceneNode(Ogre::Vector3(0.0f, 0.0f, mHeight)); 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) if(mCameraNode)
{ {
node->setOrientation(mCameraNode->getOrientation()); node->setOrientation(mCameraNode->getOrientation());
node->setPosition(mCameraNode->getPosition()); posNode->setPosition(mCameraPosNode->getPosition());
node->setScale(mCameraNode->getScale());
mCameraNode->getCreator()->destroySceneNode(mCameraNode); mCameraNode->getCreator()->destroySceneNode(mCameraNode);
mCameraNode->getCreator()->destroySceneNode(mCameraPosNode);
} }
mCameraNode = node; mCameraNode = node;
if(!mCamera->isAttached()) mCameraPosNode = posNode;
mCameraNode->attachObject(mCamera);
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() void Camera::updateListener()
@ -155,9 +180,9 @@ namespace MWRender
processViewChange(); processViewChange();
if (mFirstPersonView) { if (mFirstPersonView) {
mCamera->setPosition(0.f, 0.f, 0.f); setPosition(0.f, 0.f, 0.f);
} else { } 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); Ogre::Vector3 rot(0.f, 0.f, 0.f);
if (mVanity.enabled) { if (mVanity.enabled) {
rot.x = Ogre::Degree(-30.f).valueRadians(); rot.x = Ogre::Degree(-30.f).valueRadians();
mMainCam.offset = mCamera->getPosition().z; mMainCam.offset = mCameraPosNode->getPosition().z;
} else { } else {
rot.x = getPitch(); rot.x = getPitch();
offset = mMainCam.offset; offset = mMainCam.offset;
} }
rot.z = getYaw(); rot.z = getYaw();
mCamera->setPosition(0.f, 0.f, offset); setPosition(0.f, 0.f, offset);
rotateCamera(rot, false); rotateCamera(rot, false);
return true; return true;
@ -215,7 +240,7 @@ namespace MWRender
mPreviewMode = enable; mPreviewMode = enable;
processViewChange(); processViewChange();
float offset = mCamera->getPosition().z; float offset = mCameraPosNode->getPosition().z;
if (mPreviewMode) { if (mPreviewMode) {
mMainCam.offset = offset; mMainCam.offset = offset;
offset = mPreviewCam.offset; offset = mPreviewCam.offset;
@ -224,7 +249,7 @@ namespace MWRender
offset = mMainCam.offset; offset = mMainCam.offset;
} }
mCamera->setPosition(0.f, 0.f, offset); setPosition(0.f, 0.f, offset);
} }
void Camera::setSneakOffset(float offset) void Camera::setSneakOffset(float offset)
@ -283,7 +308,7 @@ namespace MWRender
float Camera::getCameraDistance() const float Camera::getCameraDistance() const
{ {
return mCamera->getPosition().z; return mCameraPosNode->getPosition().z;
} }
void Camera::setCameraDistance(float dist, bool adjust, bool override) void Camera::setCameraDistance(float dist, bool adjust, bool override)
@ -295,7 +320,7 @@ namespace MWRender
Ogre::Vector3 v(0.f, 0.f, dist); Ogre::Vector3 v(0.f, 0.f, dist);
if (adjust) { if (adjust) {
v += mCamera->getPosition(); v += mCameraPosNode->getPosition();
} }
if (v.z >= mFurthest) { if (v.z >= mFurthest) {
v.z = mFurthest; v.z = mFurthest;
@ -305,7 +330,7 @@ namespace MWRender
v.z = mNearest; v.z = mNearest;
mIsNearest = true; mIsNearest = true;
} }
mCamera->setPosition(v); setPosition(v);
if (override) { if (override) {
if (mVanity.enabled || mPreviewMode) { if (mVanity.enabled || mPreviewMode) {
@ -322,9 +347,9 @@ namespace MWRender
{ {
if (mDistanceAdjusted) { if (mDistanceAdjusted) {
if (mVanity.enabled || mPreviewMode) { if (mVanity.enabled || mPreviewMode) {
mCamera->setPosition(0, 0, mPreviewCam.offset); setPosition(0, 0, mPreviewCam.offset);
} else if (!mFirstPersonView) { } else if (!mFirstPersonView) {
mCamera->setPosition(0, 0, mCameraDistance); setPosition(0, 0, mCameraDistance);
} }
} }
mDistanceAdjusted = false; mDistanceAdjusted = false;
@ -358,7 +383,7 @@ namespace MWRender
else else
{ {
mAnimation->setViewMode(NpcAnimation::VM_Normal); mAnimation->setViewMode(NpcAnimation::VM_Normal);
mCameraNode->attachObject(mCamera); mCameraPosNode->attachObject(mCamera);
} }
rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false);
} }
@ -368,8 +393,7 @@ namespace MWRender
mCamera->getParentSceneNode()->needUpdate(true); mCamera->getParentSceneNode()->needUpdate(true);
camera = mCamera->getRealPosition(); camera = mCamera->getRealPosition();
focal = Ogre::Vector3((mCamera->getParentNode()->_getFullTransform() * focal = mCameraNode->_getDerivedPosition();
Ogre::Vector4(0.0f, 0.0f, 0.0f, 1.0f)).ptr());
} }
void Camera::togglePlayerLooking(bool enable) void Camera::togglePlayerLooking(bool enable)

View file

@ -27,6 +27,7 @@ namespace MWRender
Ogre::Camera *mCamera; Ogre::Camera *mCamera;
Ogre::SceneNode *mCameraNode; Ogre::SceneNode *mCameraNode;
Ogre::SceneNode *mCameraPosNode;
NpcAnimation *mAnimation; NpcAnimation *mAnimation;
@ -52,6 +53,9 @@ namespace MWRender
/// Updates sound manager listener data /// Updates sound manager listener data
void updateListener(); void updateListener();
void setPosition(const Ogre::Vector3& position);
void setPosition(float x, float y, float z);
public: public:
Camera(Ogre::Camera *camera); Camera(Ogre::Camera *camera);
~Camera(); ~Camera();
@ -72,7 +76,7 @@ namespace MWRender
const std::string &getHandle() const; const std::string &getHandle() const;
/// Attach camera to object /// 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. /// @param Force view mode switch, even if currently not allowed by the animation.
void toggleViewMode(bool force=false); void toggleViewMode(bool force=false);

View file

@ -312,7 +312,7 @@ void RenderingManager::updatePlayerPtr(const MWWorld::Ptr &ptr)
if(mPlayerAnimation) if(mPlayerAnimation)
mPlayerAnimation->updatePtr(ptr); mPlayerAnimation->updatePtr(ptr);
if(mCamera->getHandle() == ptr.getRefData().getHandle()) if(mCamera->getHandle() == ptr.getRefData().getHandle())
mCamera->attachTo(ptr); attachCameraTo(ptr);
} }
void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr) void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
@ -327,7 +327,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
anim->rebuild(); anim->rebuild();
if(mCamera->getHandle() == ptr.getRefData().getHandle()) if(mCamera->getHandle() == ptr.getRefData().getHandle())
{ {
mCamera->attachTo(ptr); attachCameraTo(ptr);
mCamera->setAnimation(anim); mCamera->setAnimation(anim);
} }
} }
@ -869,7 +869,13 @@ void RenderingManager::getTriangleBatchCount(unsigned int &triangles, unsigned i
void RenderingManager::setupPlayer(const MWWorld::Ptr &ptr) void RenderingManager::setupPlayer(const MWWorld::Ptr &ptr)
{ {
ptr.getRefData().setBaseNode(mRendering.getScene()->getSceneNode("player")); 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) void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr)

View file

@ -221,6 +221,8 @@ private:
void setAmbientMode(); void setAmbientMode();
void applyFog(bool underwater); void applyFog(bool underwater);
void attachCameraTo(const MWWorld::Ptr& ptr);
void setMenuTransparency(float val); void setMenuTransparency(float val);
bool mSunEnabled; bool mSunEnabled;

View file

@ -382,9 +382,7 @@ void SkyManager::clearRain()
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end();) for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end();)
{ {
it->second.setNull(); it->second.setNull();
Ogre::SceneNode* parent = it->first->getParentSceneNode();
mSceneMgr->destroySceneNode(it->first); mSceneMgr->destroySceneNode(it->first);
mSceneMgr->destroySceneNode(parent);
mRainModels.erase(it++); mRainModels.erase(it++);
} }
} }
@ -402,9 +400,7 @@ void SkyManager::updateRain(float dt)
if (pos.z < -minHeight) if (pos.z < -minHeight)
{ {
it->second.setNull(); it->second.setNull();
Ogre::SceneNode* parent = it->first->getParentSceneNode();
mSceneMgr->destroySceneNode(it->first); mSceneMgr->destroySceneNode(it->first);
mSceneMgr->destroySceneNode(parent);
mRainModels.erase(it++); mRainModels.erase(it++);
} }
else else
@ -420,17 +416,20 @@ void SkyManager::updateRain(float dt)
{ {
mRainTimer = 0; mRainTimer = 0;
// TODO: handle rain settings from Morrowind.ini
const float rangeRandom = 100; const float rangeRandom = 100;
float xOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2); float xOffs = (std::rand()/(RAND_MAX+1.0)) * rangeRandom - (rangeRandom/2);
float yOffs = (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 // 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 // consider the orientation of the parent node for its position, just not for its orientation
float startHeight = 700; 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); NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(offsetNode, mRainEffect);
for (unsigned int i=0; i<objects->mEntities.size(); ++i) for (unsigned int i=0; i<objects->mEntities.size(); ++i)
{ {
@ -562,12 +561,6 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
} }
else else
{ {
if (!mParticleNode)
{
mParticleNode = mCamera->getParentSceneNode()->createChildSceneNode();
mParticleNode->setInheritOrientation(false);
}
mParticle = NifOgre::Loader::createObjects(mParticleNode, mCurrentParticleEffect); mParticle = NifOgre::Loader::createObjects(mParticleNode, mCurrentParticleEffect);
for(size_t i = 0; i < mParticle->mParticles.size(); ++i) for(size_t i = 0; i < mParticle->mParticles.size(); ++i)
{ {
@ -783,3 +776,16 @@ void SkyManager::setGlareEnabled (bool enabled)
return; return;
mSunGlare->setVisible (mSunEnabled && enabled); mSunGlare->setVisible (mSunEnabled && enabled);
} }
void SkyManager::attachToNode(SceneNode *sceneNode)
{
if (!mParticleNode)
{
mParticleNode = sceneNode->createChildSceneNode();
mParticleNode->setInheritOrientation(false);
}
else
{
sceneNode->addChild(mParticleNode);
}
}

View file

@ -116,6 +116,9 @@ namespace MWRender
SkyManager(Ogre::SceneNode* root, Ogre::Camera* pCamera); SkyManager(Ogre::SceneNode* root, Ogre::Camera* pCamera);
~SkyManager(); ~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 update(float duration);
void enable(); void enable();