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

« back to all changes in this revision

Viewing changes to src/components/ogre/AvatarCamera.h

  • 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
    Copyright (C) 2004  Erik Hjortsberg
 
3
 
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
*/
 
18
 
 
19
 
 
20
/*
 
21
 * An instance of this is a player controlled camera fastened to the Avatar.
 
22
 * It should be possible to subclass this in order to provide different behaviour
 
23
 */
 
24
 
 
25
 
 
26
#ifndef AVATARCAMERA_H
 
27
#define AVATARCAMERA_H
 
28
 
 
29
#include "EmberOgrePrerequisites.h"
 
30
 
 
31
#include <sigc++/trackable.h>
 
32
 
 
33
 
 
34
#include "framework/ConsoleObject.h"
 
35
 
 
36
#include "services/input/Input.h"
 
37
#include <stack>
 
38
#include <memory>
 
39
 
 
40
namespace Ember
 
41
{
 
42
struct MouseMotion;
 
43
}
 
44
 
 
45
namespace EmberOgre {
 
46
 
 
47
class Avatar;
 
48
class EmberEntity;
 
49
struct EntityPickResult;
 
50
class IWorldPickListener;
 
51
struct MousePickerArgs;
 
52
class AvatarTerrainCursor;
 
53
 
 
54
class Recorder :public Ogre::FrameListener
 
55
{
 
56
public:
 
57
        Recorder();
 
58
        void startRecording();
 
59
        void stopRecording();   
 
60
        /**
 
61
         * Methods from Ogre::FrameListener
 
62
         */
 
63
        bool frameStarted(const Ogre::FrameEvent& event);
 
64
private:
 
65
        int mSequence;
 
66
        float mAccruedTime;
 
67
        float mFramesPerSecond;
 
68
};
 
69
 
 
70
/**
 
71
The main camera in the system, for historical reasons named "AvatarCamera". While Ogre allows you to have multiple cameras, only one will be used for the "main screen".
 
72
 
 
73
This class handles rotation and positioning of the camera as the mouse changes. It can operate in two modes: either attached to an avatar, or in free flying mode.
 
74
 
 
75
By default it makes checks against the terrain, so as not to dip below it. It's also not possible to "invert" the camera by moving it so the world is upside down.
 
76
 
 
77
It also takes care of initializing picking operations when the user picks something in the world.
 
78
 
 
79
TODO: refactor this into a better system, where the different camera setups are handled by different classes, and where the movement of the avatar contra the movement of the camera is handled better. See ICameraMount
 
80
*/
 
81
class AvatarCamera 
 
82
:
 
83
public sigc::trackable,
 
84
public Ember::ConsoleObject,
 
85
public Ogre::FrameListener
 
86
{
 
87
public:
 
88
 
 
89
        /**
 
90
        The different modes of the camera.
 
91
        TODO: this should be removed in favour of different classes instead
 
92
        */
 
93
        enum Mode {
 
94
                /**
 
95
                Third person mode is when the camera is watching the avatar from afar.
 
96
                */
 
97
                MODE_THIRD_PERSON = 1,
 
98
                /**
 
99
                First person mode is when the camera reflects what the avatar is seeing through its eyes.
 
100
                */
 
101
                MODE_FIRST_PERSON = 2
 
102
        };
 
103
        
 
104
        /**
 
105
         *    Ctor.
 
106
         Creates a camera and attaches it to a node.
 
107
         * @param avatarNode The main avatar node to which the camera should be attached.
 
108
         * @param sceneManager The main scene manager, through which the needed Ogre objects (such as Ogre::RayQuery) will be created.
 
109
         * @param window The window to which the camera will render.
 
110
         * @param input 
 
111
         * @param camera 
 
112
         */
 
113
        AvatarCamera(Ogre::SceneNode* avatarNode, Ogre::SceneManager& sceneManager, Ogre::RenderWindow& window, Ember::Input& input, Ogre::Camera& camera);
 
114
        virtual ~AvatarCamera();
 
115
 
 
116
        /**
 
117
         * @brief Pitches the camera the supplied degrees.
 
118
         * It's not possible to pitch the camera upside down, i.e. over the vertical axis of the node it's attached to. Trying to do so will result in the amount of pitch applied will be truncated.
 
119
         * @param degrees The amount of degrees to pitch.
 
120
         */
 
121
        virtual void pitch(Ogre::Degree degrees);
 
122
        
 
123
        /**
 
124
         * @brief Yaws the camera the supplied degrees.
 
125
         * @param degrees The amount of degrees to yaw.
 
126
         */
 
127
        virtual void yaw(Ogre::Degree degrees);
 
128
        
 
129
        /**
 
130
         * @brief Returns the current degrees of pitch from the cameras initial position.
 
131
         * @return The amount of degrees the camera currently is pitched.
 
132
         */
 
133
        const Ogre::Degree& getPitch() const;
 
134
        
 
135
        /**
 
136
         * @brief Returns the current degrees of yaw from the cameras initial position.
 
137
         * @return The amount of degrees the camera currently is yawed.
 
138
         */
 
139
        const Ogre::Degree& getYaw() const;
 
140
        
 
141
        /**
 
142
         * @brief Accessor for the main Ogre::Camera instance 
 
143
         * @return The main ogre camera instance.
 
144
         */
 
145
        Ogre::Camera& getCamera();
 
146
        
 
147
        /**
 
148
         * @brief Accessor for the main Ogre::Camera instance 
 
149
         * @return The main ogre camera instance.
 
150
         */
 
151
        Ogre::Camera& getCamera() const;
 
152
        
 
153
        /**
 
154
         * @brief Returns the current camera orientation in the world.
 
155
         * @param onlyHorizontal whether only the horizontal orientation should be returned.
 
156
         * @return The world orientation of the camera.
 
157
         */
 
158
        virtual const Ogre::Quaternion& getOrientation(bool onlyHorizontal = true) const;
 
159
        
 
160
        
 
161
        /**
 
162
         *  @brief Returns the position of the camera in the world.
 
163
         * @return The world position of the camera.
 
164
         */
 
165
        const Ogre::Vector3& getPosition() const;
 
166
        
 
167
        
 
168
        /**
 
169
         *    @brief Sets the mode of the camera (for example first or third person).
 
170
         * @param mode The new mode of the camera.
 
171
         */
 
172
        void setMode(Mode mode);
 
173
        
 
174
        /**
 
175
         * @brief Sets the node to which the camera is attached.
 
176
         * @param sceneNode The node to which the camera should be attached.
 
177
         */
 
178
        virtual void setAvatarNode(Ogre::SceneNode* sceneNode);
 
179
        
 
180
        /**
 
181
        * @brief Emitted when the camera moves.
 
182
        * The argument is the camera instance being moved.
 
183
        */
 
184
        sigc::signal<void, Ogre::Camera&> MovedCamera;
 
185
        
 
186
        /**
 
187
        * @brief Emitted when the distance between the camera and the avatar has changed.
 
188
    * @param Ogre::Real The new distance, in world units.
 
189
        */
 
190
        sigc::signal<void, Ogre::Real> EventChangedCameraDistance;
 
191
        
 
192
//      int xPosition, int yPosition, Ogre::Real xRelativeMovement, Ogre::Real yRelativeMovement, Ogre::Real timeSinceLastMovement);
 
193
 
 
194
//      void mouseMoved (Ogre::MouseEvent *e);
 
195
//      void mouseDragged (Ogre::MouseEvent *e) {};
 
196
 
 
197
        /**
 
198
         * @brief Starts an world pick action.
 
199
         * whenever the user clicks the mouse in the world (i.e. not on any gui element) a "picking action" is performed. The outcome of this is dependent on both what the user picks, and what current mode Ember is.
 
200
         * In order to determine what to do, Ember will iterate over its internal list of IWorldPickListener instances, calling each in turn for every object that was picked (typically a lot of different objects will be hit by the ray that we'll use to determine whether anything was picked). It's then up to these instances of IWorldPickListener to determine if something should be done.
 
201
         * The standard case is probably that the user picks an entity in the world, and that the EntityWorldPickListener then acts on this. However, if you want any other behaviour, you can yourself provide an implementation of IWorldPickListener and then register it here, thus allowing you to handle other objects.
 
202
         * @see IWorldPickListener
 
203
         * @see pushWorldPickListener
 
204
         * @param mouseX The relative horizontal mouse position for the picking action (0 is in the left corner, 1 in the right)
 
205
         * @param mouseY The relative vertical mouse position for the picking action (0 is in the top, 1 is in the bottom)
 
206
         * @param args The original mouse picker args
 
207
         */
 
208
        void pickInWorld(Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& args);
 
209
        
 
210
//      void setClosestPickingDistance(Ogre::Real distance);
 
211
//      Ogre::Real getClosestPickingDistance();
 
212
 
 
213
        /**
 
214
         * @brief Maps the position of an entity in the world to a 2d screen position.
 
215
         * This will return the 2d position of an entity, in relative terms where 0 is the left upper corner and 1 is the right lower corner.
 
216
         * @param worldPos The world position to map to the screen.
 
217
         * @param screenPos The screen position, in relative terms.
 
218
         * @return True if the entity is within the current screen, else false (i.e. the world position is somewhere it can't be seen from the current camera).
 
219
         */
 
220
        bool worldToScreen(const Ogre::Vector3& worldPos, Ogre::Vector2& screenPos);
 
221
        
 
222
        /**
 
223
         * @brief Attaches the camera to the specified scene node.
 
224
         * If the camera already is attached to another node, it will first be detached from it.
 
225
         * @param toNode The node to attach to.
 
226
         */
 
227
        void attach(Ogre::SceneNode* toNode);
 
228
        
 
229
        /**
 
230
         * @brief Adjusts the camera for the terrain, so it doesn't dip below it.
 
231
         * This is done by shooting a ray from the base node of the camera (around which the camera swivels if in third person mode) to the camera. if there's any terrain being hit, the camera will be moved closer to the base node.
 
232
         * @return If the camera had to be adjusted for the terrain (i.e. moved closer to the base node) the method will return true.
 
233
         */
 
234
        bool adjustForTerrain();
 
235
        
 
236
 
 
237
        /**
 
238
         *    Reimplements the ConsoleObject::runCommand method
 
239
         * @param command 
 
240
         * @param args 
 
241
         */
 
242
        virtual void runCommand(const std::string &command, const std::string &args);
 
243
 
 
244
        
 
245
        /**
 
246
         *    Sets the distance from the camera to the avatar.
 
247
         * @param distance the new distance
 
248
         */
 
249
        void setCameraDistance(Ogre::Real distance);
 
250
        
 
251
        /**
 
252
         * Methods from Ogre::FrameListener
 
253
         */
 
254
        bool frameStarted(const Ogre::FrameEvent& event);
 
255
        //bool frameEnded(const Ogre::FrameEvent& event);
 
256
        
 
257
        /**
 
258
         * @brief Enables and disables a compositor by name.
 
259
         * @param compositorName 
 
260
         * @param enable 
 
261
         */
 
262
        void enableCompositor(const std::string& compositorName, bool enable);
 
263
        
 
264
        
 
265
        /**
 
266
         * @brief Adds a new world pick listener to the queue of listeners.
 
267
         * @param worldPickListener The world pick listener which show start recive world pick events.
 
268
         */
 
269
        void pushWorldPickListener(IWorldPickListener* worldPickListener);
 
270
        
 
271
        /**
 
272
         * @brief Removes a world pick listener which previously has been added through pushWorldPickListener().
 
273
         * @param worldPickListener The world pick listener which should be removed. If the listener haven't been added nothing will happen.
 
274
         */
 
275
        void removeWorldPickListener(IWorldPickListener* worldPickListener);
 
276
        
 
277
        const Ember::ConsoleCommandWrapper SetCameraDistance;
 
278
        const Ember::ConsoleCommandWrapper ToggleRendermode;
 
279
        const Ember::ConsoleCommandWrapper ToggleFullscreen;
 
280
        const Ember::ConsoleCommandWrapper Screenshot;
 
281
        const Ember::ConsoleCommandWrapper Record;
 
282
        
 
283
        /**
 
284
         * @brief Toggles between wireframe and solid render mode.
 
285
         */
 
286
        void toggleRenderMode();
 
287
        
 
288
        /**
 
289
         * Takes a screen shot and writes it to disk 
 
290
         */
 
291
        void takeScreenshot();
 
292
        
 
293
        /**
 
294
         * @brief Gets the terrain cursor, used for efficiently getting the position of the terrain currently under the cursor.
 
295
         * @return An object which can be used to get the terrain that intersects the terrain at the current cursor.
 
296
         */
 
297
        AvatarTerrainCursor& getTerrainCursor();
 
298
        
 
299
        /**
 
300
         * @brief Gets the root node, to which the whole camera mount is hinged on.
 
301
         * @return The root node of the camera mount.
 
302
         */
 
303
        Ogre::SceneNode* getRootNode() const;
 
304
 
 
305
        
 
306
protected:
 
307
 
 
308
        typedef std::deque<IWorldPickListener*> WorldPickListenersStore;
 
309
        WorldPickListenersStore mPickListeners;
 
310
                
 
311
        typedef std::vector<std::string> CompositorNameStore;
 
312
        
 
313
        Recorder mRecorder;
 
314
        
 
315
        CompositorNameStore mLoadedCompositors;
 
316
 
 
317
        Mode mMode;
 
318
        
 
319
        bool mIsAttached;
 
320
        
 
321
        /**
 
322
        If true, the camera is inverted in the y axis.
 
323
        */
 
324
        bool mInvertCamera;
 
325
        
 
326
        /**
 
327
        Creates the rays needed for mouse picking and camera adjustment.
 
328
        */
 
329
        void createRayQueries();
 
330
        
 
331
        
 
332
        /**
 
333
         * creates all nodes needed for the camera 
 
334
         */
 
335
        void createNodesForCamera();
 
336
        
 
337
        const std::string _takeScreenshot();
 
338
        
 
339
        void createViewPort();
 
340
        
 
341
        Ogre::Camera& mCamera;
 
342
        Ogre::SceneNode* mAvatarNode;
 
343
        Ogre::SceneManager& mSceneManager;
 
344
        //Ogre::Quaternion mLastOrientationOfTheCamera;
 
345
 
 
346
        Ogre::SceneNode* mAvatarCameraRootNode;
 
347
        Ogre::SceneNode* mAvatarCameraPitchNode;
 
348
        Ogre::SceneNode* mAvatarCameraNode;
 
349
 
 
350
        Ogre::Degree mDegreeOfPitchPerSecond;
 
351
        Ogre::Degree mDegreeOfYawPerSecond;
 
352
 
 
353
        Ogre::Degree degreePitch;       
 
354
        Ogre::Degree degreeYaw; 
 
355
        Ogre::RenderWindow& mWindow;
 
356
        Ogre::Viewport* mViewPort;
 
357
        
 
358
        //in meters how far we can pick objects
 
359
        Ogre::Real mClosestPickingDistance;
 
360
 
 
361
        Ogre::Vector3 mLastPosition;
 
362
        Ogre::Real mWantedCameraDistance, mCurrentCameraDistance;
 
363
        
 
364
        Ogre::RaySceneQuery *mAdjustTerrainRaySceneQuery, *mCameraRaySceneQuery;
 
365
        Ogre::Ray mAdjustTerrainRay;
 
366
        
 
367
        bool mIsAdjustedToTerrain;
 
368
        std::auto_ptr<AvatarTerrainCursor> mAvatarTerrainCursor;
 
369
 
 
370
        void Input_MouseMoved(const Ember::MouseMotion& motion, Ember::Input::InputMode mode);
 
371
 
 
372
        void ConfigService_EventChangedConfigItem(const std::string& section, const std::string& key);
 
373
        
 
374
        void updateValuesFromConfig();
 
375
 
 
376
        /**
 
377
         *    Internal method for setting the camera distance.
 
378
         * @param distance the new distance
 
379
         */
 
380
        void _setCameraDistance(Ogre::Real distance);
 
381
        
 
382
        /**
 
383
         * @brief Call this whenever you've moved any node which will make the derived position or orientation of the camera change.
 
384
         * We need to mark the parent node of the camera as dirty. The update of the derived orientation and position of the node should normally occur when the scene tree is traversed, but in some instances we need to access the derived position or orientataion of the camera before the traversal occurs, and if we don't mark the node as dirty it won't be updated
 
385
         */
 
386
        void markCameraNodeAsDirty();
 
387
 
 
388
};
 
389
 
 
390
 
 
391
///inline implementations
 
392
 
 
393
        inline const Ogre::Degree& AvatarCamera::getPitch() const
 
394
        {
 
395
                return degreePitch;
 
396
        }
 
397
        
 
398
        inline const Ogre::Degree& AvatarCamera::getYaw() const
 
399
        {
 
400
                return degreeYaw;
 
401
        }
 
402
        
 
403
        inline Ogre::Camera& AvatarCamera::getCamera()  {
 
404
                return mCamera; 
 
405
        }
 
406
        inline Ogre::Camera& AvatarCamera::getCamera() const {
 
407
                return mCamera; 
 
408
        }
 
409
 
 
410
        inline AvatarTerrainCursor& AvatarCamera::getTerrainCursor()
 
411
        {
 
412
                return *mAvatarTerrainCursor.get();
 
413
        }
 
414
        
 
415
        inline Ogre::SceneNode* AvatarCamera::getRootNode() const
 
416
        {
 
417
                return mAvatarCameraRootNode;
 
418
        }
 
419
 
 
420
 
 
421
 
 
422
class ICameraMount
 
423
{
 
424
        virtual ~ICameraMount() {};
 
425
        
 
426
        /**
 
427
         * Pitches the camera the supplied degrees
 
428
         */
 
429
        virtual void pitch(Ogre::Degree degrees) = 0;
 
430
        
 
431
        /**
 
432
         * Yaws the camera the supplied degrees
 
433
         */
 
434
        virtual void yaw(Ogre::Degree degrees) = 0;
 
435
        
 
436
        /**
 
437
         * returns the current degrees of pitch from the cameras initial position
 
438
         */
 
439
        virtual const Ogre::Degree& getPitch() const = 0;
 
440
        
 
441
        /**
 
442
         * returns the current degrees of yaw from the cameras initial position
 
443
         */
 
444
        virtual const Ogre::Degree& getYaw() const = 0;
 
445
        
 
446
        /**
 
447
         * Returns the current camera orientation in the world
 
448
         */
 
449
        virtual const Ogre::Quaternion& getOrientation(bool onlyHorizontal = true) const = 0;
 
450
        
 
451
        /**
 
452
         *    Returns the position of the camera in the world.
 
453
         * @return 
 
454
         */
 
455
        virtual const Ogre::Vector3& getPosition() const = 0;
 
456
        
 
457
        void setMode(AvatarCamera::Mode mode);
 
458
 
 
459
        /**
 
460
         * sets the node to which the camera is attached
 
461
         */
 
462
        virtual void setAvatarNode(Ogre::SceneNode* sceneNode);
 
463
 
 
464
};
 
465
 
 
466
class MainCamera
 
467
{
 
468
        virtual ~MainCamera() {}
 
469
 
 
470
        /**
 
471
         * returns a pointer to the Ogre::Camera instance 
 
472
         */
 
473
        Ogre::Camera* getCamera();
 
474
        Ogre::Camera* getCamera() const;
 
475
        
 
476
        /**
 
477
        * emitted when the camra moves
 
478
        */
 
479
        sigc::signal<void, Ogre::Camera*> MovedCamera;
 
480
        
 
481
 
 
482
        void pickInWorld(Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& args);
 
483
        
 
484
        void setClosestPickingDistance(Ogre::Real distance);
 
485
        Ogre::Real getClosestPickingDistance();
 
486
 
 
487
        /**
 
488
         * returns true if the worldPos is on screen, putting the screen pos into the x & y of the second Vector3 
 
489
         * returns false if the worldPos is off screen 
 
490
         * @param worldPos 
 
491
         * @param screenPos 
 
492
         * @return 
 
493
         */
 
494
        bool worldToScreen(const Ogre::Vector3& worldPos, Ogre::Vector3& screenPos);
 
495
 
 
496
        /**
 
497
         *    Reimplements the ConsoleObject::runCommand method
 
498
         * @param command 
 
499
         * @param args 
 
500
         */
 
501
        virtual void runCommand(const std::string &command, const std::string &args);
 
502
 
 
503
        /**
 
504
         * Methods from Ogre::FrameListener
 
505
         */
 
506
        bool frameStarted(const Ogre::FrameEvent& event);
 
507
        
 
508
        /**
 
509
         *    Enables and disables a compositor by name.
 
510
         * @param compositorName 
 
511
         * @param enable 
 
512
         */
 
513
        void enableCompositor(const std::string& compositorName, bool enable);
 
514
        
 
515
        
 
516
        /**
 
517
         *    Adds a new world pick listener to the queue of listeners.
 
518
         * @param worldPickListener 
 
519
         */
 
520
        void pushWorldPickListener(IWorldPickListener* worldPickListener);
 
521
        
 
522
        const Ember::ConsoleCommandWrapper ToggleRendermode;
 
523
        const Ember::ConsoleCommandWrapper ToggleFullscreen;
 
524
        const Ember::ConsoleCommandWrapper Screenshot;
 
525
        const Ember::ConsoleCommandWrapper Record;
 
526
 
 
527
        /**
 
528
                Toggles between wireframe and solid render mode.
 
529
        */
 
530
        void toggleRenderMode();
 
531
        
 
532
        /**
 
533
         * takes a screen shot and writes it to disk 
 
534
         */
 
535
        void takeScreenshot();
 
536
 
 
537
};
 
538
 
 
539
class AvatarCameraMount : ICameraMount
 
540
{
 
541
        /**
 
542
        * emitted when the distance between the camera and the avatar has changed
 
543
    * @param Ogre::Real the new distance
 
544
        */
 
545
        sigc::signal<void, Ogre::Real> EventChangedCameraDistance;
 
546
 
 
547
        /**
 
548
         *    Sets the distance from the camera to the avatar.
 
549
         * @param distance the new distance
 
550
         */
 
551
        void setCameraDistance(Ogre::Real distance);
 
552
 
 
553
        const Ember::ConsoleCommandWrapper SetCameraDistance;
 
554
        
 
555
};
 
556
 
 
557
class FreeFlyingMount : ICameraMount
 
558
{
 
559
};
 
560
 
 
561
 
 
562
 
 
563
}
 
564
 
 
565
#endif // AVATARCAMERA_H