~ubuntu-branches/debian/sid/ember/sid

« back to all changes in this revision

Viewing changes to src/components/ogre/widgets/Compass.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2009-07-23 07:46:40 UTC
  • Revision ID: james.westby@ubuntu.com-20090723074640-wh0ukzis0kda36qv
Tags: upstream-0.5.6
ImportĀ upstreamĀ versionĀ 0.5.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// C++ Implementation: Compass
 
3
//
 
4
// Description: 
 
5
//
 
6
//
 
7
// Author: Erik Hjortsberg <erik.hjortsberg@gmail.com>, (C) 2008
 
8
//
 
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.
 
13
// 
 
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.
 
18
// 
 
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.//
 
22
//
 
23
#ifdef HAVE_CONFIG_H
 
24
#include "config.h"
 
25
#endif
 
26
 
 
27
#include "Compass.h"
 
28
 
 
29
#include <Ogre.h>
 
30
 
 
31
#include <CEGUIImageset.h>
 
32
#include <CEGUIImage.h>
 
33
#include <CEGUIRect.h>
 
34
 
 
35
#include "../terrain/Map.h"
 
36
 
 
37
#include "framework/LoggingInstance.h"
 
38
#include "../EmberOgre.h"
 
39
#include "../Avatar.h"
 
40
#include "../AvatarCamera.h"
 
41
 
 
42
using namespace EmberOgre::Terrain;
 
43
 
 
44
namespace EmberOgre {
 
45
 
 
46
namespace Gui {
 
47
 
 
48
Compass::Compass(ICompassImpl* compassImpl)
 
49
: mMap(new Map()), mCompassImpl(compassImpl)
 
50
{
 
51
        mMap->initialize();
 
52
        if (compassImpl) {
 
53
                compassImpl->setCompass(this);
 
54
        }
 
55
}
 
56
 
 
57
 
 
58
Compass::~Compass()
 
59
{
 
60
}
 
61
 
 
62
Terrain::Map& Compass::getMap()
 
63
{
 
64
        return *mMap;
 
65
}
 
66
 
 
67
void Compass::reposition(float x, float y)
 
68
{
 
69
        if (mCompassImpl) {
 
70
                mCompassImpl->reposition(x, y);
 
71
        }
 
72
}
 
73
 
 
74
void Compass::rotate(const Ogre::Degree& degree)
 
75
{
 
76
        if (mCompassImpl) {
 
77
                mCompassImpl->rotate(degree);
 
78
        }
 
79
}
 
80
 
 
81
///Note: duplicate method to make it easier for scripts interacting with the code
 
82
void Compass::rotate(const Ogre::Radian& radian)
 
83
{
 
84
        rotate(Ogre::Degree(radian));
 
85
}
 
86
 
 
87
void Compass::refresh()
 
88
{
 
89
        if (mCompassImpl) {
 
90
                mCompassImpl->refresh();
 
91
        }
 
92
}
 
93
 
 
94
 
 
95
ICompassImpl::ICompassImpl()
 
96
: mMap(0)
 
97
, mCompass(0)
 
98
{
 
99
}
 
100
 
 
101
void ICompassImpl::setCompass(Compass* compass)
 
102
{
 
103
        mCompass = compass;
 
104
        mMap = &compass->getMap();
 
105
        _setCompass(compass);
 
106
}
 
107
 
 
108
 
 
109
CEGUICompassImpl::CEGUICompassImpl()
 
110
: mViewImage(0)
 
111
{
 
112
}
 
113
 
 
114
CEGUICompassImpl::~CEGUICompassImpl()
 
115
{
 
116
}
 
117
 
 
118
const CEGUI::Image* CEGUICompassImpl::getViewImage() 
 
119
{
 
120
        return mViewImage;
 
121
}
 
122
 
 
123
void CEGUICompassImpl::reposition(float x, float y)
 
124
{
 
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));
 
133
}
 
134
 
 
135
void CEGUICompassImpl::rotate(const Ogre::Degree& degree)
 
136
{
 
137
        ///we can't rotate CEGUI windows so we won't do anything
 
138
}
 
139
 
 
140
void CEGUICompassImpl::refresh()
 
141
{
 
142
        //TODO: implement
 
143
}
 
144
 
 
145
void CEGUICompassImpl::_setCompass(Compass* compass)
 
146
{
 
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");
 
152
        
 
153
}
 
154
 
 
155
 
 
156
 
 
157
 
 
158
 
 
159
OverlayCompassImpl::OverlayCompassImpl()
 
160
: mCompassOverlay(0)
 
161
{
 
162
        Ogre::OverlayManager& omgr = Ogre::OverlayManager::getSingleton();
 
163
        mCompassOverlay = (Ogre::Overlay*)omgr.getByName("CompassOverlay");
 
164
}
 
165
 
 
166
OverlayCompassImpl::~OverlayCompassImpl()
 
167
{
 
168
        if (mCompassOverlay) {
 
169
                mCompassOverlay->hide();
 
170
/*              Ogre::OverlayManager& omgr = Ogre::OverlayManager::getSingleton();
 
171
                omgr.destroy(mCompassOverlay);*/
 
172
        }
 
173
 
 
174
}
 
175
 
 
176
void OverlayCompassImpl::_setCompass(Compass* compass)
 
177
{
 
178
        if (mCompassOverlay)
 
179
        {
 
180
                mCompassMaterial = (Ogre::MaterialPtr)Ogre::MaterialManager::getSingleton().getByName("/ui/compass");
 
181
                mCompassMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureName(mMap->getTexture()->getName());
 
182
                mCompassOverlay->show();
 
183
        }
 
184
}
 
185
 
 
186
void OverlayCompassImpl::reposition(float x, float y)
 
187
{
 
188
        mMap->getView().reposition(Ogre::Vector2(x, y));
 
189
        
 
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);
 
194
        }
 
195
}
 
196
 
 
197
void OverlayCompassImpl::rotate(const Ogre::Degree& degree)
 
198
{
 
199
        return;
 
200
//      Point<2> center = Ogre2Atlas(mMap->getView().getRelativeViewPosition());
 
201
//      Vector<2> dimensions(0.5, 0.5);
 
202
//      Quaternion qRot;
 
203
//      qRot = qRot.rotation(2, degree);
 
204
//      
 
205
//      RotBox<2> rotbox(center, dimensions, qRot);
 
206
 
 
207
 
 
208
 
 
209
        if (!mCompassMaterial.isNull()) {
 
210
                Ogre::TextureUnitState* tus(mCompassMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0));
 
211
                tus->setTextureRotate(degree);
 
212
                
 
213
//              tus->setTextureRotate(EmberOgre::getSingleton().getMainCamera()->getYaw());
 
214
        }
 
215
}
 
216
 
 
217
void OverlayCompassImpl::refresh()
 
218
{
 
219
        //TODO: implement
 
220
}
 
221
 
 
222
 
 
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)
 
225
{
 
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);
 
228
}
 
229
 
 
230
RenderedCompassImpl::~RenderedCompassImpl()
 
231
{
 
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());
 
235
//      }
 
236
        
 
237
        if (mCamera) {
 
238
                mSceneManager->destroyCamera(mCamera);
 
239
        }
 
240
        
 
241
        Ogre::Root::getSingleton().destroySceneManager(mSceneManager);
 
242
        
 
243
 
 
244
        OGRE_DELETE mMapRectangle;
 
245
        
 
246
}
 
247
 
 
248
void RenderedCompassImpl::reposition(float x, float y)
 
249
{
 
250
        mMap->getView().reposition(Ogre::Vector2(x, y));
 
251
        
 
252
        if (mCompassMaterialMapTUS) {
 
253
                const Ogre::Vector2& relPosition(mMap->getView().getRelativeViewPosition());
 
254
                mCompassMaterialMapTUS->setTextureScroll(-0.5f + relPosition.x, -0.5f + relPosition.y);
 
255
                
 
256
                mRenderTexture->update();
 
257
        }
 
258
        mX = x;
 
259
        mY = y;
 
260
}
 
261
 
 
262
void RenderedCompassImpl::rotate(const Ogre::Degree& degree)
 
263
{
 
264
        mPointer.rotate(degree);
 
265
        ///We won't rotate the image.
 
266
//      return;
 
267
}
 
268
 
 
269
void RenderedCompassImpl::refresh()
 
270
{
 
271
        reposition(mX, mY);
 
272
}
 
273
 
 
274
 
 
275
void RenderedCompassImpl::_setCompass(Compass* compass)
 
276
{
 
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()) {
 
281
                        Ogre::Pass* pass(0);
 
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());
 
286
                
 
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);
 
292
                                        
 
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);
 
300
                                
 
301
                                        mMapRectangle = OGRE_NEW Ogre::Rectangle2D(true);
 
302
                                        mMapRectangle->setMaterial(mMaterialName);
 
303
                                        
 
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);
 
309
                                        
 
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);
 
314
 
 
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);
 
317
                                        
 
318
                                        ///Return early since everything is good.
 
319
                                        return;
 
320
                                }
 
321
                        }
 
322
                }
 
323
        } 
 
324
        S_LOG_WARNING("Could not load material '" << mMaterialName << "' for the compass.");
 
325
}
 
326
 
 
327
Ogre::TexturePtr RenderedCompassImpl::getTexture() const
 
328
{
 
329
        return mTexture;
 
330
}
 
331
 
 
332
Ogre::TexturePtr RenderedCompassImpl::getPointerTexture() const
 
333
{
 
334
        return mPointer.getTexture();
 
335
}
 
336
 
 
337
 
 
338
 
 
339
RenderedCompassPointer::RenderedCompassPointer(std::string materialName)
 
340
: mRenderTexture(0), mCamera(0), mSceneManager(0), mViewport(0), mPointerTUS(0), mPointerRectangle(0)
 
341
{
 
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);
 
344
        
 
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()) {
 
349
                        Ogre::Pass* pass(0);
 
350
                        if (tech->getNumPasses() && (pass = tech->getPass(0))) {
 
351
                                if ((mPointerTUS = pass->getTextureUnitState("Pointer"))) {
 
352
                
 
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);
 
360
                                        
 
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);
 
368
                                
 
369
                                        mPointerRectangle = OGRE_NEW Ogre::Rectangle2D(true);
 
370
                                        mPointerRectangle->setMaterial(materialName);
 
371
                                        
 
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);
 
377
                                        
 
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);
 
382
 
 
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);
 
385
                                        
 
386
                                        ///Return early since everything is good.
 
387
                                        return;
 
388
                                }
 
389
                        }
 
390
                }
 
391
        } 
 
392
        S_LOG_WARNING("Could not load material '" << materialName << "' for the compass pointer.");
 
393
}
 
394
 
 
395
RenderedCompassPointer::~RenderedCompassPointer()
 
396
{
 
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());
 
400
//      }
 
401
        
 
402
        if (mCamera) {
 
403
                mSceneManager->destroyCamera(mCamera);
 
404
        }
 
405
        
 
406
        Ogre::Root::getSingleton().destroySceneManager(mSceneManager);
 
407
        
 
408
 
 
409
        OGRE_DELETE mPointerRectangle;
 
410
}
 
411
 
 
412
void RenderedCompassPointer::rotate(const Ogre::Degree& degree)
 
413
{
 
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));
 
417
                
 
418
                mRenderTexture->update();
 
419
                mPreviousRotation = degree;
 
420
        }
 
421
}
 
422
 
 
423
Ogre::TexturePtr RenderedCompassPointer::getTexture() const
 
424
{
 
425
        return mTexture;
 
426
}
 
427
 
 
428
 
 
429
 
 
430
 
 
431
CompassAnchor::CompassAnchor(Compass& compass, const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
 
432
: mCompass(compass)
 
433
, mPreviousX(0)
 
434
, mPreviousZ(0)
 
435
, mPosition(position)
 
436
, mOrientation(orientation)
 
437
{
 
438
        /// Register this as a frame listener
 
439
        Ogre::Root::getSingleton().addFrameListener(this);
 
440
}
 
441
 
 
442
CompassAnchor::~CompassAnchor()
 
443
{
 
444
        Ogre::Root::getSingleton().removeFrameListener(this);
 
445
}
 
446
 
 
447
bool CompassAnchor::frameStarted(const Ogre::FrameEvent& event)
 
448
{
 
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;
 
454
        }
 
455
        return true;
 
456
}
 
457
 
 
458
 
 
459
 
 
460
 
 
461
CompassCameraAnchor::CompassCameraAnchor(Compass& compass, Ogre::Camera* camera)
 
462
: mAnchor(compass, camera->getDerivedPosition(), camera->getDerivedOrientation())
 
463
, mCamera(camera)
 
464
{
 
465
}
 
466
 
 
467
CompassCameraAnchor::~CompassCameraAnchor()
 
468
{
 
469
}
 
470
 
 
471
 
 
472
CompassSceneNodeAnchor::CompassSceneNodeAnchor(Compass& compass, Ogre::SceneNode* sceneNode)
 
473
: mAnchor(compass, sceneNode->_getDerivedPosition(), sceneNode->_getDerivedOrientation())
 
474
, mSceneNode(sceneNode)
 
475
{
 
476
}
 
477
 
 
478
CompassSceneNodeAnchor::~CompassSceneNodeAnchor()
 
479
{
 
480
}
 
481
 
 
482
CompassThirdPersonCameraAnchor::CompassThirdPersonCameraAnchor(Compass& compass, Ogre::Camera* camera, Ogre::SceneNode* sceneNode)
 
483
: mAnchor(compass, sceneNode->_getDerivedPosition(), camera->getDerivedOrientation())
 
484
, mCamera(camera), mSceneNode(sceneNode)
 
485
{
 
486
}
 
487
 
 
488
CompassThirdPersonCameraAnchor::~CompassThirdPersonCameraAnchor()
 
489
{
 
490
}
 
491
 
 
492
 
 
493
}
 
494
 
 
495
}