2
// C++ Implementation: Compass
7
// Author: Erik Hjortsberg <erik.hjortsberg@gmail.com>, (C) 2008
9
// This program is free software; you can redistribute it and/or modify
10
// it under the terms of the GNU General Public License as published by
11
// the Free Software Foundation; either version 2 of the License, or
12
// (at your option) any later version.
14
// This program is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
// GNU General Public License for more details.
19
// You should have received a copy of the GNU General Public License
20
// along with this program; if not, write to the Free Software
21
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//
31
#include <CEGUIImageset.h>
32
#include <CEGUIImage.h>
33
#include <CEGUIRect.h>
35
#include "../terrain/Map.h"
37
#include "framework/LoggingInstance.h"
38
#include "../EmberOgre.h"
39
#include "../Avatar.h"
40
#include "../AvatarCamera.h"
42
using namespace EmberOgre::Terrain;
48
Compass::Compass(ICompassImpl* compassImpl)
49
: mMap(new Map()), mCompassImpl(compassImpl)
53
compassImpl->setCompass(this);
62
Terrain::Map& Compass::getMap()
67
void Compass::reposition(float x, float y)
70
mCompassImpl->reposition(x, y);
74
void Compass::rotate(const Ogre::Degree& degree)
77
mCompassImpl->rotate(degree);
81
///Note: duplicate method to make it easier for scripts interacting with the code
82
void Compass::rotate(const Ogre::Radian& radian)
84
rotate(Ogre::Degree(radian));
87
void Compass::refresh()
90
mCompassImpl->refresh();
95
ICompassImpl::ICompassImpl()
101
void ICompassImpl::setCompass(Compass* compass)
104
mMap = &compass->getMap();
105
_setCompass(compass);
109
CEGUICompassImpl::CEGUICompassImpl()
114
CEGUICompassImpl::~CEGUICompassImpl()
118
const CEGUI::Image* CEGUICompassImpl::getViewImage()
123
void CEGUICompassImpl::reposition(float x, float y)
125
// S_LOG_VERBOSE("pos x: " << x << " y: " << y);
126
mMap->getView().reposition(Ogre::Vector2(x, y));
127
const Ogre::TRect<float>& viewBounds(mMap->getView().getRelativeViewBounds());
128
CEGUI::Rect& rect = const_cast<CEGUI::Rect&>(mViewImage->getSourceTextureArea());
129
int textureWidth = mTexturePair.getOgreTexture()->getWidth();
130
rect.setSize(CEGUI::Size(textureWidth * 0.5, textureWidth * 0.5));
131
// const Ogre::Vector2& viewPos(mMap->getView().getRelativeViewPosition());
132
rect.setPosition(CEGUI::Point(textureWidth * viewBounds.left, textureWidth * viewBounds.top));
135
void CEGUICompassImpl::rotate(const Ogre::Degree& degree)
137
///we can't rotate CEGUI windows so we won't do anything
140
void CEGUICompassImpl::refresh()
145
void CEGUICompassImpl::_setCompass(Compass* compass)
147
AssetsManager assetsManager;
148
mTexturePair = assetsManager.createTextureImage(mMap->getTexture(), "CompassMap");
149
int halfOffset = static_cast<int>(mMap->getTexture()->getWidth() * 0.25f);
150
mTexturePair.getTextureImageset()->defineImage("view", CEGUI::Rect(halfOffset, halfOffset, mMap->getTexture()->getWidth() - halfOffset, mMap->getTexture()->getWidth() - halfOffset), CEGUI::Point(0,0));
151
mViewImage = &mTexturePair.getTextureImageset()->getImage("view");
159
OverlayCompassImpl::OverlayCompassImpl()
162
Ogre::OverlayManager& omgr = Ogre::OverlayManager::getSingleton();
163
mCompassOverlay = (Ogre::Overlay*)omgr.getByName("CompassOverlay");
166
OverlayCompassImpl::~OverlayCompassImpl()
168
if (mCompassOverlay) {
169
mCompassOverlay->hide();
170
/* Ogre::OverlayManager& omgr = Ogre::OverlayManager::getSingleton();
171
omgr.destroy(mCompassOverlay);*/
176
void OverlayCompassImpl::_setCompass(Compass* compass)
180
mCompassMaterial = (Ogre::MaterialPtr)Ogre::MaterialManager::getSingleton().getByName("/ui/compass");
181
mCompassMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureName(mMap->getTexture()->getName());
182
mCompassOverlay->show();
186
void OverlayCompassImpl::reposition(float x, float y)
188
mMap->getView().reposition(Ogre::Vector2(x, y));
190
if (!mCompassMaterial.isNull()) {
191
Ogre::TextureUnitState* tus(mCompassMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0));
192
const Ogre::Vector2& relPosition(mMap->getView().getRelativeViewPosition());
193
tus->setTextureScroll(-0.5f + relPosition.x, -0.5f + relPosition.y);
197
void OverlayCompassImpl::rotate(const Ogre::Degree& degree)
200
// Point<2> center = Ogre2Atlas(mMap->getView().getRelativeViewPosition());
201
// Vector<2> dimensions(0.5, 0.5);
203
// qRot = qRot.rotation(2, degree);
205
// RotBox<2> rotbox(center, dimensions, qRot);
209
if (!mCompassMaterial.isNull()) {
210
Ogre::TextureUnitState* tus(mCompassMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0));
211
tus->setTextureRotate(degree);
213
// tus->setTextureRotate(EmberOgre::getSingleton().getMainCamera()->getYaw());
217
void OverlayCompassImpl::refresh()
223
RenderedCompassImpl::RenderedCompassImpl(std::string compassMaterialName, std::string pointerMaterialName)
224
: mRenderTexture(0), mCamera(0), mSceneManager(0), mViewport(0), mCompassMaterialMapTUS(0), mMapRectangle(0), mPointer(pointerMaterialName), mMaterialName(compassMaterialName)
226
mSceneManager = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "RenderedCompassImpl_sceneManager");
227
mSceneManager->setFog(Ogre::FOG_EXP2, Ogre::ColourValue(0,0,0,0), 0.0f, 0.0f, 0.0f);
230
RenderedCompassImpl::~RenderedCompassImpl()
232
///We should probably not do this ourselves, since it will corrupt the material.
233
// if (!mTexture.isNull()) {
234
// Ogre::TextureManager::getSingleton().remove(mTexture->getName());
238
mSceneManager->destroyCamera(mCamera);
241
Ogre::Root::getSingleton().destroySceneManager(mSceneManager);
244
OGRE_DELETE mMapRectangle;
248
void RenderedCompassImpl::reposition(float x, float y)
250
mMap->getView().reposition(Ogre::Vector2(x, y));
252
if (mCompassMaterialMapTUS) {
253
const Ogre::Vector2& relPosition(mMap->getView().getRelativeViewPosition());
254
mCompassMaterialMapTUS->setTextureScroll(-0.5f + relPosition.x, -0.5f + relPosition.y);
256
mRenderTexture->update();
262
void RenderedCompassImpl::rotate(const Ogre::Degree& degree)
264
mPointer.rotate(degree);
265
///We won't rotate the image.
269
void RenderedCompassImpl::refresh()
275
void RenderedCompassImpl::_setCompass(Compass* compass)
277
mCompassMaterial = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(mMaterialName));
278
if (!mCompassMaterial.isNull()) {
279
mCompassMaterial->load();
280
if (Ogre::Technique* tech = mCompassMaterial->getBestTechnique()) {
282
if (tech->getNumPasses() && (pass = tech->getPass(0))) {
283
if ((mCompassMaterialMapTUS = pass->getTextureUnitState("Background"))) {
284
///Make sure that the compass material is using the map texture for the base rendering
285
mCompassMaterialMapTUS->setTextureName(mMap->getTexture()->getName());
287
mTexture = Ogre::TextureManager::getSingleton().createManual("RenderedCompass", "Gui", Ogre::TEX_TYPE_2D, 128, 128, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET);
288
mRenderTexture = mTexture->getBuffer()->getRenderTarget();
289
mRenderTexture->removeAllViewports();
290
mRenderTexture->setAutoUpdated(false);
291
mRenderTexture->setActive(true);
293
mCamera = mSceneManager->createCamera("RenderedCompassCamera");
294
mViewport = mRenderTexture->addViewport(mCamera);
295
mViewport->setOverlaysEnabled(false);
296
mViewport->setShadowsEnabled(false);
297
mViewport->setSkiesEnabled(false);
298
mViewport->setClearEveryFrame(true);
299
mViewport->setBackgroundColour(Ogre::ColourValue::ZERO);
301
mMapRectangle = OGRE_NEW Ogre::Rectangle2D(true);
302
mMapRectangle->setMaterial(mMaterialName);
304
///We need to maximise the rendered texture to cover the whole screen
305
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
306
Ogre::Real hOffset = rs->getHorizontalTexelOffset() / (0.5 * mViewport->getActualWidth());
307
Ogre::Real vOffset = rs->getVerticalTexelOffset() / (0.5 * mViewport->getActualHeight());
308
mMapRectangle->setCorners(-1 + hOffset, 1 - vOffset, 1 + hOffset, -1 - vOffset);
310
///Since a Rectangle2D instance is a moveable object it won't be rendered unless it's in the frustrum. If we set the axis aligned box to be "infinite" it will always be rendered.
311
Ogre::AxisAlignedBox aabInf;
312
aabInf.setInfinite();
313
mMapRectangle->setBoundingBox(aabInf);
315
///We can't attach something to the root node, so we'll attach it to a newly created node. We won't keep a reference to this node since it will be destroyed along with the scene manager when we ourselves are destroyed.
316
mSceneManager->getRootSceneNode()->createChildSceneNode()->attachObject(mMapRectangle);
318
///Return early since everything is good.
324
S_LOG_WARNING("Could not load material '" << mMaterialName << "' for the compass.");
327
Ogre::TexturePtr RenderedCompassImpl::getTexture() const
332
Ogre::TexturePtr RenderedCompassImpl::getPointerTexture() const
334
return mPointer.getTexture();
339
RenderedCompassPointer::RenderedCompassPointer(std::string materialName)
340
: mRenderTexture(0), mCamera(0), mSceneManager(0), mViewport(0), mPointerTUS(0), mPointerRectangle(0)
342
mSceneManager = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "RenderedCompassPointer_sceneManager");
343
mSceneManager->setFog(Ogre::FOG_EXP2, Ogre::ColourValue(0,0,0,0), 0.0f, 0.0f, 0.0f);
345
mPointerMaterial = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(materialName));
346
if (!mPointerMaterial.isNull()) {
347
mPointerMaterial->load();
348
if (Ogre::Technique* tech = mPointerMaterial->getBestTechnique()) {
350
if (tech->getNumPasses() && (pass = tech->getPass(0))) {
351
if ((mPointerTUS = pass->getTextureUnitState("Pointer"))) {
353
///Since we need to rotate the arrow we'll make the image twice as big (32px) as the width of the arrow (16px), else it will be truncated when it's turned 45 degrees.
354
///The material used must those use a 0.5 scale so that the compass arrow is half the size.
355
mTexture = Ogre::TextureManager::getSingleton().createManual("RenderedCompassPointer", "Gui", Ogre::TEX_TYPE_2D, 32, 32, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET);
356
mRenderTexture = mTexture->getBuffer()->getRenderTarget();
357
mRenderTexture->removeAllViewports();
358
mRenderTexture->setAutoUpdated(false);
359
mRenderTexture->setActive(true);
361
mCamera = mSceneManager->createCamera("RenderedCompassPointerCamera");
362
mViewport = mRenderTexture->addViewport(mCamera);
363
mViewport->setOverlaysEnabled(false);
364
mViewport->setShadowsEnabled(false);
365
mViewport->setSkiesEnabled(false);
366
mViewport->setClearEveryFrame(true);
367
mViewport->setBackgroundColour(Ogre::ColourValue::ZERO);
369
mPointerRectangle = OGRE_NEW Ogre::Rectangle2D(true);
370
mPointerRectangle->setMaterial(materialName);
372
///We need to maximise the rendered texture to cover the whole screen
373
Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem();
374
Ogre::Real hOffset = rs->getHorizontalTexelOffset() / (0.5 * 32);
375
Ogre::Real vOffset = rs->getVerticalTexelOffset() / (0.5 * 32);
376
mPointerRectangle->setCorners(-1 + hOffset, 1 - vOffset, 1 + hOffset, -1 - vOffset);
378
///Since a Rectangle2D instance is a moveable object it won't be rendered unless it's in the frustrum. If we set the axis aligned box to be "infinite" it will always be rendered.
379
Ogre::AxisAlignedBox aabInf;
380
aabInf.setInfinite();
381
mPointerRectangle->setBoundingBox(aabInf);
383
///We can't attach something to the root node, so we'll attach it to a newly created node. We won't keep a reference to this node since it will be destroyed along with the scene manager when we ourselves are destroyed.
384
mSceneManager->getRootSceneNode()->createChildSceneNode()->attachObject(mPointerRectangle);
386
///Return early since everything is good.
392
S_LOG_WARNING("Could not load material '" << materialName << "' for the compass pointer.");
395
RenderedCompassPointer::~RenderedCompassPointer()
397
///We should probably not do this ourselves, since it will corrupt the material.
398
// if (!mTexture.isNull()) {
399
// Ogre::TextureManager::getSingleton().remove(mTexture->getName());
403
mSceneManager->destroyCamera(mCamera);
406
Ogre::Root::getSingleton().destroySceneManager(mSceneManager);
409
OGRE_DELETE mPointerRectangle;
412
void RenderedCompassPointer::rotate(const Ogre::Degree& degree)
414
if (mPointerTUS && mPreviousRotation != degree) {
415
///The pointer image is pointing to the upper left corner, so we need to adjust it by 45 degrees to have it point directly upwards
416
mPointerTUS->setTextureRotate(-degree - Ogre::Degree(45));
418
mRenderTexture->update();
419
mPreviousRotation = degree;
423
Ogre::TexturePtr RenderedCompassPointer::getTexture() const
431
CompassAnchor::CompassAnchor(Compass& compass, const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
435
, mPosition(position)
436
, mOrientation(orientation)
438
/// Register this as a frame listener
439
Ogre::Root::getSingleton().addFrameListener(this);
442
CompassAnchor::~CompassAnchor()
444
Ogre::Root::getSingleton().removeFrameListener(this);
447
bool CompassAnchor::frameStarted(const Ogre::FrameEvent& event)
449
mCompass.rotate(-mOrientation.getYaw());
450
if (mPosition.x != mPreviousX || mPosition.z != mPreviousZ) {
451
mCompass.reposition(mPosition.x, mPosition.z);
452
mPreviousX = mPosition.x;
453
mPreviousZ = mPosition.z;
461
CompassCameraAnchor::CompassCameraAnchor(Compass& compass, Ogre::Camera* camera)
462
: mAnchor(compass, camera->getDerivedPosition(), camera->getDerivedOrientation())
467
CompassCameraAnchor::~CompassCameraAnchor()
472
CompassSceneNodeAnchor::CompassSceneNodeAnchor(Compass& compass, Ogre::SceneNode* sceneNode)
473
: mAnchor(compass, sceneNode->_getDerivedPosition(), sceneNode->_getDerivedOrientation())
474
, mSceneNode(sceneNode)
478
CompassSceneNodeAnchor::~CompassSceneNodeAnchor()
482
CompassThirdPersonCameraAnchor::CompassThirdPersonCameraAnchor(Compass& compass, Ogre::Camera* camera, Ogre::SceneNode* sceneNode)
483
: mAnchor(compass, sceneNode->_getDerivedPosition(), camera->getDerivedOrientation())
484
, mCamera(camera), mSceneNode(sceneNode)
488
CompassThirdPersonCameraAnchor::~CompassThirdPersonCameraAnchor()