1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 20:53:50 +00:00

initial 3d-person camera support

This commit is contained in:
greye 2012-08-12 15:50:37 +04:00
parent 2a11a28e81
commit c46eeaa100
10 changed files with 184 additions and 79 deletions

View file

@ -67,7 +67,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
mEnvironment.setFrameDuration (evt.timeSinceLastFrame);
// update input
MWBase::Environment::get().getInputManager()->update();
MWBase::Environment::get().getInputManager()->update(evt.timeSinceLastFrame);
// sound
if (mUseSound)

View file

@ -248,6 +248,8 @@ namespace MWBase
virtual bool isSwimming(const MWWorld::Ptr &object) = 0;
virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos) = 0;
virtual void togglePOV() = 0;
};
}

View file

@ -62,6 +62,7 @@ namespace MWInput
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
A_ToggleWalk, //Toggle Walking/Running
A_Crouch,
A_TogglePOV,
A_QuickSave,
A_QuickLoad,
@ -90,6 +91,8 @@ namespace MWInput
std::map<std::string, bool> mControlSwitch;
float mPreviewPOVDelay;
/* InputImpl Methods */
public:
void adjustMouseRegion(int width, int height)
@ -340,6 +343,8 @@ private:
poller.bind(A_Jump, KC_E);
poller.bind(A_Crouch, KC_LCONTROL);
poller.bind(A_TogglePOV, KC_TAB);
}
void setDragDrop(bool dragDrop)
@ -348,7 +353,7 @@ private:
}
//NOTE: Used to check for movement keys
void update ()
void update (float duration)
{
// Tell OIS to handle all input events
input.capture();
@ -400,6 +405,21 @@ private:
player.setUpDown (-1);
else
player.setUpDown (0);
if (poller.isDown(A_TogglePOV)) {
if (mPreviewPOVDelay <= 0.5 &&
(mPreviewPOVDelay += duration) > 0.5)
{
// enable preview mode
}
} else {
if (mPreviewPOVDelay > 0.5) {
//disable preview mode
} else if (mPreviewPOVDelay > 0.f) {
togglePOV();
}
mPreviewPOVDelay = 0.f;
}
}
}
@ -452,6 +472,11 @@ private:
mControlSwitch[sw] = value;
}
void togglePOV()
{
MWBase::Environment::get().getWorld()->togglePOV();
}
};
/***CONSTRUCTOR***/
@ -470,9 +495,9 @@ private:
delete impl;
}
void MWInputManager::update()
void MWInputManager::update(float duration)
{
impl->update();
impl->update(duration);
}
void MWInputManager::setDragDrop(bool dragDrop)

View file

@ -52,7 +52,7 @@ namespace MWInput
OMW::Engine& engine);
virtual ~MWInputManager();
virtual void update();
void update(float duration);
virtual void changeInputMode(bool guiMode);

View file

@ -2,6 +2,7 @@
#include <OgreSceneNode.h>
#include <OgreCamera.h>
#include <OgreRay.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
@ -12,82 +13,119 @@
namespace MWRender
{
Player::Player (Ogre::Camera *camera, Ogre::SceneNode* node)
: mCamera (camera),
mNode (node),
: mCamera(camera),
mPlayerNode(node),
mCameraNode(mPlayerNode->createChildSceneNode()),
mFirstPersonView(true),
mVanityModeEnabled(false)
{}
bool Player::setRotation(const Ogre::Vector3 &rot)
mVanityMode(false),
mPreviewMode(false)
{
Ogre::SceneNode *sceneNode = mNode;
Ogre::Node* yawNode = sceneNode->getChildIterator().getNext();
Ogre::Node* pitchNode = yawNode->getChildIterator().getNext();
Ogre::SceneNode *pitchNode = mCameraNode->createChildSceneNode();
pitchNode->attachObject(mCamera);
}
bool Player::rotate(const Ogre::Vector3 &rot, bool adjust)
{
bool force = !mVanityMode && !mPreviewMode;
Ogre::Vector3 newRot = rot;
// we are only interested in X and Y rotation
rotateCamera(newRot, adjust);
// Rotate around X axis
Ogre::Radian radx(rot.x);
if (radx.valueDegrees() > 89.5f) {
radx = Ogre::Degree(89.5f);
} else if (radx.valueDegrees() < -89.5f) {
radx = Ogre::Degree(-89.5f);
if (!force || !mFirstPersonView) {
moveCamera(400.f, 1600.f);
}
Ogre::Quaternion xr(radx, Ogre::Vector3::UNIT_X);
// Rotate around Y axis
Ogre::Quaternion yr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Y);
pitchNode->setOrientation(xr);
yawNode->setOrientation(yr);
updateListener();
return !mVanityModeEnabled;
return force;
}
std::string Player::getHandle() const
{
return mNode->getName();
}
void Player::attachTo(const MWWorld::Ptr &ptr)
{
ptr.getRefData().setBaseNode(mNode);
}
bool Player::adjustRotation(const Ogre::Vector3 &rot)
void Player::rotateCamera(Ogre::Vector3 &rot, bool adjust)
{
Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode();
Ogre::SceneNode *yawNode = pitchNode->getParentSceneNode();
float f = controlFlip(Ogre::Radian(rot.x).valueDegrees());
if (f != 0.0) {
pitchNode->pitch(Ogre::Degree(f));
if (adjust) {
float f =
limitPitchAngle(89.5f, Ogre::Radian(rot.x).valueDegrees());
if (f != 0.0) {
pitchNode->pitch(Ogre::Degree(f));
}
yawNode->yaw(Ogre::Radian(-rot.z));
} else {
Ogre::Radian radx(rot.x);
if (radx.valueDegrees() > 89.5f) {
radx = Ogre::Degree(89.5f);
} else if (radx.valueDegrees() < -89.5f) {
radx = Ogre::Degree(-89.5f);
}
Ogre::Quaternion xr(radx, Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Y);
pitchNode->setOrientation(xr);
yawNode->setOrientation(yr);
}
yawNode->yaw(Ogre::Radian(-rot.z));
updateListener();
return !mVanityModeEnabled;
}
float Player::controlFlip(float shift)
void Player::moveCamera(float rsq, float hsq)
{
Ogre::SceneNode *pitchNode = mCamera->getParentSceneNode();
Ogre::Quaternion orient = pitchNode->getOrientation();
/*
Ogre::Quaternion orient =
mCamera->getParentSceneNode()->getOrientation();
float pitchAngle =
(2 * Ogre::Degree(Ogre::Math::ASin(orient.x)).valueDegrees());
if (pitchAngle + shift < 89.5f && pitchAngle + shift > -89.5f) {
orient = mCameraNode->getOrientation();
float yawAngle =
(2 * Ogre::Degree(Ogre::Math::ASin(orient.y)).valueDegrees());
float tana = Ogre::Math::Tan(Ogre::Degree(pitchAngle));
float tansq = tana * tana;
float r1 = hsq * rsq / (hsq + rsq * tansq);
float zsq = r1 * tansq;
r1 = Ogre::Math::Sqrt(r1);
Ogre::Vector3 pos;
pos.y = -Ogre::Math::Sqrt(zsq);
pos.z = r1 * Ogre::Math::Sin(Ogre::Degree(yawAngle).valueDegrees());
pos.x = r1 * Ogre::Math::Cos(Ogre::Degree(yawAngle).valueDegrees());
*/
Ogre::Vector3 dir = mCamera->getRealDirection();
dir.x = -dir.x, dir.y = -dir.y, dir.z = -dir.z;
Ogre::Ray ray(Ogre::Vector3(0, 0, 0), dir);
mCameraNode->setPosition(ray.getPoint(800.f));
}
std::string Player::getHandle() const
{
return mPlayerNode->getName();
}
void Player::attachTo(const MWWorld::Ptr &ptr)
{
ptr.getRefData().setBaseNode(mPlayerNode);
}
float Player::limitPitchAngle(float limitAbs, float shift)
{
Ogre::Quaternion orient =
mCamera->getParentSceneNode()->getOrientation();
float pitchAngle =
(2 * Ogre::Degree(Ogre::Math::ASin(orient.x)).valueDegrees());
if (pitchAngle + shift < limitAbs && pitchAngle + shift > -limitAbs) {
return shift;
}
if (pitchAngle > 0) {
float f = 89.5f - pitchAngle - shift;
float f = limitAbs - pitchAngle - shift;
return (f > 0.f) ? f : 0.f;
} else if (pitchAngle < 0) {
float f = -89.5 - pitchAngle - shift;
float f = -limitAbs - pitchAngle - shift;
return (f < 0.f) ? f : 0.f;
}
return 0.f;
@ -104,4 +142,38 @@ namespace MWRender
MWBase::Environment::get().getSoundManager()->setListenerPosDir(pos, dir);
}
void Player::update(float duration)
{
if (mFirstPersonView && !mVanityMode) {
return;
}
if (mVanityMode) {
/// \todo adjust rotation constantly
} else {
/// \todo move camera closer or change view mode if needed
}
}
void Player::toggleViewMode()
{
mFirstPersonView = !mFirstPersonView;
if (mFirstPersonView) {
mCameraNode->setPosition(0.f, 0.f, 0.f);
} else {
moveCamera(400.f, 1600.f);
}
}
void Player::toggleVanityMode()
{
/// \todo move camera
mVanityMode = !mVanityMode;
}
void Player::togglePreviewMode()
{
/// \todo move camera
mPreviewMode = !mPreviewMode;
}
}

View file

@ -22,16 +22,24 @@ namespace MWRender
class Player
{
Ogre::Camera *mCamera;
Ogre::SceneNode* mNode;
Ogre::SceneNode *mPlayerNode;
Ogre::SceneNode *mCameraNode;
bool mFirstPersonView;
bool mVanityModeEnabled;
bool mVanityMode;
bool mPreviewMode;
float controlFlip(float shift = 0.f);
float mTimeIdle;
float limitPitchAngle(float limitAbs, float shift = 0.f);
/// Updates sound manager listener data
void updateListener();
void rotateCamera(Ogre::Vector3 &rot, bool adjust);
void moveCamera(float r, float h);
public:
Player (Ogre::Camera *camera, Ogre::SceneNode* mNode);
@ -39,11 +47,7 @@ namespace MWRender
/// Set where the player is looking at. Uses Morrowind (euler) angles
/// \param rot Rotation angles in radians
/// \return true if player object needs to bo rotated physically
bool setRotation(const Ogre::Vector3 &rot);
/// \param rot Rotation angles in radians
/// \return true if player object needs to bo rotated physically
bool adjustRotation(const Ogre::Vector3 &rot);
bool rotate(const Ogre::Vector3 &rot, bool adjust);
std::string getHandle() const;
@ -52,13 +56,13 @@ namespace MWRender
/// several different objects
void attachTo(const MWWorld::Ptr &);
void toggleViewMode() {
mFirstPersonView = !mFirstPersonView;
}
void toggleViewMode();
void toggleVanityMode() {
mVanityModeEnabled = !mVanityModeEnabled;
}
void toggleVanityMode();
void togglePreviewMode();
void update(float duration);
};
}

View file

@ -133,11 +133,10 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mObjects.setMwRoot(mMwRoot);
mActors.setMwRoot(mMwRoot);
Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player");
playerNode->pitch(Degree(90));
Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode();
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
cameraPitchNode->attachObject(mRendering.getCamera());
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mShadows = new Shadows(&mRendering);
@ -147,7 +146,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mSun = 0;
mDebugging = new Debugging(mMwRoot, engine);
@ -259,11 +257,7 @@ RenderingManager::rotateObject(
bool force = true;
if (isPlayer) {
if (adjust) {
force = mPlayer->adjustRotation(rot);
} else {
force = mPlayer->setRotation(rot);
}
force = mPlayer->rotate(rot, adjust);
}
MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z);
@ -329,6 +323,8 @@ void RenderingManager::update (float duration){
);
mWater->update(duration);
}
mPlayer->update(duration);
}
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){

View file

@ -56,6 +56,10 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine);
virtual ~RenderingManager();
void togglePOV() {
mPlayer->toggleViewMode();
}
void attachCameraTo(const MWWorld::Ptr &ptr);
SkyManager* getSkyManager();

View file

@ -1151,5 +1151,4 @@ namespace MWWorld
}
return pos.z < cell.water;
}
}

View file

@ -277,6 +277,9 @@ namespace MWWorld
virtual bool isSwimming(const MWWorld::Ptr &object);
virtual bool isUnderwater(const ESM::Cell &cell, const Ogre::Vector3 &pos);
virtual void togglePOV() {
mRendering->togglePOV();
}
};
}