From b50c7e07887ae7b8a37e0933727997b181499dc7 Mon Sep 17 00:00:00 2001 From: Armin Preiml Date: Tue, 3 Aug 2010 16:26:43 +0200 Subject: [PATCH 1/3] Some experimental implementation of a RaySceneQuery. --- apps/openmw/mwinput/inputmanager.cpp | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index f32e207dc2..484491e09a 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -41,6 +41,8 @@ namespace MWInput A_MoveForward, // Forward / Backward A_MoveBackward, + A_Activate, + A_LAST // Marker for the last item }; @@ -57,6 +59,10 @@ namespace MWInput MWRender::PlayerPos &player; MWGui::WindowManager &windows; + //may be better placed at OEngine::Renderer + Ogre::RaySceneQuery *mRaySceneQuery; + + // Count screenshots. int shotCount; @@ -133,6 +139,51 @@ namespace MWInput else setGuiMode(GM_Console); } + void activate() + { + Ogre::Camera *mCamera = ogre.getCamera(); + + //get a ray pointing to the center of the viewport + Ogre::Ray centerRay = mCamera->getCameraToViewportRay ( 0.5, 0.5 ); + + // get all objects touched by the ray + mRaySceneQuery->setRay ( centerRay ); + Ogre::RaySceneQueryResult &result = mRaySceneQuery->execute(); + Ogre::RaySceneQueryResult::iterator itr = result.begin(); + + Ogre::RaySceneQueryResult::iterator nearest = result.end(); + + for ( ; itr != result.end(); itr++ ) + { + /*if ( itr->worldFragment ) //world fragments aren't currently used by openw + { + Ogre::Vector3 location = itr->worldFragment->singleIntersection; + std::cout << "WorldFragment: (" << location.x << ", " << location.y << ", " << location.z << ")" << std::endl; + } // if*/ + + // Is this result a MovableObject? + // there seem to be omnipresent objects like the caelum sky dom, + // the distance of these objects is always 0 so this if excludes these + if ( itr->movable && itr->distance >= 0.1) + { + std::cout << "Movobj: " << itr->movable->getName() << " dist: " << itr->distance << "\n"; + + if ( nearest == result.end() ) //if no object is set + { + nearest = itr; + } + else if ( itr->distance < nearest->distance ) + { + nearest = itr; + } + } + } + + if ( nearest != result.end() ) + std::cout << "Nearest MovableObject: " << nearest->movable->getName() + << " Distance: " << nearest->distance << std::endl; + } + // Exit program now button (which is disabled in GUI mode) void exitNow() { @@ -170,6 +221,8 @@ namespace MWInput "Toggle inventory screen"); disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this), "Toggle console"); + disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this), + "Activate"); // Add the exit listener @@ -198,6 +251,9 @@ namespace MWInput // Start out in game mode setGuiMode(MWGui::GM_Game); + //init rayscene query (would be also better placed at Oengine::Renderer) + mRaySceneQuery = ogre.getScene()->createRayQuery(Ogre::Ray()); + /********************************** Key binding section @@ -212,6 +268,7 @@ namespace MWInput disp->bind(A_Screenshot, KC_SYSRQ); disp->bind(A_Inventory, KC_I); disp->bind(A_Console, KC_F1); + disp->bind(A_Activate, KC_SPACE); // Key bindings for polled keys @@ -257,6 +314,7 @@ namespace MWInput if(moveX != 0 || moveY != 0 || moveZ != 0) player.moveRel(moveX, moveY, moveZ); + return true; } }; From c000bfb43df6fa6810d55bd33504c9bf69a17617 Mon Sep 17 00:00:00 2001 From: Armin Preiml Date: Tue, 3 Aug 2010 20:17:31 +0200 Subject: [PATCH 2/3] moved object focus code to mwscene --- apps/openmw/mwinput/inputmanager.cpp | 47 -------------------------- apps/openmw/mwrender/mwscene.cpp | 50 ++++++++++++++++++++++++++++ apps/openmw/mwrender/mwscene.hpp | 6 ++++ 3 files changed, 56 insertions(+), 47 deletions(-) diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 484491e09a..f851b43b2e 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -59,10 +59,6 @@ namespace MWInput MWRender::PlayerPos &player; MWGui::WindowManager &windows; - //may be better placed at OEngine::Renderer - Ogre::RaySceneQuery *mRaySceneQuery; - - // Count screenshots. int shotCount; @@ -141,47 +137,7 @@ namespace MWInput void activate() { - Ogre::Camera *mCamera = ogre.getCamera(); - - //get a ray pointing to the center of the viewport - Ogre::Ray centerRay = mCamera->getCameraToViewportRay ( 0.5, 0.5 ); - - // get all objects touched by the ray - mRaySceneQuery->setRay ( centerRay ); - Ogre::RaySceneQueryResult &result = mRaySceneQuery->execute(); - Ogre::RaySceneQueryResult::iterator itr = result.begin(); - - Ogre::RaySceneQueryResult::iterator nearest = result.end(); - for ( ; itr != result.end(); itr++ ) - { - /*if ( itr->worldFragment ) //world fragments aren't currently used by openw - { - Ogre::Vector3 location = itr->worldFragment->singleIntersection; - std::cout << "WorldFragment: (" << location.x << ", " << location.y << ", " << location.z << ")" << std::endl; - } // if*/ - - // Is this result a MovableObject? - // there seem to be omnipresent objects like the caelum sky dom, - // the distance of these objects is always 0 so this if excludes these - if ( itr->movable && itr->distance >= 0.1) - { - std::cout << "Movobj: " << itr->movable->getName() << " dist: " << itr->distance << "\n"; - - if ( nearest == result.end() ) //if no object is set - { - nearest = itr; - } - else if ( itr->distance < nearest->distance ) - { - nearest = itr; - } - } - } - - if ( nearest != result.end() ) - std::cout << "Nearest MovableObject: " << nearest->movable->getName() - << " Distance: " << nearest->distance << std::endl; } // Exit program now button (which is disabled in GUI mode) @@ -251,9 +207,6 @@ namespace MWInput // Start out in game mode setGuiMode(MWGui::GM_Game); - //init rayscene query (would be also better placed at Oengine::Renderer) - mRaySceneQuery = ogre.getScene()->createRayQuery(Ogre::Ray()); - /********************************** Key binding section diff --git a/apps/openmw/mwrender/mwscene.cpp b/apps/openmw/mwrender/mwscene.cpp index 489b5f2421..7ba75193a2 100644 --- a/apps/openmw/mwrender/mwscene.cpp +++ b/apps/openmw/mwrender/mwscene.cpp @@ -31,4 +31,54 @@ MWScene::MWScene(OEngine::Render::OgreRenderer &_rend) SceneNode *rt = rend.getScene()->getRootSceneNode(); mwRoot = rt->createChildSceneNode(); mwRoot->pitch(Degree(-90)); + + //used to obtain ingame information of ogre objects (which are faced or selected) + mRaySceneQuery = rend.getScene()->createRayQuery(Ray()); } + +void MWScene::getFacedHandle(std::string& handle, float& distance) +{ + handle = ""; + distance = -1; + + //get a ray pointing to the center of the viewport + Ray centerRay = getCamera()->getCameraToViewportRay( + getViewport()->getWidth()/2, + getViewport()->getHeight()/2); + + // get all objects touched by the ray + getRaySceneQuery()->setRay (centerRay ); + RaySceneQueryResult &result = getRaySceneQuery()->execute(); + + RaySceneQueryResult::iterator nearest = result.end(); + + for (RaySceneQueryResult::iterator itr = result.begin(); + itr != result.end(); itr++ ) + { + // there seem to be omnipresent objects like the caelum sky dom, + // the distance of these objects is always 0 so this if excludes these + // TODO: Check if the object can be focused (ignore walls etc.. + // in this state of openmw not possible) + if ( itr->movable && itr->distance >= 0.1) + { + if ( nearest == result.end() ) //if no object is set + { + nearest = itr; + } + else if ( itr->distance < nearest->distance ) + { + nearest = itr; + } + } + } + + if ( nearest != result.end() ) + { + std::cout << "Nearest MovableObject: " << nearest->movable->getParentSceneNode()->getName() + << " Distance: " << nearest->distance << std::endl; + + handle = nearest->movable->getParentSceneNode()->getName(); + distance = nearest->distance; + } +} + diff --git a/apps/openmw/mwrender/mwscene.hpp b/apps/openmw/mwrender/mwscene.hpp index a7339e1c84..fcd63df395 100644 --- a/apps/openmw/mwrender/mwscene.hpp +++ b/apps/openmw/mwrender/mwscene.hpp @@ -9,6 +9,7 @@ namespace Ogre class Viewport; class SceneManager; class SceneNode; + class RaySceneQuery; } namespace MWRender @@ -26,6 +27,7 @@ namespace MWRender // that the OGRE coordinate system matches that used internally in // Morrowind. Ogre::SceneNode *mwRoot; + Ogre::RaySceneQuery *mRaySceneQuery; public: MWScene(OEngine::Render::OgreRenderer &_rend); @@ -34,6 +36,10 @@ namespace MWRender Ogre::SceneNode *getRoot() { return mwRoot; } Ogre::SceneManager *getMgr() { return rend.getScene(); } Ogre::Viewport *getViewport() { return rend.getViewport(); } + Ogre::RaySceneQuery *getRaySceneQuery() { return mRaySceneQuery; } + + //gets the handle of the object the player is looking at + void getFacedHandle(std::string& handle, float& distance); }; } From adc209d1351b1e519d429f5bdb4abd4fea0cec73 Mon Sep 17 00:00:00 2001 From: Armin Preiml Date: Tue, 3 Aug 2010 20:40:45 +0200 Subject: [PATCH 3/3] Implemented the faced handle method to the engine. Faced handles will be written to stdout every 10th frame. --- apps/openmw/engine.cpp | 12 ++++++++++++ apps/openmw/engine.hpp | 3 +++ apps/openmw/mwrender/mwscene.cpp | 11 +++++------ apps/openmw/mwrender/mwscene.hpp | 6 +++++- apps/openmw/mwworld/world.hpp | 2 ++ 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 43a01b271e..d7d215d023 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -68,6 +69,15 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) // update actors mEnvironment.mMechanicsManager->update(); + if (focusFrameCounter++ == focusUpdateFrame) + { + std::pair handle = mEnvironment.mWorld->getMWScene()->getFacedHandle(); + + std::cout << "Object: " << handle.first << ", distance: " << handle.second << std::endl; + + focusFrameCounter = 0; + } + return true; } @@ -230,6 +240,8 @@ void OMW::Engine::go() MWInput::MWInputManager input(mOgre, mEnvironment.mWorld->getPlayerPos(), *mEnvironment.mWindowManager, mDebug); + focusFrameCounter = 0; + std::cout << "\nPress Q/ESC or close window to exit.\n"; mOgre.getRoot()->addFrameListener (this); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 9923f49906..412c4fa736 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -65,6 +65,9 @@ namespace OMW Compiler::Context *mScriptContext; OEngine::GUI::MyGUIManager *mGuiManager; + int focusFrameCounter; + static const int focusUpdateFrame = 10; + // not implemented Engine (const Engine&); Engine& operator= (const Engine&); diff --git a/apps/openmw/mwrender/mwscene.cpp b/apps/openmw/mwrender/mwscene.cpp index 7ba75193a2..15163d7a28 100644 --- a/apps/openmw/mwrender/mwscene.cpp +++ b/apps/openmw/mwrender/mwscene.cpp @@ -36,10 +36,10 @@ MWScene::MWScene(OEngine::Render::OgreRenderer &_rend) mRaySceneQuery = rend.getScene()->createRayQuery(Ray()); } -void MWScene::getFacedHandle(std::string& handle, float& distance) +std::pair MWScene::getFacedHandle() { - handle = ""; - distance = -1; + std::string handle = ""; + float distance = -1; //get a ray pointing to the center of the viewport Ray centerRay = getCamera()->getCameraToViewportRay( @@ -74,11 +74,10 @@ void MWScene::getFacedHandle(std::string& handle, float& distance) if ( nearest != result.end() ) { - std::cout << "Nearest MovableObject: " << nearest->movable->getParentSceneNode()->getName() - << " Distance: " << nearest->distance << std::endl; - handle = nearest->movable->getParentSceneNode()->getName(); distance = nearest->distance; } + + return std::pair(handle, distance); } diff --git a/apps/openmw/mwrender/mwscene.hpp b/apps/openmw/mwrender/mwscene.hpp index fcd63df395..ce04efc92e 100644 --- a/apps/openmw/mwrender/mwscene.hpp +++ b/apps/openmw/mwrender/mwscene.hpp @@ -1,6 +1,7 @@ #ifndef _GAME_RENDER_MWSCENE_H #define _GAME_RENDER_MWSCENE_H +#include #include namespace Ogre @@ -39,7 +40,10 @@ namespace MWRender Ogre::RaySceneQuery *getRaySceneQuery() { return mRaySceneQuery; } //gets the handle of the object the player is looking at - void getFacedHandle(std::string& handle, float& distance); + //pair + //name is empty and distance = -1 if there is no object which + //can be faced + std::pair getFacedHandle(); }; } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 953fe93e43..88267abe8b 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -80,6 +80,8 @@ namespace MWWorld const std::string& dataDir, bool newGame, Environment& environment); ~World(); + + MWRender::MWScene* getMWScene() { return &mScene; } MWRender::PlayerPos& getPlayerPos();