2
Copyright (C) 2004 Erik Hjortsberg
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.
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.
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.
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
26
#ifndef AVATARCAMERA_H
27
#define AVATARCAMERA_H
29
#include "EmberOgrePrerequisites.h"
31
#include <sigc++/trackable.h>
34
#include "framework/ConsoleObject.h"
36
#include "services/input/Input.h"
49
struct EntityPickResult;
50
class IWorldPickListener;
51
struct MousePickerArgs;
52
class AvatarTerrainCursor;
54
class Recorder :public Ogre::FrameListener
58
void startRecording();
61
* Methods from Ogre::FrameListener
63
bool frameStarted(const Ogre::FrameEvent& event);
67
float mFramesPerSecond;
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".
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.
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.
77
It also takes care of initializing picking operations when the user picks something in the world.
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
83
public sigc::trackable,
84
public Ember::ConsoleObject,
85
public Ogre::FrameListener
90
The different modes of the camera.
91
TODO: this should be removed in favour of different classes instead
95
Third person mode is when the camera is watching the avatar from afar.
97
MODE_THIRD_PERSON = 1,
99
First person mode is when the camera reflects what the avatar is seeing through its eyes.
101
MODE_FIRST_PERSON = 2
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.
113
AvatarCamera(Ogre::SceneNode* avatarNode, Ogre::SceneManager& sceneManager, Ogre::RenderWindow& window, Ember::Input& input, Ogre::Camera& camera);
114
virtual ~AvatarCamera();
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.
121
virtual void pitch(Ogre::Degree degrees);
124
* @brief Yaws the camera the supplied degrees.
125
* @param degrees The amount of degrees to yaw.
127
virtual void yaw(Ogre::Degree degrees);
130
* @brief Returns the current degrees of pitch from the cameras initial position.
131
* @return The amount of degrees the camera currently is pitched.
133
const Ogre::Degree& getPitch() const;
136
* @brief Returns the current degrees of yaw from the cameras initial position.
137
* @return The amount of degrees the camera currently is yawed.
139
const Ogre::Degree& getYaw() const;
142
* @brief Accessor for the main Ogre::Camera instance
143
* @return The main ogre camera instance.
145
Ogre::Camera& getCamera();
148
* @brief Accessor for the main Ogre::Camera instance
149
* @return The main ogre camera instance.
151
Ogre::Camera& getCamera() const;
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.
158
virtual const Ogre::Quaternion& getOrientation(bool onlyHorizontal = true) const;
162
* @brief Returns the position of the camera in the world.
163
* @return The world position of the camera.
165
const Ogre::Vector3& getPosition() const;
169
* @brief Sets the mode of the camera (for example first or third person).
170
* @param mode The new mode of the camera.
172
void setMode(Mode mode);
175
* @brief Sets the node to which the camera is attached.
176
* @param sceneNode The node to which the camera should be attached.
178
virtual void setAvatarNode(Ogre::SceneNode* sceneNode);
181
* @brief Emitted when the camera moves.
182
* The argument is the camera instance being moved.
184
sigc::signal<void, Ogre::Camera&> MovedCamera;
187
* @brief Emitted when the distance between the camera and the avatar has changed.
188
* @param Ogre::Real The new distance, in world units.
190
sigc::signal<void, Ogre::Real> EventChangedCameraDistance;
192
// int xPosition, int yPosition, Ogre::Real xRelativeMovement, Ogre::Real yRelativeMovement, Ogre::Real timeSinceLastMovement);
194
// void mouseMoved (Ogre::MouseEvent *e);
195
// void mouseDragged (Ogre::MouseEvent *e) {};
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
208
void pickInWorld(Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& args);
210
// void setClosestPickingDistance(Ogre::Real distance);
211
// Ogre::Real getClosestPickingDistance();
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).
220
bool worldToScreen(const Ogre::Vector3& worldPos, Ogre::Vector2& screenPos);
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.
227
void attach(Ogre::SceneNode* toNode);
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.
234
bool adjustForTerrain();
238
* Reimplements the ConsoleObject::runCommand method
242
virtual void runCommand(const std::string &command, const std::string &args);
246
* Sets the distance from the camera to the avatar.
247
* @param distance the new distance
249
void setCameraDistance(Ogre::Real distance);
252
* Methods from Ogre::FrameListener
254
bool frameStarted(const Ogre::FrameEvent& event);
255
//bool frameEnded(const Ogre::FrameEvent& event);
258
* @brief Enables and disables a compositor by name.
259
* @param compositorName
262
void enableCompositor(const std::string& compositorName, bool enable);
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.
269
void pushWorldPickListener(IWorldPickListener* worldPickListener);
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.
275
void removeWorldPickListener(IWorldPickListener* worldPickListener);
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;
284
* @brief Toggles between wireframe and solid render mode.
286
void toggleRenderMode();
289
* Takes a screen shot and writes it to disk
291
void takeScreenshot();
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.
297
AvatarTerrainCursor& getTerrainCursor();
300
* @brief Gets the root node, to which the whole camera mount is hinged on.
301
* @return The root node of the camera mount.
303
Ogre::SceneNode* getRootNode() const;
308
typedef std::deque<IWorldPickListener*> WorldPickListenersStore;
309
WorldPickListenersStore mPickListeners;
311
typedef std::vector<std::string> CompositorNameStore;
315
CompositorNameStore mLoadedCompositors;
322
If true, the camera is inverted in the y axis.
327
Creates the rays needed for mouse picking and camera adjustment.
329
void createRayQueries();
333
* creates all nodes needed for the camera
335
void createNodesForCamera();
337
const std::string _takeScreenshot();
339
void createViewPort();
341
Ogre::Camera& mCamera;
342
Ogre::SceneNode* mAvatarNode;
343
Ogre::SceneManager& mSceneManager;
344
//Ogre::Quaternion mLastOrientationOfTheCamera;
346
Ogre::SceneNode* mAvatarCameraRootNode;
347
Ogre::SceneNode* mAvatarCameraPitchNode;
348
Ogre::SceneNode* mAvatarCameraNode;
350
Ogre::Degree mDegreeOfPitchPerSecond;
351
Ogre::Degree mDegreeOfYawPerSecond;
353
Ogre::Degree degreePitch;
354
Ogre::Degree degreeYaw;
355
Ogre::RenderWindow& mWindow;
356
Ogre::Viewport* mViewPort;
358
//in meters how far we can pick objects
359
Ogre::Real mClosestPickingDistance;
361
Ogre::Vector3 mLastPosition;
362
Ogre::Real mWantedCameraDistance, mCurrentCameraDistance;
364
Ogre::RaySceneQuery *mAdjustTerrainRaySceneQuery, *mCameraRaySceneQuery;
365
Ogre::Ray mAdjustTerrainRay;
367
bool mIsAdjustedToTerrain;
368
std::auto_ptr<AvatarTerrainCursor> mAvatarTerrainCursor;
370
void Input_MouseMoved(const Ember::MouseMotion& motion, Ember::Input::InputMode mode);
372
void ConfigService_EventChangedConfigItem(const std::string& section, const std::string& key);
374
void updateValuesFromConfig();
377
* Internal method for setting the camera distance.
378
* @param distance the new distance
380
void _setCameraDistance(Ogre::Real distance);
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
386
void markCameraNodeAsDirty();
391
///inline implementations
393
inline const Ogre::Degree& AvatarCamera::getPitch() const
398
inline const Ogre::Degree& AvatarCamera::getYaw() const
403
inline Ogre::Camera& AvatarCamera::getCamera() {
406
inline Ogre::Camera& AvatarCamera::getCamera() const {
410
inline AvatarTerrainCursor& AvatarCamera::getTerrainCursor()
412
return *mAvatarTerrainCursor.get();
415
inline Ogre::SceneNode* AvatarCamera::getRootNode() const
417
return mAvatarCameraRootNode;
424
virtual ~ICameraMount() {};
427
* Pitches the camera the supplied degrees
429
virtual void pitch(Ogre::Degree degrees) = 0;
432
* Yaws the camera the supplied degrees
434
virtual void yaw(Ogre::Degree degrees) = 0;
437
* returns the current degrees of pitch from the cameras initial position
439
virtual const Ogre::Degree& getPitch() const = 0;
442
* returns the current degrees of yaw from the cameras initial position
444
virtual const Ogre::Degree& getYaw() const = 0;
447
* Returns the current camera orientation in the world
449
virtual const Ogre::Quaternion& getOrientation(bool onlyHorizontal = true) const = 0;
452
* Returns the position of the camera in the world.
455
virtual const Ogre::Vector3& getPosition() const = 0;
457
void setMode(AvatarCamera::Mode mode);
460
* sets the node to which the camera is attached
462
virtual void setAvatarNode(Ogre::SceneNode* sceneNode);
468
virtual ~MainCamera() {}
471
* returns a pointer to the Ogre::Camera instance
473
Ogre::Camera* getCamera();
474
Ogre::Camera* getCamera() const;
477
* emitted when the camra moves
479
sigc::signal<void, Ogre::Camera*> MovedCamera;
482
void pickInWorld(Ogre::Real mouseX, Ogre::Real mouseY, const MousePickerArgs& args);
484
void setClosestPickingDistance(Ogre::Real distance);
485
Ogre::Real getClosestPickingDistance();
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
494
bool worldToScreen(const Ogre::Vector3& worldPos, Ogre::Vector3& screenPos);
497
* Reimplements the ConsoleObject::runCommand method
501
virtual void runCommand(const std::string &command, const std::string &args);
504
* Methods from Ogre::FrameListener
506
bool frameStarted(const Ogre::FrameEvent& event);
509
* Enables and disables a compositor by name.
510
* @param compositorName
513
void enableCompositor(const std::string& compositorName, bool enable);
517
* Adds a new world pick listener to the queue of listeners.
518
* @param worldPickListener
520
void pushWorldPickListener(IWorldPickListener* worldPickListener);
522
const Ember::ConsoleCommandWrapper ToggleRendermode;
523
const Ember::ConsoleCommandWrapper ToggleFullscreen;
524
const Ember::ConsoleCommandWrapper Screenshot;
525
const Ember::ConsoleCommandWrapper Record;
528
Toggles between wireframe and solid render mode.
530
void toggleRenderMode();
533
* takes a screen shot and writes it to disk
535
void takeScreenshot();
539
class AvatarCameraMount : ICameraMount
542
* emitted when the distance between the camera and the avatar has changed
543
* @param Ogre::Real the new distance
545
sigc::signal<void, Ogre::Real> EventChangedCameraDistance;
548
* Sets the distance from the camera to the avatar.
549
* @param distance the new distance
551
void setCameraDistance(Ogre::Real distance);
553
const Ember::ConsoleCommandWrapper SetCameraDistance;
557
class FreeFlyingMount : ICameraMount
565
#endif // AVATARCAMERA_H