Overte C++ Documentation
Camera.h
1 //
2 // Camera.h
3 // interface/src
4 //
5 // Copyright 2013 High Fidelity, Inc.
6 // Copyright 2020 Vircadia contributors.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_Camera_h
13 #define hifi_Camera_h
14 
15 #include "../GLMHelpers.h"
16 #include "../RegisteredMetaTypes.h"
17 #include "../ViewFrustum.h"
18 #include "../SettingHandle.h"
19 
20 enum CameraMode
21 {
22  CAMERA_MODE_NULL = -1,
23  CAMERA_MODE_THIRD_PERSON,
24  CAMERA_MODE_FIRST_PERSON_LOOK_AT,
25  CAMERA_MODE_FIRST_PERSON,
26  CAMERA_MODE_MIRROR,
27  CAMERA_MODE_INDEPENDENT,
28  CAMERA_MODE_ENTITY,
29  CAMERA_MODE_LOOK_AT,
30  CAMERA_MODE_SELFIE,
31  NUM_CAMERA_MODES
32 };
33 
34 Q_DECLARE_METATYPE(CameraMode);
35 
36 #if defined(__GNUC__) && !defined(__clang__)
37 __attribute__((unused))
38 #endif
39 static int cameraModeId = qRegisterMetaType<CameraMode>();
40 
41 class Camera : public QObject {
42  Q_OBJECT
43 
44  Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)
45  Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
46  Q_PROPERTY(QString mode READ getModeString WRITE setModeString NOTIFY modeUpdated)
47  Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT)
48  Q_PROPERTY(bool captureMouse READ getCaptureMouse WRITE setCaptureMouse NOTIFY captureMouseChanged)
49  Q_PROPERTY(float sensitivity READ getSensitivity WRITE setSensitivity)
50 
51 public:
52  Camera();
53 
54  void initialize(); // instantly put the camera at the ideal position and orientation.
55 
56  void update();
57 
58  CameraMode getMode() const { return _mode; }
59  void setMode(CameraMode m);
60 
61  void loadViewFrustum(ViewFrustum& frustum) const;
62 
63  const glm::mat4& getTransform() const { return _transform; }
64  void setTransform(const glm::mat4& transform);
65 
66  const glm::mat4& getProjection() const { return _projection; }
67  void setProjection(const glm::mat4& projection);
68 
69  QVariantMap getViewFrustum();
70 
71 public slots:
72  /*@jsdoc
73  * Gets the current camera mode. You can also get the mode using the {@link Camera|Camera.mode} property.
74  * @function Camera.getModeString
75  * @returns {Camera.Mode} The current camera mode.
76  */
77  QString getModeString() const;
78 
79  /*@jsdoc
80  * Sets the camera mode. You can also set the mode using the {@link Camera|Camera.mode} property.
81  * @function Camera.setModeString
82  * @param {Camera.Mode} mode - The mode to set the camera to.
83  */
84  void setModeString(const QString& mode);
85 
86  /*@jsdoc
87  * Gets the current camera position. You can also get the position using the {@link Camera|Camera.position} property.
88  * @function Camera.getPosition
89  * @returns {Vec3} The current camera position.
90  */
91  glm::vec3 getPosition() const { return _position; }
92 
93  /*@jsdoc
94  * Sets the camera position. You can also set the position using the {@link Camera|Camera.position} property. Only works if
95  * the camera is in independent mode.
96  * @function Camera.setPosition
97  * @param {Vec3} position - The position to set the camera at.
98  */
99  void setPosition(const glm::vec3& position);
100 
101  /*@jsdoc
102  * Gets the current camera orientation. You can also get the orientation using the {@link Camera|Camera.orientation}
103  * property.
104  * @function Camera.getOrientation
105  * @returns {Quat} The current camera orientation.
106  */
107  glm::quat getOrientation() const { return _orientation; }
108 
109  /*@jsdoc
110  * Sets the camera orientation. You can also set the orientation using the {@link Camera|Camera.orientation} property. Only
111  * works if the camera is in independent mode.
112  * @function Camera.setOrientation
113  * @param {Quat} orientation - The orientation to set the camera to.
114  */
115  void setOrientation(const glm::quat& orientation);
116 
117  /*@jsdoc
118  * Gets the current mouse capture state.
119  * @function Camera.getCaptureMouse
120  * @returns {boolean} <code>true</code> if the mouse is captured (is invisible and cannot leave the bounds of Interface,
121  * if Interface is the active window and no menu item is selected), <code>false</code> if the mouse is behaving normally.
122  */
123  bool getCaptureMouse() const { return _captureMouse; }
124 
125  /*@jsdoc
126  * Sets the mouse capture state. When <code>true</code>, the mouse is invisible and cannot leave the bounds of
127  * Interface, as long as Interface is the active window and no menu item is selected. When <code>false</code>, the mouse
128  * behaves normally.
129  * @function Camera.setCaptureMouse
130  * @param {boolean} captureMouse - <code>true</code> to capture the mouse, <code>false</code> to release the mouse.
131  */
132  void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseChanged(captureMouse); }
133 
134  /*@jsdoc
135  * Gets the current mouse look setting state.
136  * @function Camera.getMouseLook
137  * @returns {boolean} <code>true</code> if the mouse look setting is enabled (mouse look can be toggled with M key in this
138  * mode), <code>false</code> if the mouse look setting is disabled.
139  */
140  bool getMouseLook() const { return Setting::Handle<bool>{"MouseLookAllowed", false }.get(); }
141 
142  /*@jsdoc
143  * Sets the mouse look setting state. When <code>true</code>, the mouse look setting is enabled (mouse look can be toggled
144  * with M key in this mode). When <code>false</code>, the mouse behaves normally.
145  * @function Camera.setMouseLook
146  * @param {boolean} mouseLook - <code>true</code> to enable mouse look setting, <code>false</code> to disable mouse look
147  * setting.
148  */
149  void setMouseLook(bool mouseLook);
150 
151  /*@jsdoc
152  * Gets the current camera sensitivity.
153  * @function Camera.getSensitivity
154  * @returns {number} The current camera sensitivity. Must be positive.
155  */
156  float getSensitivity() const { return _sensitivity; }
157 
158  /*@jsdoc
159  * Sets the camera sensitivity. Higher values mean that the camera will be more sensitive to mouse movements.
160  * @function Camera.setSensitivity
161  * @param {number} sensitivity - The desired camera sensitivity. Must be positive.
162  */
163  void setSensitivity(float sensitivity) { _sensitivity = glm::max(0.0f, sensitivity); }
164 
165  /*@jsdoc
166  * Computes a {@link PickRay} based on the current camera configuration and the specified <code>x, y</code> position on the
167  * screen. The {@link PickRay} can be used in functions such as {@link Entities.findRayIntersection} and
168  * {@link Overlays.findRayIntersection}.
169  * @function Camera.computePickRay
170  * @param {number} x - X-coordinate on screen.
171  * @param {number} y - Y-coordinate on screen.
172  * @returns {PickRay} The computed {@link PickRay}.
173  * @example <caption>Use a PickRay to detect mouse clicks on entities.</caption>
174  * function onMousePressEvent(event) {
175  * var pickRay = Camera.computePickRay(event.x, event.y);
176  * var intersection = Entities.findRayIntersection(pickRay);
177  * if (intersection.intersects) {
178  * print("You clicked on entity " + intersection.entityID);
179  * }
180  * }
181  *
182  * Controller.mousePressEvent.connect(onMousePressEvent);
183  */
184  virtual PickRay computePickRay(float x, float y) const = 0;
185 
186  /*@jsdoc
187  * Rotates the camera to look at the specified <code>position</code>. Only works if the camera is in independent mode.
188  * @function Camera.lookAt
189  * @param {Vec3} position - The position to look at.
190  * @example <caption>Rotate your camera to look at entities as you click on them with your mouse.</caption>
191  * function onMousePressEvent(event) {
192  * var pickRay = Camera.computePickRay(event.x, event.y);
193  * var intersection = Entities.findRayIntersection(pickRay);
194  * if (intersection.intersects) {
195  * // Switch to independent mode.
196  * Camera.mode = "independent";
197  * // Look at the entity that was clicked.
198  * var properties = Entities.getEntityProperties(intersection.entityID, "position");
199  * Camera.lookAt(properties.position);
200  * }
201  * }
202  *
203  * Controller.mousePressEvent.connect(onMousePressEvent);
204  */
205  void lookAt(const glm::vec3& position);
206 
207  /*@jsdoc
208  * Sets the camera to continue looking at the specified <code>position</code> even while the camera moves. Only works if
209  * the camera is in independent mode.
210  * @function Camera.keepLookingAt
211  * @param {Vec3} position - The position to keep looking at.
212  */
213  void keepLookingAt(const glm::vec3& position);
214 
215  /*@jsdoc
216  * Stops the camera from continually looking at the position that was set with {@link Camera.keepLookingAt}.
217  * @function Camera.stopLookingAt
218  */
219  void stopLooking() { _isKeepLookingAt = false; }
220 
221 signals:
222  /*@jsdoc
223  * Triggered when the camera mode changes.
224  * @function Camera.modeUpdated
225  * @param {Camera.Mode} newMode - The new camera mode.
226  * @returns {Signal}
227  * @example <caption>Report camera mode changes.</caption>
228  * function onCameraModeUpdated(newMode) {
229  * print("The camera mode has changed to " + newMode);
230  * }
231  *
232  * Camera.modeUpdated.connect(onCameraModeUpdated);
233  */
234  void modeUpdated(const QString& newMode);
235 
236  /*@jsdoc
237  * Triggered when the camera mouse capture state changes.
238  * @function Camera.captureMouseChanged
239  * @param {boolean} newCaptureMouse - The new mouse capture state.
240  * @returns {Signal}
241  * @example <caption>Report mouse capture state changes.</caption>
242  * function onCaptureMouseChanged(newCaptureMouse) {
243  * print("The mouse capture has changed to " + newCaptureMouse);
244  * }
245  *
246  * Camera.captureMouseChanged.connect(onCaptureMouseChanged);
247  */
248  void captureMouseChanged(bool newCaptureMouse);
249 
250  /*@jsdoc
251  * Triggered when mouse look setting changes.
252  * @function Camera.mouseLookChanged
253  * @param {boolean} mouseLookChanged - The new mouse look state.
254  * @returns {Signal}
255  * @example <caption>Report mouse look state changes.</caption>
256  * function onMouseLookChanged(newMouseLook) {
257  * print("The mouse look has changed to " + newMouseLook);
258  * }
259  *
260  * Camera.mouseLookChanged.connect(onMouseLookChanged);
261  */
262  void mouseLookChanged(bool newMouseLook);
263 
264 private:
265  void recompose();
266  void decompose();
267 
268  CameraMode _mode{ CAMERA_MODE_LOOK_AT };
269  glm::mat4 _transform;
270  glm::mat4 _projection;
271 
272  // derived
273  glm::vec3 _position { 0.0f, 0.0f, 0.0f };
274  glm::quat _orientation;
275  bool _isKeepLookingAt{ false };
276  glm::vec3 _lookingAt;
277 
278  bool _captureMouse { false };
279  float _sensitivity { 1.0f };
280 };
281 
282 #endif // hifi_Camera_h
T get() const
Returns the value of the setting, or the default value if not found.
Definition: SettingHandle.h:240