Skip to content

Commit

Permalink
GRAPHICS: Add support for picking objects
Browse files Browse the repository at this point in the history
  • Loading branch information
DrMcCoy committed Mar 20, 2014
1 parent 515b961 commit f66411c
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 17 deletions.
15 changes: 11 additions & 4 deletions src/graphics/aurora/cube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ namespace Graphics {

namespace Aurora {

Cube::Cube(const Common::UString &texture) {
Cube::Cube(const Common::UString &texture) : _entity(0) {
Common::UString name = Common::generateIDRandomString();

try {
Expand Down Expand Up @@ -104,16 +104,19 @@ Cube::Cube(const Common::UString &texture) {

// Create entity, put the requested material on it and attach it to a scene node

Ogre::Entity *entity = getOgreSceneManager().createEntity(mesh);
_entity = getOgreSceneManager().createEntity(mesh);
_entity->setQueryFlags(kSelectableNone);

_entity->getUserObjectBindings().setUserAny("renderable", Ogre::Any((Renderable *) this));

Ogre::MaterialPtr material = MaterialMan.get(texture);

entity->setMaterial(material);
_entity->setMaterial(material);

//_rootNode = getOgreSceneManager().createSceneNode(name.c_str());
_rootNode = getOgreSceneManager().getRootSceneNode()->createChildSceneNode(name.c_str());

_rootNode->attachObject(entity);
_rootNode->attachObject(_entity);
_rootNode->setVisible(false);

// Create a rotating animations
Expand Down Expand Up @@ -177,6 +180,10 @@ void Cube::stopRotate() {
getOgreSceneManager().getAnimationState(_rootNode->getName())->setEnabled(false);
}

void Cube::setSelectable(bool selectable) {
_entity->setQueryFlags(selectable ? kSelectableCube : kSelectableNone);
}

} // End of namespace Aurora

} // End of namespace Graphics
10 changes: 10 additions & 0 deletions src/graphics/aurora/cube.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@

#include "graphics/aurora/renderable.h"

namespace Ogre {
class Entity;
}

namespace Common {
class UString;
}
Expand All @@ -47,6 +51,12 @@ class Cube : public Renderable {

void startRotate();
void stopRotate();

/** Change whether the cube can be selected (picked) by the user. */
void setSelectable(bool selectable);

private:
Ogre::Entity *_entity;
};

} // End of namespace Aurora
Expand Down
5 changes: 5 additions & 0 deletions src/graphics/aurora/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ bool Model::stopAnimation() {
return true;
}

void Model::setSelectable(bool selectable) {
for (EntityList::iterator e = _entities.begin(); e != _entities.end(); ++e)
(*e)->setQueryFlags(selectable ? kSelectableModel : kSelectableNone);
}

void Model::showBoundingBox(bool show) {
if (_currentState) {
for (NodeEntities::iterator n = _currentState->nodeEntities.begin(); n != _currentState->nodeEntities.end(); ++n)
Expand Down
3 changes: 3 additions & 0 deletions src/graphics/aurora/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class Model : public Renderable {
/** Stop any currently playing animation. */
bool stopAnimation();

/** Change whether the model can be selected (picked) by the user. */
void setSelectable(bool selectable);

/** Show/Hide the bouding box(es) of this model. */
void showBoundingBox(bool show);

Expand Down
6 changes: 6 additions & 0 deletions src/graphics/aurora/model_nwn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,9 @@ void Model_NWN::readBinaryMesh(ParserContext &ctx) {
mesh->load();

Ogre::Entity *entity = getOgreSceneManager().createEntity(mesh);
entity->setQueryFlags(kSelectableNone);

entity->getUserObjectBindings().setUserAny("renderable", Ogre::Any((Renderable *) this));

// Assign a material to the entity

Expand Down Expand Up @@ -1266,6 +1269,9 @@ void Model_NWN::processASCIIMesh(ParserContext &ctx, MeshASCII &mesh) {
ogreMesh->load();

Ogre::Entity *entity = getOgreSceneManager().createEntity(ogreMesh);
entity->setQueryFlags(kSelectableNone);

entity->getUserObjectBindings().setUserAny("renderable", Ogre::Any((Renderable *) this));

// Assign a material to the entity

Expand Down
7 changes: 7 additions & 0 deletions src/graphics/aurora/renderable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ bool Renderable::isVisible() const {
return _visible;
}

Common::UString Renderable::getID() const {
if (!_rootNode)
return "";

return _rootNode->getName().c_str();
}

void Renderable::setBasePosition(float x, float y, float z) {
_basePosition[0] = x;
_basePosition[1] = y;
Expand Down
11 changes: 7 additions & 4 deletions src/graphics/aurora/renderable.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,13 @@
#ifndef GRAPHICS_AURORA_RENDERABLE_H
#define GRAPHICS_AURORA_RENDERABLE_H

#include "common/ustring.h"

namespace Ogre {
class SceneNode;
class Animation;
}

namespace Common {
class UString;
}

namespace Graphics {

namespace Aurora {
Expand All @@ -52,6 +50,8 @@ class Renderable {

bool isVisible() const;

Common::UString getID() const;

virtual void setVisible(bool visible);

/** Set the base position. All positioning will be done relative to the base position. */
Expand Down Expand Up @@ -85,6 +85,9 @@ class Renderable {
/** Show/Hide the bouding box(es) of this renderable. */
virtual void showBoundingBox(bool show);

/** Change whether the renderable can be selected (picked) by the user. */
virtual void setSelectable(bool selectable) = 0;

protected:
Ogre::SceneNode *_rootNode;

Expand Down
37 changes: 37 additions & 0 deletions src/graphics/aurora/sceneman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "common/error.h"
#include "common/threads.h"

#include "graphics/cameraman.h"

#include "graphics/aurora/meshutil.h"
#include "graphics/aurora/sceneman.h"
#include "graphics/aurora/renderable.h"
Expand Down Expand Up @@ -123,6 +125,41 @@ Model *SceneManager::createModel(const Common::UString &model, const Common::USt
return modelInstance;
}

Renderable *SceneManager::getRenderableAt(int x, int y, SelectableType type, float &distance) {
Ogre::SceneManager &scene = getOgreSceneManager();

const Ogre::Ray mouseRay = CameraMan.castRay(x, y);

Ogre::RaySceneQuery *query = scene.createRayQuery(mouseRay, (uint32) type);
query->setSortByDistance(true);

Ogre::RaySceneQueryResult &results = query->execute();

Renderable *renderable = 0;
for (Ogre::RaySceneQueryResult::iterator result = results.begin(); result != results.end(); ++result) {
// Check that this result has a moveable that contains a visible renderable

if (!result->movable)
continue;

const Ogre::Any &movableRenderable = result->movable->getUserObjectBindings().getUserAny("renderable");
if (movableRenderable.isEmpty())
continue;

Renderable *resultRenderable = Ogre::any_cast<Renderable *>(movableRenderable);
if (!resultRenderable->isVisible())
continue;

renderable = resultRenderable;
distance = result->distance;
break;
}

scene.destroyQuery(query);

return renderable;
}

} // End of namespace Aurora

} // End of namespace Graphics
3 changes: 3 additions & 0 deletions src/graphics/aurora/sceneman.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class SceneManager : public Common::Singleton<SceneManager> {
/** Create a complex Aurora model. */
Model *createModel(const Common::UString &model, const Common::UString &texture = "");

/** Return the nearest renderable at these screen coordinates. */
Renderable *getRenderableAt(int x, int y, SelectableType type, float &distance);

// Singleton interface
static void destroy();

Expand Down
11 changes: 11 additions & 0 deletions src/graphics/aurora/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ enum ModelType {
kModelTypeTheWitcher
};

/** Type of a selectable renderable. */
enum SelectableType {
kSelectableNone = 0, ///< Nothing.

kSelectableCube = 1 << 0, ///< A cube.
kSelectableModel = 1 << 1, ///< A model.

/** All renderable. */
kSelectableRenderable = kSelectableCube | kSelectableModel
};

} // End of namespace Aurora

} // End of namespace Graphics
Expand Down
25 changes: 22 additions & 3 deletions src/graphics/cameraman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ DECLARE_SINGLETON(Graphics::CameraManager)

namespace Graphics {

CameraManager::CameraManager() : _camera(0) {
CameraManager::CameraManager() : _camera(0), _screenWidth(0), _screenHeight(0) {
}

CameraManager::~CameraManager() {
Expand Down Expand Up @@ -72,8 +72,11 @@ Ogre::Viewport *CameraManager::createViewport(Ogre::RenderWindow *window) {
return window->addViewport(_camera);
}

void CameraManager::setAspectRatio(float aspect) {
_camera->setAspectRatio(aspect);
void CameraManager::setScreenSize(int width, int height) {
_screenWidth = width;
_screenHeight = height;

_camera->setAspectRatio(Ogre::Real(width) / Ogre::Real(height));
}

void CameraManager::reset() {
Expand All @@ -98,6 +101,18 @@ void CameraManager::getDirection(float &x, float &y, float &z) const {
z = dir.z;
}

void CameraManager::getOrientation(float &radian, float &x, float &y, float &z) const {
Ogre::Radian angle;
Ogre::Vector3 axis;

_camera->getOrientation().ToAngleAxis(angle, axis);

radian = angle.valueRadians();
x = axis.x;
y = axis.y;
z = axis.z;
}

void CameraManager::setPosition(float x, float y, float z) {
_camera->setPosition(x, y, z);
}
Expand Down Expand Up @@ -138,4 +153,8 @@ void CameraManager::pitch(float radian) {
_camera->pitch(Ogre::Radian(radian));
}

Ogre::Ray CameraManager::castRay(int x, int y) const {
return _camera->getCameraToViewportRay(x / ((float) _screenWidth), y / ((float) _screenHeight));
}

} // End of namespace Graphics
14 changes: 11 additions & 3 deletions src/graphics/cameraman.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#ifndef GRAPHICS_CAMERAMAN_H
#define GRAPHICS_CAMERAMAN_H

#include <OgreRay.h>

#include "common/singleton.h"

namespace Ogre {
Expand All @@ -51,21 +53,21 @@ class CameraManager : public Common::Singleton<CameraManager> {
/** Create a viewport for the camera in that window. */
Ogre::Viewport *createViewport(Ogre::RenderWindow *window);
/** Adjust the aspect ratio of the camera. */
void setAspectRatio(float aspect);
void setScreenSize(int width, int height);

/** Reset the position and orientation of the camera. */
void reset();

void getPosition(float &x, float &y, float &z) const;
void getDirection(float &x, float &y, float &z) const;
void getOrientation(float &radian, float &x, float &y, float &z) const;

void setPosition(float x, float y, float z);
void setDirection(float x, float y, float z);
void setOrientation(float radian, float x, float y, float z);

void lookAt(float x, float y, float z);

void setOrientation(float radian, float x, float y, float z);

void move(float x, float y, float z);
void moveRelative(float x, float y, float z);

Expand All @@ -75,8 +77,14 @@ class CameraManager : public Common::Singleton<CameraManager> {
void yaw(float radian);
void pitch(float radian);

/** Cast a ray from the camera through the viewport at these coordinates into the world. */
Ogre::Ray castRay(int x, int y) const;

private:
Ogre::Camera *_camera; ///< The OGRE camera.

int _screenWidth;
int _screenHeight;
};

} // End of namespace Graphics
Expand Down
6 changes: 3 additions & 3 deletions src/graphics/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ void Renderer::createScene() {

_viewPort = CameraMan.createViewport(_renderWindow);

CameraMan.setAspectRatio(Ogre::Real(_viewPort->getActualWidth()) / Ogre::Real(_viewPort->getActualHeight()));
CameraMan.setScreenSize(_viewPort->getActualWidth(), _viewPort->getActualHeight());

_animator = new OgreAnimator;
_root->addFrameListener(_animator);
Expand Down Expand Up @@ -349,7 +349,7 @@ bool Renderer::recreate(SDL_Window &screen, bool vsync, int fsaa) {
// Reattach camera
_viewPort = CameraMan.createViewport(_renderWindow);

CameraMan.setAspectRatio(Ogre::Real(_viewPort->getActualWidth()) / Ogre::Real(_viewPort->getActualHeight()));
CameraMan.setScreenSize(_viewPort->getActualWidth(), _viewPort->getActualHeight());

return true;
}
Expand All @@ -358,7 +358,7 @@ void Renderer::resized(int width, int height) {
_renderWindow->resize(width, height);
_renderWindow->windowMovedOrResized();

CameraMan.setAspectRatio(Ogre::Real(_viewPort->getActualWidth()) / Ogre::Real(_viewPort->getActualHeight()));
CameraMan.setScreenSize(_viewPort->getActualWidth(), _viewPort->getActualHeight());
}

void Renderer::render() {
Expand Down

0 comments on commit f66411c

Please sign in to comment.