Source

ogre-ccs / CameraControlSystem / include / CCSCameraControlSystem.h

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
/* -------------------------------------------------------
Copyright (c) 2012 Alberto G. Salguero (alberto.salguero at uca.es)

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions of
the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------- */

#ifndef _CameraControlSystem_H_
#define _CameraControlSystem_H_

#include "CCSPrerequisites.h"

#include "CCSFastDelegate.h"

namespace CCS
{
    class DllExport CameraControlSystem 
	{
	public:

		/**
		 * @brief Abstract common base class of all camera modes
		 *
		 * Common base class of all camera modes. All derived camera modes
		 * should implement, at least, the "update" and "instantUpdate" methods
		 */
        class CameraMode
        {
        public:

			/**
			 * @brief Constructor
			 * @param cam a reference to a valid CCS
			 */
            CameraMode(CameraControlSystem* cam) : mCameraCS(cam)
                , mCameraPosition(Ogre::Vector3::ZERO)
                , mCameraOrientation(Ogre::Quaternion::IDENTITY) {};

			/**
			 * @brief Destructor
			 */
			virtual ~CameraMode() {};

			/**
			 * @brief Called when the camera mode is activated
			 *
			 * This method is called each time the camera mode is activated.
			 * All the initializations the camera mode needs in order to work
			 * should be performed here.
			 *
			 * @return true if no errors found
			 */
            virtual bool init()
			{ 
				mCameraPosition = mCameraCS->getCameraPosition(); 
				mCameraOrientation = mCameraCS->getCameraOrientation();
				return true; 
			};

			/**
			 * @brief Called when the camera mode is deactivated
			 *
			 * This method is called each time the camera mode is deactivated.
			 * All the actions performed in the init method which affect to other 
			 * camera modes should be resersed here.
			 */
            virtual void stop(){ };

			/**
			 * @brief Update camera position
			 *
			 * This method is called once per frame. The camera position and
			 * orientation variable members should be modified in this method.
			 */
            virtual void update(const Ogre::Real &timeSinceLastFrame) = 0;

			/**
			 * @brief Update camera position instantaneously
			 *
			 * This method is usually called just after the init method. The camera 
			 * position and orientation variable members should be modified in this
			 * method.
			 */
            virtual void instantUpdate() = 0;

            const Ogre::Vector3& getCameraPosition() const { return mCameraPosition; }
            const Ogre::Quaternion& getCameraOrientation() const { return mCameraOrientation; }

        protected:
            CameraControlSystem* mCameraCS;
            Ogre::Vector3 mCameraPosition;
            Ogre::Quaternion mCameraOrientation;
        };

		/**
		 * @brief Abstract base camera mode with tightness
		 */
        class CameraModeWithTightness : public CameraMode
        {
        public:

			/**
			 * @brief Constructor
			 * @param cam a reference to a valid CCS
			 */
            CameraModeWithTightness(CameraControlSystem* cam) 
				: CameraMode(cam)
				, mTightness(1)
			{};

			/**
			 * @brief Destructor
			 */
            virtual ~CameraModeWithTightness() {};

            inline void setCameraTightness(Ogre::Real value) { mTightness = value; }
            inline Ogre::Real getCameraTightness() const { return mTightness; }

        protected:
            Ogre::Real mTightness;
        };

		/**
		 * @brief Base class for collidable camera modes
		 */
        class DllExport CollidableCamera
        {
        public:

			/**
			 * @brief Constructor
			 * @param cam a reference to a valid CCS
			 */
			CollidableCamera(CameraControlSystem* cam, Ogre::Real margin = 0.1f) 				
				: mCameraCS2(cam)
				, mCollisionsEnabled(false)
				, mMargin(margin)
			{ };

			/**
			 * @brief Destructor
			 */
            virtual ~CollidableCamera() {};

            inline virtual void setCollisionsEnabled(bool value) { mCollisionsEnabled = value; }
            inline virtual bool getCollisionsEnabled() const { return mCollisionsEnabled; }

			/**
			 * @brief Margin value for the collision delegates
			 * 
			 * @param margin the distance 
			 */
			inline void setMargin(Ogre::Real margin){ mMargin = margin; }

			inline Ogre::Real getMargin() const { return mMargin; }

			// A CollisionDelegate takes as params the position of the target and the camera, and returns the 
			// the new camera position.
			typedef fastdelegate::FastDelegate2<Ogre::Vector3, Ogre::Vector3, Ogre::Vector3> CollisionDelegate;
			
			CollisionDelegate collisionDelegate;

			template <class X, class Y>
			static CollisionDelegate newCollisionDelegate(Y* x, Ogre::Vector3 (X::*func)(Ogre::Vector3 targetPosition, Ogre::Vector3 cameraPosition)) { 
				return fastdelegate::MakeDelegate(x, func);
			}

			/**
			 * @brief Collisions detection based on the basic Ogre raycasting 
			 * 
			 * @param cameraTargetPosition the position of the camera target
			 * @param cameraPosition the position of the camera
			 *
			 * @return the first hit between the camera target position and the camera position.
			 */
			Ogre::Vector3 DefaultCollisionDetectionFunction(Ogre::Vector3 cameraTargetPosition, Ogre::Vector3 cameraPosition);

			/**
			* @brief Ignore the object in collision delegates that use Ogre's ray scene queries.
			*
			* @param object The object that shoud be ignored
			*/
			void addToIgnoreList(Ogre::MovableObject* object){ mIgnoreList.insert(object); };

		protected:
			CameraControlSystem* mCameraCS2;
			bool mCollisionsEnabled;
			Ogre::Real mMargin;

			std::set<Ogre::MovableObject*> mIgnoreList;
		};

		/** 
		 * @brief Contructor 
		 *
		 * @param sm Ogre Scene manager pointer
		 * @param name Name of the instance
         * @param camera Ogre camera. If null it will be created by the CCS
		 * @param recalculateOnTargetMoving If true the camera position will be recalculated at the end of the frame if the target scene node is changed within the current frame.
		 */
		CameraControlSystem(Ogre::SceneManager* sm, const Ogre::String& name, Ogre::Camera *camera = NULL, bool recalculateOnTargetMoving = true);

		/** 
		 * @brief Contructor
		 *
		 * @param sm Ogre Scene manager pointer
		 * @param name Name of the instance
         * @param customCameraSceneNode External scenenode holding the Ogre camera. 
		 * @param recalculateOnTargetMoving If true the customCameraSceneNode position will be recalculated at the end of the frame if the target scene node is changed within the current frame.
		 */
		CameraControlSystem(Ogre::SceneManager* sm, const Ogre::String& name, Ogre::SceneNode* customCameraSceneNode, bool recalculateOnTargetMoving = true);

		/**
		 * @brief Destructor
		 */
		~CameraControlSystem();

		/**
		 * @brief Add a new camera mode
		 *
		 * Add a new named camera mode instance to the CCS. Multiple instances of the
		 * same camera mode, with the same or different parameters, can be registered 
		 * in the same CCS if their instance names are differents. 
		 *
		 * @param name the name to assign to the camera mode
		 * @param cameraMode cameraMode the camera mode to be registered
		 */
        inline void registerCameraMode(Ogre::String name, CameraMode* cameraMode)
        {
            mCameraModes[name] = cameraMode;
        }

		/**
		 * @brief Remove an instance of a camera mode in a CCS. NOT IMPLEMENTED YET.
		 *
		 * @param cameraMode camera mode instance to be removed
		 */
        inline void removeCameraMode(CameraMode* cameraMode){ throw new Ogre::Exception(1000,"Not implemented.","CCSCameraControlSystem.h"); };

		/**
		 * @brief Remove all camera modes associated to the CCS. 
		 */
		void deleteAllCameraModes();

		/**
		 * @brief Get the camera mode instance by name
		 *
		 * @param name the name of the camera mode to search for
		 *
		 * @return the cameraMode or null if not found
		 */
        CameraMode* getCameraMode(const Ogre::String& name);

		/**
		 * @brief Get the next camera mode instance (alphabetic order)
		 *
		 * @return the next cameraMode instance or the first if the current 
		 * is the latest one
		 */
        CameraMode* getNextCameraMode();

		/**
		 * @brief Get the name of a camera mode instance
		 *
		 * @param camMode the camera mode instance
		 *
		 * @return the name of the camera mode instance or an empty string
		 * if the camera instance has not been found in the CCS
		 */
        const Ogre::String& getCameraModeName(CameraMode* camMode) const;

		/**
		 * @brief Get the current camera mode instance
		 *
		 * @return the current camera mode instance
		 */
        inline CameraMode* getCurrentCameraMode(){ return mCurrentCameraMode; };

		/**
		 * @brief Set the current camera mode instance
		 *
		 * @param cameraMode the camera mode instance to be set
		 */
        void setCurrentCameraMode(CameraMode* cameraMode);

		/**
		 * @brief Update the CCS
		 *
		 * This method should be called once per frame
		 *
		 * @param timeSinceLastFrame time elapsed since last frame
		 */
        void update(const Ogre::Real &timeSinceLastFrame);
		
		/**
		 * @brief Get the ogre::camera associated to the CCS
		 *
		 * @return the ogre::camera
		 */
		inline Ogre::Camera* getOgreCamera(){ return mCamera; }

		/**
		 * @brief Set the ogre::camera associated to the CCS
		 */
		inline void setOgreCamera(Ogre::Camera* camera){ mCamera = camera; }

		/**
		 * @brief Set the focus of the scene
		 *
		 * This does not mean that the camera will always look to the focus. It
		 * depends on the camera mode
		 *
		 * @param targetNode the focus 
		 */
        void setCameraTarget(Ogre::SceneNode* targetNode);

		/**
		 * @brief Get wheter the CCS has a scene focus defined
		 *
		 * @return true if it has or false in other case
		 */
        inline bool hasCameraTarget() const { return (mTargetNode)?true:false; };

		/**
		 * @brief Get the scene node which holds the focus of the scene
		 *
		 * @return the scene node holding the scene focus 
		 */
        inline Ogre::SceneNode* getTargetSceneNode(){ return mTargetNode; }

		/**
		 * @brief Get the scene node the camera is attached to
		 *
		 * @return the scene node the camera is attached to
		 */
        inline Ogre::SceneNode* getCameraSceneNode(){ return mCameraNode; }

		/**
		 * @brief Get the derived focus position
		 *
		 * @return the position in global coordinate system
		 */
        inline const Ogre::Vector3& getCameraTargetPosition() const { return mTargetNode->_getDerivedPosition(); }

		/**
		 * @brief Get the derived camera position
		 *
		 * @return the position in global coordinate system
		 */
        inline const Ogre::Vector3& getCameraPosition() const { return mCameraNode->_getDerivedPosition(); }

		/**
		 * @brief Get the derived focus orientation
		 *
		 * @return the orientation in global coordinate system
		 */
        inline const Ogre::Quaternion& getCameraTargetOrientation() const { return mTargetNode->_getDerivedOrientation(); }

		/**
		 * @brief Get the derived camera orientation
		 *
		 * @return the orientation in global coordinate system
		 */
        inline const Ogre::Quaternion& getCameraOrientation() const { return mCameraNode->_getDerivedOrientation(); }

		/**
		 * @brief set wheter the camera will always points to the scene focus or not
		 *
		 * The method setFixedYawAxis should be used in combination with this one.
		 *
		 * @param autoTracking if true the camera will always automatically points
		 * to the scene focus
		 */
        void setAutoTrackingTarget(bool autoTracking);

		bool isAutoTrackingTarget() const;

		/**
		 * @brief Set the fixed yaw axis
		 *
		 * @param useFixedAxis if true, the next parameter is considered
		 * @param fixedAxis the axis which will be used to completely 
		 * define the rotation when using autotracking
		 */
        inline void setFixedYawAxis(bool useFixedAxis, const Ogre::Vector3 &fixedAxis = Ogre::Vector3::UNIT_Y )
        {
            mCameraNode->setFixedYawAxis(useFixedAxis,fixedAxis);
        }

		/**
		 * @brief Get the last timeSinceLastFrame value when the CCS was updated.
		 * 
		 * @return The timeSinceLastFrame value
		 */
		inline Ogre::Real getTimeSinceLastFrameLastUpdate(){ return mTimeSinceLastFrameLastUpdate; };
		inline Ogre::Real getTimeSinceLastFrameLastUpdate() const { return mTimeSinceLastFrameLastUpdate; };

		inline Ogre::SceneManager* getSceneManager(){ return mSceneMgr; };

		/**
		 * @brief Ignore the object in collision delegates that use Ogre's ray scene queries FOR ALL THE REGISTERED CAMERA MODES.
		 *
		 * @param object The object that shoud be ignored
		 */
		void addToIgnoreList(Ogre::MovableObject* object);

		/**
		 * @brief Set camera position manually. Use it with care: the position of the camera will be overridden by any camera mode (if set).
		 *
		 * @param position The position of the camera node
		 */
		void _setCameraPosition(Ogre::Vector3& position);

		/**
		 * @brief Set camera orientation manually. Use it with care: the orientation of the camera will be overridden by any camera mode (if set).
		 *
		 * @param orientation The orientation of the camera node
		 */
		void _setCameraOrientation(Ogre::Quaternion& orientation);

	protected:

		/**
		 * @brief This class is internally used to notify the CameraControlSystem class the target scene node has been moved within the current frame
		 */
		class NodeListener : public Ogre::Node::Listener
		{
		public:
			NodeListener(CameraControlSystem* cam) : mCameraCS(cam){};
			~NodeListener(){};
			void nodeUpdated(const Ogre::Node *nod){ mCameraCS->update( mCameraCS->getTimeSinceLastFrameLastUpdate() ); };
		protected:
			Ogre::Real mTimeSinceLastFrame;
			CameraControlSystem* mCameraCS;
		};

        Ogre::SceneManager *mSceneMgr;
		Ogre::String mName;

		Ogre::Camera* mCamera; // ogre camera
        Ogre::SceneNode* mCameraNode; // Where the camera is attached to
        bool mOwnCamera; // true if the ogre camera has been created by this class

        Ogre::SceneNode* mTargetNode; // The scene focus
		NodeListener* mTargetNodeListener; // To recalculate the camera position if the target scenenode has been changed within the current frame
		Ogre::Real mTimeSinceLastFrameLastUpdate; // Time value passed to the last call of the method "update"
		bool mRecalculateOnTargetMoving;

        CameraMode* mCurrentCameraMode;
        std::map<Ogre::String, CameraMode*> mCameraModes; // The list of camera mode instances

        static const Ogre::String BLANK; // allow us to return by ref where local doesn't exist. 
	};
}

#endif