Preliminary editor camera

openmw-39
Aesylwinn 9 years ago
parent 2cff2cd643
commit 08fe914ba1

@ -89,8 +89,8 @@ opencs_units (view/render
)
opencs_units_noqt (view/render
lighting lightingday lightingnight
lightingbright object cell terrainstorage tagbase cellarrow cellmarker cellborder
lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
cellarrow cellmarker cellborder cameracontroller
)
opencs_hdrs_noqt (view/render

@ -0,0 +1,458 @@
#include "cameracontroller.hpp"
#include <QKeyEvent>
#include <osg/Camera>
#include <osg/Matrixd>
#include <osg/Quat>
namespace CSVRender
{
/*
Camera Controller
*/
const osg::Vec3d CameraController::LocalUp = osg::Vec3d(0, 1, 0);
const osg::Vec3d CameraController::LocalLeft = osg::Vec3d(1, 0, 0);
const osg::Vec3d CameraController::LocalForward = osg::Vec3d(0, 0, 1);
const double CameraController::LinearSpeed = 1000;
const double CameraController::RotationalSpeed = osg::PI / 2.f;
const double CameraController::SpeedMultiplier = 8;
CameraController::CameraController()
: mActive(false)
, mModified(false)
, mMouseScalar(-1/350.f)
, mCamera(NULL)
{
}
CameraController::~CameraController()
{
}
bool CameraController::isActive() const
{
return mActive;
}
bool CameraController::isModified() const
{
return mModified;
}
osg::Camera* CameraController::getCamera() const
{
return mCamera;
}
double CameraController::getMouseScalar() const
{
return mMouseScalar;
}
void CameraController::setCamera(osg::Camera* camera)
{
mCamera = camera;
mActive = (mCamera != NULL);
if (mActive)
onActivate();
}
void CameraController::setMouseScalar(double value)
{
mMouseScalar = value;
}
void CameraController::setModified()
{
mModified = true;
}
void CameraController::resetModified()
{
mModified = false;
}
/*
Free Camera Controller
*/
FreeCameraController::FreeCameraController()
: mLockUpright(false)
, mFast(false)
, mLeft(false)
, mRight(false)
, mForward(false)
, mBackward(false)
, mRollLeft(false)
, mRollRight(false)
, mUp(LocalUp)
{
}
void FreeCameraController::fixUpAxis(const osg::Vec3d& up)
{
mLockUpright = true;
mUp = up;
}
void FreeCameraController::unfixUpAxis()
{
mLockUpright = false;
}
bool FreeCameraController::handleKeyEvent(QKeyEvent* event, bool pressed)
{
if (!isActive())
return false;
if (event->key() == Qt::Key_Q)
{
mRollLeft = pressed;
setModified();
}
else if (event->key() == Qt::Key_E)
{
mRollRight = pressed;
setModified();
}
else if (event->key() == Qt::Key_A)
{
mLeft = pressed;
setModified();
}
else if (event->key() == Qt::Key_D)
{
mRight = pressed;
setModified();
}
else if (event->key() == Qt::Key_W)
{
mForward = pressed;
setModified();
}
else if (event->key() == Qt::Key_S)
{
mBackward = pressed;
setModified();
}
else if (event->key() == Qt::Key_Shift)
{
mFast = pressed;
setModified();
}
else
{
return false;
}
return true;
}
bool FreeCameraController::handleMouseMoveEvent(std::string mode, int x, int y)
{
if (!isActive())
return false;
if (mode == "p-navi")
{
yaw(x * getMouseScalar());
pitch(y * getMouseScalar());
setModified();
}
else if (mode == "s-navi")
{
translate(LocalLeft * x + LocalUp * -y);
setModified();
}
else if (mode == "t-navi")
{
translate(LocalForward * x * (mFast ? SpeedMultiplier : 1));
}
else
{
return false;
}
return true;
}
void FreeCameraController::update(double dt)
{
if (!isActive())
return;
double linDist = LinearSpeed * dt;
double rotDist = RotationalSpeed * dt;
if (mFast)
linDist *= SpeedMultiplier;
if (mLeft)
translate(LocalLeft * linDist);
if (mRight)
translate(LocalLeft * -linDist);
if (mForward)
translate(LocalForward * linDist);
if (mBackward)
translate(LocalForward * -linDist);
if (!mLockUpright)
{
if (mRollLeft)
roll(-rotDist);
if (mRollRight)
roll(rotDist);
}
else if(isModified())
{
stabilize();
}
// Normalize the matrix to counter drift
getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix());
resetModified();
}
void FreeCameraController::yaw(double value)
{
getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalUp);
}
void FreeCameraController::pitch(double value)
{
getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalLeft);
}
void FreeCameraController::roll(double value)
{
getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalForward);
}
void FreeCameraController::translate(const osg::Vec3d& offset)
{
getCamera()->getViewMatrix() *= osg::Matrixd::translate(offset);
}
void FreeCameraController::stabilize()
{
osg::Vec3d eye, center, up;
getCamera()->getViewMatrixAsLookAt(eye, center, up);
getCamera()->setViewMatrixAsLookAt(eye, center, mUp);
}
/*
Orbit Camera Controller
*/
OrbitCameraController::OrbitCameraController()
: mInitialized(false)
, mFast(false)
, mLeft(false)
, mRight(false)
, mUp(false)
, mDown(false)
, mRollLeft(false)
, mRollRight(false)
, mCenter(0,0,0)
{
}
bool OrbitCameraController::handleKeyEvent(QKeyEvent* event, bool pressed)
{
if (!isActive())
return false;
if (!mInitialized)
initialize();
if (event->key() == Qt::Key_Q)
{
mRollLeft = pressed;
setModified();
}
else if (event->key() == Qt::Key_E)
{
mRollRight = pressed;
setModified();
}
else if (event->key() == Qt::Key_A)
{
mLeft = pressed;
setModified();
}
else if (event->key() == Qt::Key_D)
{
mRight = pressed;
setModified();
}
else if (event->key() == Qt::Key_W)
{
mUp = pressed;
setModified();
}
else if (event->key() == Qt::Key_S)
{
mDown = pressed;
setModified();
}
else if (event->key() == Qt::Key_Shift)
{
mFast = pressed;
setModified();
}
else
{
return false;
}
return true;
}
bool OrbitCameraController::handleMouseMoveEvent(std::string mode, int x, int y)
{
if (!isActive())
return false;
if (!mInitialized)
initialize();
if (mode == "p-navi")
{
rotateHorizontal(x * getMouseScalar());
rotateVertical(y * getMouseScalar());
setModified();
}
else if (mode == "s-navi")
{
translate(LocalLeft * x + LocalUp * -y);
setModified();
}
else if (mode == "t-navi")
{
zoom(x * (mFast ? SpeedMultiplier : 1));
}
else
{
return false;
}
return true;
}
void OrbitCameraController::update(double dt)
{
if (!isActive())
return;
if (!mInitialized)
initialize();
double rotDist = RotationalSpeed * dt;
if (mFast)
rotDist *= SpeedMultiplier;
if (mLeft)
rotateHorizontal(-rotDist);
if (mRight)
rotateHorizontal(rotDist);
if (mUp)
rotateVertical(rotDist);
if (mDown)
rotateVertical(-rotDist);
if (mRollLeft)
roll(-rotDist);
if (mRollRight)
roll(rotDist);
lookAtCenter();
// Normalize the matrix to counter drift
getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix());
resetModified();
}
void OrbitCameraController::onActivate()
{
mInitialized = false;
}
void OrbitCameraController::initialize()
{
static const int DefaultStartDistance = 10000.f;
osg::Quat rotation = getCamera()->getViewMatrix().getRotate();
osg::Vec3d position = getCamera()->getViewMatrix().getTrans();
osg::Vec3d offset = rotation * (LocalForward * DefaultStartDistance);
mCenter = position + offset;
mInitialized = true;
}
void OrbitCameraController::rotateHorizontal(double value)
{
osg::Vec3d position = getCamera()->getViewMatrix().getTrans();
osg::Vec3d offset = position - mCenter;
osg::Quat rotation = getCamera()->getViewMatrix().getRotate();
osg::Quat offsetRotation = osg::Quat(value, LocalUp);
osg::Vec3d newOffset = (rotation * offsetRotation) * (rotation.inverse() * offset);
getCamera()->getViewMatrix().setTrans(mCenter + newOffset);
}
void OrbitCameraController::rotateVertical(double value)
{
osg::Vec3d position = getCamera()->getViewMatrix().getTrans();
osg::Vec3d offset = position - mCenter;
osg::Quat rotation = getCamera()->getViewMatrix().getRotate();
osg::Quat offsetRotation = osg::Quat(value, LocalLeft);
osg::Vec3d newOffset = (rotation * offsetRotation) * (rotation.inverse() * offset);
getCamera()->getViewMatrix().setTrans(mCenter + newOffset);
}
void OrbitCameraController::roll(double value)
{
getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalForward);
}
void OrbitCameraController::translate(const osg::Vec3d& offset)
{
mCenter += offset;
getCamera()->getViewMatrix() *= osg::Matrixd::translate(offset);
}
void OrbitCameraController::zoom(double value)
{
osg::Vec3d dir = mCenter - getCamera()->getViewMatrix().getTrans();
double distance = dir.normalize();
if (distance > 1 || value < 0)
{
getCamera()->getViewMatrix() *= osg::Matrixd::translate(dir * value);
}
}
void OrbitCameraController::lookAtCenter()
{
osg::Vec3d position = getCamera()->getViewMatrix().getTrans();
osg::Vec3d offset = mCenter - position;
osg::Quat rotation = getCamera()->getViewMatrix().getRotate();
osg::Quat newRotation;
newRotation.makeRotate(LocalForward, offset);
getCamera()->getViewMatrix().setRotate(newRotation);
}
}

@ -0,0 +1,121 @@
#ifndef OPENCS_VIEW_CAMERACONTROLLER_H
#define OPENCS_VIEW_CAMERACONTROLLER_H
#include <string>
#include <osg/ref_ptr>
#include <osg/Vec3d>
class QKeyEvent;
namespace osg
{
class Camera;
}
namespace CSVRender
{
class CameraController
{
public:
static const osg::Vec3d LocalUp;
static const osg::Vec3d LocalLeft;
static const osg::Vec3d LocalForward;
static const double LinearSpeed;
static const double RotationalSpeed;
static const double SpeedMultiplier;
CameraController();
virtual ~CameraController();
bool isActive() const;
bool isModified() const;
osg::Camera* getCamera() const;
double getMouseScalar() const;
void setCamera(osg::Camera*);
void setMouseScalar(double value);
virtual bool handleKeyEvent(QKeyEvent* event, bool pressed) = 0;
virtual bool handleMouseMoveEvent(std::string mode, int x, int y) = 0;
virtual void update(double dt) = 0;
protected:
void setModified();
void resetModified();
virtual void onActivate(){}
private:
bool mActive, mModified;
double mMouseScalar;
osg::Camera* mCamera;
};
class FreeCameraController : public CameraController
{
public:
FreeCameraController();
void fixUpAxis(const osg::Vec3d& up);
void unfixUpAxis();
bool handleKeyEvent(QKeyEvent* event, bool pressed);
bool handleMouseMoveEvent(std::string mode, int x, int y);
void update(double dt);
private:
void yaw(double value);
void pitch(double value);
void roll(double value);
void translate(const osg::Vec3d& offset);
void stabilize();
bool mLockUpright;
bool mFast, mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight;
osg::Vec3d mUp;
};
class OrbitCameraController : public CameraController
{
public:
OrbitCameraController();
bool handleKeyEvent(QKeyEvent* event, bool pressed);
bool handleMouseMoveEvent(std::string mode, int x, int y);
void update(double dt);
private:
void onActivate();
void initialize();
void rotateHorizontal(double value);
void rotateVertical(double value);
void roll(double value);
void translate(const osg::Vec3d& offset);
void zoom(double value);
void lookAtCenter();
bool mInitialized;
bool mFast, mLeft, mRight, mUp, mDown, mRollLeft, mRollRight;
osg::Vec3d mCenter;
};
}
#endif

@ -25,6 +25,7 @@
#include "lighting.hpp"
#include "mask.hpp"
#include "cameracontroller.hpp"
namespace CSVRender
{
@ -141,8 +142,12 @@ CompositeViewer &CompositeViewer::get()
void CompositeViewer::update()
{
mSimulationTime += mFrameTimer.time_s();
double dt = mFrameTimer.time_s();
mFrameTimer.setStartTick();
emit simulationUpdated(dt);
mSimulationTime += dt;
frame(mSimulationTime);
}
@ -154,7 +159,14 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
, mResourceSystem(resourceSystem)
, mLighting(NULL)
, mHasDefaultAmbient(false)
, mPrevMouseX(0)
, mPrevMouseY(0)
, mFreeCamControl(new FreeCameraController())
, mOrbitCamControl(new OrbitCameraController())
, mCurrentCamControl(mFreeCamControl.get())
{
selectNavigationMode("free");
// we handle lighting manually
mView->setLightingMode(osgViewer::View::NO_LIGHT);
@ -175,6 +187,8 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
CSMPrefs::get()["3D Scene Input"].update();
CSMPrefs::get()["Tooltips"].update();
}
connect (&CompositeViewer::get(), SIGNAL (simulationUpdated(double)), this, SLOT (update(double)));
}
SceneWidget::~SceneWidget()
@ -256,28 +270,43 @@ void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour)
void SceneWidget::mousePressEvent (QMouseEvent *event)
{
std::string button = mapButton(event);
mMouseMode = mapButton(event);
// TODO placeholders
if (button == "p-navi")
{
mPrevMouseX = event->x();
mPrevMouseY = event->y();
}
else if (button == "s-navi")
void SceneWidget::mouseReleaseEvent (QMouseEvent *event)
{
mMouseMode = "";
}
void SceneWidget::mouseMoveEvent (QMouseEvent *event)
{
mCurrentCamControl->handleMouseMoveEvent(mMouseMode, event->x() - mPrevMouseX, event->y() - mPrevMouseY);
mPrevMouseX = event->x();
mPrevMouseY = event->y();
}
void SceneWidget::mouseReleaseEvent (QMouseEvent *event)
void SceneWidget::wheelEvent(QWheelEvent *event)
{
std::string button = mapButton(event);
mCurrentCamControl->handleMouseMoveEvent("t-navi", event->delta(), 0);
}
// TODO placeholders
if (button == "p-navi")
void SceneWidget::keyPressEvent (QKeyEvent *event)
{
mCurrentCamControl->handleKeyEvent(event, true);
}
else if (button == "s-navi")
void SceneWidget::keyReleaseEvent (QKeyEvent *event)
{
mCurrentCamControl->handleKeyEvent(event, false);
}
void SceneWidget::update(double dt)
{
mCurrentCamControl->update(dt);
}
void SceneWidget::settingChanged (const CSMPrefs::Setting *setting)
@ -288,13 +317,31 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting)
void SceneWidget::selectNavigationMode (const std::string& mode)
{
if (mode=="1st")
mView->setCameraManipulator(new osgGA::FirstPersonManipulator);
{
mCurrentCamControl->setCamera(NULL);
mCurrentCamControl = mFreeCamControl.get();
mCurrentCamControl->setCamera(getCamera());
mFreeCamControl->fixUpAxis(osg::Vec3d(0,0,1));
}
else if (mode=="free")
mView->setCameraManipulator(new osgGA::FirstPersonManipulator);
{
mCurrentCamControl->setCamera(NULL);
mCurrentCamControl = mFreeCamControl.get();
mCurrentCamControl->setCamera(getCamera());
mFreeCamControl->unfixUpAxis();
}
else if (mode=="orbit")
mView->setCameraManipulator(new osgGA::OrbitManipulator);
{
mCurrentCamControl->setCamera(NULL);
mCurrentCamControl = mOrbitCamControl.get();
mCurrentCamControl->setCamera(getCamera());
}
else if (mode=="trackball")
mView->setCameraManipulator(new osgGA::TrackballManipulator);
{
mCurrentCamControl->setCamera(NULL);
mCurrentCamControl = mOrbitCamControl.get();
mCurrentCamControl->setCamera(getCamera());
}
}
bool SceneWidget::storeMappingSetting (const CSMPrefs::Setting *setting)

@ -2,6 +2,7 @@
#define OPENCS_VIEW_SCENEWIDGET_H
#include <map>
#include <memory>
#include <QWidget>
#include <QTimer>
@ -39,6 +40,9 @@ namespace CSMPrefs
namespace CSVRender
{
class CameraController;
class FreeCameraController;
class OrbitCameraController;
class Lighting;
class RenderWidget : public QWidget
@ -88,6 +92,10 @@ namespace CSVRender
virtual void mousePressEvent (QMouseEvent *event);
virtual void mouseReleaseEvent (QMouseEvent *event);
virtual void mouseMoveEvent (QMouseEvent *event);
virtual void wheelEvent (QWheelEvent *event);
virtual void keyPressEvent (QKeyEvent *event);
virtual void keyReleaseEvent (QKeyEvent *event);
/// \return Is \a key a button mapping setting? (ignored otherwise)
virtual bool storeMappingSetting (const CSMPrefs::Setting *setting);
@ -104,8 +112,17 @@ namespace CSVRender
LightingNight mLightingNight;
LightingBright mLightingBright;
int mPrevMouseX, mPrevMouseY;
std::string mMouseMode;
std::auto_ptr<FreeCameraController> mFreeCamControl;
std::auto_ptr<OrbitCameraController> mOrbitCamControl;
CameraController* mCurrentCamControl;
std::map<std::pair<Qt::MouseButton, bool>, std::string> mButtonMapping;
public slots:
void update(double dt);
protected slots:
virtual void settingChanged (const CSMPrefs::Setting *setting);
@ -139,6 +156,9 @@ namespace CSVRender
public slots:
void update();
signals:
void simulationUpdated(double dt);
};
}

Loading…
Cancel
Save