Using QT keyboard and mouse events with Ogre

Problems building or running the engine, queries about how to use features etc.
Post Reply
Freepax
Gnoblar
Posts: 3
Joined: Wed Nov 16, 2011 4:34 pm

Using QT keyboard and mouse events with Ogre

Post by Freepax »

Hi all.

I've been googleing around all day, but have not found a proper solution to my problem so sorry if the right solution is out there some where already...

What I would like to is using OgreBites::SdkCameraMan to control camera movement, but not using OIS but QT mouse and keyboard events ( eg. QMouseEvent, QKeyEvent etc. ). I've found a project that seems to try to achieve this ( http://code.google.com/p/qtogreggg/ ), but "Activity" on this project is "None". This project does not seem to use SdkCameraMan at all but "reimplements" all transformation calculations instead.

Anyone know a nice way to do this? Is there a wrapper or something out there some where?

Thanks
Freepax
User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia
x 81

Re: Using QT keyboard and mouse events with Ogre

Post by Mind Calamity »

Last time I tried anything with the OGRE widget for Qt I remember it didn't monitor mouse move events unless the widget was focused by clicking on it.

If you can manage to get the mouse-move event of the ogre widget properly, converting OgreBites::SdkCameraMan would be a trivial thing to do.

If you do manage what I said, please post the source code if you can, as I wasn't able to, and I had weird camera movement because of the sudden coordinate change.

This is my camera manager for Qt, incomplete and very buggy, but it should give you an idea about how to handle events:

Code: Select all

/*
 -----------------------------------------------------------------------------
 Based on SdkCameraMan.h
 -----------------------------------------------------------------------------
 */
#ifndef __QtCameraMan_H__
#define __QtCameraMan_H__

#include "Ogre.h"
#include <QtGui>
#include <limits>

namespace QOgre
{
    enum CameraStyle   // enumerator values for different styles of camera movement
    {
	    CS_ORBIT,
	    CS_FREELOOK,
	    CS_MANUAL
    };

    enum PositionType
    {
	PT_ABSOLUTE,
	PT_RELATIVE
    };

    /*=============================================================================
    | Utility class for controlling the camera in samples.
    =============================================================================*/

    class MousePosition
    {
    private:
	Ogre::Vector2 Relative;
	Ogre::Vector2 Absolute;

    public:
	MousePosition()
	{
	    Relative = Ogre::Vector2(0, 0);
	    Absolute = Ogre::Vector2(0, 0);
	}

	Ogre::Vector2 getMousePosition(PositionType type)
	{
	    if (type == PT_ABSOLUTE)
		return Relative;
	    else
		return Absolute;
	}

	void setMousePosition(PositionType type, int x, int y)
	{
	    if (type == PT_ABSOLUTE)
		Absolute = Ogre::Vector2(x, y);
	    else
		Relative = Ogre::Vector2(x, y);
	}
    };

    class QtCameraMan
    {
    public:
		QtCameraMan(Ogre::Camera* cam)
		: mCamera(0)
		, mTarget(0)
		, mOrbiting(false)
		, mZooming(false)
		, mCameraNode(0)
		, mTargetEntity(0)
		{

			setCamera(cam);
		}

		virtual ~QtCameraMan() {}

		/*-----------------------------------------------------------------------------
		| Swaps the camera on our camera man for another camera.
		-----------------------------------------------------------------------------*/
		virtual void setCamera(Ogre::Camera* cam)
		{
			mCamera = cam;
			mCameraNode = mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode( "Camera Node" );
			mCameraNode->attachObject( mCamera );
			mCameraNode->pitch( Ogre::Degree( -45.0f ) );
			mCamera->setPosition( Ogre::Vector3::UNIT_Z * 10.0f );
			mCamera->lookAt( Ogre::Vector3( 0.0f, 0.0f, 0.0f ) );
		}

		virtual Ogre::Camera* getCamera()
		{
			return mCamera;
		}

		/*-----------------------------------------------------------------------------
		| Sets the target we will revolve around. Only applies for orbit style.
		-----------------------------------------------------------------------------*/
		virtual void setTarget(Ogre::SceneNode* target)
		{
			if (target != mTarget)
			{
				mTarget = target;
				if(target)
				{
					//setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
					//mCamera->setAutoTracking(true, mTarget);
				}
				else
				{
					mCamera->setAutoTracking(false);
				}

			}


		}

		virtual Ogre::Entity* getTargetEntity()
		{
			return mTargetEntity;
		}

		virtual Ogre::SceneNode* getTarget()
		{
			return mTarget;
		}

		/*-----------------------------------------------------------------------------
		| Sets the spatial offset from the target. Only applies for orbit style.
		-----------------------------------------------------------------------------*/
		virtual void setYawPitchDist(Ogre::Radian yaw, Ogre::Radian pitch, Ogre::Real dist)
		{
			mCamera->setPosition(mTarget->_getDerivedPosition());
			mCamera->setOrientation(mTarget->_getDerivedOrientation());
			mCamera->yaw(yaw);
			mCamera->pitch(-pitch);
			mCamera->moveRelative(Ogre::Vector3(0, 0, dist));
		}

		/*-----------------------------------------------------------------------------
		| Sets the movement style of our camera man.
		-----------------------------------------------------------------------------*/
		virtual void setStyle(CameraStyle style)
		{
			if (mStyle != CS_ORBIT && style == CS_ORBIT)
			{
				setTarget(mTarget ? mTarget : mCamera->getSceneManager()->getRootSceneNode());
				mCamera->setFixedYawAxis(true);
				setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
			}
			mStyle = style;

		}

		virtual CameraStyle getStyle()
		{
			return mStyle;
		}

		/*-----------------------------------------------------------------------------
		| Gets the old position of the cursor over the widget.
		-----------------------------------------------------------------------------*/
		virtual QPoint getMousePosition(PositionType type)
		{
		    if (type == PT_ABSOLUTE)
			return mAbsolute;
		    else
			return mRelative;
		}

		virtual bool frameRenderingQueued(Ogre::FrameEvent& evt)
		{
		    return true;
		}

		/*-----------------------------------------------------------------------------
		| Processes key presses for free-look style movement.
		-----------------------------------------------------------------------------*/
		virtual void injectKeyDown(const QKeyEvent *evt)
		{
		    if (evt->key() == Qt::Key_Shift)
			mShiftDown = true;
		}

		/*-----------------------------------------------------------------------------
		| Processes key releases for free-look style movement.
		-----------------------------------------------------------------------------*/
		virtual void injectKeyUp(const QKeyEvent* evt)
		{
		    if (evt->key() == Qt::Key_Shift)
			mShiftDown = false;
		}

		/*-----------------------------------------------------------------------------
		| Processes mouse movement differently for each style.
		-----------------------------------------------------------------------------*/
		virtual void injectMouseMove(const QMouseEvent* evt)
		{
		    QPoint oldPos = mAbsolute;

		    mAbsolute = evt->pos();

		    mRelative = mAbsolute - oldPos;

		    if (mStyle == CS_FREELOOK)
		    {
			    mCamera->yaw(Ogre::Degree(-mRelative.x() * 0.15f));
			    mCamera->pitch(Ogre::Degree(-mRelative.y() * 0.15f));
		    }
		}

		virtual void injectMouseWheel(const QWheelEvent* evt)
		{
		    mMouseWheelDelta = evt->delta();

		    Ogre::Real dist = (mCamera->getPosition() - mTarget->_getDerivedPosition()).length();

		    mCamera->moveRelative(Ogre::Vector3(0, 0, -mMouseWheelDelta * 0.0008f * dist));

		}

		virtual void injectMouseDown(const QMouseEvent* evt)
		{
			if (mStyle == CS_ORBIT)
			{
				if (evt->button() == Qt::LeftButton) mOrbiting = true;
				else if (evt->button() == Qt::RightButton) mZooming = true;
			}
		}

		/*-----------------------------------------------------------------------------
		| Processes mouse releases. Only applies for orbit style.
		| Left button is for orbiting, and right button is for zooming.
		-----------------------------------------------------------------------------*/
		virtual void injectMouseUp(const QMouseEvent* evt)
		{
			if (mStyle == CS_ORBIT)
			{
			    if (evt->button() == Qt::LeftButton) mOrbiting = false;
			    else if (evt->button() == Qt::RightButton) mZooming = false;
			}
		}

		virtual void rotate(int x, int y)
		{
		    mCameraNode->yaw( Ogre::Degree( -x * 0.4f ), Ogre::Node::TS_PARENT );
		    mCameraNode->pitch( Ogre::Degree( -y * 0.4f ) );
		}

		virtual void move(int x, int y)
		{
			Ogre::Vector3 vTrans( -x, y, 0 );
			vTrans *= mCamera->getSceneManager()->getEntity("mainEntity")->getBoundingRadius() * 0.005f;
			mCameraNode->translate( vTrans, Ogre::Node::TS_LOCAL );
		}

		virtual void zoom(double wheelDelta)
		{

		    float factor = 1.0f;
		    if( mTarget->getAttachedObject(0) )
			    factor = mTarget->getAttachedObject(0)->getBoundingRadius() * 0.5f;
		    mCamera->move( Ogre::Vector3::UNIT_Z * wheelDelta * factor );

		    //Clamp max zoom in, to keep going use slideCamera

		    float maxZoom = -5.0f;

		    if( mCamera->getPosition().z < maxZoom )
			mCamera->setPosition( Ogre::Vector3::ZERO );

		}

		virtual void slide(int x, int z)
		{
		    if (mTarget->getAttachedObject(0))
		    {
			    Ogre::Vector3 vTrans( -x, 0, -z );
			    vTrans *= mTarget->getAttachedObject(0)->getBoundingRadius() * 0.005f;
			    mCameraNode->translate( vTrans, Ogre::Node::TS_LOCAL );
		    }
		}

    protected:

		Ogre::Camera* mCamera;
		CameraStyle mStyle;
		Ogre::SceneNode* mTarget;
		Ogre::Entity* mTargetEntity;
		Ogre::SceneNode* mCameraNode;
		bool mOrbiting;
		bool mZooming;

		bool mRID;
		bool mLID;
		bool mShiftDown;

		QPoint mAbsolute;
		QPoint mRelative;
		int mMouseWheelDelta;

    };
}

#endif
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
Freepax
Gnoblar
Posts: 3
Joined: Wed Nov 16, 2011 4:34 pm

Re: Using QT keyboard and mouse events with Ogre

Post by Freepax »

Sorry late reply, I've been away for the weekend.

Looks like you have used the Samples/Common/include/SdkCameraMan.h file as your starting point. I played a bit with the code that you sent me and then I took a copy of the SdkCameraMan.h file and started to substitude all OIS variables with QKeyEvent and QMouseEvent variables.

I have not had that much success by now. It seems like injectMouseMove works ok with style == CS__ORBIT but not with style == CS__FREELOOK. The camera does not yaw or pitch at all which is very strange - must be something wrong with the camera pointer, but I cannot figure out what...

The next issue is to feed the frameRenderingQueued function with "timeSinceLastFrame" (which is the only variable in the Ogre::FrameEvent thats used in this function). If we could figure out a way to find the time elapsed between calls to the paintEvent slot, the frameRenderingQueued function could be called from the paintEvent with this time as argument. (correct me if I'm thining wrong here).

Hope you and other people on this forum can help out :)
Freepax
Gnoblar
Posts: 3
Joined: Wed Nov 16, 2011 4:34 pm

Re: Using QT keyboard and mouse events with Ogre

Post by Freepax »

Yo - think CS_FREELOOK mode now works :D

Here are the file:
cameraman.h
SdkCameraMan changed to work with QKey- and QMouse- Events
(12.31 KiB) Downloaded 266 times
I call the frameRenderingQueued from my paintGL function with a calculated timeSinceLastFrame number.

I have not tested the CS_ORBIT mode very much, all I know is that the rotation (using mouse) worked last time I tried...

Freepax
User avatar
Mind Calamity
Ogre Magi
Posts: 1255
Joined: Sat Dec 25, 2010 2:55 pm
Location: Macedonia
x 81

Re: Using QT keyboard and mouse events with Ogre

Post by Mind Calamity »

Thanks for sharing, mate. I had a problem with my widget when I needed it, as I think I mentioned (too lazy to check), it didn't record the mouse positions correctly, but I'm glad you solved your problem.
BitBucket username changed to iboshkov (from MindCalamity)
Do you need help? What have you tried?
- xavier
---------------------
HkOgre - a Havok Integration for OGRE | Simple SSAO | My Blog | My YouTube | My DeviantArt
Post Reply